From 045bb64c5e903214de7e3cbcbaec111aa7398715 Mon Sep 17 00:00:00 2001 From: Edd Robinson Date: Thu, 17 Jan 2019 12:21:25 +0000 Subject: [PATCH 01/95] Add skeleton TSI design doc --- tsdb/tsi1/DESIGN.md | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tsdb/tsi1/DESIGN.md diff --git a/tsdb/tsi1/DESIGN.md b/tsdb/tsi1/DESIGN.md new file mode 100644 index 0000000000..9935a2bac3 --- /dev/null +++ b/tsdb/tsi1/DESIGN.md @@ -0,0 +1,83 @@ +# Time-Series Index + +## Introduction + +## Architecture + +### index structures and access patterns +### series ID sets +### partitioning and file types +### compactions + +## File Format + +## Access Times + +### Insertion + +TODO + +### Retrieval + +This section provides some general idea of the typical timings one can expect to experience when accessing the index. + +#### Measurement Retrieval + +Approximate times for retrieving _all_ measurements, equivalent to executing `SHOW MEASUREMENTS`, follow. These types of query only involve materialising data held in the index. + + - Retrieve 1 measurement from TSI index: `~100µs` + - Retrieve 100 measurements from TSI index: `~200µs` + - Retrieve 10,000 measurements from TSI index: `~8ms` + + +Note: as the number of measurements gets larger, much of the time will be spent allocating and materialising the measurements into a `[][]byte` to be returned to the caller. + + +#### Tag Keys Retrieval + +Approximate times for retrieving _all_ tag keys, equivalent to executing `SHOW TAG KEYS`, follow. These types of query only involve materialising data held in the index. + + - Retrieve 1 tag key from TSI index: `~65µs` + - Retrieve 100 tag keys from TSI index: `~90µs` + - Retrieve 1,000 tag keys from TSI index: `~1.3ms` + +Note: the times here show only the TSI index access for retrieving the tag keys. In practice, the measurement retrieval times need to be added on top, since you need a measurement name to access the tag keys. + + +#### Tag Value Retrieval + +Approximate times for retrieving _all_ tag values for a _specific_ tag key, equivalent to `SHOW TAG VALUES WITH KEY = "region"`, follow. These types of query only involve materialising data held in the index. + + - Retrieve 1 tag value from TSI index: `~20µs` + - Retrieve 100 tag values from TSI index: `~240µs` + - Retrieve 10,000 tag values from TSI index: `~13ms` + + +#### Series ID Retrieval + +Approximate times for retrieving a set of matching series ids for different total cardinalities, follow. + + - Retrieve 1 series id for db with cardinality 1: `~50µs` (`10µs`) + - Retrieve 10 series ids for db with cardinality 100: `~50µs` (`10µs`) + - Retrieve 100 series ids for db with cardinality 10,000: `~80µs` (`10µs`) + - Retrieve 10,000 series ids for db with cardinality 1,000,000: `~600µs` (`10µs`) + - Retrieve 100,000 series ids for db with cardinality 10,000,000: `~22ms` (`10µs`) + + +Note: the initial time is for the first observation. The second—parenthesised—time is for subsequent observations. Subsequent observations make use of the TSI bitset cache introduced in [#10234](https://github.com/influxdata/influxdb/pull/10234). + + +## Complex Series ID Retrieval + +Approximate times for retrieving a set of matching series ids for different total cardinalities. In these cases, each retrieval is based on two tag key/value predicates, e.g., `SHOW SERIES WHERE "region" = 'west' AND "zone" = 'a'` + + - Retrieve 1,000 series ids for db with cardinality 1,000,000: `~8ms` (`15µs`) + - Retrieve 10,000 series ids for db with cardinality 10,000,000: `~7ms` (`25µs`) + + +Note: the initial time is for the first observation. The second—parenthesised—time is for subsequent observations. Subsequent observations make use of the TSI bitset cache introduced in [#10234](https://github.com/influxdata/influxdb/pull/10234). +In these more complex cases, a series ID set is retrieved for each of the predicates. The sets are then intersected to identify the final set. Cache times, then, are typically doubled since each series id set for each predicate is stored separately. +There will be some additional overhead for the intersection operation. + + + From 0d1d2c841e81f052bbed3af88e4a53c78e5d976f Mon Sep 17 00:00:00 2001 From: Ahmed Ashour Date: Wed, 23 Jan 2019 13:33:09 +0100 Subject: [PATCH 02/95] Fix typo --- tsdb/cursor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsdb/cursor.go b/tsdb/cursor.go index 849835d446..f63461c5f9 100644 --- a/tsdb/cursor.go +++ b/tsdb/cursor.go @@ -2,7 +2,7 @@ package tsdb import "github.com/influxdata/influxdb/tsdb/cursors" -// These aliases exist to maintain api compatability when they were moved +// These aliases exist to maintain api compatibility when they were moved // into their own package to avoid having a heavy dependency in order to // talk about consuming data. From d8fde82f3dd0fb9e39ad4f35af6cca7e86298385 Mon Sep 17 00:00:00 2001 From: AJ Bond Date: Thu, 24 Jan 2019 09:41:47 -0500 Subject: [PATCH 03/95] chore(docker): Update Influxd Dockerfile * Update ca-certificates install * Clean up apt-get cache directories * Reduce copy steps to single copy operation --- docker/influxd/Dockerfile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docker/influxd/Dockerfile b/docker/influxd/Dockerfile index c0385ef69b..3c78907c21 100644 --- a/docker/influxd/Dockerfile +++ b/docker/influxd/Dockerfile @@ -1,13 +1,19 @@ FROM debian:stable-slim -COPY influxd /usr/bin/influxd -COPY influx /usr/bin/influx +COPY influx influxd /usr/bin/ EXPOSE 9999 -RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* +ENV DEBIAN_FRONTEND noninteractive COPY docker/influxd/entrypoint.sh /entrypoint.sh + +RUN apt-get update \ + && apt-get install -y \ + ca-certificates \ + tzdata \ + && apt-get clean autoclean \ + && apt-get autoremove --yes \ + && rm -rf /var/lib/{apt,dpkg,cache,log} + ENTRYPOINT ["/entrypoint.sh"] CMD ["influxd"] From 854b2a43ebb5cf0661d33d88a2a40fd832924742 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Fri, 25 Jan 2019 14:08:57 -0800 Subject: [PATCH 04/95] test(ui): component integration testing w/ mock redux store (#11577) * wip: introduce connected async component test * test(query-builder): mock findBuckets * test(ui): add ability to pass arbitrary state to renderWithRedux * test(ui/queryBuilder): click bucket and tag * test(ui/queryBuilder): use regex matchers to query all * test(ui/queryBuilder): it can click a tag value * chore: change id to ID * chore: move QueryBuilderFetcher * test(ui/queryBuilder): try waiting for dropdown-items * test(ui/queryBuilder): move initial state out of beforeEach * test(ui/queryBuilder): get by bucket name * wip * test: put back to default * test: remove await --- ui/jestSetup.ts | 6 + ui/mocks/dummyData.ts | 20 ++- ui/package-lock.json | 33 +++++ ui/package.json | 2 + .../components/dropdowns/Dropdown.tsx | 10 +- .../components/dropdowns/DropdownButton.tsx | 4 +- .../components/dropdowns/DropdownItem.tsx | 4 +- .../dataExplorer/components/DataExplorer.tsx | 2 +- ui/src/mockState.tsx | 41 ++++++ .../shared/components/SearchableDropdown.tsx | 3 +- ui/src/store/configureStore.ts | 8 +- ui/src/timeMachine/actions/queryBuilder.ts | 6 +- .../timeMachine/apis/QueryBuilderFetcher.ts | 127 +++++++++++++++++ .../apis/__mocks__/queryBuilder.ts | 14 ++ ui/src/timeMachine/apis/queryBuilder.ts | 134 ++---------------- ui/src/timeMachine/components/Queries.tsx | 1 + .../components/QueryBuilder.test.tsx | 94 ++++++++++++ .../timeMachine/components/QueryBuilder.tsx | 2 +- .../components/QueryBuilderBucketDropdown.tsx | 2 + ui/src/timeMachine/components/TagSelector.tsx | 7 +- ui/src/timeMachine/reducers/index.ts | 25 +++- ui/src/types/localStorage.ts | 4 +- 22 files changed, 394 insertions(+), 155 deletions(-) create mode 100644 ui/jestSetup.ts create mode 100644 ui/src/mockState.tsx create mode 100644 ui/src/timeMachine/apis/QueryBuilderFetcher.ts create mode 100644 ui/src/timeMachine/apis/__mocks__/queryBuilder.ts create mode 100644 ui/src/timeMachine/components/QueryBuilder.test.tsx diff --git a/ui/jestSetup.ts b/ui/jestSetup.ts new file mode 100644 index 0000000000..fb260ffb9f --- /dev/null +++ b/ui/jestSetup.ts @@ -0,0 +1,6 @@ +import {cleanup} from 'react-testing-library' + +// cleans up state between react-testing-library tests +afterEach(() => { + cleanup() +}) diff --git a/ui/mocks/dummyData.ts b/ui/mocks/dummyData.ts index f902b53bc3..b534af907a 100644 --- a/ui/mocks/dummyData.ts +++ b/ui/mocks/dummyData.ts @@ -1,11 +1,5 @@ -import { - Source, - SourceAuthenticationMethod, - Template, - SourceLinks, - TemplateType, - TemplateValueType, -} from 'src/types' +import {Template, SourceLinks, TemplateType, TemplateValueType} from 'src/types' +import {Source} from 'src/api' import {Cell, Dashboard, Label} from 'src/types/v2' import {Links} from 'src/types/v2/links' import {Task} from 'src/types/v2/tasks' @@ -123,14 +117,12 @@ export const sourceLinks: SourceLinks = { export const source: Source = { id: '16', name: 'ssl', - type: 'influx', + type: Source.TypeEnum.Self, username: 'admin', url: 'https://localhost:9086', insecureSkipVerify: true, - default: false, telegraf: 'telegraf', links: sourceLinks, - authentication: SourceAuthenticationMethod.Basic, } export const timeRange = { @@ -583,7 +575,11 @@ export const setSetupParamsResponse = { userID: '033bc62520fe3000', user: 'iris', permissions: [ - {action: 'read', resource: 'authorizations', orgID: '033bc62534be3000'}, + { + action: 'read', + resource: 'authorizations', + orgID: '033bc62534be3000', + }, { action: 'write', resource: 'authorizations', diff --git a/ui/package-lock.json b/ui/package-lock.json index ccd47ce491..6d814d51a0 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -902,6 +902,12 @@ "physical-cpu-count": "^2.0.0" } }, + "@sheerun/mutationobserver-shim": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz", + "integrity": "sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==", + "dev": true + }, "@types/abstract-leveldown": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz", @@ -3738,6 +3744,18 @@ } } }, + "dom-testing-library": { + "version": "3.16.4", + "resolved": "https://registry.npmjs.org/dom-testing-library/-/dom-testing-library-3.16.4.tgz", + "integrity": "sha512-D8tFLGe0xInL8F/KxZM7gc4r/vOCTgFGM93zXLB/AjFPz2O86y0UaruXl45K6xhqyclJFHHxUtgwaRddRyqxFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.1.5", + "@sheerun/mutationobserver-shim": "^0.3.2", + "pretty-format": "^23.6.0", + "wait-for-expect": "^1.1.0" + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -10629,6 +10647,15 @@ "schedule": "^0.5.0" } }, + "react-testing-library": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/react-testing-library/-/react-testing-library-5.4.4.tgz", + "integrity": "sha512-/TiERZ+URSNhZQfjrUXh0VLsiLSmhqP1WP+2e2wWqWqrRIWpcAxrfuBxzlT75LYMDNmicEikaXJqRDi/pqCEDg==", + "dev": true, + "requires": { + "dom-testing-library": "^3.13.1" + } + }, "react-tooltip": { "version": "3.8.4", "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.8.4.tgz", @@ -13000,6 +13027,12 @@ "browser-process-hrtime": "^0.1.2" } }, + "wait-for-expect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-1.1.0.tgz", + "integrity": "sha512-vQDokqxyMyknfX3luCDn16bSaRcOyH6gGuUXMIbxBLeTo6nWuEWYqMTT9a+44FmW8c2m6TRWBdNvBBjA1hwEKg==", + "dev": true + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", diff --git a/ui/package.json b/ui/package.json index 1d634145eb..33645d6e4c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -30,6 +30,7 @@ "tsc:watch": "tsc -p ./tsconfig.json --noEmit --pretty -w" }, "jest": { + "setupTestFrameworkScriptFile": "./jestSetup.ts", "displayName": "test", "testURL": "http://localhost", "testPathIgnorePatterns": [ @@ -104,6 +105,7 @@ "jsdom": "^9.0.0", "parcel": "^1.11.0", "prettier": "^1.14.3", + "react-testing-library": "^5.4.4", "sass": "^1.15.3", "ts-jest": "^23.10.3", "tslib": "^1.9.0", diff --git a/ui/src/clockface/components/dropdowns/Dropdown.tsx b/ui/src/clockface/components/dropdowns/Dropdown.tsx index 2495af08a2..98a2749f46 100644 --- a/ui/src/clockface/components/dropdowns/Dropdown.tsx +++ b/ui/src/clockface/components/dropdowns/Dropdown.tsx @@ -43,6 +43,8 @@ export interface Props { mode?: DropdownMode titleText?: string menuHeader?: JSX.Element + testID: string + buttonTestID: string } interface State { @@ -122,6 +124,7 @@ class Dropdown extends Component { icon, children, titleText, + buttonTestID, } = this.props const {expanded} = this.state @@ -147,6 +150,7 @@ class Dropdown extends Component { onClick={this.toggleMenu} status={status} title={titleText} + testID={buttonTestID} > {dropdownLabel} @@ -160,6 +164,7 @@ class Dropdown extends Component { menuHeader, menuColor, children, + testID, } = this.props const {expanded} = this.state @@ -174,7 +179,10 @@ class Dropdown extends Component { autoHeight={true} maxHeight={maxMenuHeight} > -
+
{menuHeader && menuHeader} {React.Children.map(children, (child: JSX.Element) => { if (this.childTypeIsValid(child)) { diff --git a/ui/src/clockface/components/dropdowns/DropdownButton.tsx b/ui/src/clockface/components/dropdowns/DropdownButton.tsx index a2fd5401e1..74dbd16982 100644 --- a/ui/src/clockface/components/dropdowns/DropdownButton.tsx +++ b/ui/src/clockface/components/dropdowns/DropdownButton.tsx @@ -23,6 +23,7 @@ interface Props { size?: ComponentSize icon?: IconFont title?: string + testID: string } @ErrorHandling @@ -35,7 +36,7 @@ class DropdownButton extends Component { } public render() { - const {onClick, children, title} = this.props + const {onClick, children, title, testID} = this.props return ( - -
- -
- - - - - - + + + + + + + + + + +
+ active +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +
+
diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index cfe25a5c34..0ddee4bf94 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -4,12 +4,7 @@ import _ from 'lodash' import {setupAPI, sourcesAPI} from 'src/utils/api' // Utils -import { - telegrafsAPI, - authorizationsAPI, - writeAPI, - scraperTargetsApi, -} from 'src/utils/api' +import {telegrafsAPI, writeAPI, scraperTargetsApi} from 'src/utils/api' import { Telegraf, @@ -101,17 +96,6 @@ export const getTelegrafConfigs = async (org: string): Promise => { } } -export const getAuthorizationToken = async ( - username: string -): Promise => { - try { - const data = await authorizationsAPI.authorizationsGet(undefined, username) - return getDeep(data, 'data.authorizations.0.token', '') - } catch (error) { - console.error(error) - } -} - export const writeLineProtocol = async ( org: string, bucket: string, diff --git a/ui/src/onboarding/apis/mocks.ts b/ui/src/onboarding/apis/mocks.ts index e8dd9dc473..793e510611 100644 --- a/ui/src/onboarding/apis/mocks.ts +++ b/ui/src/onboarding/apis/mocks.ts @@ -1,6 +1,5 @@ import { getTelegrafConfigsResponse, - authResponse, createTelegrafConfigResponse, setSetupParamsResponse, } from 'mocks/dummyData' @@ -12,7 +11,6 @@ const telegrafsPost = jest.fn(() => const telegrafsTelegrafIDPut = jest.fn(() => Promise.resolve(createTelegrafConfigResponse) ) -const authorizationsGet = jest.fn(() => Promise.resolve(authResponse)) const setupPost = jest.fn(() => Promise.resolve(setSetupParamsResponse)) const setupGet = jest.fn(() => Promise.resolve({data: {allowed: true}})) @@ -26,7 +24,3 @@ export const setupAPI = { setupPost, setupGet, } - -export const authorizationsAPI = { - authorizationsGet, -} diff --git a/ui/src/onboarding/apis/onboarding.test.ts b/ui/src/onboarding/apis/onboarding.test.ts index a492aed197..1c8d8afa5c 100644 --- a/ui/src/onboarding/apis/onboarding.test.ts +++ b/ui/src/onboarding/apis/onboarding.test.ts @@ -4,15 +4,10 @@ import { SetupParams, getTelegrafConfigs, createTelegrafConfig, - getAuthorizationToken, } from 'src/onboarding/apis' -import {telegrafConfig, token} from 'mocks/dummyData' -import { - telegrafsAPI, - authorizationsAPI, - setupAPI, -} from 'src/onboarding/apis/mocks' +import {telegrafConfig} from 'mocks/dummyData' +import {telegrafsAPI, setupAPI} from 'src/onboarding/apis/mocks' jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks')) @@ -58,17 +53,4 @@ describe('Onboarding.Apis', () => { expect(result).toEqual(telegrafConfig) }) }) - - describe('getAuthorizationToken', () => { - it('should return a token', async () => { - const username = 'iris' - const result = await getAuthorizationToken(username) - - expect(result).toEqual(token) - expect(authorizationsAPI.authorizationsGet).toBeCalledWith( - undefined, - username - ) - }) - }) }) From f0371e67169b86c7ec1d30e0b1a1cfc48b2971e6 Mon Sep 17 00:00:00 2001 From: Delmer Date: Fri, 25 Jan 2019 15:28:52 -0800 Subject: [PATCH 06/95] fix(ui): fix overlay transition focusing (#11619) Co-authored-by: Chris Henn --- ui/src/clockface/components/label/LabelSelector.tsx | 1 + ui/src/clockface/components/overlays/Overlay.scss | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/src/clockface/components/label/LabelSelector.tsx b/ui/src/clockface/components/label/LabelSelector.tsx index efbd0d38bf..4236e5c6f7 100644 --- a/ui/src/clockface/components/label/LabelSelector.tsx +++ b/ui/src/clockface/components/label/LabelSelector.tsx @@ -79,6 +79,7 @@ class LabelSelector extends Component { onKeyDown={this.handleKeyDown} onChange={this.handleInputChange} size={inputSize} + autoFocus={true} /> {this.suggestionMenu} diff --git a/ui/src/clockface/components/overlays/Overlay.scss b/ui/src/clockface/components/overlays/Overlay.scss index 3cdb13877d..1b0ec6e130 100644 --- a/ui/src/clockface/components/overlays/Overlay.scss +++ b/ui/src/clockface/components/overlays/Overlay.scss @@ -39,12 +39,14 @@ $overlay-gutter: $ix-marg-d; .overlay-tech { @extend %overlay-styles; - visibility: hidden; transition: all 0.25s ease; z-index: $z--overlays; + pointer-events: none; + opacity: 0; &.show { - visibility: visible; + opacity: 1; + pointer-events: all; } } From 3f0e40812e0e4a3bec260341a456ad6850f72723 Mon Sep 17 00:00:00 2001 From: Mark Rushakoff Date: Fri, 25 Jan 2019 15:17:30 -0800 Subject: [PATCH 07/95] fix(http): return 404 when task or run is not found For an operation that looks up a task or a run, when that operation fails, only set the status to 404 if that operation explicitly returns ErrTaskNotFound or ErrRunNotFound. It's possible that the operation could fail for a reason other than the ID being invalid: for example, if there was an IO error preventing the lookup from succeeding. Harden that behavior with tests for the task handler. Closes #11589. --- http/task_service.go | 66 +++++---- http/task_service_test.go | 275 +++++++++++++++++++++++++++++++++++++- 2 files changed, 309 insertions(+), 32 deletions(-) diff --git a/http/task_service.go b/http/task_service.go index 41cf73034e..b9b0445809 100644 --- a/http/task_service.go +++ b/http/task_service.go @@ -462,10 +462,13 @@ func (h *TaskHandler) handleUpdateTask(w http.ResponseWriter, r *http.Request) { } task, err := h.TaskService.UpdateTask(ctx, req.TaskID, req.Update) if err != nil { - err = &platform.Error{ + err := &platform.Error{ Err: err, Msg: "failed to update task", } + if err.Err == backend.ErrTaskNotFound { + err.Code = platform.ENotFound + } EncodeError(ctx, err, w) return } @@ -541,10 +544,13 @@ func (h *TaskHandler) handleDeleteTask(w http.ResponseWriter, r *http.Request) { } if err := h.TaskService.DeleteTask(ctx, req.TaskID); err != nil { - err = &platform.Error{ + err := &platform.Error{ Err: err, Msg: "failed to delete task", } + if err.Err == backend.ErrTaskNotFound { + err.Code = platform.ENotFound + } EncodeError(ctx, err, w) return } @@ -592,10 +598,13 @@ func (h *TaskHandler) handleGetLogs(w http.ResponseWriter, r *http.Request) { logs, _, err := h.TaskService.FindLogs(ctx, req.filter) if err != nil { - err = &platform.Error{ + err := &platform.Error{ Err: err, Msg: "failed to find task logs", } + if err.Err == backend.ErrTaskNotFound || err.Err == backend.ErrRunNotFound { + err.Code = platform.ENotFound + } EncodeError(ctx, err, w) return } @@ -671,10 +680,12 @@ func (h *TaskHandler) handleGetRuns(w http.ResponseWriter, r *http.Request) { runs, _, err := h.TaskService.FindRuns(ctx, req.filter) if err != nil { - err = &platform.Error{ - Err: err, - Code: platform.EInvalid, - Msg: "failed to find runs", + err := &platform.Error{ + Err: err, + Msg: "failed to find runs", + } + if err.Err == backend.ErrTaskNotFound { + err.Code = platform.ENotFound } EncodeError(ctx, err, w) return @@ -792,12 +803,12 @@ func (h *TaskHandler) handleForceRun(w http.ResponseWriter, r *http.Request) { run, err := h.TaskService.ForceRun(ctx, req.TaskID, req.Timestamp) if err != nil { - if err == backend.ErrRunNotFound { - err = &platform.Error{ - Code: platform.ENotFound, - Msg: "failed to force run", - Err: err, - } + err := &platform.Error{ + Err: err, + Msg: "failed to force run", + } + if err.Err == backend.ErrTaskNotFound { + err.Code = platform.ENotFound } EncodeError(ctx, err, w) return @@ -868,12 +879,12 @@ func (h *TaskHandler) handleGetRun(w http.ResponseWriter, r *http.Request) { run, err := h.TaskService.FindRunByID(ctx, req.TaskID, req.RunID) if err != nil { - if err == backend.ErrRunNotFound { - err = &platform.Error{ - Err: err, - Msg: "failed to find run", - Code: platform.ENotFound, - } + err := &platform.Error{ + Err: err, + Msg: "failed to find run", + } + if err.Err == backend.ErrTaskNotFound || err.Err == backend.ErrRunNotFound { + err.Code = platform.ENotFound } EncodeError(ctx, err, w) return @@ -974,10 +985,13 @@ func (h *TaskHandler) handleCancelRun(w http.ResponseWriter, r *http.Request) { err = h.TaskService.CancelRun(ctx, req.TaskID, req.RunID) if err != nil { - err = &platform.Error{ + err := &platform.Error{ Err: err, Msg: "failed to cancel run", } + if err.Err == backend.ErrTaskNotFound || err.Err == backend.ErrRunNotFound { + err.Code = platform.ENotFound + } EncodeError(ctx, err, w) return } @@ -999,12 +1013,12 @@ func (h *TaskHandler) handleRetryRun(w http.ResponseWriter, r *http.Request) { run, err := h.TaskService.RetryRun(ctx, req.TaskID, req.RunID) if err != nil { - if err == backend.ErrRunNotFound { - err = &platform.Error{ - Code: platform.ENotFound, - Msg: "failed to retry run", - Err: err, - } + err := &platform.Error{ + Err: err, + Msg: "failed to retry run", + } + if err.Err == backend.ErrTaskNotFound || err.Err == backend.ErrRunNotFound { + err.Code = platform.ENotFound } EncodeError(ctx, err, w) return diff --git a/http/task_service_test.go b/http/task_service_test.go index 0ba937b01a..56f128d8bd 100644 --- a/http/task_service_test.go +++ b/http/task_service_test.go @@ -4,19 +4,22 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io/ioutil" "net/http" "net/http/httptest" - "os" + "strings" "testing" platform "github.com/influxdata/influxdb" pcontext "github.com/influxdata/influxdb/context" - "github.com/influxdata/influxdb/logger" + "github.com/influxdata/influxdb/inmem" "github.com/influxdata/influxdb/mock" _ "github.com/influxdata/influxdb/query/builtin" + "github.com/influxdata/influxdb/task/backend" platformtesting "github.com/influxdata/influxdb/testing" "github.com/julienschmidt/httprouter" + "go.uber.org/zap/zaptest" ) func mockOrgService() platform.OrganizationService { @@ -161,7 +164,7 @@ func TestTaskHandler_handleGetTasks(t *testing.T) { r := httptest.NewRequest("GET", "http://any.url", nil) w := httptest.NewRecorder() - h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), logger.New(os.Stdout), mock.NewUserService()) + h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), zaptest.NewLogger(t), mock.NewUserService()) h.OrganizationService = mockOrgService() h.TaskService = tt.fields.taskService h.LabelService = tt.fields.labelService @@ -262,7 +265,7 @@ func TestTaskHandler_handlePostTasks(t *testing.T) { w := httptest.NewRecorder() - h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), logger.New(os.Stdout), mock.NewUserService()) + h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), zaptest.NewLogger(t), mock.NewUserService()) h.OrganizationService = mockOrgService() h.TaskService = tt.fields.taskService h.handlePostTask(w, r) @@ -367,7 +370,7 @@ func TestTaskHandler_handleGetRun(t *testing.T) { }, })) w := httptest.NewRecorder() - h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), logger.New(os.Stdout), mock.NewUserService()) + h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), zaptest.NewLogger(t), mock.NewUserService()) h.OrganizationService = mockOrgService() h.TaskService = tt.fields.taskService h.handleGetRun(w, r) @@ -476,7 +479,7 @@ func TestTaskHandler_handleGetRuns(t *testing.T) { }, })) w := httptest.NewRecorder() - h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), logger.New(os.Stdout), mock.NewUserService()) + h := NewTaskHandler(mock.NewUserResourceMappingService(), mock.NewLabelService(), zaptest.NewLogger(t), mock.NewUserService()) h.OrganizationService = mockOrgService() h.TaskService = tt.fields.taskService h.handleGetRuns(w, r) @@ -497,3 +500,263 @@ func TestTaskHandler_handleGetRuns(t *testing.T) { }) } } + +func TestTaskHandler_NotFoundStatus(t *testing.T) { + // Ensure that the HTTP handlers return 404s for missing resources, and OKs for matching. + + im := inmem.NewService() + h := NewTaskHandler(im, im, zaptest.NewLogger(t), im) + h.OrganizationService = im + + o := platform.Organization{Name: "o"} + ctx := context.Background() + if err := h.OrganizationService.CreateOrganization(ctx, &o); err != nil { + t.Fatal(err) + } + + const taskID, runID = platform.ID(0xCCCCCC), platform.ID(0xAAAAAA) + + var ( + okTask = []interface{}{taskID} + okTaskRun = []interface{}{taskID, runID} + + notFoundTask = [][]interface{}{ + {taskID + 1}, + } + notFoundTaskRun = [][]interface{}{ + {taskID, runID + 1}, + {taskID + 1, runID}, + {taskID + 1, runID + 1}, + } + ) + + tcs := []struct { + name string + svc *mock.TaskService + method string + body string + pathFmt string + okPathArgs []interface{} + notFoundPathArgs [][]interface{} + }{ + { + name: "get task", + svc: &mock.TaskService{ + FindTaskByIDFn: func(_ context.Context, id platform.ID) (*platform.Task, error) { + if id == taskID { + return &platform.Task{ID: taskID, Organization: "o"}, nil + } + + return nil, backend.ErrTaskNotFound + }, + }, + method: http.MethodGet, + pathFmt: "/tasks/%s", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "update task", + svc: &mock.TaskService{ + UpdateTaskFn: func(_ context.Context, id platform.ID, _ platform.TaskUpdate) (*platform.Task, error) { + if id == taskID { + return &platform.Task{ID: taskID, Organization: "o"}, nil + } + + return nil, backend.ErrTaskNotFound + }, + }, + method: http.MethodPatch, + body: "{}", + pathFmt: "/tasks/%s", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "delete task", + svc: &mock.TaskService{ + DeleteTaskFn: func(_ context.Context, id platform.ID) error { + if id == taskID { + return nil + } + + return backend.ErrTaskNotFound + }, + }, + method: http.MethodDelete, + pathFmt: "/tasks/%s", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "get task logs", + svc: &mock.TaskService{ + FindLogsFn: func(_ context.Context, f platform.LogFilter) ([]*platform.Log, int, error) { + if *f.Task == taskID { + return nil, 0, nil + } + + return nil, 0, backend.ErrTaskNotFound + }, + }, + method: http.MethodGet, + pathFmt: "/tasks/%s/logs", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "get run logs", + svc: &mock.TaskService{ + FindLogsFn: func(_ context.Context, f platform.LogFilter) ([]*platform.Log, int, error) { + if *f.Task != taskID { + return nil, 0, backend.ErrTaskNotFound + } + if *f.Run != runID { + return nil, 0, backend.ErrRunNotFound + } + + return nil, 0, nil + }, + }, + method: http.MethodGet, + pathFmt: "/tasks/%s/runs/%s/logs", + okPathArgs: okTaskRun, + notFoundPathArgs: notFoundTaskRun, + }, + { + name: "get runs", + svc: &mock.TaskService{ + FindRunsFn: func(_ context.Context, f platform.RunFilter) ([]*platform.Run, int, error) { + if *f.Task != taskID { + return nil, 0, backend.ErrTaskNotFound + } + + return nil, 0, nil + }, + }, + method: http.MethodGet, + pathFmt: "/tasks/%s/runs", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "force run", + svc: &mock.TaskService{ + ForceRunFn: func(_ context.Context, tid platform.ID, _ int64) (*platform.Run, error) { + if tid != taskID { + return nil, backend.ErrTaskNotFound + } + + return &platform.Run{ID: runID, TaskID: taskID, Status: backend.RunScheduled.String()}, nil + }, + }, + method: http.MethodPost, + body: "{}", + pathFmt: "/tasks/%s/runs", + okPathArgs: okTask, + notFoundPathArgs: notFoundTask, + }, + { + name: "get run", + svc: &mock.TaskService{ + FindRunByIDFn: func(_ context.Context, tid, rid platform.ID) (*platform.Run, error) { + if tid != taskID { + return nil, backend.ErrTaskNotFound + } + if rid != runID { + return nil, backend.ErrRunNotFound + } + + return &platform.Run{ID: runID, TaskID: taskID, Status: backend.RunScheduled.String()}, nil + }, + }, + method: http.MethodGet, + pathFmt: "/tasks/%s/runs/%s", + okPathArgs: okTaskRun, + notFoundPathArgs: notFoundTaskRun, + }, + { + name: "retry run", + svc: &mock.TaskService{ + RetryRunFn: func(_ context.Context, tid, rid platform.ID) (*platform.Run, error) { + if tid != taskID { + return nil, backend.ErrTaskNotFound + } + if rid != runID { + return nil, backend.ErrRunNotFound + } + + return &platform.Run{ID: runID, TaskID: taskID, Status: backend.RunScheduled.String()}, nil + }, + }, + method: http.MethodPost, + pathFmt: "/tasks/%s/runs/%s/retry", + okPathArgs: okTaskRun, + notFoundPathArgs: notFoundTaskRun, + }, + { + name: "cancel run", + svc: &mock.TaskService{ + CancelRunFn: func(_ context.Context, tid, rid platform.ID) error { + if tid != taskID { + return backend.ErrTaskNotFound + } + if rid != runID { + return backend.ErrRunNotFound + } + + return nil + }, + }, + method: http.MethodDelete, + pathFmt: "/tasks/%s/runs/%s", + okPathArgs: okTaskRun, + notFoundPathArgs: notFoundTaskRun, + }, + } + + for _, tc := range tcs { + tc := tc + t.Run(tc.name, func(t *testing.T) { + h.TaskService = tc.svc + + okPath := fmt.Sprintf(tc.pathFmt, tc.okPathArgs...) + t.Run("matching ID: "+tc.method+" "+okPath, func(t *testing.T) { + w := httptest.NewRecorder() + r := httptest.NewRequest(tc.method, "http://task.example/api/v2"+okPath, strings.NewReader(tc.body)) + + h.ServeHTTP(w, r) + + res := w.Result() + defer res.Body.Close() + + if res.StatusCode < 200 || res.StatusCode > 299 { + t.Errorf("expected OK, got %d", res.StatusCode) + b, _ := ioutil.ReadAll(res.Body) + t.Fatalf("body: %s", string(b)) + } + }) + + t.Run("mismatched ID", func(t *testing.T) { + for _, nfa := range tc.notFoundPathArgs { + path := fmt.Sprintf(tc.pathFmt, nfa...) + t.Run(tc.method+" "+path, func(t *testing.T) { + w := httptest.NewRecorder() + r := httptest.NewRequest(tc.method, "http://task.example/api/v2"+path, strings.NewReader(tc.body)) + + h.ServeHTTP(w, r) + + res := w.Result() + defer res.Body.Close() + + if res.StatusCode != http.StatusNotFound { + t.Errorf("expected Not Found, got %d", res.StatusCode) + b, _ := ioutil.ReadAll(res.Body) + t.Fatalf("body: %s", string(b)) + } + }) + } + }) + }) + } +} From ae3139cc656ac472542a6487bf509962cf7aec18 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Fri, 25 Jan 2019 16:33:30 -0800 Subject: [PATCH 08/95] Switch write to client library --- ui/src/dataLoaders/actions/dataLoaders.ts | 4 ++-- ui/src/onboarding/apis/index.ts | 22 +--------------------- ui/src/utils/api.ts | 4 ---- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/ui/src/dataLoaders/actions/dataLoaders.ts b/ui/src/dataLoaders/actions/dataLoaders.ts index deb3e83590..7bbd082e4e 100644 --- a/ui/src/dataLoaders/actions/dataLoaders.ts +++ b/ui/src/dataLoaders/actions/dataLoaders.ts @@ -3,13 +3,13 @@ import _ from 'lodash' // Apis import { - writeLineProtocol, createTelegrafConfig, updateTelegrafConfig, createScraperTarget, updateScraperTarget, getTelegrafConfig, } from 'src/onboarding/apis/index' +import {client} from 'src/utils/api' // Utils import {createNewPlugin} from 'src/dataLoaders/utils/pluginConfigs' @@ -418,7 +418,7 @@ export const writeLineProtocolAction = ( ) => async dispatch => { try { dispatch(setLPStatus(RemoteDataState.Loading)) - await writeLineProtocol(org, bucket, body, precision) + await client.write.create(org, bucket, body, {precision}) dispatch(setLPStatus(RemoteDataState.Done)) } catch (error) { dispatch(setLPStatus(RemoteDataState.Error)) diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index 0ddee4bf94..e917af74f7 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -4,11 +4,10 @@ import _ from 'lodash' import {setupAPI, sourcesAPI} from 'src/utils/api' // Utils -import {telegrafsAPI, writeAPI, scraperTargetsApi} from 'src/utils/api' +import {telegrafsAPI, scraperTargetsApi} from 'src/utils/api' import { Telegraf, - WritePrecision, TelegrafRequest, OnboardingResponse, ScraperTargetRequest, @@ -96,25 +95,6 @@ export const getTelegrafConfigs = async (org: string): Promise => { } } -export const writeLineProtocol = async ( - org: string, - bucket: string, - body: string, - precision: WritePrecision -): Promise => { - const data = await writeAPI.writePost( - org, - bucket, - body, - undefined, - undefined, - undefined, - undefined, - precision - ) - return data -} - export const createTelegrafConfig = async ( telegrafConfig: TelegrafRequest ): Promise => { diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 112f5a0aa3..08f3f446b0 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -2,9 +2,7 @@ import { DashboardsApi, CellsApi, TelegrafsApi, - AuthorizationsApi, ViewsApi, - WriteApi, SourcesApi, QueryApi, SetupApi, @@ -22,8 +20,6 @@ export const viewsAPI = new ViewsApi({basePath}) export const dashboardsAPI = new DashboardsApi({basePath}) export const cellsAPI = new CellsApi({basePath}) export const telegrafsAPI = new TelegrafsApi({basePath}) -export const authorizationsAPI = new AuthorizationsApi({basePath}) -export const writeAPI = new WriteApi({basePath}) export const sourcesAPI = new SourcesApi({basePath}) export const queryAPI = new QueryApi({basePath}) export const setupAPI = new SetupApi({basePath}) From 064e13d13cae2afaed8a7e9241a4b4eb92b94d33 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Thu, 31 Jan 2019 10:05:40 -0800 Subject: [PATCH 09/95] Move scraper api calls to client library --- ui/src/dataLoaders/actions/dataLoaders.ts | 13 ++++-- ui/src/onboarding/apis/index.ts | 41 +------------------ .../onboarding/components/CompletionStep.tsx | 15 +++---- ui/src/organizations/apis/index.ts | 23 +---------- ui/src/organizations/components/Scrapers.tsx | 12 +++--- .../containers/OrganizationView.tsx | 11 +++-- ui/src/utils/api.ts | 2 - 7 files changed, 34 insertions(+), 83 deletions(-) diff --git a/ui/src/dataLoaders/actions/dataLoaders.ts b/ui/src/dataLoaders/actions/dataLoaders.ts index 7bbd082e4e..ab8d6e15c7 100644 --- a/ui/src/dataLoaders/actions/dataLoaders.ts +++ b/ui/src/dataLoaders/actions/dataLoaders.ts @@ -5,11 +5,10 @@ import _ from 'lodash' import { createTelegrafConfig, updateTelegrafConfig, - createScraperTarget, - updateScraperTarget, getTelegrafConfig, } from 'src/onboarding/apis/index' import {client} from 'src/utils/api' +import {ScraperTargetRequest} from 'src/api' // Utils import {createNewPlugin} from 'src/dataLoaders/utils/pluginConfigs' @@ -440,9 +439,15 @@ export const saveScraperTarget = () => async ( try { if (id) { - await updateScraperTarget(id, url, bucketID) + await client.scrapers.update(id, {url, bucketID}) } else { - const newTarget = await createScraperTarget(url, orgID, bucketID) + const newTarget = await client.scrapers.create({ + name: 'new target', + type: ScraperTargetRequest.TypeEnum.Prometheus, + url, + bucketID, + orgID, + }) dispatch(setScraperTargetID(newTarget.id)) } } catch (error) { diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index e917af74f7..2aab3617c3 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -1,18 +1,10 @@ // Libraries import _ from 'lodash' -import {setupAPI, sourcesAPI} from 'src/utils/api' - // Utils -import {telegrafsAPI, scraperTargetsApi} from 'src/utils/api' +import {telegrafsAPI, setupAPI, sourcesAPI} from 'src/utils/api' -import { - Telegraf, - TelegrafRequest, - OnboardingResponse, - ScraperTargetRequest, - ScraperTargetResponse, -} from 'src/api' +import {Telegraf, TelegrafRequest, OnboardingResponse} from 'src/api' import {getDeep} from 'src/utils/wrappers' @@ -122,32 +114,3 @@ export const updateTelegrafConfig = async ( console.error(error) } } - -export const createScraperTarget = async ( - url: string, - orgID: string, - bucketID: string -): Promise => { - const response = await scraperTargetsApi.scrapersPost({ - name: 'new target', - type: ScraperTargetRequest.TypeEnum.Prometheus, - url, - orgID, - bucketID, - }) - - return response.data -} - -export const updateScraperTarget = async ( - id: string, - url: string, - bucketID: string -): Promise => { - const response = await scraperTargetsApi.scrapersScraperTargetIDPatch(id, { - url, - bucketID, - }) - - return response.data -} diff --git a/ui/src/onboarding/components/CompletionStep.tsx b/ui/src/onboarding/components/CompletionStep.tsx index 9174c972f4..f16605ed0b 100644 --- a/ui/src/onboarding/components/CompletionStep.tsx +++ b/ui/src/onboarding/components/CompletionStep.tsx @@ -16,7 +16,6 @@ import { // APIs import {getDashboards} from 'src/organizations/apis' -import {createScraperTarget} from 'src/onboarding/apis' import {client} from 'src/utils/api' // Types @@ -27,7 +26,7 @@ import { Grid, Columns, } from 'src/clockface' -import {Organization, Dashboard} from 'src/api' +import {Organization, Dashboard, ScraperTargetRequest} from 'src/api' import {OnboardingStepProps} from 'src/onboarding/containers/OnboardingWizard' import {QUICKSTART_SCRAPER_TARGET_URL} from 'src/dataLoaders/constants/pluginConfigs' @@ -140,11 +139,13 @@ class CompletionStep extends PureComponent { private handleQuickStart = async () => { try { - await createScraperTarget( - QUICKSTART_SCRAPER_TARGET_URL, - this.props.orgID, - this.props.bucketID - ) + await client.scrapers.create({ + name: 'new target', + type: ScraperTargetRequest.TypeEnum.Prometheus, + url: QUICKSTART_SCRAPER_TARGET_URL, + bucketID: this.props.bucketID, + orgID: this.props.orgID, + }) this.props.notify(QuickstartScraperCreationSuccess) } catch (err) { this.props.notify(QuickstartScraperCreationError) diff --git a/ui/src/organizations/apis/index.ts b/ui/src/organizations/apis/index.ts index 4b26ced0ed..3fbb311379 100644 --- a/ui/src/organizations/apis/index.ts +++ b/ui/src/organizations/apis/index.ts @@ -4,10 +4,10 @@ import _ from 'lodash' // Utils import {getDeep} from 'src/utils/wrappers' -import {dashboardsAPI, telegrafsAPI, scraperTargetsApi} from 'src/utils/api' +import {dashboardsAPI, telegrafsAPI} from 'src/utils/api' // Types -import {Organization, Telegraf, ScraperTargetResponses} from 'src/api' +import {Organization, Telegraf} from 'src/api' import {Dashboard} from 'src/types/v2' // CRUD APIs for Organizations and Organization resources @@ -71,22 +71,3 @@ export const deleteTelegrafConfig = async ( console.error(error) } } - -// Scrapers -export const getScrapers = async (): Promise => { - try { - const response = await scraperTargetsApi.scrapersGet() - - return response.data - } catch (error) { - console.error(error) - } -} - -export const deleteScraper = async (scraperTargetID: string): Promise => { - try { - await scraperTargetsApi.scrapersScraperTargetIDDelete(scraperTargetID) - } catch (error) { - console.error(error) - } -} diff --git a/ui/src/organizations/components/Scrapers.tsx b/ui/src/organizations/components/Scrapers.tsx index 6144548018..ddfb0f75cd 100644 --- a/ui/src/organizations/components/Scrapers.tsx +++ b/ui/src/organizations/components/Scrapers.tsx @@ -3,7 +3,7 @@ import _ from 'lodash' import React, {PureComponent, ChangeEvent} from 'react' // APIs -import {deleteScraper} from 'src/organizations/apis/index' +import {client} from 'src/utils/api' // Components import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader' @@ -23,12 +23,12 @@ import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' import {ErrorHandling} from 'src/shared/decorators/errors' // Types -import {ScraperTargetResponses, ScraperTargetResponse, Bucket} from 'src/api' +import {ScraperTargetResponse, Bucket} from 'src/api' import {OverlayState} from 'src/types/v2' import {DataLoaderType, DataLoaderStep} from 'src/types/v2/dataLoaders' interface Props { - scrapers: ScraperTargetResponses + scrapers: ScraperTargetResponse[] onChange: () => void orgName: string buckets: Bucket[] @@ -96,11 +96,11 @@ export default class Scrapers extends PureComponent { const {scrapers} = this.props const {searchTerm} = this.state - if (!scrapers || !scrapers.configurations) { + if (!scrapers || !scrapers) { return [] } - return scrapers.configurations.filter(c => { + return scrapers.filter(c => { if (!searchTerm) { return true } @@ -162,7 +162,7 @@ export default class Scrapers extends PureComponent { } private handleDeleteScraper = async (scraper: ScraperTargetResponse) => { - await deleteScraper(scraper.id) + await client.scrapers.deleteScraper(scraper.id) this.props.onChange() } diff --git a/ui/src/organizations/containers/OrganizationView.tsx b/ui/src/organizations/containers/OrganizationView.tsx index 69134ea101..785e6d942e 100644 --- a/ui/src/organizations/containers/OrganizationView.tsx +++ b/ui/src/organizations/containers/OrganizationView.tsx @@ -5,10 +5,13 @@ import {connect} from 'react-redux' import _ from 'lodash' // APIs -import {getDashboards, getCollectors, getScrapers} from 'src/organizations/apis' - +import {getDashboards, getCollectors} from 'src/organizations/apis' import {client} from 'src/utils/api' +const getScrapers = async () => { + return await client.scrapers.getAll() +} + const getBuckets = async (org: Organization) => { return client.buckets.getAllByOrg(org) } @@ -43,7 +46,7 @@ import { Organization, Task, Telegraf, - ScraperTargetResponses, + ScraperTargetResponse, } from 'src/api' import * as NotificationsActions from 'src/types/actions/notifications' @@ -197,7 +200,7 @@ class OrganizationView extends PureComponent { url="scrapers_tab" title="Scrapers" > - + organization={org} fetcher={getScrapers} > diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 08f3f446b0..d509dc5101 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -6,7 +6,6 @@ import { SourcesApi, QueryApi, SetupApi, - ScraperTargetsApi, ProtosApi, } from 'src/api' @@ -23,5 +22,4 @@ export const telegrafsAPI = new TelegrafsApi({basePath}) export const sourcesAPI = new SourcesApi({basePath}) export const queryAPI = new QueryApi({basePath}) export const setupAPI = new SetupApi({basePath}) -export const scraperTargetsApi = new ScraperTargetsApi({basePath}) export const protosAPI = new ProtosApi({basePath}) From 1aa5c471ee9c4264af520d95ac6e685a2c586a73 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Thu, 31 Jan 2019 11:09:36 -0800 Subject: [PATCH 10/95] Move telegraf configs api to client library --- ui/package-lock.json | 6 +- ui/package.json | 2 +- ui/src/dataLoaders/actions/dataLoaders.ts | 31 ++++---- ui/src/onboarding/apis/index.ts | 73 +------------------ ui/src/onboarding/apis/mocks.ts | 16 +++- ui/src/onboarding/apis/onboarding.test.ts | 29 +------- ui/src/organizations/apis/index.ts | 46 +----------- .../organizations/components/Collectors.tsx | 9 +-- ui/src/organizations/components/Scrapers.tsx | 2 +- .../containers/OrganizationView.tsx | 6 +- ui/src/utils/api.ts | 2 - 11 files changed, 45 insertions(+), 177 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index ad58866f4f..45d706f7f4 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.5.tgz", - "integrity": "sha512-fU9kcNCjPv1fY7CzLcNgPmh2iV1I56pN5H5v9aqDA5jEgw2mf4vQM9rPi1TAhk1xZw/CdsYKatI9hAbh7BbWKw==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.6.tgz", + "integrity": "sha512-741E/MphkxvZF5DJqnQLBMkbmtqb5ghJadHoCUIEUZwfgjuy5+N8nOcJk0Nfb5E+FlblkDqsz4T/511yiIrE5Q==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 9ab2b28e84..5eae3802cf 100644 --- a/ui/package.json +++ b/ui/package.json @@ -116,7 +116,7 @@ "typescript": "^3.1.3" }, "dependencies": { - "@influxdata/influx": "^0.1.5", + "@influxdata/influx": "^0.1.6", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/dataLoaders/actions/dataLoaders.ts b/ui/src/dataLoaders/actions/dataLoaders.ts index ab8d6e15c7..a8689b53f1 100644 --- a/ui/src/dataLoaders/actions/dataLoaders.ts +++ b/ui/src/dataLoaders/actions/dataLoaders.ts @@ -2,11 +2,6 @@ import _ from 'lodash' // Apis -import { - createTelegrafConfig, - updateTelegrafConfig, - getTelegrafConfig, -} from 'src/onboarding/apis/index' import {client} from 'src/utils/api' import {ScraperTargetRequest} from 'src/api' @@ -310,23 +305,23 @@ export const createOrUpdateTelegrafConfigAsync = (authToken: string) => async ( }, } - let plugins: Plugin[] = [influxDB2Out] - telegrafPlugins.forEach(tp => { - if (tp.configured === ConfigurationState.Configured) { - plugins = [...plugins, tp.plugin || createNewPlugin(tp.name)] - } - }) + const plugins = telegrafPlugins.reduce( + (acc, tp) => { + if (tp.configured === ConfigurationState.Configured) { + return [...acc, tp.plugin || createNewPlugin(tp.name)] + } + + return acc + }, + [influxDB2Out] + ) if (telegrafConfigID) { - const telegrafConfig = await getTelegrafConfig(telegrafConfigID) - const id = _.get(telegrafConfig, 'id', '') - - await updateTelegrafConfig(id, { - ...telegrafConfig, + await client.telegrafConfigs.update(telegrafConfigID, { name: telegrafConfigName, plugins, }) - dispatch(setTelegrafConfigID(id)) + dispatch(setTelegrafConfigID(telegrafConfigID)) return } @@ -337,7 +332,7 @@ export const createOrUpdateTelegrafConfigAsync = (authToken: string) => async ( plugins, } - const created = await createTelegrafConfig(telegrafRequest) + const created = await client.telegrafConfigs.create(telegrafRequest) dispatch(setTelegrafConfigID(created.id)) } diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index 2aab3617c3..e6b7b3f111 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -2,11 +2,9 @@ import _ from 'lodash' // Utils -import {telegrafsAPI, setupAPI, sourcesAPI} from 'src/utils/api' +import {setupAPI, sourcesAPI} from 'src/utils/api' -import {Telegraf, TelegrafRequest, OnboardingResponse} from 'src/api' - -import {getDeep} from 'src/utils/wrappers' +import {OnboardingResponse} from 'src/api' export const getSetupStatus = async (): Promise => { try { @@ -19,23 +17,6 @@ export const getSetupStatus = async (): Promise => { } } -export const getTelegrafConfigTOML = async ( - telegrafID: string -): Promise => { - const options = { - headers: { - Accept: 'application/toml', - }, - } - - const response = await telegrafsAPI.telegrafsTelegrafIDGet( - telegrafID, - options - ) - - return response.data as string // response.data is string with 'application/toml' header -} - export interface SetupParams { username: string password: string @@ -64,53 +45,3 @@ export const trySources = async (): Promise => { return false } } - -export const getTelegrafConfig = async ( - telegrafConfigID -): Promise => { - try { - const response = await telegrafsAPI.telegrafsTelegrafIDGet(telegrafConfigID) - return response.data - } catch (error) { - console.error(error) - return null - } -} - -export const getTelegrafConfigs = async (org: string): Promise => { - try { - const data = await telegrafsAPI.telegrafsGet(org) - - return getDeep(data, 'data.configurations', []) - } catch (error) { - console.error(error) - } -} - -export const createTelegrafConfig = async ( - telegrafConfig: TelegrafRequest -): Promise => { - try { - const {data} = await telegrafsAPI.telegrafsPost(telegrafConfig) - - return data - } catch (error) { - console.error(error) - } -} - -export const updateTelegrafConfig = async ( - telegrafID: string, - telegrafConfig: TelegrafRequest -): Promise => { - try { - const {data} = await telegrafsAPI.telegrafsTelegrafIDPut( - telegrafID, - telegrafConfig - ) - - return data - } catch (error) { - console.error(error) - } -} diff --git a/ui/src/onboarding/apis/mocks.ts b/ui/src/onboarding/apis/mocks.ts index 793e510611..756f8ec8f6 100644 --- a/ui/src/onboarding/apis/mocks.ts +++ b/ui/src/onboarding/apis/mocks.ts @@ -4,12 +4,14 @@ import { setSetupParamsResponse, } from 'mocks/dummyData' -const telegrafsGet = jest.fn(() => Promise.resolve(getTelegrafConfigsResponse)) +const telegrafsGet = jest.fn(() => + Promise.resolve(getTelegrafConfigsResponse.data) +) const telegrafsPost = jest.fn(() => - Promise.resolve(createTelegrafConfigResponse) + Promise.resolve(createTelegrafConfigResponse.data) ) const telegrafsTelegrafIDPut = jest.fn(() => - Promise.resolve(createTelegrafConfigResponse) + Promise.resolve(createTelegrafConfigResponse.data) ) const setupPost = jest.fn(() => Promise.resolve(setSetupParamsResponse)) const setupGet = jest.fn(() => Promise.resolve({data: {allowed: true}})) @@ -20,6 +22,14 @@ export const telegrafsAPI = { telegrafsTelegrafIDPut, } +export const client = { + telegrafConfigs: { + getAll: telegrafsGet, + getAllByOrg: telegrafsGet, + create: telegrafsPost, + }, +} + export const setupAPI = { setupPost, setupGet, diff --git a/ui/src/onboarding/apis/onboarding.test.ts b/ui/src/onboarding/apis/onboarding.test.ts index 1c8d8afa5c..5709fb8e50 100644 --- a/ui/src/onboarding/apis/onboarding.test.ts +++ b/ui/src/onboarding/apis/onboarding.test.ts @@ -1,13 +1,6 @@ -import { - getSetupStatus, - setSetupParams, - SetupParams, - getTelegrafConfigs, - createTelegrafConfig, -} from 'src/onboarding/apis' +import {getSetupStatus, setSetupParams, SetupParams} from 'src/onboarding/apis' -import {telegrafConfig} from 'mocks/dummyData' -import {telegrafsAPI, setupAPI} from 'src/onboarding/apis/mocks' +import {setupAPI} from 'src/onboarding/apis/mocks' jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks')) @@ -35,22 +28,4 @@ describe('Onboarding.Apis', () => { expect(setupAPI.setupPost).toHaveBeenCalledWith(setupParams) }) }) - - describe('getTelegrafConfigs', () => { - it('should return an array of configs', async () => { - const org = 'default' - const result = await getTelegrafConfigs(org) - - expect(result).toEqual([telegrafConfig]) - expect(telegrafsAPI.telegrafsGet).toBeCalledWith(org) - }) - }) - - describe('createTelegrafConfig', () => { - it('should return the newly created config', async () => { - const result = await createTelegrafConfig(telegrafConfig) - - expect(result).toEqual(telegrafConfig) - }) - }) }) diff --git a/ui/src/organizations/apis/index.ts b/ui/src/organizations/apis/index.ts index 3fbb311379..cd9a01b213 100644 --- a/ui/src/organizations/apis/index.ts +++ b/ui/src/organizations/apis/index.ts @@ -1,13 +1,10 @@ // Libraries import _ from 'lodash' -// Utils -import {getDeep} from 'src/utils/wrappers' - -import {dashboardsAPI, telegrafsAPI} from 'src/utils/api' +import {dashboardsAPI} from 'src/utils/api' // Types -import {Organization, Telegraf} from 'src/api' +import {Organization} from 'src/api' import {Dashboard} from 'src/types/v2' // CRUD APIs for Organizations and Organization resources @@ -32,42 +29,3 @@ export const getDashboards = async ( throw error } } - -export const getCollectors = async (org: Organization): Promise => { - try { - const data = await telegrafsAPI.telegrafsGet(org.id) - - return getDeep(data, 'data.configurations', []) - } catch (error) { - console.error(error) - } -} - -export const getTelegrafConfigTOML = async ( - telegrafID: string -): Promise => { - const options = { - headers: { - Accept: 'application/toml', - }, - } - - const response = await telegrafsAPI.telegrafsTelegrafIDGet( - telegrafID, - options - ) - - return response.data as string // response.data is string with 'application/toml' header -} - -export const deleteTelegrafConfig = async ( - telegrafID: string -): Promise => { - try { - const response = await telegrafsAPI.telegrafsTelegrafIDDelete(telegrafID) - - return response.data - } catch (error) { - console.error(error) - } -} diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index 82ea06ef58..106adb02f9 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -24,10 +24,7 @@ import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' import FilterList from 'src/shared/components/Filter' // APIS -import { - getTelegrafConfigTOML, - deleteTelegrafConfig, -} from 'src/organizations/apis/index' +import {client} from 'src/utils/api' // Actions import * as NotificationsActions from 'src/types/actions/notifications' @@ -178,14 +175,14 @@ export default class Collectors extends PureComponent { telegrafName: string ) => { try { - const config = await getTelegrafConfigTOML(telegrafID) + const config = await client.telegrafConfigs.getTOML(telegrafID) downloadTextFile(config, `${telegrafName || 'config'}.toml`) } catch (error) { notify(getTelegrafConfigFailed()) } } private handleDeleteTelegraf = async (telegrafID: string) => { - await deleteTelegrafConfig(telegrafID) + await client.telegrafConfigs.delete(telegrafID) this.props.onChange() } diff --git a/ui/src/organizations/components/Scrapers.tsx b/ui/src/organizations/components/Scrapers.tsx index ddfb0f75cd..80127b39c6 100644 --- a/ui/src/organizations/components/Scrapers.tsx +++ b/ui/src/organizations/components/Scrapers.tsx @@ -162,7 +162,7 @@ export default class Scrapers extends PureComponent { } private handleDeleteScraper = async (scraper: ScraperTargetResponse) => { - await client.scrapers.deleteScraper(scraper.id) + await client.scrapers.delete(scraper.id) this.props.onChange() } diff --git a/ui/src/organizations/containers/OrganizationView.tsx b/ui/src/organizations/containers/OrganizationView.tsx index 785e6d942e..af8123af75 100644 --- a/ui/src/organizations/containers/OrganizationView.tsx +++ b/ui/src/organizations/containers/OrganizationView.tsx @@ -5,9 +5,13 @@ import {connect} from 'react-redux' import _ from 'lodash' // APIs -import {getDashboards, getCollectors} from 'src/organizations/apis' +import {getDashboards} from 'src/organizations/apis' import {client} from 'src/utils/api' +const getCollectors = async (org: Organization) => { + return client.telegrafConfigs.getAllByOrg(org) +} + const getScrapers = async () => { return await client.scrapers.getAll() } diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index d509dc5101..95259eeba3 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -1,7 +1,6 @@ import { DashboardsApi, CellsApi, - TelegrafsApi, ViewsApi, SourcesApi, QueryApi, @@ -18,7 +17,6 @@ export const client = new Client(basePath) export const viewsAPI = new ViewsApi({basePath}) export const dashboardsAPI = new DashboardsApi({basePath}) export const cellsAPI = new CellsApi({basePath}) -export const telegrafsAPI = new TelegrafsApi({basePath}) export const sourcesAPI = new SourcesApi({basePath}) export const queryAPI = new QueryApi({basePath}) export const setupAPI = new SetupApi({basePath}) From 559cbc776eb8c59d160ee4fd30983082702f5504 Mon Sep 17 00:00:00 2001 From: Mark Rushakoff Date: Thu, 31 Jan 2019 10:07:04 -0800 Subject: [PATCH 11/95] fix(task): return ErrRunNotFound when finding run by ID This is necessary to return 404 from the HTTP handler. --- task/backend/query_logreader.go | 5 ++++- task/backend/storetest/logstoretest.go | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/task/backend/query_logreader.go b/task/backend/query_logreader.go index b290f1b81e..4a5af2e89f 100644 --- a/task/backend/query_logreader.go +++ b/task/backend/query_logreader.go @@ -175,7 +175,10 @@ from(bucketID: "000000000000000a") if err != nil { return nil, err } - if len(runs) != 1 { + if len(runs) == 0 { + return nil, ErrRunNotFound + } + if len(runs) > 1 { return nil, fmt.Errorf("expected one run, got %d", len(runs)) } diff --git a/task/backend/storetest/logstoretest.go b/task/backend/storetest/logstoretest.go index 628e92666a..388f7b40cd 100644 --- a/task/backend/storetest/logstoretest.go +++ b/task/backend/storetest/logstoretest.go @@ -330,6 +330,11 @@ func findRunByIDTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFu if reflect.DeepEqual(returnedRun, rr2) { t.Fatalf("updateing returned run modified RunStore data") } + + _, err = reader.FindRunByID(ctx, task.Org, 0xccc) + if err != backend.ErrRunNotFound { + t.Fatalf("expected finding run with invalid ID to return %v, got %v", backend.ErrRunNotFound, err) + } } func listLogsTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) { From f3cd889d1e9a8191d447e4cada51cbcd8586b136 Mon Sep 17 00:00:00 2001 From: Gershon Shif Date: Thu, 31 Jan 2019 15:13:34 -0800 Subject: [PATCH 12/95] Add slack notifications to litmus nightly runs (#11648) - Add a conditional slack notifications to litmus nightly job. --- .circleci/config.yml | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 96445e307e..107ba5c9f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,9 +5,41 @@ jobs: steps: - run: docker login -u=$QUAY_USER -p=$QUAY_PASS quay.io - run: docker run --entrypoint "./run_litmus_tests_oss.sh" -e TEST_LIST=tests_lists/gateway_api_tests.list --net host -v /var/run/docker.sock:/var/run/docker.sock -v ~/project:/Litmus/result quay.io/influxdb/litmus:latest + - run: + name: Litmus Nightly Tests Success + when: on_success + command: | + curl -X POST https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $SLACK_TOKEN" \ + -H "Content-type: application/json; charset=utf-8" \ + --data @<(cat < Date: Fri, 1 Feb 2019 14:02:13 +0800 Subject: [PATCH 13/95] chore(http): simplify code --- http/dashboard_test.go | 2 +- http/macro_test.go | 4 ++-- http/telegraf_test.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/http/dashboard_test.go b/http/dashboard_test.go index 9fd204fd1a..a3919ef4a9 100644 --- a/http/dashboard_test.go +++ b/http/dashboard_test.go @@ -247,7 +247,7 @@ func TestService_handleGetDashboards(t *testing.T) { }, args: args{ map[string][]string{ - "orgID": []string{"0000000000000001"}, + "orgID": {"0000000000000001"}, }, }, wants: wants{ diff --git a/http/macro_test.go b/http/macro_test.go index b85c468332..9c49be7931 100644 --- a/http/macro_test.go +++ b/http/macro_test.go @@ -82,7 +82,7 @@ func TestMacroService_handleGetMacros(t *testing.T) { }, args: args{ map[string][]string{ - "limit": []string{"1"}, + "limit": {"1"}, }, }, wants: wants{ @@ -113,7 +113,7 @@ func TestMacroService_handleGetMacros(t *testing.T) { }, args: args{ map[string][]string{ - "orgID": []string{"0000000000000001"}, + "orgID": {"0000000000000001"}, }, }, wants: wants{ diff --git a/http/telegraf_test.go b/http/telegraf_test.go index afbe8c0462..1b7d52fc73 100644 --- a/http/telegraf_test.go +++ b/http/telegraf_test.go @@ -36,7 +36,7 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { FindTelegrafConfigsF: func(ctx context.Context, filter platform.TelegrafConfigFilter, opt ...platform.FindOptions) ([]*platform.TelegrafConfig, int, error) { if filter.OrganizationID != nil && *filter.OrganizationID == platform.ID(2) { return []*platform.TelegrafConfig{ - &platform.TelegrafConfig{ + { ID: platform.ID(1), OrganizationID: platform.ID(2), Name: "tc1", @@ -86,7 +86,7 @@ func TestTelegrafHandler_handleGetTelegrafs(t *testing.T) { svc: &mock.TelegrafConfigStore{ FindTelegrafConfigsF: func(ctx context.Context, filter platform.TelegrafConfigFilter, opt ...platform.FindOptions) ([]*platform.TelegrafConfig, int, error) { return []*platform.TelegrafConfig{ - &platform.TelegrafConfig{ + { ID: platform.ID(1), OrganizationID: platform.ID(2), Name: "my config", @@ -722,7 +722,7 @@ func Test_newTelegrafResponses(t *testing.T) { { args: args{ tcs: []*platform.TelegrafConfig{ - &platform.TelegrafConfig{ + { ID: platform.ID(1), OrganizationID: platform.ID(2), Name: "my config", From e024b13a2e537640da2ae2156c397b6ef5f5d992 Mon Sep 17 00:00:00 2001 From: zhulongcheng Date: Fri, 1 Feb 2019 11:10:05 +0800 Subject: [PATCH 14/95] fix(http): rename desc to descending --- http/bucket_service.go | 24 ++++-------------------- http/dashboard_service.go | 24 ++++-------------------- http/org_service.go | 29 ++++++----------------------- http/user_service.go | 24 ++++-------------------- 4 files changed, 18 insertions(+), 83 deletions(-) diff --git a/http/bucket_service.go b/http/bucket_service.go index aec64081b6..757d472ec9 100644 --- a/http/bucket_service.go +++ b/http/bucket_service.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "path" - "strconv" "time" platform "github.com/influxdata/influxdb" @@ -810,29 +809,14 @@ func decodeGetBucketLogRequest(ctx context.Context, r *http.Request) (*getBucket return nil, err } - opts := platform.DefaultOperationLogFindOptions - qp := r.URL.Query() - if v := qp.Get("desc"); v == "false" { - opts.Descending = false - } - if v := qp.Get("limit"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Limit = i - } - if v := qp.Get("offset"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Offset = i + opts, err := decodeFindOptions(ctx, r) + if err != nil { + return nil, err } return &getBucketLogRequest{ BucketID: i, - opts: opts, + opts: *opts, }, nil } diff --git a/http/dashboard_service.go b/http/dashboard_service.go index 42b168dc10..8d57b6671b 100644 --- a/http/dashboard_service.go +++ b/http/dashboard_service.go @@ -8,7 +8,6 @@ import ( "io/ioutil" "net/http" "path" - "strconv" platform "github.com/influxdata/influxdb" "github.com/julienschmidt/httprouter" @@ -474,29 +473,14 @@ func decodeGetDashboardLogRequest(ctx context.Context, r *http.Request) (*getDas return nil, err } - opts := platform.DefaultOperationLogFindOptions - qp := r.URL.Query() - if v := qp.Get("desc"); v == "false" { - opts.Descending = false - } - if v := qp.Get("limit"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Limit = i - } - if v := qp.Get("offset"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Offset = i + opts, err := decodeFindOptions(ctx, r) + if err != nil { + return nil, err } return &getDashboardLogRequest{ DashboardID: i, - opts: opts, + opts: *opts, }, nil } diff --git a/http/org_service.go b/http/org_service.go index 3f9682a571..6a5a6509c6 100644 --- a/http/org_service.go +++ b/http/org_service.go @@ -5,13 +5,11 @@ import ( "context" "encoding/json" "fmt" - "net/http" - "path" - "strconv" - platform "github.com/influxdata/influxdb" "github.com/julienschmidt/httprouter" "go.uber.org/zap" + "net/http" + "path" ) // OrgHandler represents an HTTP API handler for orgs. @@ -758,29 +756,14 @@ func decodeGetOrganizationLogRequest(ctx context.Context, r *http.Request) (*get return nil, err } - opts := platform.DefaultOperationLogFindOptions - qp := r.URL.Query() - if v := qp.Get("desc"); v == "false" { - opts.Descending = false - } - if v := qp.Get("limit"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Limit = i - } - if v := qp.Get("offset"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Offset = i + opts, err := decodeFindOptions(ctx, r) + if err != nil { + return nil, err } return &getOrganizationLogRequest{ OrganizationID: i, - opts: opts, + opts: *opts, }, nil } diff --git a/http/user_service.go b/http/user_service.go index c42c8d0dea..453275463a 100644 --- a/http/user_service.go +++ b/http/user_service.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "path" - "strconv" platform "github.com/influxdata/influxdb" platcontext "github.com/influxdata/influxdb/context" @@ -703,29 +702,14 @@ func decodeGetUserLogRequest(ctx context.Context, r *http.Request) (*getUserLogR return nil, err } - opts := platform.DefaultOperationLogFindOptions - qp := r.URL.Query() - if v := qp.Get("desc"); v == "false" { - opts.Descending = false - } - if v := qp.Get("limit"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Limit = i - } - if v := qp.Get("offset"); v != "" { - i, err := strconv.Atoi(v) - if err != nil { - return nil, err - } - opts.Offset = i + opts, err := decodeFindOptions(ctx, r) + if err != nil { + return nil, err } return &getUserLogRequest{ UserID: i, - opts: opts, + opts: *opts, }, nil } From 06b2d0033de5c606e2eacde306fed03d955473eb Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Thu, 31 Jan 2019 19:04:07 -0800 Subject: [PATCH 15/95] Move setup api calls to client library --- ui/package-lock.json | 6 ++-- ui/package.json | 2 +- ui/src/Setup.tsx | 6 ++-- ui/src/onboarding/actions/index.ts | 17 +++++----- ui/src/onboarding/apis/index.ts | 27 +--------------- ui/src/onboarding/apis/onboarding.test.ts | 31 ------------------- .../containers/OnboardingWizardPage.tsx | 6 ++-- ui/src/onboarding/containers/SigninPage.tsx | 6 ++-- ui/src/utils/api.ts | 2 -- 9 files changed, 21 insertions(+), 82 deletions(-) delete mode 100644 ui/src/onboarding/apis/onboarding.test.ts diff --git a/ui/package-lock.json b/ui/package-lock.json index 45d706f7f4..a7ded7d3c5 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.6.tgz", - "integrity": "sha512-741E/MphkxvZF5DJqnQLBMkbmtqb5ghJadHoCUIEUZwfgjuy5+N8nOcJk0Nfb5E+FlblkDqsz4T/511yiIrE5Q==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.7.tgz", + "integrity": "sha512-n7YuYSj/lr2KCpTs6HysJfCT9yFDrFsxz7JVKtAdGr1m1QEUtEBLP016MRXEc+VQSYbPb3zZ4C8zbtu7RpbicA==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 5eae3802cf..7337f572cd 100644 --- a/ui/package.json +++ b/ui/package.json @@ -116,7 +116,7 @@ "typescript": "^3.1.3" }, "dependencies": { - "@influxdata/influx": "^0.1.6", + "@influxdata/influx": "^0.1.7", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/Setup.tsx b/ui/src/Setup.tsx index 42c541aec9..f1239b5445 100644 --- a/ui/src/Setup.tsx +++ b/ui/src/Setup.tsx @@ -4,7 +4,7 @@ import {connect} from 'react-redux' import {InjectedRouter} from 'react-router' // APIs -import {getSetupStatus} from 'src/onboarding/apis' +import {client} from 'src/utils/api' // Actions import {notify as notifyAction} from 'src/shared/actions/notifications' @@ -50,12 +50,12 @@ export class Setup extends PureComponent { return } - const isSetupAllowed = await getSetupStatus() + const {allowed} = await client.setup.status() this.setState({ loading: RemoteDataState.Done, }) - if (!isSetupAllowed) { + if (!allowed) { return } diff --git a/ui/src/onboarding/actions/index.ts b/ui/src/onboarding/actions/index.ts index 33cd569cae..6b072c4427 100644 --- a/ui/src/onboarding/actions/index.ts +++ b/ui/src/onboarding/actions/index.ts @@ -8,10 +8,7 @@ import {notify} from 'src/shared/actions/notifications' import {client} from 'src/utils/api' // Types -import { - SetupParams, - setSetupParams as setSetupParamsAJAX, -} from 'src/onboarding/apis' +import {SetupParams} from 'src/onboarding/apis' export type Action = | SetSetupParams @@ -65,18 +62,18 @@ export const setBucketID = (bucketID: string): SetBucketID => ({ payload: {bucketID}, }) -export const setupAdmin = (setupParams: SetupParams) => async dispatch => { +export const setupAdmin = (params: SetupParams) => async dispatch => { try { - dispatch(setSetupParams(setupParams)) - const onboardingResponse = await setSetupParamsAJAX(setupParams) + dispatch(setSetupParams(params)) + const response = await client.setup.create(params) - const {id: orgID} = onboardingResponse.org - const {id: bucketID} = onboardingResponse.bucket + const {id: orgID} = response.org + const {id: bucketID} = response.bucket dispatch(setOrganizationID(orgID)) dispatch(setBucketID(bucketID)) - const {username, password} = setupParams + const {username, password} = params await client.auth.signin(username, password) dispatch(notify(SetupSuccess)) diff --git a/ui/src/onboarding/apis/index.ts b/ui/src/onboarding/apis/index.ts index e6b7b3f111..ef08fde867 100644 --- a/ui/src/onboarding/apis/index.ts +++ b/ui/src/onboarding/apis/index.ts @@ -2,20 +2,7 @@ import _ from 'lodash' // Utils -import {setupAPI, sourcesAPI} from 'src/utils/api' - -import {OnboardingResponse} from 'src/api' - -export const getSetupStatus = async (): Promise => { - try { - const {data} = await setupAPI.setupGet() - const {allowed} = data - return allowed - } catch (error) { - console.error("Can't get setup status", error) - throw error - } -} +import {sourcesAPI} from 'src/utils/api' export interface SetupParams { username: string @@ -24,18 +11,6 @@ export interface SetupParams { bucket: string } -export const setSetupParams = async ( - setupParams: SetupParams -): Promise => { - try { - const result = await setupAPI.setupPost(setupParams) - return result.data - } catch (error) { - console.error("Can't set setup parameters", error) - throw error - } -} - export const trySources = async (): Promise => { try { await sourcesAPI.sourcesGet('') diff --git a/ui/src/onboarding/apis/onboarding.test.ts b/ui/src/onboarding/apis/onboarding.test.ts deleted file mode 100644 index 5709fb8e50..0000000000 --- a/ui/src/onboarding/apis/onboarding.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {getSetupStatus, setSetupParams, SetupParams} from 'src/onboarding/apis' - -import {setupAPI} from 'src/onboarding/apis/mocks' - -jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks')) - -describe('Onboarding.Apis', () => { - afterEach(() => { - jest.clearAllMocks() - }) - - describe('getSetupStatus', () => { - it('is called with the expected body', () => { - getSetupStatus() - expect(setupAPI.setupGet).toHaveBeenCalled() - }) - }) - - describe('setSetupParams', () => { - it('is called with the expected body', () => { - const setupParams: SetupParams = { - username: 'moo', - password: 'pwoo', - bucket: 'boo', - org: 'ooo', - } - setSetupParams(setupParams) - expect(setupAPI.setupPost).toHaveBeenCalledWith(setupParams) - }) - }) -}) diff --git a/ui/src/onboarding/containers/OnboardingWizardPage.tsx b/ui/src/onboarding/containers/OnboardingWizardPage.tsx index e1fe1e2077..a1f2b72cd7 100644 --- a/ui/src/onboarding/containers/OnboardingWizardPage.tsx +++ b/ui/src/onboarding/containers/OnboardingWizardPage.tsx @@ -4,7 +4,7 @@ import {connect} from 'react-redux' import {withRouter, WithRouterProps} from 'react-router' // APIs -import {getSetupStatus} from 'src/onboarding/apis' +import {client} from 'src/utils/api' // Actions import {notify as notifyAction} from 'src/shared/actions/notifications' @@ -65,8 +65,8 @@ export class OnboardingWizardPage extends PureComponent { public async componentDidMount() { this.setState({loading: RemoteDataState.Loading}) try { - const canSetUp = await getSetupStatus() - if (!canSetUp) { + const {allowed} = await client.setup.status() + if (!allowed) { this.setState({isSetupComplete: true}) } this.setState({loading: RemoteDataState.Done}) diff --git a/ui/src/onboarding/containers/SigninPage.tsx b/ui/src/onboarding/containers/SigninPage.tsx index 43870944e6..a6d25178a2 100644 --- a/ui/src/onboarding/containers/SigninPage.tsx +++ b/ui/src/onboarding/containers/SigninPage.tsx @@ -4,7 +4,7 @@ import {withRouter, WithRouterProps} from 'react-router' import _ from 'lodash' // apis -import {getSetupStatus} from 'src/onboarding/apis' +import {client} from 'src/utils/api' // Components import {ErrorHandling} from 'src/shared/decorators/errors' @@ -28,9 +28,9 @@ class SigninPage extends PureComponent { } } public async componentDidMount() { - const isSetupAllowed = await getSetupStatus() + const {allowed} = await client.setup.status() - if (isSetupAllowed) { + if (allowed) { this.props.router.push('/onboarding/0') } diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 95259eeba3..5d5435d1a3 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -4,7 +4,6 @@ import { ViewsApi, SourcesApi, QueryApi, - SetupApi, ProtosApi, } from 'src/api' @@ -19,5 +18,4 @@ export const dashboardsAPI = new DashboardsApi({basePath}) export const cellsAPI = new CellsApi({basePath}) export const sourcesAPI = new SourcesApi({basePath}) export const queryAPI = new QueryApi({basePath}) -export const setupAPI = new SetupApi({basePath}) export const protosAPI = new ProtosApi({basePath}) From c9bb55b889c5286b3f66d0a69aebe8e369476531 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Wed, 16 Jan 2019 13:37:12 -0700 Subject: [PATCH 16/95] refactor: move the tsm1/wal into the storage/wal package Because the WAL relies on the tsm1.Value type, we move that into its own tsm1/value package and set up some aliases forwarding them into tsm1. This also required adding some methods and changing consumers to avoid the unexported fields. I imagine this step will be useful one day when we make the write path more efficient with respect to consuming points. This commit additionally fixes some issues with generation. The iterator.tmpldata and generation for array_cursor_* were removed accidentally when removing iterators, making those generated files stale. Restore that and regenerate. No change in functionality. --- cmd/influx_inspect/buildtsi/buildtsi.go | 3 +- storage/engine.go | 11 +- storage/reads/array_cursor.gen.go.tmpl | 22 +- storage/wal/helpers_test.go | 28 +++ storage/wal/metrics.go | 69 ++++++ storage/wal/metrics_test.go | 75 ++++++ {tsdb/tsm1 => storage/wal}/pools.go | 2 +- {tsdb/tsm1 => storage/wal}/wal.go | 118 ++++------ {tsdb/tsm1 => storage/wal}/wal_test.go | 212 ++++++++--------- tsdb/tsm1/array_cursor.gen.go | 60 ++--- tsdb/tsm1/array_cursor.gen.go.tmpl | 16 +- tsdb/tsm1/array_cursor.gen.go.tmpldata | 42 ++++ tsdb/tsm1/cache.go | 11 +- tsdb/tsm1/cache_test.go | 20 +- tsdb/tsm1/encoding.gen.go | 40 ++-- tsdb/tsm1/encoding.gen.go.tmpl | 8 +- tsdb/tsm1/encoding.gen_test.go | 8 +- tsdb/tsm1/encoding.go | 297 ++++++------------------ tsdb/tsm1/engine.go | 21 +- tsdb/tsm1/metrics.go | 62 ----- tsdb/tsm1/metrics_test.go | 67 ------ tsdb/tsm1/temp_log.go | 47 ++++ tsdb/tsm1/value/value.go | 236 +++++++++++++++++++ 23 files changed, 823 insertions(+), 652 deletions(-) create mode 100644 storage/wal/helpers_test.go create mode 100644 storage/wal/metrics.go create mode 100644 storage/wal/metrics_test.go rename {tsdb/tsm1 => storage/wal}/pools.go (97%) rename {tsdb/tsm1 => storage/wal}/wal.go (91%) rename {tsdb/tsm1 => storage/wal}/wal_test.go (79%) create mode 100644 tsdb/tsm1/array_cursor.gen.go.tmpldata create mode 100644 tsdb/tsm1/temp_log.go create mode 100644 tsdb/tsm1/value/value.go diff --git a/cmd/influx_inspect/buildtsi/buildtsi.go b/cmd/influx_inspect/buildtsi/buildtsi.go index db67fbe407..e94e228b3c 100644 --- a/cmd/influx_inspect/buildtsi/buildtsi.go +++ b/cmd/influx_inspect/buildtsi/buildtsi.go @@ -17,6 +17,7 @@ import ( "github.com/influxdata/influxdb/logger" "github.com/influxdata/influxdb/models" "github.com/influxdata/influxdb/storage" + "github.com/influxdata/influxdb/storage/wal" "github.com/influxdata/influxdb/toml" "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxdb/tsdb/tsi1" @@ -422,7 +423,7 @@ func collectWALFiles(path string) ([]string, error) { var paths []string for _, fi := range fis { - if filepath.Ext(fi.Name()) != "."+tsm1.WALFileExtension { + if filepath.Ext(fi.Name()) != "."+wal.WALFileExtension { continue } paths = append(paths, filepath.Join(path, fi.Name())) diff --git a/storage/engine.go b/storage/engine.go index c0c7429648..176672fb8d 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -12,6 +12,7 @@ import ( platform "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/logger" "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/storage/wal" "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxdb/tsdb/tsi1" "github.com/influxdata/influxdb/tsdb/tsm1" @@ -38,7 +39,7 @@ type Engine struct { index *tsi1.Index sfile *tsdb.SeriesFile engine *tsm1.Engine - wal *tsm1.WAL + wal *wal.WAL retentionEnforcer *retentionEnforcer defaultMetricLabels prometheus.Labels @@ -119,17 +120,17 @@ func NewEngine(path string, c Config, options ...Option) *Engine { tsi1.WithPath(c.GetIndexPath(path))) // Initialize WAL - var wal tsm1.Log = new(tsm1.NopWAL) + var w tsm1.Log = new(tsm1.NopWAL) if c.WAL.Enabled { - e.wal = tsm1.NewWAL(c.GetWALPath(path)) + e.wal = wal.NewWAL(c.GetWALPath(path)) e.wal.WithFsyncDelay(time.Duration(c.WAL.FsyncDelay)) e.wal.EnableTraceLogging(c.TraceLoggingEnabled) - wal = e.wal + w = e.wal } // Initialise Engine e.engine = tsm1.NewEngine(c.GetEnginePath(path), e.index, c.Engine, - tsm1.WithWAL(wal), + tsm1.WithWAL(w), tsm1.WithTraceLogging(c.TraceLoggingEnabled)) // Apply options. diff --git a/storage/reads/array_cursor.gen.go.tmpl b/storage/reads/array_cursor.gen.go.tmpl index e56c4e0ad7..8bf15b0319 100644 --- a/storage/reads/array_cursor.gen.go.tmpl +++ b/storage/reads/array_cursor.gen.go.tmpl @@ -106,7 +106,7 @@ func (c *{{.name}}MultiShardArrayCursor) reset(cur cursors.{{.Name}}ArrayCursor, } -func (c *{{.name}}MultiShardArrayCursor) Err() error { return c.err } +func (c *{{.name}}MultiShardArrayCursor) Err() error { return c.err } func (c *{{.name}}MultiShardArrayCursor) Stats() cursors.CursorStats { return c.{{.Name}}ArrayCursor.Stats() @@ -200,17 +200,17 @@ func (c {{$type}}) Next() {{$arrayType}} { var acc {{.Type}} for { - for _, v := range a.Values { - acc += v - } + for _, v := range a.Values { + acc += v + } a = c.{{.Name}}ArrayCursor.Next() - if len(a.Timestamps) == 0 { + if len(a.Timestamps) == 0 { c.ts[0] = ts c.vs[0] = acc c.res.Timestamps = c.ts[:] c.res.Values = c.vs[:] return c.res - } + } } } @@ -230,11 +230,11 @@ func (c *integer{{.Name}}CountArrayCursor) Next() *cursors.IntegerArray { return &cursors.IntegerArray{} } - ts := a.Timestamps[0] - var acc int64 - for { - acc += int64(len(a.Timestamps)) - a = c.{{.Name}}ArrayCursor.Next() + ts := a.Timestamps[0] + var acc int64 + for { + acc += int64(len(a.Timestamps)) + a = c.{{.Name}}ArrayCursor.Next() if len(a.Timestamps) == 0 { res := cursors.NewIntegerArrayLen(1) res.Timestamps[0] = ts diff --git a/storage/wal/helpers_test.go b/storage/wal/helpers_test.go new file mode 100644 index 0000000000..e5a5278d1c --- /dev/null +++ b/storage/wal/helpers_test.go @@ -0,0 +1,28 @@ +package wal + +import ( + "fmt" + "io/ioutil" + "os" + "testing" +) + +func MustTempDir() string { + dir, err := ioutil.TempDir("", "tsm1-test") + if err != nil { + panic(fmt.Sprintf("failed to create temp dir: %v", err)) + } + return dir +} + +func MustTempFile(dir string) *os.File { + f, err := ioutil.TempFile(dir, "tsm1test") + if err != nil { + panic(fmt.Sprintf("failed to create temp file: %v", err)) + } + return f +} + +func fatal(t *testing.T, msg string, err error) { + t.Fatalf("unexpected error %v: %v", msg, err) +} diff --git a/storage/wal/metrics.go b/storage/wal/metrics.go new file mode 100644 index 0000000000..c6a648c01c --- /dev/null +++ b/storage/wal/metrics.go @@ -0,0 +1,69 @@ +package wal + +import ( + "sort" + + "github.com/prometheus/client_golang/prometheus" +) + +// namespace is the leading part of all published metrics for the Storage service. +const namespace = "storage" + +const walSubsystem = "wal" // sub-system associated with metrics for the WAL. + +// walMetrics are a set of metrics concerned with tracking data about compactions. +type walMetrics struct { + OldSegmentBytes *prometheus.GaugeVec + CurrentSegmentBytes *prometheus.GaugeVec + Segments *prometheus.GaugeVec + Writes *prometheus.CounterVec +} + +// newWALMetrics initialises the prometheus metrics for tracking the WAL. +func newWALMetrics(labels prometheus.Labels) *walMetrics { + var names []string + for k := range labels { + names = append(names, k) + } + sort.Strings(names) + + writeNames := append(append([]string(nil), names...), "status") + sort.Strings(writeNames) + + return &walMetrics{ + OldSegmentBytes: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: walSubsystem, + Name: "old_segment_bytes", + Help: "Number of bytes old WAL segments using on disk.", + }, names), + CurrentSegmentBytes: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: walSubsystem, + Name: "current_segment_bytes", + Help: "Number of bytes TSM files using on disk.", + }, names), + Segments: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: walSubsystem, + Name: "segments_total", + Help: "Number of WAL segment files on disk.", + }, names), + Writes: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: walSubsystem, + Name: "writes_total", + Help: "Number of writes to the WAL.", + }, writeNames), + } +} + +// PrometheusCollectors satisfies the prom.PrometheusCollector interface. +func (m *walMetrics) PrometheusCollectors() []prometheus.Collector { + return []prometheus.Collector{ + m.OldSegmentBytes, + m.CurrentSegmentBytes, + m.Segments, + m.Writes, + } +} diff --git a/storage/wal/metrics_test.go b/storage/wal/metrics_test.go new file mode 100644 index 0000000000..12025892f7 --- /dev/null +++ b/storage/wal/metrics_test.go @@ -0,0 +1,75 @@ +package wal + +import ( + "testing" + + "github.com/influxdata/influxdb/kit/prom/promtest" + "github.com/prometheus/client_golang/prometheus" +) + +func TestMetrics_WAL(t *testing.T) { + // metrics to be shared by multiple file stores. + metrics := newWALMetrics(prometheus.Labels{"engine_id": "", "node_id": ""}) + + t1 := newWALTracker(metrics, prometheus.Labels{"engine_id": "0", "node_id": "0"}) + t2 := newWALTracker(metrics, prometheus.Labels{"engine_id": "1", "node_id": "0"}) + + reg := prometheus.NewRegistry() + reg.MustRegister(metrics.PrometheusCollectors()...) + + base := namespace + "_" + walSubsystem + "_" + + // All the metric names + gauges := []string{ + base + "old_segment_bytes", + base + "current_segment_bytes", + base + "segments_total", + } + + counters := []string{ + base + "writes_total", + } + + // Generate some measurements. + for i, tracker := range []*walTracker{t1, t2} { + tracker.SetOldSegmentSize(uint64(i + len(gauges[0]))) + tracker.SetCurrentSegmentSize(uint64(i + len(gauges[1]))) + tracker.SetSegments(uint64(i + len(gauges[2]))) + + labels := tracker.Labels() + labels["status"] = "ok" + tracker.metrics.Writes.With(labels).Add(float64(i + len(counters[0]))) + } + + // Test that all the correct metrics are present. + mfs, err := reg.Gather() + if err != nil { + t.Fatal(err) + } + + // The label variants for the two caches. + labelVariants := []prometheus.Labels{ + prometheus.Labels{"engine_id": "0", "node_id": "0"}, + prometheus.Labels{"engine_id": "1", "node_id": "0"}, + } + + for i, labels := range labelVariants { + for _, name := range gauges { + exp := float64(i + len(name)) + metric := promtest.MustFindMetric(t, mfs, name, labels) + if got := metric.GetGauge().GetValue(); got != exp { + t.Errorf("[%s %d] got %v, expected %v", name, i, got, exp) + } + } + + for _, name := range counters { + exp := float64(i + len(name)) + + labels["status"] = "ok" + metric := promtest.MustFindMetric(t, mfs, name, labels) + if got := metric.GetCounter().GetValue(); got != exp { + t.Errorf("[%s %d] got %v, expected %v", name, i, got, exp) + } + } + } +} diff --git a/tsdb/tsm1/pools.go b/storage/wal/pools.go similarity index 97% rename from tsdb/tsm1/pools.go rename to storage/wal/pools.go index 02d4d6231e..140102f528 100644 --- a/tsdb/tsm1/pools.go +++ b/storage/wal/pools.go @@ -1,4 +1,4 @@ -package tsm1 +package wal import "sync" diff --git a/tsdb/tsm1/wal.go b/storage/wal/wal.go similarity index 91% rename from tsdb/tsm1/wal.go rename to storage/wal/wal.go index 2200a2bacd..3be7ef61fd 100644 --- a/tsdb/tsm1/wal.go +++ b/storage/wal/wal.go @@ -1,4 +1,4 @@ -package tsm1 +package wal import ( "bufio" @@ -17,6 +17,8 @@ import ( "sync/atomic" "time" + "github.com/influxdata/influxdb/tsdb/tsm1/value" + "github.com/golang/snappy" "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/pool" @@ -24,23 +26,6 @@ import ( "go.uber.org/zap" ) -// Log describes an interface for a durable disk-based log. -type Log interface { - Open() error - Close() error - Path() string - - LastWriteTime() time.Time - DiskSizeBytes() int64 - - WriteMulti(values map[string][]Value) (int, error) - DeleteRange(keys [][]byte, min, max int64) (int, error) - - CloseSegment() error - ClosedSegments() ([]string, error) - Remove(files []string) error -} - const ( // DefaultSegmentSize of 10MB is the size at which segment files will be rolled over. DefaultSegmentSize = 10 * 1024 * 1024 @@ -182,7 +167,7 @@ func (l *WAL) Open() error { return err } - segments, err := segmentFileNames(l.path) + segments, err := SegmentFileNames(l.path) if err != nil { return err } @@ -300,7 +285,7 @@ func (l *WAL) sync() { // WriteMulti writes the given values to the WAL. It returns the WAL segment ID to // which the points were written. If an error is returned the segment ID should // be ignored. -func (l *WAL) WriteMulti(values map[string][]Value) (int, error) { +func (l *WAL) WriteMulti(values map[string][]value.Value) (int, error) { entry := &WriteWALEntry{ Values: values, } @@ -329,7 +314,7 @@ func (l *WAL) ClosedSegments() ([]string, error) { currentFile = l.currentSegmentWriter.path() } - files, err := segmentFileNames(l.path) + files, err := SegmentFileNames(l.path) if err != nil { return nil, err } @@ -357,7 +342,7 @@ func (l *WAL) Remove(files []string) error { } // Refresh the on-disk size stats - segments, err := segmentFileNames(l.path) + segments, err := SegmentFileNames(l.path) if err != nil { return err } @@ -538,8 +523,8 @@ func (l *WAL) Close() error { return nil } -// segmentFileNames will return all files that are WAL segment files in sorted order by ascending ID. -func segmentFileNames(dir string) ([]string, error) { +// SegmentFileNames will return all files that are WAL segment files in sorted order by ascending ID. +func SegmentFileNames(dir string) ([]string, error) { names, err := filepath.Glob(filepath.Join(dir, fmt.Sprintf("%s*.%s", WALFilePrefix, WALFileExtension))) if err != nil { return nil, err @@ -666,7 +651,7 @@ type WALEntry interface { // WriteWALEntry represents a write of points. type WriteWALEntry struct { - Values map[string][]Value + Values map[string][]value.Value sz int } @@ -687,17 +672,17 @@ func (w *WriteWALEntry) MarshalSize() int { encLen += 8 * len(v) // timestamps (8) switch v[0].(type) { - case FloatValue, IntegerValue, UnsignedValue: + case value.FloatValue, value.IntegerValue, value.UnsignedValue: encLen += 8 * len(v) - case BooleanValue: + case value.BooleanValue: encLen += 1 * len(v) - case StringValue: + case value.StringValue: for _, vv := range v { - str, ok := vv.(StringValue) + str, ok := vv.(value.StringValue) if !ok { return 0 } - encLen += 4 + len(str.value) + encLen += 4 + len(str.RawValue()) } default: return 0 @@ -746,15 +731,15 @@ func (w *WriteWALEntry) Encode(dst []byte) ([]byte, error) { for k, v := range w.Values { switch v[0].(type) { - case FloatValue: + case value.FloatValue: curType = float64EntryType - case IntegerValue: + case value.IntegerValue: curType = integerEntryType - case UnsignedValue: + case value.UnsignedValue: curType = unsignedEntryType - case BooleanValue: + case value.BooleanValue: curType = booleanEntryType - case StringValue: + case value.StringValue: curType = stringEntryType default: return nil, fmt.Errorf("unsupported value type: %T", v[0]) @@ -774,41 +759,41 @@ func (w *WriteWALEntry) Encode(dst []byte) ([]byte, error) { n += 8 switch vv := vv.(type) { - case FloatValue: + case value.FloatValue: if curType != float64EntryType { return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint64(dst[n:n+8], math.Float64bits(vv.value)) + binary.BigEndian.PutUint64(dst[n:n+8], math.Float64bits(vv.RawValue())) n += 8 - case IntegerValue: + case value.IntegerValue: if curType != integerEntryType { return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.value)) + binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.RawValue())) n += 8 - case UnsignedValue: + case value.UnsignedValue: if curType != unsignedEntryType { return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.value)) + binary.BigEndian.PutUint64(dst[n:n+8], uint64(vv.RawValue())) n += 8 - case BooleanValue: + case value.BooleanValue: if curType != booleanEntryType { return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - if vv.value { + if vv.RawValue() { dst[n] = 1 } else { dst[n] = 0 } n++ - case StringValue: + case value.StringValue: if curType != stringEntryType { return nil, fmt.Errorf("incorrect value found in %T slice: %T", v[0].Value(), vv) } - binary.BigEndian.PutUint32(dst[n:n+4], uint32(len(vv.value))) + binary.BigEndian.PutUint32(dst[n:n+4], uint32(len(vv.RawValue()))) n += 4 - n += copy(dst[n:], vv.value) + n += copy(dst[n:], vv.RawValue()) default: return nil, fmt.Errorf("unsupported value found in %T slice: %T", v[0].Value(), vv) } @@ -863,13 +848,13 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { return ErrWALCorrupt } - values := make([]Value, 0, nvals) + values := make([]value.Value, 0, nvals) for j := 0; j < nvals; j++ { un := int64(binary.BigEndian.Uint64(b[i : i+8])) i += 8 v := math.Float64frombits((binary.BigEndian.Uint64(b[i : i+8]))) i += 8 - values = append(values, NewFloatValue(un, v)) + values = append(values, value.NewFloatValue(un, v)) } w.Values[k] = values case integerEntryType: @@ -877,13 +862,13 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { return ErrWALCorrupt } - values := make([]Value, 0, nvals) + values := make([]value.Value, 0, nvals) for j := 0; j < nvals; j++ { un := int64(binary.BigEndian.Uint64(b[i : i+8])) i += 8 v := int64(binary.BigEndian.Uint64(b[i : i+8])) i += 8 - values = append(values, NewIntegerValue(un, v)) + values = append(values, value.NewIntegerValue(un, v)) } w.Values[k] = values @@ -892,13 +877,13 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { return ErrWALCorrupt } - values := make([]Value, 0, nvals) + values := make([]value.Value, 0, nvals) for j := 0; j < nvals; j++ { un := int64(binary.BigEndian.Uint64(b[i : i+8])) i += 8 v := binary.BigEndian.Uint64(b[i : i+8]) i += 8 - values = append(values, NewUnsignedValue(un, v)) + values = append(values, value.NewUnsignedValue(un, v)) } w.Values[k] = values @@ -907,7 +892,7 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { return ErrWALCorrupt } - values := make([]Value, 0, nvals) + values := make([]value.Value, 0, nvals) for j := 0; j < nvals; j++ { un := int64(binary.BigEndian.Uint64(b[i : i+8])) i += 8 @@ -915,15 +900,15 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { v := b[i] i += 1 if v == 1 { - values = append(values, NewBooleanValue(un, true)) + values = append(values, value.NewBooleanValue(un, true)) } else { - values = append(values, NewBooleanValue(un, false)) + values = append(values, value.NewBooleanValue(un, false)) } } w.Values[k] = values case stringEntryType: - values := make([]Value, 0, nvals) + values := make([]value.Value, 0, nvals) for j := 0; j < nvals; j++ { if i+12 > len(b) { return ErrWALCorrupt @@ -945,7 +930,7 @@ func (w *WriteWALEntry) UnmarshalBinary(b []byte) error { v := string(b[i : i+length]) i += length - values = append(values, NewStringValue(un, v)) + values = append(values, value.NewStringValue(un, v)) } w.Values[k] = values @@ -1250,7 +1235,7 @@ func (r *WALSegmentReader) Next() bool { switch WalEntryType(entryType) { case WriteWALEntryType: r.entry = &WriteWALEntry{ - Values: make(map[string][]Value), + Values: make(map[string][]value.Value), } case DeleteWALEntryType: r.entry = &DeleteWALEntry{} @@ -1310,20 +1295,3 @@ func idFromFileName(name string) (int, error) { return int(id), err } - -// NopWAL implements the Log interface and provides a no-op WAL implementation. -type NopWAL struct{} - -func (w NopWAL) Open() error { return nil } -func (w NopWAL) Close() error { return nil } -func (w NopWAL) Path() string { return "" } - -func (w NopWAL) LastWriteTime() time.Time { return time.Time{} } -func (w NopWAL) DiskSizeBytes() int64 { return 0 } - -func (w NopWAL) WriteMulti(values map[string][]Value) (int, error) { return 0, nil } -func (w NopWAL) DeleteRange(keys [][]byte, min, max int64) (int, error) { return 0, nil } - -func (w NopWAL) CloseSegment() error { return nil } -func (w NopWAL) ClosedSegments() ([]string, error) { return nil, nil } -func (w NopWAL) Remove(files []string) error { return nil } diff --git a/tsdb/tsm1/wal_test.go b/storage/wal/wal_test.go similarity index 79% rename from tsdb/tsm1/wal_test.go rename to storage/wal/wal_test.go index de78110fd7..7b3a638d96 100644 --- a/tsdb/tsm1/wal_test.go +++ b/storage/wal/wal_test.go @@ -1,4 +1,4 @@ -package tsm1_test +package wal import ( "fmt" @@ -9,30 +9,30 @@ import ( "github.com/golang/snappy" "github.com/influxdata/influxdb/pkg/slices" - "github.com/influxdata/influxdb/tsdb/tsm1" + "github.com/influxdata/influxdb/tsdb/tsm1/value" ) func TestWALWriter_WriteMulti_Single(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - p1 := tsm1.NewValue(1, 1.1) - p2 := tsm1.NewValue(1, int64(1)) - p3 := tsm1.NewValue(1, true) - p4 := tsm1.NewValue(1, "string") - p5 := tsm1.NewValue(1, ^uint64(0)) + p1 := value.NewValue(1, 1.1) + p2 := value.NewValue(1, int64(1)) + p3 := value.NewValue(1, true) + p4 := value.NewValue(1, "string") + p5 := value.NewValue(1, ^uint64(0)) - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#float": []tsm1.Value{p1}, - "cpu,host=A#!~#int": []tsm1.Value{p2}, - "cpu,host=A#!~#bool": []tsm1.Value{p3}, - "cpu,host=A#!~#string": []tsm1.Value{p4}, - "cpu,host=A#!~#unsigned": []tsm1.Value{p5}, + values := map[string][]value.Value{ + "cpu,host=A#!~#float": []value.Value{p1}, + "cpu,host=A#!~#int": []value.Value{p2}, + "cpu,host=A#!~#bool": []value.Value{p3}, + "cpu,host=A#!~#string": []value.Value{p4}, + "cpu,host=A#!~#unsigned": []value.Value{p5}, } - entry := &tsm1.WriteWALEntry{ + entry := &WriteWALEntry{ Values: values, } @@ -48,7 +48,7 @@ func TestWALWriter_WriteMulti_Single(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) if !r.Next() { t.Fatalf("expected next, got false") @@ -59,7 +59,7 @@ func TestWALWriter_WriteMulti_Single(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.WriteWALEntry) + e, ok := we.(*WriteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -81,19 +81,19 @@ func TestWALWriter_WriteMulti_LargeBatch(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - var points []tsm1.Value + var points []value.Value for i := 0; i < 100000; i++ { - points = append(points, tsm1.NewValue(int64(i), int64(1))) + points = append(points, value.NewValue(int64(i), int64(1))) } - values := map[string][]tsm1.Value{ + values := map[string][]value.Value{ "cpu,host=A,server=01,foo=bar,tag=really-long#!~#float": points, "mem,host=A,server=01,foo=bar,tag=really-long#!~#float": points, } - entry := &tsm1.WriteWALEntry{ + entry := &WriteWALEntry{ Values: values, } @@ -109,7 +109,7 @@ func TestWALWriter_WriteMulti_LargeBatch(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) if !r.Next() { t.Fatalf("expected next, got false") @@ -120,7 +120,7 @@ func TestWALWriter_WriteMulti_LargeBatch(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.WriteWALEntry) + e, ok := we.(*WriteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -141,22 +141,22 @@ func TestWALWriter_WriteMulti_Multiple(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - p1 := tsm1.NewValue(1, int64(1)) - p2 := tsm1.NewValue(1, int64(2)) + p1 := value.NewValue(1, int64(1)) + p2 := value.NewValue(1, int64(2)) exp := []struct { key string - values []tsm1.Value + values []value.Value }{ - {"cpu,host=A#!~#value", []tsm1.Value{p1}}, - {"cpu,host=B#!~#value", []tsm1.Value{p2}}, + {"cpu,host=A#!~#value", []value.Value{p1}}, + {"cpu,host=B#!~#value", []value.Value{p2}}, } for _, v := range exp { - entry := &tsm1.WriteWALEntry{ - Values: map[string][]tsm1.Value{v.key: v.values}, + entry := &WriteWALEntry{ + Values: map[string][]value.Value{v.key: v.values}, } if err := w.Write(mustMarshalEntry(entry)); err != nil { @@ -172,7 +172,7 @@ func TestWALWriter_WriteMulti_Multiple(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) for _, ep := range exp { if !r.Next() { @@ -184,7 +184,7 @@ func TestWALWriter_WriteMulti_Multiple(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.WriteWALEntry) + e, ok := we.(*WriteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -215,9 +215,9 @@ func TestWALWriter_WriteDelete_Single(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - entry := &tsm1.DeleteWALEntry{ + entry := &DeleteWALEntry{ Keys: [][]byte{[]byte("cpu")}, } @@ -233,7 +233,7 @@ func TestWALWriter_WriteDelete_Single(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) if !r.Next() { t.Fatalf("expected next, got false") @@ -244,7 +244,7 @@ func TestWALWriter_WriteDelete_Single(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.DeleteWALEntry) + e, ok := we.(*DeleteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -262,14 +262,14 @@ func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - p1 := tsm1.NewValue(1, true) - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#value": []tsm1.Value{p1}, + p1 := value.NewValue(1, true) + values := map[string][]value.Value{ + "cpu,host=A#!~#value": []value.Value{p1}, } - writeEntry := &tsm1.WriteWALEntry{ + writeEntry := &WriteWALEntry{ Values: values, } @@ -282,7 +282,7 @@ func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { } // Write the delete entry - deleteEntry := &tsm1.DeleteWALEntry{ + deleteEntry := &DeleteWALEntry{ Keys: [][]byte{[]byte("cpu,host=A#!~value")}, } @@ -299,7 +299,7 @@ func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) // Read the write points first if !r.Next() { @@ -311,7 +311,7 @@ func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.WriteWALEntry) + e, ok := we.(*WriteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -338,7 +338,7 @@ func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { fatal(t, "read entry", err) } - de, ok := we.(*tsm1.DeleteWALEntry) + de, ok := we.(*DeleteWALEntry) if !ok { t.Fatalf("expected DeleteWALEntry: got %#v", e) } @@ -356,17 +356,17 @@ func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - p1 := tsm1.NewValue(1, 1.0) - p2 := tsm1.NewValue(2, 2.0) - p3 := tsm1.NewValue(3, 3.0) + p1 := value.NewValue(1, 1.0) + p2 := value.NewValue(2, 2.0) + p3 := value.NewValue(3, 3.0) - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#value": []tsm1.Value{p1, p2, p3}, + values := map[string][]value.Value{ + "cpu,host=A#!~#value": []value.Value{p1, p2, p3}, } - writeEntry := &tsm1.WriteWALEntry{ + writeEntry := &WriteWALEntry{ Values: values, } @@ -379,7 +379,7 @@ func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { } // Write the delete entry - deleteEntry := &tsm1.DeleteRangeWALEntry{ + deleteEntry := &DeleteRangeWALEntry{ Keys: [][]byte{[]byte("cpu,host=A#!~value")}, Min: 2, Max: 3, @@ -398,7 +398,7 @@ func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) // Read the write points first if !r.Next() { @@ -410,7 +410,7 @@ func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*tsm1.WriteWALEntry) + e, ok := we.(*WriteWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } @@ -437,7 +437,7 @@ func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { fatal(t, "read entry", err) } - de, ok := we.(*tsm1.DeleteRangeWALEntry) + de, ok := we.(*DeleteRangeWALEntry) if !ok { t.Fatalf("expected DeleteWALEntry: got %#v", e) } @@ -464,7 +464,7 @@ func TestWAL_ClosedSegments(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) - w := tsm1.NewWAL(dir) + w := NewWAL(dir) if err := w.Open(); err != nil { t.Fatalf("error opening WAL: %v", err) } @@ -478,9 +478,9 @@ func TestWAL_ClosedSegments(t *testing.T) { t.Fatalf("close segment length mismatch: got %v, exp %v", got, exp) } - if _, err := w.WriteMulti(map[string][]tsm1.Value{ - "cpu,host=A#!~#value": []tsm1.Value{ - tsm1.NewValue(1, 1.1), + if _, err := w.WriteMulti(map[string][]value.Value{ + "cpu,host=A#!~#value": []value.Value{ + value.NewValue(1, 1.1), }, }); err != nil { t.Fatalf("error writing points: %v", err) @@ -491,7 +491,7 @@ func TestWAL_ClosedSegments(t *testing.T) { } // Re-open the WAL - w = tsm1.NewWAL(dir) + w = NewWAL(dir) defer w.Close() if err := w.Open(); err != nil { t.Fatalf("error opening WAL: %v", err) @@ -510,7 +510,7 @@ func TestWAL_Delete(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) - w := tsm1.NewWAL(dir) + w := NewWAL(dir) if err := w.Open(); err != nil { t.Fatalf("error opening WAL: %v", err) } @@ -533,7 +533,7 @@ func TestWAL_Delete(t *testing.T) { } // Re-open the WAL - w = tsm1.NewWAL(dir) + w = NewWAL(dir) defer w.Close() if err := w.Open(); err != nil { t.Fatalf("error opening WAL: %v", err) @@ -552,15 +552,15 @@ func TestWALWriter_Corrupt(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) corruption := []byte{1, 4, 0, 0, 0} - p1 := tsm1.NewValue(1, 1.1) - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#float": []tsm1.Value{p1}, + p1 := value.NewValue(1, 1.1) + values := map[string][]value.Value{ + "cpu,host=A#!~#float": []value.Value{p1}, } - entry := &tsm1.WriteWALEntry{ + entry := &WriteWALEntry{ Values: values, } if err := w.Write(mustMarshalEntry(entry)); err != nil { @@ -580,7 +580,7 @@ func TestWALWriter_Corrupt(t *testing.T) { if _, err := f.Seek(0, io.SeekStart); err != nil { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) // Try to decode two entries. @@ -611,15 +611,15 @@ func TestWALSegmentReader_Corrupt(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - p4 := tsm1.NewValue(1, "string") + p4 := value.NewValue(1, "string") - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#string": []tsm1.Value{p4, p4}, + values := map[string][]value.Value{ + "cpu,host=A#!~#string": []value.Value{p4, p4}, } - entry := &tsm1.WriteWALEntry{ + entry := &WriteWALEntry{ Values: values, } @@ -642,7 +642,7 @@ func TestWALSegmentReader_Corrupt(t *testing.T) { fatal(t, "seek", err) } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) defer r.Close() // Try to decode two entries. @@ -652,21 +652,21 @@ func TestWALSegmentReader_Corrupt(t *testing.T) { } func TestWriteWALSegment_UnmarshalBinary_WriteWALCorrupt(t *testing.T) { - p1 := tsm1.NewValue(1, 1.1) - p2 := tsm1.NewValue(1, int64(1)) - p3 := tsm1.NewValue(1, true) - p4 := tsm1.NewValue(1, "string") - p5 := tsm1.NewValue(1, uint64(1)) + p1 := value.NewValue(1, 1.1) + p2 := value.NewValue(1, int64(1)) + p3 := value.NewValue(1, true) + p4 := value.NewValue(1, "string") + p5 := value.NewValue(1, uint64(1)) - values := map[string][]tsm1.Value{ - "cpu,host=A#!~#float": []tsm1.Value{p1, p1}, - "cpu,host=A#!~#int": []tsm1.Value{p2, p2}, - "cpu,host=A#!~#bool": []tsm1.Value{p3, p3}, - "cpu,host=A#!~#string": []tsm1.Value{p4, p4}, - "cpu,host=A#!~#unsigned": []tsm1.Value{p5, p5}, + values := map[string][]value.Value{ + "cpu,host=A#!~#float": []value.Value{p1, p1}, + "cpu,host=A#!~#int": []value.Value{p2, p2}, + "cpu,host=A#!~#bool": []value.Value{p3, p3}, + "cpu,host=A#!~#string": []value.Value{p4, p4}, + "cpu,host=A#!~#unsigned": []value.Value{p5, p5}, } - w := &tsm1.WriteWALEntry{ + w := &WriteWALEntry{ Values: values, } @@ -681,7 +681,7 @@ func TestWriteWALSegment_UnmarshalBinary_WriteWALCorrupt(t *testing.T) { truncated := make([]byte, i) copy(truncated, b[:i]) err := w.UnmarshalBinary(truncated) - if err != nil && err != tsm1.ErrWALCorrupt { + if err != nil && err != ErrWALCorrupt { t.Fatalf("unexpected error: %v", err) } } @@ -715,13 +715,13 @@ func TestDeleteWALEntry_UnmarshalBinary(t *testing.T) { } for i, example := range examples { - w := &tsm1.DeleteWALEntry{Keys: slices.StringsToBytes(example.In...)} + w := &DeleteWALEntry{Keys: slices.StringsToBytes(example.In...)} b, err := w.MarshalBinary() if err != nil { t.Fatalf("[example %d] unexpected error, got %v", i, err) } - out := &tsm1.DeleteWALEntry{} + out := &DeleteWALEntry{} if err := out.UnmarshalBinary(b); err != nil { t.Fatalf("[example %d] %v", i, err) } @@ -733,7 +733,7 @@ func TestDeleteWALEntry_UnmarshalBinary(t *testing.T) { } func TestWriteWALSegment_UnmarshalBinary_DeleteWALCorrupt(t *testing.T) { - w := &tsm1.DeleteWALEntry{ + w := &DeleteWALEntry{ Keys: [][]byte{[]byte("foo"), []byte("bar")}, } @@ -748,14 +748,14 @@ func TestWriteWALSegment_UnmarshalBinary_DeleteWALCorrupt(t *testing.T) { truncated := make([]byte, i) copy(truncated, b[:i]) err := w.UnmarshalBinary(truncated) - if err != nil && err != tsm1.ErrWALCorrupt { + if err != nil && err != ErrWALCorrupt { t.Fatalf("unexpected error: %v", err) } } } func TestWriteWALSegment_UnmarshalBinary_DeleteRangeWALCorrupt(t *testing.T) { - w := &tsm1.DeleteRangeWALEntry{ + w := &DeleteRangeWALEntry{ Keys: [][]byte{[]byte("foo"), []byte("bar")}, Min: 1, Max: 2, @@ -772,26 +772,26 @@ func TestWriteWALSegment_UnmarshalBinary_DeleteRangeWALCorrupt(t *testing.T) { truncated := make([]byte, i) copy(truncated, b[:i]) err := w.UnmarshalBinary(truncated) - if err != nil && err != tsm1.ErrWALCorrupt { + if err != nil && err != ErrWALCorrupt { t.Fatalf("unexpected error: %v", err) } } } func BenchmarkWALSegmentWriter(b *testing.B) { - points := map[string][]tsm1.Value{} + points := map[string][]value.Value{} for i := 0; i < 5000; i++ { k := "cpu,host=A#!~#value" - points[k] = append(points[k], tsm1.NewValue(int64(i), 1.1)) + points[k] = append(points[k], value.NewValue(int64(i), 1.1)) } dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - write := &tsm1.WriteWALEntry{ + write := &WriteWALEntry{ Values: points, } @@ -804,19 +804,19 @@ func BenchmarkWALSegmentWriter(b *testing.B) { } func BenchmarkWALSegmentReader(b *testing.B) { - points := map[string][]tsm1.Value{} + points := map[string][]value.Value{} for i := 0; i < 5000; i++ { k := "cpu,host=A#!~#value" - points[k] = append(points[k], tsm1.NewValue(int64(i), 1.1)) + points[k] = append(points[k], value.NewValue(int64(i), 1.1)) } dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) - w := tsm1.NewWALSegmentWriter(f) + w := NewWALSegmentWriter(f) - write := &tsm1.WriteWALEntry{ + write := &WriteWALEntry{ Values: points, } @@ -826,7 +826,7 @@ func BenchmarkWALSegmentReader(b *testing.B) { } } - r := tsm1.NewWALSegmentReader(f) + r := NewWALSegmentReader(f) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -852,7 +852,7 @@ func MustReadFileSize(f *os.File) int64 { return stat.Size() } -func mustMarshalEntry(entry tsm1.WALEntry) (tsm1.WalEntryType, []byte) { +func mustMarshalEntry(entry WALEntry) (WalEntryType, []byte) { bytes := make([]byte, 1024<<2) b, err := entry.Encode(bytes) diff --git a/tsdb/tsm1/array_cursor.gen.go b/tsdb/tsm1/array_cursor.gen.go index a18b183784..a6e753fe48 100644 --- a/tsdb/tsm1/array_cursor.gen.go +++ b/tsdb/tsm1/array_cursor.gen.go @@ -83,12 +83,12 @@ func (c *floatArrayAscendingCursor) Next() *tsdb.FloatArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -126,7 +126,7 @@ func (c *floatArrayAscendingCursor) Next() *tsdb.FloatArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() pos++ c.cache.pos++ } @@ -247,12 +247,12 @@ func (c *floatArrayDescendingCursor) Next() *tsdb.FloatArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -285,7 +285,7 @@ func (c *floatArrayDescendingCursor) Next() *tsdb.FloatArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).value + c.res.Values[pos] = cvals[c.cache.pos].(FloatValue).RawValue() pos++ c.cache.pos-- } @@ -391,12 +391,12 @@ func (c *integerArrayAscendingCursor) Next() *tsdb.IntegerArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -434,7 +434,7 @@ func (c *integerArrayAscendingCursor) Next() *tsdb.IntegerArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() pos++ c.cache.pos++ } @@ -555,12 +555,12 @@ func (c *integerArrayDescendingCursor) Next() *tsdb.IntegerArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -593,7 +593,7 @@ func (c *integerArrayDescendingCursor) Next() *tsdb.IntegerArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).value + c.res.Values[pos] = cvals[c.cache.pos].(IntegerValue).RawValue() pos++ c.cache.pos-- } @@ -699,12 +699,12 @@ func (c *unsignedArrayAscendingCursor) Next() *tsdb.UnsignedArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -742,7 +742,7 @@ func (c *unsignedArrayAscendingCursor) Next() *tsdb.UnsignedArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() pos++ c.cache.pos++ } @@ -863,12 +863,12 @@ func (c *unsignedArrayDescendingCursor) Next() *tsdb.UnsignedArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -901,7 +901,7 @@ func (c *unsignedArrayDescendingCursor) Next() *tsdb.UnsignedArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).value + c.res.Values[pos] = cvals[c.cache.pos].(UnsignedValue).RawValue() pos++ c.cache.pos-- } @@ -1007,12 +1007,12 @@ func (c *stringArrayAscendingCursor) Next() *tsdb.StringArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -1050,7 +1050,7 @@ func (c *stringArrayAscendingCursor) Next() *tsdb.StringArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() pos++ c.cache.pos++ } @@ -1173,12 +1173,12 @@ func (c *stringArrayDescendingCursor) Next() *tsdb.StringArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -1211,7 +1211,7 @@ func (c *stringArrayDescendingCursor) Next() *tsdb.StringArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(StringValue).value + c.res.Values[pos] = cvals[c.cache.pos].(StringValue).RawValue() pos++ c.cache.pos-- } @@ -1319,12 +1319,12 @@ func (c *booleanArrayAscendingCursor) Next() *tsdb.BooleanArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -1362,7 +1362,7 @@ func (c *booleanArrayAscendingCursor) Next() *tsdb.BooleanArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() pos++ c.cache.pos++ } @@ -1483,12 +1483,12 @@ func (c *booleanArrayDescendingCursor) Next() *tsdb.BooleanArray { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -1521,7 +1521,7 @@ func (c *booleanArrayDescendingCursor) Next() *tsdb.BooleanArray { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).value + c.res.Values[pos] = cvals[c.cache.pos].(BooleanValue).RawValue() pos++ c.cache.pos-- } diff --git a/tsdb/tsm1/array_cursor.gen.go.tmpl b/tsdb/tsm1/array_cursor.gen.go.tmpl index 3ec768e28a..e7b27dd765 100644 --- a/tsdb/tsm1/array_cursor.gen.go.tmpl +++ b/tsdb/tsm1/array_cursor.gen.go.tmpl @@ -54,7 +54,7 @@ c.end = end }) } -func (c *{{$type}}) Err() error { return nil } +func (c *{{$type}}) Err() error { return nil } // close closes the cursor and any dependent cursors. func (c *{{$type}}) Close() { @@ -82,12 +82,12 @@ func (c *{{$type}}) Next() {{$arrayType}} { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() c.cache.pos++ c.tsm.pos++ } else if ckey < tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() c.cache.pos++ } else { c.res.Timestamps[pos] = tkey @@ -125,7 +125,7 @@ func (c *{{$type}}) Next() {{$arrayType}} { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos < len(cvals) { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() pos++ c.cache.pos++ } @@ -228,7 +228,7 @@ func (c *{{$type}}) reset(seek, end int64, cacheValues Values, tsmKeyCursor *Key } } -func (c *{{$type}}) Err() error { return nil } +func (c *{{$type}}) Err() error { return nil } func (c *{{$type}}) Close() { if c.tsm.keyCursor != nil { @@ -254,12 +254,12 @@ func (c *{{$type}}) Next() {{$arrayType}} { tkey := tvals.Timestamps[c.tsm.pos] if ckey == tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() c.cache.pos-- c.tsm.pos-- } else if ckey > tkey { c.res.Timestamps[pos] = ckey - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() c.cache.pos-- } else { c.res.Timestamps[pos] = tkey @@ -292,7 +292,7 @@ func (c *{{$type}}) Next() {{$arrayType}} { // TSM was exhausted for pos < len(c.res.Timestamps) && c.cache.pos >= 0 { c.res.Timestamps[pos] = cvals[c.cache.pos].UnixNano() - c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).value + c.res.Values[pos] = cvals[c.cache.pos].({{.Name}}Value).RawValue() pos++ c.cache.pos-- } diff --git a/tsdb/tsm1/array_cursor.gen.go.tmpldata b/tsdb/tsm1/array_cursor.gen.go.tmpldata new file mode 100644 index 0000000000..648898fbdb --- /dev/null +++ b/tsdb/tsm1/array_cursor.gen.go.tmpldata @@ -0,0 +1,42 @@ +[ + { + "Name":"Float", + "name":"float", + "Type":"float64", + "ValueType":"FloatValue", + "Nil":"0", + "Size":"8" + }, + { + "Name":"Integer", + "name":"integer", + "Type":"int64", + "ValueType":"IntegerValue", + "Nil":"0", + "Size":"8" + }, + { + "Name":"Unsigned", + "name":"unsigned", + "Type":"uint64", + "ValueType":"UnsignedValue", + "Nil":"0", + "Size":"8" + }, + { + "Name":"String", + "name":"string", + "Type":"string", + "ValueType":"StringValue", + "Nil":"\"\"", + "Size":"0" + }, + { + "Name":"Boolean", + "name":"boolean", + "Type":"bool", + "ValueType":"BooleanValue", + "Nil":"false", + "Size":"1" + } +] diff --git a/tsdb/tsm1/cache.go b/tsdb/tsm1/cache.go index 25f973d00b..89981d6111 100644 --- a/tsdb/tsm1/cache.go +++ b/tsdb/tsm1/cache.go @@ -9,6 +9,7 @@ import ( "time" "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/storage/wal" "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxql" "github.com/prometheus/client_golang/prometheus" @@ -646,7 +647,7 @@ func NewCacheLoader(files []string) *CacheLoader { // continues with the next segment file. func (cl *CacheLoader) Load(cache *Cache) error { - var r *WALSegmentReader + var r *wal.WALSegmentReader for _, fn := range cl.files { if err := func() error { f, err := os.OpenFile(fn, os.O_CREATE|os.O_RDWR, 0666) @@ -668,7 +669,7 @@ func (cl *CacheLoader) Load(cache *Cache) error { } if r == nil { - r = NewWALSegmentReader(f) + r = wal.NewWALSegmentReader(f) defer r.Close() } else { r.Reset(f) @@ -686,13 +687,13 @@ func (cl *CacheLoader) Load(cache *Cache) error { } switch t := entry.(type) { - case *WriteWALEntry: + case *wal.WriteWALEntry: if err := cache.WriteMulti(t.Values); err != nil { return err } - case *DeleteRangeWALEntry: + case *wal.DeleteRangeWALEntry: cache.DeleteRange(t.Keys, t.Min, t.Max) - case *DeleteWALEntry: + case *wal.DeleteWALEntry: cache.Delete(t.Keys) } } diff --git a/tsdb/tsm1/cache_test.go b/tsdb/tsm1/cache_test.go index a5f107529c..ecc0347703 100644 --- a/tsdb/tsm1/cache_test.go +++ b/tsdb/tsm1/cache_test.go @@ -15,6 +15,8 @@ import ( "sync/atomic" "testing" + "github.com/influxdata/influxdb/storage/wal" + "github.com/golang/snappy" ) @@ -604,7 +606,7 @@ func TestCacheLoader_LoadSingle(t *testing.T) { dir := mustTempDir() defer os.RemoveAll(dir) f := mustTempFile(dir) - w := NewWALSegmentWriter(f) + w := wal.NewWALSegmentWriter(f) p1 := NewValue(1, 1.1) p2 := NewValue(1, int64(1)) @@ -616,7 +618,7 @@ func TestCacheLoader_LoadSingle(t *testing.T) { "baz": {p3}, } - entry := &WriteWALEntry{ + entry := &wal.WriteWALEntry{ Values: values, } @@ -676,7 +678,7 @@ func TestCacheLoader_LoadDouble(t *testing.T) { dir := mustTempDir() defer os.RemoveAll(dir) f1, f2 := mustTempFile(dir), mustTempFile(dir) - w1, w2 := NewWALSegmentWriter(f1), NewWALSegmentWriter(f2) + w1, w2 := wal.NewWALSegmentWriter(f1), wal.NewWALSegmentWriter(f2) p1 := NewValue(1, 1.1) p2 := NewValue(1, int64(1)) @@ -685,8 +687,8 @@ func TestCacheLoader_LoadDouble(t *testing.T) { // Write first and second segment. - segmentWrite := func(w *WALSegmentWriter, values map[string][]Value) { - entry := &WriteWALEntry{ + segmentWrite := func(w *wal.WALSegmentWriter, values map[string][]Value) { + entry := &wal.WriteWALEntry{ Values: values, } if err := w1.Write(mustMarshalEntry(entry)); err != nil { @@ -741,7 +743,7 @@ func TestCacheLoader_LoadDeleted(t *testing.T) { dir := mustTempDir() defer os.RemoveAll(dir) f := mustTempFile(dir) - w := NewWALSegmentWriter(f) + w := wal.NewWALSegmentWriter(f) p1 := NewValue(1, 1.0) p2 := NewValue(2, 2.0) @@ -751,7 +753,7 @@ func TestCacheLoader_LoadDeleted(t *testing.T) { "foo": {p1, p2, p3}, } - entry := &WriteWALEntry{ + entry := &wal.WriteWALEntry{ Values: values, } @@ -763,7 +765,7 @@ func TestCacheLoader_LoadDeleted(t *testing.T) { t.Fatalf("flush error: %v", err) } - dentry := &DeleteRangeWALEntry{ + dentry := &wal.DeleteRangeWALEntry{ Keys: [][]byte{[]byte("foo")}, Min: 2, Max: 3, @@ -857,7 +859,7 @@ func mustTempFile(dir string) *os.File { return f } -func mustMarshalEntry(entry WALEntry) (WalEntryType, []byte) { +func mustMarshalEntry(entry wal.WALEntry) (wal.WalEntryType, []byte) { bytes := make([]byte, 1024<<2) b, err := entry.Encode(bytes) diff --git a/tsdb/tsm1/encoding.gen.go b/tsdb/tsm1/encoding.gen.go index 274e35b3c8..3ff8c8db24 100644 --- a/tsdb/tsm1/encoding.gen.go +++ b/tsdb/tsm1/encoding.gen.go @@ -212,8 +212,8 @@ type FloatValues []FloatValue func NewFloatArrayFromValues(v FloatValues) *tsdb.FloatArray { a := tsdb.NewFloatArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -442,8 +442,8 @@ func encodeFloatValuesBlock(buf []byte, values []FloatValue) ([]byte, error) { var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write(v.value) + tsenc.Write(v.UnixNano()) + venc.Write(v.RawValue()) } venc.Flush() @@ -482,8 +482,8 @@ type IntegerValues []IntegerValue func NewIntegerArrayFromValues(v IntegerValues) *tsdb.IntegerArray { a := tsdb.NewIntegerArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -712,8 +712,8 @@ func encodeIntegerValuesBlock(buf []byte, values []IntegerValue) ([]byte, error) var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write(v.value) + tsenc.Write(v.UnixNano()) + venc.Write(v.RawValue()) } venc.Flush() @@ -752,8 +752,8 @@ type UnsignedValues []UnsignedValue func NewUnsignedArrayFromValues(v UnsignedValues) *tsdb.UnsignedArray { a := tsdb.NewUnsignedArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -982,8 +982,8 @@ func encodeUnsignedValuesBlock(buf []byte, values []UnsignedValue) ([]byte, erro var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write(int64(v.value)) + tsenc.Write(v.UnixNano()) + venc.Write(int64(v.RawValue())) } venc.Flush() @@ -1022,8 +1022,8 @@ type StringValues []StringValue func NewStringArrayFromValues(v StringValues) *tsdb.StringArray { a := tsdb.NewStringArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -1252,8 +1252,8 @@ func encodeStringValuesBlock(buf []byte, values []StringValue) ([]byte, error) { var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write(v.value) + tsenc.Write(v.UnixNano()) + venc.Write(v.RawValue()) } venc.Flush() @@ -1292,8 +1292,8 @@ type BooleanValues []BooleanValue func NewBooleanArrayFromValues(v BooleanValues) *tsdb.BooleanArray { a := tsdb.NewBooleanArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -1522,8 +1522,8 @@ func encodeBooleanValuesBlock(buf []byte, values []BooleanValue) ([]byte, error) var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write(v.value) + tsenc.Write(v.UnixNano()) + venc.Write(v.RawValue()) } venc.Flush() diff --git a/tsdb/tsm1/encoding.gen.go.tmpl b/tsdb/tsm1/encoding.gen.go.tmpl index 4f1114459c..9956985700 100644 --- a/tsdb/tsm1/encoding.gen.go.tmpl +++ b/tsdb/tsm1/encoding.gen.go.tmpl @@ -15,8 +15,8 @@ type {{.Name}}Values []{{.Name}}Value func New{{.Name}}ArrayFromValues(v {{.Name}}Values) *tsdb.{{.Name}}Array { a := tsdb.New{{.Name}}ArrayLen(len(v)) for i, val := range v { - a.Timestamps[i] = val.unixnano - a.Values[i] = val.value + a.Timestamps[i] = val.UnixNano() + a.Values[i] = val.RawValue() } return a } @@ -247,8 +247,8 @@ func encode{{ .Name }}ValuesBlock(buf []byte, values []{{.Name}}Value) ([]byte, var b []byte err := func() error { for _, v := range values { - tsenc.Write(v.unixnano) - venc.Write({{if .CastType}}{{.CastType}}(v.value){{else}}v.value{{end}}) + tsenc.Write(v.UnixNano()) + venc.Write({{if .CastType}}{{.CastType}}(v.RawValue()){{else}}v.RawValue(){{end}}) } venc.Flush() diff --git a/tsdb/tsm1/encoding.gen_test.go b/tsdb/tsm1/encoding.gen_test.go index 9fb01893f0..a14c15d71c 100644 --- a/tsdb/tsm1/encoding.gen_test.go +++ b/tsdb/tsm1/encoding.gen_test.go @@ -14,7 +14,7 @@ func makeIntegerValues(count int, min, max int64) IntegerValues { inc := (max - min) / int64(count) for i := 0; i < count; i++ { - vals[i].unixnano = ts + vals[i] = NewRawIntegerValue(ts, 0) ts += inc } @@ -24,7 +24,7 @@ func makeIntegerValues(count int, min, max int64) IntegerValues { func makeIntegerValuesFromSlice(t []int64) IntegerValues { iv := make(IntegerValues, len(t)) for i, v := range t { - iv[i].unixnano = v + iv[i] = NewRawIntegerValue(v, 0) } return iv } @@ -91,7 +91,7 @@ func TestIntegerValues_Exclude(t *testing.T) { vals = vals.Exclude(tc.min, tc.max) var got []int64 for _, v := range vals { - got = append(got, v.unixnano) + got = append(got, v.UnixNano()) } opt := cmp.AllowUnexported(IntegerValue{}) if !cmp.Equal(tc.exp, got, opt) { @@ -122,7 +122,7 @@ func TestIntegerValues_Include(t *testing.T) { vals = vals.Include(tc.min, tc.max) var got []int64 for _, v := range vals { - got = append(got, v.unixnano) + got = append(got, v.UnixNano()) } opt := cmp.AllowUnexported(IntegerValue{}) if !cmp.Equal(tc.exp, got, opt) { diff --git a/tsdb/tsm1/encoding.go b/tsdb/tsm1/encoding.go index 2f5e48d493..ad63b2b14f 100644 --- a/tsdb/tsm1/encoding.go +++ b/tsdb/tsm1/encoding.go @@ -4,10 +4,9 @@ import ( "encoding/binary" "fmt" "runtime" - "time" "github.com/influxdata/influxdb/pkg/pool" - "github.com/influxdata/influxdb/tsdb" + "github.com/influxdata/influxdb/tsdb/tsm1/value" "github.com/influxdata/influxql" ) @@ -32,6 +31,55 @@ const ( encodedBlockHeaderSize = 1 ) +// +// These aliases and functions forward to the value package so that other packages can depend +// on them without pulling in tsm1. Specifically, this is due to moving the WAL code out of +// this package and into the storage package. When we have a better value implementation across +// the board, we should be able to remove these. +// + +type ( + Value = value.Value + + IntegerValue = value.IntegerValue + UnsignedValue = value.UnsignedValue + FloatValue = value.FloatValue + BooleanValue = value.BooleanValue + StringValue = value.StringValue +) + +func NewValue(t int64, v interface{}) Value { return value.NewValue(t, v) } + +// NewRawIntegerValue returns a new integer value. +func NewRawIntegerValue(t int64, v int64) IntegerValue { return value.NewRawIntegerValue(t, v) } + +// NewRawUnsignedValue returns a new unsigned integer value. +func NewRawUnsignedValue(t int64, v uint64) UnsignedValue { return value.NewRawUnsignedValue(t, v) } + +// NewRawFloatValue returns a new float value. +func NewRawFloatValue(t int64, v float64) FloatValue { return value.NewRawFloatValue(t, v) } + +// NewRawBooleanValue returns a new boolean value. +func NewRawBooleanValue(t int64, v bool) BooleanValue { return value.NewRawBooleanValue(t, v) } + +// NewRawStringValue returns a new string value. +func NewRawStringValue(t int64, v string) StringValue { return value.NewRawStringValue(t, v) } + +// NewIntegerValue returns a new integer value. +func NewIntegerValue(t int64, v int64) Value { return value.NewIntegerValue(t, v) } + +// NewUnsignedValue returns a new unsigned integer value. +func NewUnsignedValue(t int64, v uint64) Value { return value.NewUnsignedValue(t, v) } + +// NewFloatValue returns a new float value. +func NewFloatValue(t int64, v float64) Value { return value.NewFloatValue(t, v) } + +// NewBooleanValue returns a new boolean value. +func NewBooleanValue(t int64, v bool) Value { return value.NewBooleanValue(t, v) } + +// NewStringValue returns a new string value. +func NewStringValue(t int64, v string) Value { return value.NewStringValue(t, v) } + func init() { // Prime the pools with one encoder/decoder for each available CPU. vals := make([]interface{}, 0, runtime.NumCPU()) @@ -93,89 +141,6 @@ var ( }) ) -// Value represents a TSM-encoded value. -type Value interface { - // UnixNano returns the timestamp of the value in nanoseconds since unix epoch. - UnixNano() int64 - - // Value returns the underlying value. - Value() interface{} - - // Size returns the number of bytes necessary to represent the value and its timestamp. - Size() int - - // String returns the string representation of the value and its timestamp. - String() string - - // internalOnly is unexported to ensure implementations of Value - // can only originate in this package. - internalOnly() -} - -// NewValue returns a new Value with the underlying type dependent on value. -func NewValue(t int64, value interface{}) Value { - switch v := value.(type) { - case int64: - return IntegerValue{unixnano: t, value: v} - case uint64: - return UnsignedValue{unixnano: t, value: v} - case float64: - return FloatValue{unixnano: t, value: v} - case bool: - return BooleanValue{unixnano: t, value: v} - case string: - return StringValue{unixnano: t, value: v} - } - return EmptyValue{} -} - -// NewIntegerValue returns a new integer value. -func NewIntegerValue(t int64, v int64) Value { - return IntegerValue{unixnano: t, value: v} -} - -// NewUnsignedValue returns a new unsigned integer value. -func NewUnsignedValue(t int64, v uint64) Value { - return UnsignedValue{unixnano: t, value: v} -} - -// NewFloatValue returns a new float value. -func NewFloatValue(t int64, v float64) Value { - return FloatValue{unixnano: t, value: v} -} - -// NewBooleanValue returns a new boolean value. -func NewBooleanValue(t int64, v bool) Value { - return BooleanValue{unixnano: t, value: v} -} - -// NewStringValue returns a new string value. -func NewStringValue(t int64, v string) Value { - return StringValue{unixnano: t, value: v} -} - -// EmptyValue is used when there is no appropriate other value. -type EmptyValue struct{} - -// UnixNano returns tsdb.EOF. -func (e EmptyValue) UnixNano() int64 { return tsdb.EOF } - -// Value returns nil. -func (e EmptyValue) Value() interface{} { return nil } - -// Size returns 0. -func (e EmptyValue) Size() int { return 0 } - -// String returns the empty string. -func (e EmptyValue) String() string { return "" } - -func (EmptyValue) internalOnly() {} -func (StringValue) internalOnly() {} -func (IntegerValue) internalOnly() {} -func (UnsignedValue) internalOnly() {} -func (BooleanValue) internalOnly() {} -func (FloatValue) internalOnly() {} - // Encode converts the values to a byte slice. If there are no values, // this function panics. func (a Values) Encode(buf []byte) ([]byte, error) { @@ -318,32 +283,6 @@ func DecodeBlock(block []byte, vals []Value) ([]Value, error) { } } -// FloatValue represents a float64 value. -type FloatValue struct { - unixnano int64 - value float64 -} - -// UnixNano returns the timestamp of the value. -func (v FloatValue) UnixNano() int64 { - return v.unixnano -} - -// Value returns the underlying float64 value. -func (v FloatValue) Value() interface{} { - return v.value -} - -// Size returns the number of bytes necessary to represent the value and its timestamp. -func (v FloatValue) Size() int { - return 16 -} - -// String returns the string representation of the value and its timestamp. -func (v FloatValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.value) -} - func encodeFloatBlock(buf []byte, values []Value) ([]byte, error) { if len(values) == 0 { return nil, nil @@ -373,8 +312,8 @@ func encodeFloatBlockUsing(buf []byte, values []Value, tsenc TimeEncoder, venc * for _, v := range values { vv := v.(FloatValue) - tsenc.Write(vv.unixnano) - venc.Write(vv.value) + tsenc.Write(vv.UnixNano()) + venc.Write(vv.RawValue()) } venc.Flush() @@ -432,7 +371,7 @@ func DecodeFloatBlock(block []byte, a *[]FloatValue) ([]FloatValue, error) { // Decode both a timestamp and value j := 0 for j < len(a) && tdec.Next() && vdec.Next() { - a[j] = FloatValue{unixnano: tdec.Read(), value: vdec.Values()} + a[j] = NewRawFloatValue(tdec.Read(), vdec.Values()) j++ } i = j @@ -453,32 +392,6 @@ func DecodeFloatBlock(block []byte, a *[]FloatValue) ([]FloatValue, error) { return (*a)[:i], err } -// BooleanValue represents a boolean value. -type BooleanValue struct { - unixnano int64 - value bool -} - -// Size returns the number of bytes necessary to represent the value and its timestamp. -func (v BooleanValue) Size() int { - return 9 -} - -// UnixNano returns the timestamp of the value in nanoseconds since unix epoch. -func (v BooleanValue) UnixNano() int64 { - return v.unixnano -} - -// Value returns the underlying boolean value. -func (v BooleanValue) Value() interface{} { - return v.value -} - -// String returns the string representation of the value and its timestamp. -func (v BooleanValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) -} - func encodeBooleanBlock(buf []byte, values []Value) ([]byte, error) { if len(values) == 0 { return nil, nil @@ -505,8 +418,8 @@ func encodeBooleanBlockUsing(buf []byte, values []Value, tenc TimeEncoder, venc for _, v := range values { vv := v.(BooleanValue) - tenc.Write(vv.unixnano) - venc.Write(vv.value) + tenc.Write(vv.UnixNano()) + venc.Write(vv.RawValue()) } // Encoded timestamp values @@ -560,7 +473,7 @@ func DecodeBooleanBlock(block []byte, a *[]BooleanValue) ([]BooleanValue, error) // Decode both a timestamp and value j := 0 for j < len(a) && tdec.Next() && vdec.Next() { - a[j] = BooleanValue{unixnano: tdec.Read(), value: vdec.Read()} + a[j] = NewRawBooleanValue(tdec.Read(), vdec.Read()) j++ } i = j @@ -580,32 +493,6 @@ func DecodeBooleanBlock(block []byte, a *[]BooleanValue) ([]BooleanValue, error) return (*a)[:i], err } -// IntegerValue represents an int64 value. -type IntegerValue struct { - unixnano int64 - value int64 -} - -// Value returns the underlying int64 value. -func (v IntegerValue) Value() interface{} { - return v.value -} - -// UnixNano returns the timestamp of the value. -func (v IntegerValue) UnixNano() int64 { - return v.unixnano -} - -// Size returns the number of bytes necessary to represent the value and its timestamp. -func (v IntegerValue) Size() int { - return 16 -} - -// String returns the string representation of the value and its timestamp. -func (v IntegerValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) -} - func encodeIntegerBlock(buf []byte, values []Value) ([]byte, error) { tenc := getTimeEncoder(len(values)) venc := getIntegerEncoder(len(values)) @@ -624,8 +511,8 @@ func encodeIntegerBlockUsing(buf []byte, values []Value, tenc TimeEncoder, venc for _, v := range values { vv := v.(IntegerValue) - tenc.Write(vv.unixnano) - venc.Write(vv.value) + tenc.Write(vv.UnixNano()) + venc.Write(vv.RawValue()) } // Encoded timestamp values @@ -679,7 +566,7 @@ func DecodeIntegerBlock(block []byte, a *[]IntegerValue) ([]IntegerValue, error) // Decode both a timestamp and value j := 0 for j < len(a) && tdec.Next() && vdec.Next() { - a[j] = IntegerValue{unixnano: tdec.Read(), value: vdec.Read()} + a[j] = NewRawIntegerValue(tdec.Read(), vdec.Read()) j++ } i = j @@ -699,32 +586,6 @@ func DecodeIntegerBlock(block []byte, a *[]IntegerValue) ([]IntegerValue, error) return (*a)[:i], err } -// UnsignedValue represents an int64 value. -type UnsignedValue struct { - unixnano int64 - value uint64 -} - -// Value returns the underlying int64 value. -func (v UnsignedValue) Value() interface{} { - return v.value -} - -// UnixNano returns the timestamp of the value. -func (v UnsignedValue) UnixNano() int64 { - return v.unixnano -} - -// Size returns the number of bytes necessary to represent the value and its timestamp. -func (v UnsignedValue) Size() int { - return 16 -} - -// String returns the string representation of the value and its timestamp. -func (v UnsignedValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) -} - func encodeUnsignedBlock(buf []byte, values []Value) ([]byte, error) { tenc := getTimeEncoder(len(values)) venc := getUnsignedEncoder(len(values)) @@ -743,8 +604,8 @@ func encodeUnsignedBlockUsing(buf []byte, values []Value, tenc TimeEncoder, venc for _, v := range values { vv := v.(UnsignedValue) - tenc.Write(vv.unixnano) - venc.Write(int64(vv.value)) + tenc.Write(vv.UnixNano()) + venc.Write(int64(vv.RawValue())) } // Encoded timestamp values @@ -798,7 +659,7 @@ func DecodeUnsignedBlock(block []byte, a *[]UnsignedValue) ([]UnsignedValue, err // Decode both a timestamp and value j := 0 for j < len(a) && tdec.Next() && vdec.Next() { - a[j] = UnsignedValue{unixnano: tdec.Read(), value: uint64(vdec.Read())} + a[j] = NewRawUnsignedValue(tdec.Read(), uint64(vdec.Read())) j++ } i = j @@ -818,35 +679,9 @@ func DecodeUnsignedBlock(block []byte, a *[]UnsignedValue) ([]UnsignedValue, err return (*a)[:i], err } -// StringValue represents a string value. -type StringValue struct { - unixnano int64 - value string -} - -// Value returns the underlying string value. -func (v StringValue) Value() interface{} { - return v.value -} - -// UnixNano returns the timestamp of the value. -func (v StringValue) UnixNano() int64 { - return v.unixnano -} - -// Size returns the number of bytes necessary to represent the value and its timestamp. -func (v StringValue) Size() int { - return 8 + len(v.value) -} - -// String returns the string representation of the value and its timestamp. -func (v StringValue) String() string { - return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) -} - func encodeStringBlock(buf []byte, values []Value) ([]byte, error) { tenc := getTimeEncoder(len(values)) - venc := getStringEncoder(len(values) * len(values[0].(StringValue).value)) + venc := getStringEncoder(len(values) * len(values[0].(StringValue).RawValue())) b, err := encodeStringBlockUsing(buf, values, tenc, venc) @@ -862,8 +697,8 @@ func encodeStringBlockUsing(buf []byte, values []Value, tenc TimeEncoder, venc S for _, v := range values { vv := v.(StringValue) - tenc.Write(vv.unixnano) - venc.Write(vv.value) + tenc.Write(vv.UnixNano()) + venc.Write(vv.RawValue()) } // Encoded timestamp values @@ -920,7 +755,7 @@ func DecodeStringBlock(block []byte, a *[]StringValue) ([]StringValue, error) { // Decode both a timestamp and value j := 0 for j < len(a) && tdec.Next() && vdec.Next() { - a[j] = StringValue{unixnano: tdec.Read(), value: vdec.Read()} + a[j] = NewRawStringValue(tdec.Read(), vdec.Read()) j++ } i = j diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index 71b68edea1..3406b08378 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -24,6 +24,7 @@ import ( "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/metrics" "github.com/influxdata/influxdb/query" + "github.com/influxdata/influxdb/storage/wal" "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxdb/tsdb/tsi1" "github.com/influxdata/influxql" @@ -31,6 +32,7 @@ import ( "go.uber.org/zap" ) +//go:generate env GO111MODULE=on go run github.com/benbjohnson/tmpl -data=@array_cursor.gen.go.tmpldata array_cursor.gen.go.tmpl array_cursor_iterator.gen.go.tmpl //go:generate env GO111MODULE=on go run github.com/influxdata/influxdb/tools/tmpl -i -data=file_store.gen.go.tmpldata file_store.gen.go.tmpl=file_store.gen.go //go:generate env GO111MODULE=on go run github.com/influxdata/influxdb/tools/tmpl -i -d isArray=y -data=file_store.gen.go.tmpldata file_store.gen.go.tmpl=file_store_array.gen.go //go:generate env GO111MODULE=on go run github.com/benbjohnson/tmpl -data=@encoding.gen.go.tmpldata encoding.gen.go.tmpl @@ -78,15 +80,15 @@ const ( type EngineOption func(i *Engine) // WithWAL sets the WAL for the Engine -var WithWAL = func(wal Log) EngineOption { +var WithWAL = func(w Log) EngineOption { // be defensive: it's very easy to pass in a nil WAL here // which will panic. Set any nil WALs to the NopWAL. - if pwal, _ := wal.(*WAL); pwal == nil { - wal = NopWAL{} + if pwal, _ := w.(*wal.WAL); pwal == nil { + w = NopWAL{} } return func(e *Engine) { - e.WAL = wal + e.WAL = w } } @@ -512,10 +514,6 @@ func (e *Engine) initTrackers() { e.FileStore.tracker = newFileTracker(bms.fileMetrics, e.defaultMetricLabels) e.Cache.tracker = newCacheTracker(bms.cacheMetrics, e.defaultMetricLabels) - // Set default metrics on WAL if enabled. - if wal, ok := e.WAL.(*WAL); ok { - wal.tracker = newWALTracker(bms.walMetrics, e.defaultMetricLabels) - } e.scheduler.setCompactionTracker(e.compactionTracker) } @@ -575,10 +573,7 @@ func (e *Engine) WithLogger(log *zap.Logger) { e.traceLogger = e.logger } - if wal, ok := e.WAL.(*WAL); ok { - wal.WithLogger(e.logger) - } - + e.WAL.WithLogger(e.logger) e.FileStore.WithLogger(e.logger) } @@ -1571,7 +1566,7 @@ func (e *Engine) fullCompactionStrategy(group CompactionGroup, optimize bool) *c // reloadCache reads the WAL segment files and loads them into the cache. func (e *Engine) reloadCache() error { now := time.Now() - files, err := segmentFileNames(e.WAL.Path()) + files, err := wal.SegmentFileNames(e.WAL.Path()) if err != nil { return err } diff --git a/tsdb/tsm1/metrics.go b/tsdb/tsm1/metrics.go index 0d2299ffd6..7677f4aaf4 100644 --- a/tsdb/tsm1/metrics.go +++ b/tsdb/tsm1/metrics.go @@ -25,7 +25,6 @@ func PrometheusCollectors() []prometheus.Collector { collectors = append(collectors, bms.compactionMetrics.PrometheusCollectors()...) collectors = append(collectors, bms.fileMetrics.PrometheusCollectors()...) collectors = append(collectors, bms.cacheMetrics.PrometheusCollectors()...) - collectors = append(collectors, bms.walMetrics.PrometheusCollectors()...) } return collectors } @@ -36,7 +35,6 @@ const namespace = "storage" const compactionSubsystem = "compactions" // sub-system associated with metrics for compactions. const fileStoreSubsystem = "tsm_files" // sub-system associated with metrics for TSM files. const cacheSubsystem = "cache" // sub-system associated with metrics for the cache. -const walSubsystem = "wal" // sub-system associated with metrics for the WAL. // blockMetrics are a set of metrics concerned with tracking data about block storage. type blockMetrics struct { @@ -44,7 +42,6 @@ type blockMetrics struct { *compactionMetrics *fileMetrics *cacheMetrics - *walMetrics } // newBlockMetrics initialises the prometheus metrics for the block subsystem. @@ -54,7 +51,6 @@ func newBlockMetrics(labels prometheus.Labels) *blockMetrics { compactionMetrics: newCompactionMetrics(labels), fileMetrics: newFileMetrics(labels), cacheMetrics: newCacheMetrics(labels), - walMetrics: newWALMetrics(labels), } } @@ -64,7 +60,6 @@ func (m *blockMetrics) PrometheusCollectors() []prometheus.Collector { metrics = append(metrics, m.compactionMetrics.PrometheusCollectors()...) metrics = append(metrics, m.fileMetrics.PrometheusCollectors()...) metrics = append(metrics, m.cacheMetrics.PrometheusCollectors()...) - metrics = append(metrics, m.walMetrics.PrometheusCollectors()...) return metrics } @@ -249,60 +244,3 @@ func (m *cacheMetrics) PrometheusCollectors() []prometheus.Collector { m.Writes, } } - -// walMetrics are a set of metrics concerned with tracking data about compactions. -type walMetrics struct { - OldSegmentBytes *prometheus.GaugeVec - CurrentSegmentBytes *prometheus.GaugeVec - Segments *prometheus.GaugeVec - Writes *prometheus.CounterVec -} - -// newWALMetrics initialises the prometheus metrics for tracking the WAL. -func newWALMetrics(labels prometheus.Labels) *walMetrics { - var names []string - for k := range labels { - names = append(names, k) - } - sort.Strings(names) - - writeNames := append(append([]string(nil), names...), "status") - sort.Strings(writeNames) - - return &walMetrics{ - OldSegmentBytes: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: walSubsystem, - Name: "old_segment_bytes", - Help: "Number of bytes old WAL segments using on disk.", - }, names), - CurrentSegmentBytes: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: walSubsystem, - Name: "current_segment_bytes", - Help: "Number of bytes TSM files using on disk.", - }, names), - Segments: prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: walSubsystem, - Name: "segments_total", - Help: "Number of WAL segment files on disk.", - }, names), - Writes: prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: walSubsystem, - Name: "writes_total", - Help: "Number of writes to the WAL.", - }, writeNames), - } -} - -// PrometheusCollectors satisfies the prom.PrometheusCollector interface. -func (m *walMetrics) PrometheusCollectors() []prometheus.Collector { - return []prometheus.Collector{ - m.OldSegmentBytes, - m.CurrentSegmentBytes, - m.Segments, - m.Writes, - } -} diff --git a/tsdb/tsm1/metrics_test.go b/tsdb/tsm1/metrics_test.go index 4b8dfb2a64..3372adf3f0 100644 --- a/tsdb/tsm1/metrics_test.go +++ b/tsdb/tsm1/metrics_test.go @@ -130,73 +130,6 @@ func TestMetrics_Cache(t *testing.T) { } } -func TestMetrics_WAL(t *testing.T) { - // metrics to be shared by multiple file stores. - metrics := newWALMetrics(prometheus.Labels{"engine_id": "", "node_id": ""}) - - t1 := newWALTracker(metrics, prometheus.Labels{"engine_id": "0", "node_id": "0"}) - t2 := newWALTracker(metrics, prometheus.Labels{"engine_id": "1", "node_id": "0"}) - - reg := prometheus.NewRegistry() - reg.MustRegister(metrics.PrometheusCollectors()...) - - base := namespace + "_" + walSubsystem + "_" - - // All the metric names - gauges := []string{ - base + "old_segment_bytes", - base + "current_segment_bytes", - base + "segments_total", - } - - counters := []string{ - base + "writes_total", - } - - // Generate some measurements. - for i, tracker := range []*walTracker{t1, t2} { - tracker.SetOldSegmentSize(uint64(i + len(gauges[0]))) - tracker.SetCurrentSegmentSize(uint64(i + len(gauges[1]))) - tracker.SetSegments(uint64(i + len(gauges[2]))) - - labels := tracker.Labels() - labels["status"] = "ok" - tracker.metrics.Writes.With(labels).Add(float64(i + len(counters[0]))) - } - - // Test that all the correct metrics are present. - mfs, err := reg.Gather() - if err != nil { - t.Fatal(err) - } - - // The label variants for the two caches. - labelVariants := []prometheus.Labels{ - prometheus.Labels{"engine_id": "0", "node_id": "0"}, - prometheus.Labels{"engine_id": "1", "node_id": "0"}, - } - - for i, labels := range labelVariants { - for _, name := range gauges { - exp := float64(i + len(name)) - metric := promtest.MustFindMetric(t, mfs, name, labels) - if got := metric.GetGauge().GetValue(); got != exp { - t.Errorf("[%s %d] got %v, expected %v", name, i, got, exp) - } - } - - for _, name := range counters { - exp := float64(i + len(name)) - - labels["status"] = "ok" - metric := promtest.MustFindMetric(t, mfs, name, labels) - if got := metric.GetCounter().GetValue(); got != exp { - t.Errorf("[%s %d] got %v, expected %v", name, i, got, exp) - } - } - } -} - func TestMetrics_Compactions(t *testing.T) { // metrics to be shared by multiple file stores. metrics := newCompactionMetrics(prometheus.Labels{"engine_id": "", "node_id": ""}) diff --git a/tsdb/tsm1/temp_log.go b/tsdb/tsm1/temp_log.go new file mode 100644 index 0000000000..b69b0d82e2 --- /dev/null +++ b/tsdb/tsm1/temp_log.go @@ -0,0 +1,47 @@ +package tsm1 + +import ( + "time" + + "go.uber.org/zap" +) + +// TODO(jeff): this only exists temporarily while we move the WAL into storage + +// Log describes an interface for a durable disk-based log. +type Log interface { + WithLogger(*zap.Logger) + + Open() error + Close() error + Path() string + + LastWriteTime() time.Time + DiskSizeBytes() int64 + + WriteMulti(values map[string][]Value) (int, error) + DeleteRange(keys [][]byte, min, max int64) (int, error) + + CloseSegment() error + ClosedSegments() ([]string, error) + Remove(files []string) error +} + +// NopWAL implements the Log interface and provides a no-op WAL implementation. +type NopWAL struct{} + +func (w NopWAL) WithLogger(*zap.Logger) {} + +func (w NopWAL) Open() error { return nil } +func (w NopWAL) Close() error { return nil } +func (w NopWAL) Path() string { return "" } + +func (w NopWAL) LastWriteTime() time.Time { return time.Time{} } +func (w NopWAL) DiskSizeBytes() int64 { return 0 } + +func (w NopWAL) WriteMulti(values map[string][]Value) (int, error) { return 0, nil } +func (w NopWAL) DeleteRange(keys [][]byte, min, max int64) (int, error) { return 0, nil } + +func (w NopWAL) CloseSegment() error { return nil } +func (w NopWAL) ClosedSegments() ([]string, error) { return nil, nil } +func (w NopWAL) Remove(files []string) error { return nil } diff --git a/tsdb/tsm1/value/value.go b/tsdb/tsm1/value/value.go new file mode 100644 index 0000000000..41320278c6 --- /dev/null +++ b/tsdb/tsm1/value/value.go @@ -0,0 +1,236 @@ +package value + +import ( + "fmt" + "time" + + "github.com/influxdata/influxdb/tsdb" +) + +// Value represents a TSM-encoded value. +type Value interface { + // UnixNano returns the timestamp of the value in nanoseconds since unix epoch. + UnixNano() int64 + + // Value returns the underlying value. + Value() interface{} + + // Size returns the number of bytes necessary to represent the value and its timestamp. + Size() int + + // String returns the string representation of the value and its timestamp. + String() string + + // internalOnly is unexported to ensure implementations of Value + // can only originate in this package. + internalOnly() +} + +// NewValue returns a new Value with the underlying type dependent on value. +func NewValue(t int64, value interface{}) Value { + switch v := value.(type) { + case int64: + return IntegerValue{unixnano: t, value: v} + case uint64: + return UnsignedValue{unixnano: t, value: v} + case float64: + return FloatValue{unixnano: t, value: v} + case bool: + return BooleanValue{unixnano: t, value: v} + case string: + return StringValue{unixnano: t, value: v} + } + return EmptyValue{} +} + +// NewRawIntegerValue returns a new integer value. +func NewRawIntegerValue(t int64, v int64) IntegerValue { return IntegerValue{unixnano: t, value: v} } + +// NewRawUnsignedValue returns a new unsigned integer value. +func NewRawUnsignedValue(t int64, v uint64) UnsignedValue { return UnsignedValue{unixnano: t, value: v} } + +// NewRawFloatValue returns a new float value. +func NewRawFloatValue(t int64, v float64) FloatValue { return FloatValue{unixnano: t, value: v} } + +// NewRawBooleanValue returns a new boolean value. +func NewRawBooleanValue(t int64, v bool) BooleanValue { return BooleanValue{unixnano: t, value: v} } + +// NewRawStringValue returns a new string value. +func NewRawStringValue(t int64, v string) StringValue { return StringValue{unixnano: t, value: v} } + +// NewIntegerValue returns a new integer value. +func NewIntegerValue(t int64, v int64) Value { return NewRawIntegerValue(t, v) } + +// NewUnsignedValue returns a new unsigned integer value. +func NewUnsignedValue(t int64, v uint64) Value { return NewRawUnsignedValue(t, v) } + +// NewFloatValue returns a new float value. +func NewFloatValue(t int64, v float64) Value { return NewRawFloatValue(t, v) } + +// NewBooleanValue returns a new boolean value. +func NewBooleanValue(t int64, v bool) Value { return NewRawBooleanValue(t, v) } + +// NewStringValue returns a new string value. +func NewStringValue(t int64, v string) Value { return NewRawStringValue(t, v) } + +// EmptyValue is used when there is no appropriate other value. +type EmptyValue struct{} + +// UnixNano returns tsdb.EOF. +func (e EmptyValue) UnixNano() int64 { return tsdb.EOF } + +// Value returns nil. +func (e EmptyValue) Value() interface{} { return nil } + +// Size returns 0. +func (e EmptyValue) Size() int { return 0 } + +// String returns the empty string. +func (e EmptyValue) String() string { return "" } + +func (EmptyValue) internalOnly() {} +func (StringValue) internalOnly() {} +func (IntegerValue) internalOnly() {} +func (UnsignedValue) internalOnly() {} +func (BooleanValue) internalOnly() {} +func (FloatValue) internalOnly() {} + +// IntegerValue represents an int64 value. +type IntegerValue struct { + unixnano int64 + value int64 +} + +// Value returns the underlying int64 value. +func (v IntegerValue) Value() interface{} { + return v.value +} + +// UnixNano returns the timestamp of the value. +func (v IntegerValue) UnixNano() int64 { + return v.unixnano +} + +// Size returns the number of bytes necessary to represent the value and its timestamp. +func (v IntegerValue) Size() int { + return 16 +} + +// String returns the string representation of the value and its timestamp. +func (v IntegerValue) String() string { + return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) +} + +func (v IntegerValue) RawValue() int64 { return v.value } + +// UnsignedValue represents an int64 value. +type UnsignedValue struct { + unixnano int64 + value uint64 +} + +// Value returns the underlying int64 value. +func (v UnsignedValue) Value() interface{} { + return v.value +} + +// UnixNano returns the timestamp of the value. +func (v UnsignedValue) UnixNano() int64 { + return v.unixnano +} + +// Size returns the number of bytes necessary to represent the value and its timestamp. +func (v UnsignedValue) Size() int { + return 16 +} + +// String returns the string representation of the value and its timestamp. +func (v UnsignedValue) String() string { + return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) +} + +func (v UnsignedValue) RawValue() uint64 { return v.value } + +// FloatValue represents a float64 value. +type FloatValue struct { + unixnano int64 + value float64 +} + +// UnixNano returns the timestamp of the value. +func (v FloatValue) UnixNano() int64 { + return v.unixnano +} + +// Value returns the underlying float64 value. +func (v FloatValue) Value() interface{} { + return v.value +} + +// Size returns the number of bytes necessary to represent the value and its timestamp. +func (v FloatValue) Size() int { + return 16 +} + +// String returns the string representation of the value and its timestamp. +func (v FloatValue) String() string { + return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.value) +} + +func (v FloatValue) RawValue() float64 { return v.value } + +// BooleanValue represents a boolean value. +type BooleanValue struct { + unixnano int64 + value bool +} + +// Size returns the number of bytes necessary to represent the value and its timestamp. +func (v BooleanValue) Size() int { + return 9 +} + +// UnixNano returns the timestamp of the value in nanoseconds since unix epoch. +func (v BooleanValue) UnixNano() int64 { + return v.unixnano +} + +// Value returns the underlying boolean value. +func (v BooleanValue) Value() interface{} { + return v.value +} + +// String returns the string representation of the value and its timestamp. +func (v BooleanValue) String() string { + return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) +} + +func (v BooleanValue) RawValue() bool { return v.value } + +// StringValue represents a string value. +type StringValue struct { + unixnano int64 + value string +} + +// Value returns the underlying string value. +func (v StringValue) Value() interface{} { + return v.value +} + +// UnixNano returns the timestamp of the value. +func (v StringValue) UnixNano() int64 { + return v.unixnano +} + +// Size returns the number of bytes necessary to represent the value and its timestamp. +func (v StringValue) Size() int { + return 8 + len(v.value) +} + +// String returns the string representation of the value and its timestamp. +func (v StringValue) String() string { + return fmt.Sprintf("%v %v", time.Unix(0, v.unixnano), v.Value()) +} + +func (v StringValue) RawValue() string { return v.value } From 95de3d52b296cbce8d92aff8c0604fc02bc2336b Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Wed, 16 Jan 2019 14:35:36 -0700 Subject: [PATCH 17/95] refactor: use concrete WAL in tsm1 At the cost of some nil checks, we don't have to have an interface, defend against subtle bugs with nils in non-nil interfaces, an empty implementation, etc. Also, the tsm1 engine is losing the WAL anyway. --- storage/engine.go | 4 +- tsdb/tsm1/engine.go | 75 ++++++++++++++++---------- tsdb/tsm1/engine_delete_measurement.go | 6 ++- tsdb/tsm1/temp_log.go | 47 ---------------- 4 files changed, 52 insertions(+), 80 deletions(-) delete mode 100644 tsdb/tsm1/temp_log.go diff --git a/storage/engine.go b/storage/engine.go index 176672fb8d..cac720760b 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -120,17 +120,15 @@ func NewEngine(path string, c Config, options ...Option) *Engine { tsi1.WithPath(c.GetIndexPath(path))) // Initialize WAL - var w tsm1.Log = new(tsm1.NopWAL) if c.WAL.Enabled { e.wal = wal.NewWAL(c.GetWALPath(path)) e.wal.WithFsyncDelay(time.Duration(c.WAL.FsyncDelay)) e.wal.EnableTraceLogging(c.TraceLoggingEnabled) - w = e.wal } // Initialise Engine e.engine = tsm1.NewEngine(c.GetEnginePath(path), e.index, c.Engine, - tsm1.WithWAL(w), + tsm1.WithWAL(e.wal), tsm1.WithTraceLogging(c.TraceLoggingEnabled)) // Apply options. diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index 3406b08378..ec832404c1 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -80,13 +80,7 @@ const ( type EngineOption func(i *Engine) // WithWAL sets the WAL for the Engine -var WithWAL = func(w Log) EngineOption { - // be defensive: it's very easy to pass in a nil WAL here - // which will panic. Set any nil WALs to the NopWAL. - if pwal, _ := w.(*wal.WAL); pwal == nil { - w = NopWAL{} - } - +var WithWAL = func(w *wal.WAL) EngineOption { return func(e *Engine) { e.WAL = w } @@ -134,7 +128,7 @@ type Engine struct { traceLogger *zap.Logger // Logger to be used when trace-logging is on. traceLogging bool - WAL Log + WAL *wal.WAL Cache *Cache Compactor *Compactor CompactionPlan CompactionPlanner @@ -209,7 +203,6 @@ func NewEngine(path string, idx *tsi1.Index, config Config, options ...EngineOpt logger: logger, traceLogger: logger, - WAL: NopWAL{}, Cache: cache, FileStore: fs, @@ -483,7 +476,7 @@ func (e *Engine) SeriesN() int64 { func (e *Engine) LastModified() time.Time { fsTime := e.FileStore.LastModified() - if e.WAL.LastWriteTime().After(fsTime) { + if e.WAL != nil && e.WAL.LastWriteTime().After(fsTime) { return e.WAL.LastWriteTime() } return fsTime @@ -496,7 +489,11 @@ func (e *Engine) MeasurementStats() (MeasurementStats, error) { // DiskSize returns the total size in bytes of all TSM and WAL segments on disk. func (e *Engine) DiskSize() int64 { - walDiskSizeBytes := e.WAL.DiskSizeBytes() + var walDiskSizeBytes int64 + if e.WAL != nil { + walDiskSizeBytes = e.WAL.DiskSizeBytes() + } + return e.FileStore.DiskSizeBytes() + walDiskSizeBytes } @@ -529,8 +526,10 @@ func (e *Engine) Open() error { return err } - if err := e.WAL.Open(); err != nil { - return err + if e.WAL != nil { + if err := e.WAL.Open(); err != nil { + return err + } } if err := e.FileStore.Open(); err != nil { @@ -562,7 +561,14 @@ func (e *Engine) Close() error { if err := e.FileStore.Close(); err != nil { return err } - return e.WAL.Close() + + if e.WAL != nil { + if err := e.WAL.Close(); err != nil { + return err + } + } + + return nil } // WithLogger sets the logger for the engine. @@ -573,7 +579,9 @@ func (e *Engine) WithLogger(log *zap.Logger) { e.traceLogger = e.logger } - e.WAL.WithLogger(e.logger) + if e.WAL != nil { + e.WAL.WithLogger(e.logger) + } e.FileStore.WithLogger(e.logger) } @@ -652,8 +660,10 @@ func (e *Engine) WritePoints(points []models.Point) error { } // Then make the write durable in the cache. - if _, err := e.WAL.WriteMulti(values); err != nil { - return err + if e.WAL != nil { + if _, err := e.WAL.WriteMulti(values); err != nil { + return err + } } return nil @@ -866,8 +876,10 @@ func (e *Engine) deleteSeriesRange(seriesKeys [][]byte, min, max int64) error { e.Cache.DeleteRange(deleteKeys, min, max) // delete from the WAL - if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { - return err + if e.WAL != nil { + if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { + return err + } } // The series are deleted on disk, but the index may still say they exist. @@ -1193,13 +1205,14 @@ func (e *Engine) WriteSnapshot() error { e.mu.Lock() defer e.mu.Unlock() - if err = e.WAL.CloseSegment(); err != nil { - return nil, nil, err - } - - segments, err = e.WAL.ClosedSegments() - if err != nil { - return nil, nil, err + if e.WAL != nil { + if err = e.WAL.CloseSegment(); err != nil { + return nil, nil, err + } + segments, err = e.WAL.ClosedSegments() + if err != nil { + return nil, nil, err + } } snapshot, err = e.Cache.Snapshot() @@ -1254,8 +1267,10 @@ func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, closedFiles []string, s // clear the snapshot from the in-memory cache, then the old WAL files e.Cache.ClearSnapshot(true) - if err := e.WAL.Remove(closedFiles); err != nil { - log.Info("Error removing closed WAL segments", zap.Error(err)) + if e.WAL != nil { + if err := e.WAL.Remove(closedFiles); err != nil { + log.Info("Error removing closed WAL segments", zap.Error(err)) + } } return nil @@ -1565,6 +1580,10 @@ func (e *Engine) fullCompactionStrategy(group CompactionGroup, optimize bool) *c // reloadCache reads the WAL segment files and loads them into the cache. func (e *Engine) reloadCache() error { + if e.WAL == nil { + return nil + } + now := time.Now() files, err := wal.SegmentFileNames(e.WAL.Path()) if err != nil { diff --git a/tsdb/tsm1/engine_delete_measurement.go b/tsdb/tsm1/engine_delete_measurement.go index 9a32886617..a74d6d4b75 100644 --- a/tsdb/tsm1/engine_delete_measurement.go +++ b/tsdb/tsm1/engine_delete_measurement.go @@ -101,8 +101,10 @@ func (e *Engine) DeleteBucket(name []byte, min, max int64) error { // Delete from the cache and WAL. e.Cache.DeleteRange(deleteKeys, min, max) - if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { - return err + if e.WAL != nil { + if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { + return err + } } // Now that all of the data is purged, we need to find if some keys are fully deleted diff --git a/tsdb/tsm1/temp_log.go b/tsdb/tsm1/temp_log.go deleted file mode 100644 index b69b0d82e2..0000000000 --- a/tsdb/tsm1/temp_log.go +++ /dev/null @@ -1,47 +0,0 @@ -package tsm1 - -import ( - "time" - - "go.uber.org/zap" -) - -// TODO(jeff): this only exists temporarily while we move the WAL into storage - -// Log describes an interface for a durable disk-based log. -type Log interface { - WithLogger(*zap.Logger) - - Open() error - Close() error - Path() string - - LastWriteTime() time.Time - DiskSizeBytes() int64 - - WriteMulti(values map[string][]Value) (int, error) - DeleteRange(keys [][]byte, min, max int64) (int, error) - - CloseSegment() error - ClosedSegments() ([]string, error) - Remove(files []string) error -} - -// NopWAL implements the Log interface and provides a no-op WAL implementation. -type NopWAL struct{} - -func (w NopWAL) WithLogger(*zap.Logger) {} - -func (w NopWAL) Open() error { return nil } -func (w NopWAL) Close() error { return nil } -func (w NopWAL) Path() string { return "" } - -func (w NopWAL) LastWriteTime() time.Time { return time.Time{} } -func (w NopWAL) DiskSizeBytes() int64 { return 0 } - -func (w NopWAL) WriteMulti(values map[string][]Value) (int, error) { return 0, nil } -func (w NopWAL) DeleteRange(keys [][]byte, min, max int64) (int, error) { return 0, nil } - -func (w NopWAL) CloseSegment() error { return nil } -func (w NopWAL) ClosedSegments() ([]string, error) { return nil, nil } -func (w NopWAL) Remove(files []string) error { return nil } From d2ddd48eeaa33852dc4bb5f8989ddb8e74eed1fe Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Wed, 16 Jan 2019 17:54:20 -0700 Subject: [PATCH 18/95] refactor: hook up metrics and wal to storage engine It turns out that LastModified and DiskSize are unused, and so it was easy to change to not care about the WAL. This hooks up metrics and starts the WAL again. --- storage/engine.go | 29 +++++- storage/wal/metrics.go | 22 +++++ storage/wal/wal.go | 24 ++++- tsdb/tsm1/engine.go | 124 +------------------------ tsdb/tsm1/engine_delete_measurement.go | 5 - tsdb/tsm1/engine_test.go | 59 ------------ 6 files changed, 75 insertions(+), 188 deletions(-) diff --git a/storage/engine.go b/storage/engine.go index cac720760b..10fe6a7a8f 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -128,17 +128,20 @@ func NewEngine(path string, c Config, options ...Option) *Engine { // Initialise Engine e.engine = tsm1.NewEngine(c.GetEnginePath(path), e.index, c.Engine, - tsm1.WithWAL(e.wal), tsm1.WithTraceLogging(c.TraceLoggingEnabled)) // Apply options. for _, option := range options { option(e) } + // Set default metrics labels. e.engine.SetDefaultMetricLabels(e.defaultMetricLabels) e.sfile.SetDefaultMetricLabels(e.defaultMetricLabels) e.index.SetDefaultMetricLabels(e.defaultMetricLabels) + if e.wal != nil { + e.wal.SetDefaultMetricLabels(e.defaultMetricLabels) + } return e } @@ -159,6 +162,9 @@ func (e *Engine) WithLogger(log *zap.Logger) { e.sfile.WithLogger(e.logger) e.index.WithLogger(e.logger) e.engine.WithLogger(e.logger) + if e.wal != nil { + e.wal.WithLogger(e.logger) + } e.retentionEnforcer.WithLogger(e.logger) } @@ -169,6 +175,7 @@ func (e *Engine) PrometheusCollectors() []prometheus.Collector { metrics = append(metrics, tsdb.PrometheusCollectors()...) metrics = append(metrics, tsi1.PrometheusCollectors()...) metrics = append(metrics, tsm1.PrometheusCollectors()...) + metrics = append(metrics, wal.PrometheusCollectors()...) metrics = append(metrics, e.retentionEnforcer.PrometheusCollectors()...) return metrics } @@ -191,6 +198,12 @@ func (e *Engine) Open() error { return err } + if e.wal != nil { + if err := e.wal.Open(); err != nil { + return err + } + } + if err := e.engine.Open(); err != nil { return err } @@ -266,15 +279,25 @@ func (e *Engine) Close() error { defer e.mu.Unlock() e.closing = nil - if err := e.sfile.Close(); err != nil { + if err := e.engine.Close(); err != nil { return err } + if e.wal != nil { + if err := e.wal.Close(); err != nil { + return err + } + } + if err := e.index.Close(); err != nil { return err } - return e.engine.Close() + if err := e.sfile.Close(); err != nil { + return err + } + + return nil } func (e *Engine) CreateSeriesCursor(ctx context.Context, req SeriesCursorRequest, cond influxql.Expr) (SeriesCursor, error) { diff --git a/storage/wal/metrics.go b/storage/wal/metrics.go index c6a648c01c..132a5f19a8 100644 --- a/storage/wal/metrics.go +++ b/storage/wal/metrics.go @@ -2,10 +2,32 @@ package wal import ( "sort" + "sync" "github.com/prometheus/client_golang/prometheus" ) +// The following package variables act as singletons, to be shared by all +// storage.Engine instantiations. This allows multiple WALs to be monitored +// within the same process. +var ( + wms *walMetrics // main metrics + mmu sync.RWMutex +) + +// PrometheusCollectors returns all the metrics associated with the tsdb package. +func PrometheusCollectors() []prometheus.Collector { + mmu.RLock() + defer mmu.RUnlock() + + var collectors []prometheus.Collector + if wms != nil { + collectors = append(collectors, wms.PrometheusCollectors()...) + } + + return collectors +} + // namespace is the leading part of all published metrics for the Storage service. const namespace = "storage" diff --git a/storage/wal/wal.go b/storage/wal/wal.go index 3be7ef61fd..0cdb7ea0d1 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -105,7 +105,9 @@ type WAL struct { // SegmentSize is the file size at which a segment file will be rotated SegmentSize int - tracker *walTracker + tracker *walTracker + defaultMetricLabels prometheus.Labels // N.B this must not be mutated after Open is called. + limiter limiter.Fixed } @@ -122,7 +124,6 @@ func NewWAL(path string) *WAL { limiter: limiter.NewFixed(defaultWaitingWALWrites), logger: logger, traceLogger: logger, - tracker: newWALTracker(newWALMetrics(nil), nil), } } @@ -148,6 +149,15 @@ func (l *WAL) WithLogger(log *zap.Logger) { } } +// SetDefaultMetricLabels sets the default labels for metrics on the engine. +// It must be called before the Engine is opened. +func (l *WAL) SetDefaultMetricLabels(labels prometheus.Labels) { + l.defaultMetricLabels = make(prometheus.Labels, len(labels)) + for k, v := range labels { + l.defaultMetricLabels[k] = v + } +} + // Path returns the directory the log was initialized with. func (l *WAL) Path() string { l.mu.RLock() @@ -160,6 +170,16 @@ func (l *WAL) Open() error { l.mu.Lock() defer l.mu.Unlock() + // Initialise metrics for trackers. + mmu.Lock() + if wms == nil { + wms = newWALMetrics(l.defaultMetricLabels) + } + mmu.Unlock() + + // Set the shared metrics for the tracker + l.tracker = newWALTracker(wms, l.defaultMetricLabels) + l.traceLogger.Info("tsm1 WAL starting", zap.Int("segment_size", l.SegmentSize)) l.traceLogger.Info("tsm1 WAL writing", zap.String("path", l.path)) diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index ec832404c1..ab9810b192 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -24,7 +24,6 @@ import ( "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/metrics" "github.com/influxdata/influxdb/query" - "github.com/influxdata/influxdb/storage/wal" "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxdb/tsdb/tsi1" "github.com/influxdata/influxql" @@ -79,13 +78,6 @@ const ( // an Engine. type EngineOption func(i *Engine) -// WithWAL sets the WAL for the Engine -var WithWAL = func(w *wal.WAL) EngineOption { - return func(e *Engine) { - e.WAL = w - } -} - // WithTraceLogging sets if trace logging is enabled for the engine. var WithTraceLogging = func(logging bool) EngineOption { return func(e *Engine) { @@ -128,7 +120,6 @@ type Engine struct { traceLogger *zap.Logger // Logger to be used when trace-logging is on. traceLogging bool - WAL *wal.WAL Cache *Cache Compactor *Compactor CompactionPlan CompactionPlanner @@ -472,31 +463,11 @@ func (e *Engine) SeriesN() int64 { return e.index.SeriesN() } -// LastModified returns the time when this shard was last modified. -func (e *Engine) LastModified() time.Time { - fsTime := e.FileStore.LastModified() - - if e.WAL != nil && e.WAL.LastWriteTime().After(fsTime) { - return e.WAL.LastWriteTime() - } - return fsTime -} - // MeasurementStats returns the current measurement stats for the engine. func (e *Engine) MeasurementStats() (MeasurementStats, error) { return e.FileStore.MeasurementStats() } -// DiskSize returns the total size in bytes of all TSM and WAL segments on disk. -func (e *Engine) DiskSize() int64 { - var walDiskSizeBytes int64 - if e.WAL != nil { - walDiskSizeBytes = e.WAL.DiskSizeBytes() - } - - return e.FileStore.DiskSizeBytes() + walDiskSizeBytes -} - func (e *Engine) initTrackers() { mmu.Lock() defer mmu.Unlock() @@ -526,20 +497,10 @@ func (e *Engine) Open() error { return err } - if e.WAL != nil { - if err := e.WAL.Open(); err != nil { - return err - } - } - if err := e.FileStore.Open(); err != nil { return err } - if err := e.reloadCache(); err != nil { - return err - } - e.Compactor.Open() if e.enableCompactionsOnOpen { @@ -562,12 +523,6 @@ func (e *Engine) Close() error { return err } - if e.WAL != nil { - if err := e.WAL.Close(); err != nil { - return err - } - } - return nil } @@ -579,9 +534,6 @@ func (e *Engine) WithLogger(log *zap.Logger) { e.traceLogger = e.logger } - if e.WAL != nil { - e.WAL.WithLogger(e.logger) - } e.FileStore.WithLogger(e.logger) } @@ -654,18 +606,10 @@ func (e *Engine) WritePoints(points []models.Point) error { e.mu.RLock() defer e.mu.RUnlock() - // first try to write to the cache if err := e.Cache.WriteMulti(values); err != nil { return err } - // Then make the write durable in the cache. - if e.WAL != nil { - if _, err := e.WAL.WriteMulti(values); err != nil { - return err - } - } - return nil } @@ -875,13 +819,6 @@ func (e *Engine) deleteSeriesRange(seriesKeys [][]byte, min, max int64) error { e.Cache.DeleteRange(deleteKeys, min, max) - // delete from the WAL - if e.WAL != nil { - if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { - return err - } - } - // The series are deleted on disk, but the index may still say they exist. // Depending on the the min,max time passed in, the series may or not actually // exists now. To reconcile the index, we walk the series keys that still exists @@ -1201,24 +1138,9 @@ func (e *Engine) WriteSnapshot() error { logEnd() }() - closedFiles, snapshot, err := func() (segments []string, snapshot *Cache, err error) { - e.mu.Lock() - defer e.mu.Unlock() - - if e.WAL != nil { - if err = e.WAL.CloseSegment(); err != nil { - return nil, nil, err - } - segments, err = e.WAL.ClosedSegments() - if err != nil { - return nil, nil, err - } - } - - snapshot, err = e.Cache.Snapshot() - return segments, snapshot, err - }() - + e.mu.Lock() + snapshot, err := e.Cache.Snapshot() + e.mu.Unlock() if err != nil { return err } @@ -1237,11 +1159,11 @@ func (e *Engine) WriteSnapshot() error { zap.String("path", e.path), zap.Duration("duration", time.Since(dedup))) - return e.writeSnapshotAndCommit(log, closedFiles, snapshot) + return e.writeSnapshotAndCommit(log, snapshot) } // writeSnapshotAndCommit will write the passed cache to a new TSM file and remove the closed WAL segments. -func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, closedFiles []string, snapshot *Cache) (err error) { +func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, snapshot *Cache) (err error) { defer func() { if err != nil { e.Cache.ClearSnapshot(false) @@ -1267,12 +1189,6 @@ func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, closedFiles []string, s // clear the snapshot from the in-memory cache, then the old WAL files e.Cache.ClearSnapshot(true) - if e.WAL != nil { - if err := e.WAL.Remove(closedFiles); err != nil { - log.Info("Error removing closed WAL segments", zap.Error(err)) - } - } - return nil } @@ -1578,36 +1494,6 @@ func (e *Engine) fullCompactionStrategy(group CompactionGroup, optimize bool) *c return s } -// reloadCache reads the WAL segment files and loads them into the cache. -func (e *Engine) reloadCache() error { - if e.WAL == nil { - return nil - } - - now := time.Now() - files, err := wal.SegmentFileNames(e.WAL.Path()) - if err != nil { - return err - } - - limit := e.Cache.MaxSize() - defer func() { - e.Cache.SetMaxSize(limit) - }() - - // Disable the max size during loading - e.Cache.SetMaxSize(0) - - loader := NewCacheLoader(files) - loader.WithLogger(e.logger) - if err := loader.Load(e.Cache); err != nil { - return err - } - - e.traceLogger.Info("Reloaded WAL cache", zap.String("path", e.WAL.Path()), zap.Duration("duration", time.Since(now))) - return nil -} - // cleanup removes all temp files and dirs that exist on disk. This is should only be run at startup to avoid // removing tmp files that are still in use. func (e *Engine) cleanup() error { diff --git a/tsdb/tsm1/engine_delete_measurement.go b/tsdb/tsm1/engine_delete_measurement.go index a74d6d4b75..466716fc46 100644 --- a/tsdb/tsm1/engine_delete_measurement.go +++ b/tsdb/tsm1/engine_delete_measurement.go @@ -101,11 +101,6 @@ func (e *Engine) DeleteBucket(name []byte, min, max int64) error { // Delete from the cache and WAL. e.Cache.DeleteRange(deleteKeys, min, max) - if e.WAL != nil { - if _, err := e.WAL.DeleteRange(deleteKeys, min, max); err != nil { - return err - } - } // Now that all of the data is purged, we need to find if some keys are fully deleted // and if so, remove them from the index. diff --git a/tsdb/tsm1/engine_test.go b/tsdb/tsm1/engine_test.go index 5b6e4c0149..a1ab2674bb 100644 --- a/tsdb/tsm1/engine_test.go +++ b/tsdb/tsm1/engine_test.go @@ -630,65 +630,6 @@ func TestEngine_DeleteSeriesRange_OutsideTime(t *testing.T) { } } -func TestEngine_LastModified(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode") - } - - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 1000000000") - p2 := MustParsePointString("cpu,host=B value=1.2 2000000000") - p3 := MustParsePointString("cpu,host=A sum=1.3 3000000000") - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - e.SetEnabled(false) - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - lm := e.LastModified() - if lm.IsZero() { - t.Fatalf("expected non-zero time, got %v", lm.UTC()) - } - e.SetEnabled(true) - - // Artificial sleep added due to filesystems caching the mod time - // of files. This prevents the WAL last modified time from being - // returned and newer than the filestore's mod time. - time.Sleep(2 * time.Second) // Covers most filesystems. - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - lm2 := e.LastModified() - - if got, exp := lm.Equal(lm2), false; exp != got { - t.Fatalf("expected time change, got %v, exp %v: %s == %s", got, exp, lm.String(), lm2.String()) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A")}} - if err := e.DeleteSeriesRange(itr, math.MinInt64, math.MaxInt64); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - lm3 := e.LastModified() - if got, exp := lm2.Equal(lm3), false; exp != got { - t.Fatalf("expected time change, got %v, exp %v", got, exp) - } -} - func TestEngine_SnapshotsDisabled(t *testing.T) { sfile := MustOpenSeriesFile() defer sfile.Close() From 8dbd98ccbe34ce1df8315bbd961b0d3d446a4817 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Wed, 16 Jan 2019 18:28:57 -0700 Subject: [PATCH 19/95] refactor: change the way the engine opens and closes and reload the cache Open and Close now proceed as best as they are able to in the presence of errors and clean up appropriately. --- storage/engine.go | 89 ++++++++++++++++++++++++++-------------------- storage/opener.go | 61 +++++++++++++++++++++++++++++++ storage/wal/wal.go | 19 ++++++++-- 3 files changed, 128 insertions(+), 41 deletions(-) create mode 100644 storage/opener.go diff --git a/storage/engine.go b/storage/engine.go index 10fe6a7a8f..5d26c7ef68 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -120,11 +120,10 @@ func NewEngine(path string, c Config, options ...Option) *Engine { tsi1.WithPath(c.GetIndexPath(path))) // Initialize WAL - if c.WAL.Enabled { - e.wal = wal.NewWAL(c.GetWALPath(path)) - e.wal.WithFsyncDelay(time.Duration(c.WAL.FsyncDelay)) - e.wal.EnableTraceLogging(c.TraceLoggingEnabled) - } + e.wal = wal.NewWAL(c.GetWALPath(path)) + e.wal.WithFsyncDelay(time.Duration(c.WAL.FsyncDelay)) + e.wal.EnableTraceLogging(c.TraceLoggingEnabled) + e.wal.SetEnabled(c.WAL.Enabled) // Initialise Engine e.engine = tsm1.NewEngine(c.GetEnginePath(path), e.index, c.Engine, @@ -162,9 +161,7 @@ func (e *Engine) WithLogger(log *zap.Logger) { e.sfile.WithLogger(e.logger) e.index.WithLogger(e.logger) e.engine.WithLogger(e.logger) - if e.wal != nil { - e.wal.WithLogger(e.logger) - } + e.wal.WithLogger(e.logger) e.retentionEnforcer.WithLogger(e.logger) } @@ -182,7 +179,7 @@ func (e *Engine) PrometheusCollectors() []prometheus.Collector { // Open opens the store and all underlying resources. It returns an error if // any of the underlying systems fail to open. -func (e *Engine) Open() error { +func (e *Engine) Open() (err error) { e.mu.Lock() defer e.mu.Unlock() @@ -190,23 +187,20 @@ func (e *Engine) Open() error { return nil // Already open } - if err := e.sfile.Open(); err != nil { + // Open the services in order and clean up if any fail. + var oh openHelper + oh.Open(e.sfile) + oh.Open(e.index) + oh.Open(e.wal) + oh.Open(e.engine) + if err := oh.Done(); err != nil { return err } - if err := e.index.Open(); err != nil { + if err := e.reloadCache(); err != nil { return err } - if e.wal != nil { - if err := e.wal.Open(); err != nil { - return err - } - } - - if err := e.engine.Open(); err != nil { - return err - } e.engine.SetCompactionsEnabled(true) // TODO(edd):is this needed? e.closing = make(chan struct{}) @@ -219,6 +213,36 @@ func (e *Engine) Open() error { return nil } +// reloadCache reads the WAL segment files and loads them into the cache. +func (e *Engine) reloadCache() error { + if !e.config.WAL.Enabled { + return nil + } + + now := time.Now() + files, err := wal.SegmentFileNames(e.wal.Path()) + if err != nil { + return err + } + + limit := e.engine.Cache.MaxSize() + defer func() { + e.engine.Cache.SetMaxSize(limit) + }() + + // Disable the max size during loading + e.engine.Cache.SetMaxSize(0) + + loader := tsm1.NewCacheLoader(files) + loader.WithLogger(e.logger) + if err := loader.Load(e.engine.Cache); err != nil { + return err + } + + e.logger.Info("Reloaded WAL cache", zap.String("path", e.wal.Path()), zap.Duration("duration", time.Since(now))) + return nil +} + // runRetentionEnforcer runs the retention enforcer in a separate goroutine. // // Currently this just runs on an interval, but in the future we will add the @@ -279,25 +303,12 @@ func (e *Engine) Close() error { defer e.mu.Unlock() e.closing = nil - if err := e.engine.Close(); err != nil { - return err - } - - if e.wal != nil { - if err := e.wal.Close(); err != nil { - return err - } - } - - if err := e.index.Close(); err != nil { - return err - } - - if err := e.sfile.Close(); err != nil { - return err - } - - return nil + var ch closeHelper + ch.Close(e.engine) + ch.Close(e.wal) + ch.Close(e.index) + ch.Close(e.sfile) + return ch.Done() } func (e *Engine) CreateSeriesCursor(ctx context.Context, req SeriesCursorRequest, cond influxql.Expr) (SeriesCursor, error) { diff --git a/storage/opener.go b/storage/opener.go new file mode 100644 index 0000000000..024d872f5a --- /dev/null +++ b/storage/opener.go @@ -0,0 +1,61 @@ +package storage + +import ( + "io" +) + +// opener is something that can be opened and closed. +type opener interface { + Open() error + io.Closer +} + +// openHelper is a helper to abstract the pattern of opening multiple things, +// exiting early if any open fails, and closing any of the opened things +// in the case of failure. +type openHelper struct { + opened []io.Closer + err error +} + +// Open attempts to open the opener. If an error has happened already +// then no calls are made to the opener. +func (o *openHelper) Open(op opener) { + if o.err != nil { + return + } + o.err = op.Open() + if o.err == nil { + o.opened = append(o.opened, op) + } +} + +// Done returns the error of the first open and closes in reverse +// order any opens that have already happened if there was an error. +func (o *openHelper) Done() error { + if o.err == nil { + return nil + } + for i := len(o.opened) - 1; i >= 0; i-- { + o.opened[i].Close() + } + return o.err +} + +// closeHelper is a helper to abstract the pattern of closing multiple +// things and keeping track of the first encountered error. +type closeHelper struct { + err error +} + +// Close closes the closer and keeps track of the first error. +func (c *closeHelper) Close(cl io.Closer) { + if err := cl.Close(); c.err == nil { + c.err = err + } +} + +// Done returns the first error. +func (c *closeHelper) Done() error { + return c.err +} diff --git a/storage/wal/wal.go b/storage/wal/wal.go index 0cdb7ea0d1..c303726443 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -82,7 +82,8 @@ type WAL struct { mu sync.RWMutex lastWriteTime time.Time - path string + path string + enabled bool // write variables currentSegmentID int @@ -115,7 +116,8 @@ type WAL struct { func NewWAL(path string) *WAL { logger := zap.NewNop() return &WAL{ - path: path, + path: path, + enabled: true, // these options should be overriden by any options in the config SegmentSize: DefaultSegmentSize, @@ -140,6 +142,11 @@ func (l *WAL) WithFsyncDelay(delay time.Duration) { l.syncDelay = delay } +// SetEnabled sets if the WAL is enabled and should be called before the WAL is opened. +func (l *WAL) SetEnabled(enabled bool) { + l.enabled = enabled +} + // WithLogger sets the WAL's logger. func (l *WAL) WithLogger(log *zap.Logger) { l.logger = log.With(zap.String("service", "wal")) @@ -170,6 +177,10 @@ func (l *WAL) Open() error { l.mu.Lock() defer l.mu.Unlock() + if !l.enabled { + return nil + } + // Initialise metrics for trackers. mmu.Lock() if wms == nil { @@ -528,6 +539,10 @@ func (l *WAL) Close() error { l.mu.Lock() defer l.mu.Unlock() + if !l.enabled { + return nil + } + l.once.Do(func() { // Close, but don't set to nil so future goroutines can still be signaled l.traceLogger.Info("Closing WAL file", zap.String("path", l.path)) From 2f469375273288f07f0fdd35ba8bc8de745c342e Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Thu, 17 Jan 2019 11:18:02 -0700 Subject: [PATCH 20/95] refactor: move value package up to tsdb --- storage/wal/wal.go | 3 +-- storage/wal/wal_test.go | 2 +- tsdb/tsm1/encoding.go | 2 +- tsdb/{tsm1 => }/value/value.go | 0 4 files changed, 3 insertions(+), 4 deletions(-) rename tsdb/{tsm1 => }/value/value.go (100%) diff --git a/storage/wal/wal.go b/storage/wal/wal.go index c303726443..7e7b566a62 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -17,11 +17,10 @@ import ( "sync/atomic" "time" - "github.com/influxdata/influxdb/tsdb/tsm1/value" - "github.com/golang/snappy" "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/pool" + "github.com/influxdata/influxdb/tsdb/value" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) diff --git a/storage/wal/wal_test.go b/storage/wal/wal_test.go index 7b3a638d96..b7590cf98d 100644 --- a/storage/wal/wal_test.go +++ b/storage/wal/wal_test.go @@ -9,7 +9,7 @@ import ( "github.com/golang/snappy" "github.com/influxdata/influxdb/pkg/slices" - "github.com/influxdata/influxdb/tsdb/tsm1/value" + "github.com/influxdata/influxdb/tsdb/value" ) func TestWALWriter_WriteMulti_Single(t *testing.T) { diff --git a/tsdb/tsm1/encoding.go b/tsdb/tsm1/encoding.go index ad63b2b14f..d6eecfd272 100644 --- a/tsdb/tsm1/encoding.go +++ b/tsdb/tsm1/encoding.go @@ -6,7 +6,7 @@ import ( "runtime" "github.com/influxdata/influxdb/pkg/pool" - "github.com/influxdata/influxdb/tsdb/tsm1/value" + "github.com/influxdata/influxdb/tsdb/value" "github.com/influxdata/influxql" ) diff --git a/tsdb/tsm1/value/value.go b/tsdb/value/value.go similarity index 100% rename from tsdb/tsm1/value/value.go rename to tsdb/value/value.go From a3e66755ca017ea54f2cce9d4a3cbd8efe1dd770 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Thu, 17 Jan 2019 14:34:04 -0700 Subject: [PATCH 21/95] refactor: move value aliases into its own file --- tsdb/tsm1/encoding.go | 50 ------------------------------------------- tsdb/tsm1/value.go | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 50 deletions(-) create mode 100644 tsdb/tsm1/value.go diff --git a/tsdb/tsm1/encoding.go b/tsdb/tsm1/encoding.go index d6eecfd272..a176f42856 100644 --- a/tsdb/tsm1/encoding.go +++ b/tsdb/tsm1/encoding.go @@ -6,7 +6,6 @@ import ( "runtime" "github.com/influxdata/influxdb/pkg/pool" - "github.com/influxdata/influxdb/tsdb/value" "github.com/influxdata/influxql" ) @@ -31,55 +30,6 @@ const ( encodedBlockHeaderSize = 1 ) -// -// These aliases and functions forward to the value package so that other packages can depend -// on them without pulling in tsm1. Specifically, this is due to moving the WAL code out of -// this package and into the storage package. When we have a better value implementation across -// the board, we should be able to remove these. -// - -type ( - Value = value.Value - - IntegerValue = value.IntegerValue - UnsignedValue = value.UnsignedValue - FloatValue = value.FloatValue - BooleanValue = value.BooleanValue - StringValue = value.StringValue -) - -func NewValue(t int64, v interface{}) Value { return value.NewValue(t, v) } - -// NewRawIntegerValue returns a new integer value. -func NewRawIntegerValue(t int64, v int64) IntegerValue { return value.NewRawIntegerValue(t, v) } - -// NewRawUnsignedValue returns a new unsigned integer value. -func NewRawUnsignedValue(t int64, v uint64) UnsignedValue { return value.NewRawUnsignedValue(t, v) } - -// NewRawFloatValue returns a new float value. -func NewRawFloatValue(t int64, v float64) FloatValue { return value.NewRawFloatValue(t, v) } - -// NewRawBooleanValue returns a new boolean value. -func NewRawBooleanValue(t int64, v bool) BooleanValue { return value.NewRawBooleanValue(t, v) } - -// NewRawStringValue returns a new string value. -func NewRawStringValue(t int64, v string) StringValue { return value.NewRawStringValue(t, v) } - -// NewIntegerValue returns a new integer value. -func NewIntegerValue(t int64, v int64) Value { return value.NewIntegerValue(t, v) } - -// NewUnsignedValue returns a new unsigned integer value. -func NewUnsignedValue(t int64, v uint64) Value { return value.NewUnsignedValue(t, v) } - -// NewFloatValue returns a new float value. -func NewFloatValue(t int64, v float64) Value { return value.NewFloatValue(t, v) } - -// NewBooleanValue returns a new boolean value. -func NewBooleanValue(t int64, v bool) Value { return value.NewBooleanValue(t, v) } - -// NewStringValue returns a new string value. -func NewStringValue(t int64, v string) Value { return value.NewStringValue(t, v) } - func init() { // Prime the pools with one encoder/decoder for each available CPU. vals := make([]interface{}, 0, runtime.NumCPU()) diff --git a/tsdb/tsm1/value.go b/tsdb/tsm1/value.go new file mode 100644 index 0000000000..905a0b4cdd --- /dev/null +++ b/tsdb/tsm1/value.go @@ -0,0 +1,45 @@ +package tsm1 + +import "github.com/influxdata/influxdb/tsdb/value" + +type ( + Value = value.Value + IntegerValue = value.IntegerValue + UnsignedValue = value.UnsignedValue + FloatValue = value.FloatValue + BooleanValue = value.BooleanValue + StringValue = value.StringValue +) + +// NewValue returns a new Value with the underlying type dependent on value. +func NewValue(t int64, v interface{}) Value { return value.NewValue(t, v) } + +// NewRawIntegerValue returns a new integer value. +func NewRawIntegerValue(t int64, v int64) IntegerValue { return value.NewRawIntegerValue(t, v) } + +// NewRawUnsignedValue returns a new unsigned integer value. +func NewRawUnsignedValue(t int64, v uint64) UnsignedValue { return value.NewRawUnsignedValue(t, v) } + +// NewRawFloatValue returns a new float value. +func NewRawFloatValue(t int64, v float64) FloatValue { return value.NewRawFloatValue(t, v) } + +// NewRawBooleanValue returns a new boolean value. +func NewRawBooleanValue(t int64, v bool) BooleanValue { return value.NewRawBooleanValue(t, v) } + +// NewRawStringValue returns a new string value. +func NewRawStringValue(t int64, v string) StringValue { return value.NewRawStringValue(t, v) } + +// NewIntegerValue returns a new integer value. +func NewIntegerValue(t int64, v int64) Value { return value.NewIntegerValue(t, v) } + +// NewUnsignedValue returns a new unsigned integer value. +func NewUnsignedValue(t int64, v uint64) Value { return value.NewUnsignedValue(t, v) } + +// NewFloatValue returns a new float value. +func NewFloatValue(t int64, v float64) Value { return value.NewFloatValue(t, v) } + +// NewBooleanValue returns a new boolean value. +func NewBooleanValue(t int64, v bool) Value { return value.NewBooleanValue(t, v) } + +// NewStringValue returns a new string value. +func NewStringValue(t int64, v string) Value { return value.NewStringValue(t, v) } From 2989936d5a277c1b9b41f3eac09a8cd82a90a982 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Sat, 19 Jan 2019 14:16:52 -0700 Subject: [PATCH 22/95] refactor: write to the WAL again --- storage/engine.go | 31 +++++++++++++++++----- storage/wal/wal.go | 6 ++++- tsdb/tsm1/engine.go | 59 +++++++---------------------------------- tsdb/tsm1/value.go | 64 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 58 deletions(-) diff --git a/storage/engine.go b/storage/engine.go index 5d26c7ef68..5b06f33d7e 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -383,19 +383,38 @@ func (e *Engine) WritePoints(points []models.Point) error { return ErrEngineClosed } - // Add new series to the index and series file. Check for partial writes. + // TODO(jeff): keep track of the values in the collection so that partail write + // errors get tracked all the way. Right now, the engine doesn't drop any values + // but if it ever did, the errors could end up missing some data. + + // Add the write to the WAL to be replayed if there is a crash or shutdown. + values, err := tsm1.PointsToValues(collection.Points) + if err != nil { + return err + } + if _, err := e.wal.WriteMulti(values); err != nil { + return err + } + + // Add new series to the index and series file. if err := e.index.CreateSeriesListIfNotExists(collection); err != nil { - // ignore PartialWriteErrors. The collection captures it. - // TODO(edd/jeff): should we just remove PartialWriteError from the index then? - if _, ok := err.(tsdb.PartialWriteError); !ok { + return err + } + + // If there was a PartialWriteError already, that means the values may contain + // more than the points so we need to recreate them. + if collection.PartialWriteError() != nil { + values, err = tsm1.PointsToValues(points) + if err != nil { return err } } - // Write the points to the cache and WAL. - if err := e.engine.WritePoints(collection.Points); err != nil { + // Write the values to the engine. + if err := e.engine.WriteValues(values); err != nil { return err } + return collection.PartialWriteError() } diff --git a/storage/wal/wal.go b/storage/wal/wal.go index 7e7b566a62..c295133bbc 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -314,8 +314,12 @@ func (l *WAL) sync() { // WriteMulti writes the given values to the WAL. It returns the WAL segment ID to // which the points were written. If an error is returned the segment ID should -// be ignored. +// be ignored. If the WAL is disabled, -1 and nil is returned. func (l *WAL) WriteMulti(values map[string][]value.Value) (int, error) { + if !l.enabled { + return -1, nil + } + entry := &WriteWALEntry{ Values: values, } diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index ab9810b192..66edf9dec5 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -550,59 +550,18 @@ func (e *Engine) Free() error { return e.FileStore.Free() } -// WritePoints writes metadata and point data into the engine. -// It returns an error if new points are added to an existing key. +// WritePoints saves the set of points in the engine. func (e *Engine) WritePoints(points []models.Point) error { - values := make(map[string][]Value, len(points)) - var ( - keyBuf []byte - baseLen int - ) - - for _, p := range points { - keyBuf = append(keyBuf[:0], p.Key()...) - keyBuf = append(keyBuf, keyFieldSeparator...) - baseLen = len(keyBuf) - iter := p.FieldIterator() - t := p.Time().UnixNano() - for iter.Next() { - keyBuf = append(keyBuf[:baseLen], iter.FieldKey()...) - - var v Value - switch iter.Type() { - case models.Float: - fv, err := iter.FloatValue() - if err != nil { - return err - } - v = NewFloatValue(t, fv) - case models.Integer: - iv, err := iter.IntegerValue() - if err != nil { - return err - } - v = NewIntegerValue(t, iv) - case models.Unsigned: - iv, err := iter.UnsignedValue() - if err != nil { - return err - } - v = NewUnsignedValue(t, iv) - case models.String: - v = NewStringValue(t, iter.StringValue()) - case models.Boolean: - bv, err := iter.BooleanValue() - if err != nil { - return err - } - v = NewBooleanValue(t, bv) - default: - return fmt.Errorf("unknown field type for %s: %s", string(iter.FieldKey()), p.String()) - } - values[string(keyBuf)] = append(values[string(keyBuf)], v) - } + values, err := PointsToValues(points) + if err != nil { + return err } + return e.WriteValues(values) +} + +// WriteValues saves the set of values in the engine. +func (e *Engine) WriteValues(values map[string][]Value) error { e.mu.RLock() defer e.mu.RUnlock() diff --git a/tsdb/tsm1/value.go b/tsdb/tsm1/value.go index 905a0b4cdd..f42a3d521a 100644 --- a/tsdb/tsm1/value.go +++ b/tsdb/tsm1/value.go @@ -1,6 +1,11 @@ package tsm1 -import "github.com/influxdata/influxdb/tsdb/value" +import ( + "fmt" + + "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/tsdb/value" +) type ( Value = value.Value @@ -43,3 +48,60 @@ func NewBooleanValue(t int64, v bool) Value { return value.NewBooleanValue(t, v) // NewStringValue returns a new string value. func NewStringValue(t int64, v string) Value { return value.NewStringValue(t, v) } + +// PointsToValues takes in a slice of points and returns it as a map of series key to +// values. It returns an error if any of the points could not be converted. +func PointsToValues(points []models.Point) (map[string][]Value, error) { + values := make(map[string][]Value, len(points)) + var ( + keyBuf []byte + baseLen int + ) + + for _, p := range points { + keyBuf = append(keyBuf[:0], p.Key()...) + keyBuf = append(keyBuf, keyFieldSeparator...) + baseLen = len(keyBuf) + iter := p.FieldIterator() + t := p.Time().UnixNano() + for iter.Next() { + keyBuf = append(keyBuf[:baseLen], iter.FieldKey()...) + + var v Value + switch iter.Type() { + case models.Float: + fv, err := iter.FloatValue() + if err != nil { + return nil, err + } + v = NewFloatValue(t, fv) + case models.Integer: + iv, err := iter.IntegerValue() + if err != nil { + return nil, err + } + v = NewIntegerValue(t, iv) + case models.Unsigned: + iv, err := iter.UnsignedValue() + if err != nil { + return nil, err + } + v = NewUnsignedValue(t, iv) + case models.String: + v = NewStringValue(t, iter.StringValue()) + case models.Boolean: + bv, err := iter.BooleanValue() + if err != nil { + return nil, err + } + v = NewBooleanValue(t, bv) + default: + return nil, fmt.Errorf("unknown field type for %s: %s", + string(iter.FieldKey()), p.String()) + } + values[string(keyBuf)] = append(values[string(keyBuf)], v) + } + } + + return values, nil +} From 6deced1215518362fc6ab577627948ab07b3ba0f Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Sat, 19 Jan 2019 14:36:41 -0700 Subject: [PATCH 23/95] refactor: make the WAL part of snapshots again --- storage/engine.go | 38 +++++++++++++++++++++--- storage/wal/wal.go | 15 ++++++++++ tsdb/tsm1/engine.go | 71 ++++++++++++++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 24 deletions(-) diff --git a/storage/engine.go b/storage/engine.go index 5b06f33d7e..f983a993fe 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -127,7 +127,8 @@ func NewEngine(path string, c Config, options ...Option) *Engine { // Initialise Engine e.engine = tsm1.NewEngine(c.GetEnginePath(path), e.index, c.Engine, - tsm1.WithTraceLogging(c.TraceLoggingEnabled)) + tsm1.WithTraceLogging(c.TraceLoggingEnabled), + tsm1.WithSnapshotter(e)) // Apply options. for _, option := range options { @@ -335,9 +336,7 @@ func (e *Engine) CreateCursorIterator(ctx context.Context) (tsdb.CursorIterator, // WritePoints will however determine if there are any field type conflicts, and // return an appropriate error in that case. func (e *Engine) WritePoints(points []models.Point) error { - collection := tsdb.NewSeriesCollection(points) - - j := 0 + collection, j := tsdb.NewSeriesCollection(points), 0 for iter := collection.Iterator(); iter.Next(); { tags := iter.Tags() @@ -418,6 +417,37 @@ func (e *Engine) WritePoints(points []models.Point) error { return collection.PartialWriteError() } +// AcquireSegments closes the current WAL segment, gets the set of all the currently closed +// segments, and calls the callback. It does all of this under the lock on the engine. +func (e *Engine) AcquireSegments(fn func(segs []string) error) error { + e.mu.Lock() + defer e.mu.Unlock() + + if err := e.wal.CloseSegment(); err != nil { + return err + } + + segments, err := e.wal.ClosedSegments() + if err != nil { + return err + } + + return fn(segments) +} + +// CommitSegments calls the callback and if that does not return an error, removes the segment +// files from the WAL. It does all of this under the lock on the engine. +func (e *Engine) CommitSegments(segs []string, fn func() error) error { + e.mu.Lock() + defer e.mu.Unlock() + + if err := fn(); err != nil { + return err + } + + return e.wal.Remove(segs) +} + // DeleteBucket deletes an entire bucket from the storage engine. func (e *Engine) DeleteBucket(orgID, bucketID platform.ID) error { e.mu.RLock() diff --git a/storage/wal/wal.go b/storage/wal/wal.go index c295133bbc..f3aa6be757 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -336,8 +336,13 @@ func (l *WAL) WriteMulti(values map[string][]value.Value) (int, error) { // ClosedSegments returns a slice of the names of the closed segment files. func (l *WAL) ClosedSegments() ([]string, error) { + if !l.enabled { + return nil, nil + } + l.mu.RLock() defer l.mu.RUnlock() + // Not loading files from disk so nothing to do if l.path == "" { return nil, nil @@ -368,8 +373,13 @@ func (l *WAL) ClosedSegments() ([]string, error) { // Remove deletes the given segment file paths from disk and cleans up any associated objects. func (l *WAL) Remove(files []string) error { + if !l.enabled { + return nil + } + l.mu.Lock() defer l.mu.Unlock() + for _, fn := range files { l.traceLogger.Info("Removing WAL file", zap.String("path", fn)) os.RemoveAll(fn) @@ -489,8 +499,13 @@ func (l *WAL) rollSegment() error { // CloseSegment closes the current segment if it is non-empty and opens a new one. func (l *WAL) CloseSegment() error { + if !l.enabled { + return nil + } + l.mu.Lock() defer l.mu.Unlock() + if l.currentSegmentWriter == nil || l.currentSegmentWriter.size > 0 { if err := l.newSegmentFile(); err != nil { // A drop database or RP call could trigger this error if writes were in-flight diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index 66edf9dec5..34ea98b3c3 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -79,20 +79,40 @@ const ( type EngineOption func(i *Engine) // WithTraceLogging sets if trace logging is enabled for the engine. -var WithTraceLogging = func(logging bool) EngineOption { +func WithTraceLogging(logging bool) EngineOption { return func(e *Engine) { e.FileStore.enableTraceLogging(logging) } } // WithCompactionPlanner sets the compaction planner for the engine. -var WithCompactionPlanner = func(planner CompactionPlanner) EngineOption { +func WithCompactionPlanner(planner CompactionPlanner) EngineOption { return func(e *Engine) { planner.SetFileStore(e.FileStore) e.CompactionPlan = planner } } +// Snapshotter allows upward signaling of the tsm1 engine to the storage engine. Hopefully +// it can be removed one day. The weird interface is due to the weird inversion of locking +// that has to happen. +type Snapshotter interface { + AcquireSegments(func(segments []string) error) error + CommitSegments(segments []string, fn func() error) error +} + +type noSnapshotter struct{} + +func (noSnapshotter) AcquireSegments(fn func([]string) error) error { return fn(nil) } +func (noSnapshotter) CommitSegments(_ []string, fn func() error) error { return fn() } + +// WithSnapshotter sets the callbacks for the engine to use when creating snapshots. +func WithSnapshotter(snapshotter Snapshotter) EngineOption { + return func(e *Engine) { + e.snapshotter = snapshotter + } +} + // Engine represents a storage engine with compressed blocks. type Engine struct { mu sync.RWMutex @@ -148,7 +168,8 @@ type Engine struct { // Limiter for concurrent compactions. compactionLimiter limiter.Fixed - scheduler *scheduler + scheduler *scheduler + snapshotter Snapshotter } // NewEngine returns a new instance of Engine. @@ -207,6 +228,7 @@ func NewEngine(path string, idx *tsi1.Index, config Config, options ...EngineOpt formatFileName: DefaultFormatFileName, compactionLimiter: limiter.NewFixed(maxCompactions), scheduler: newScheduler(maxCompactions), + snapshotter: new(noSnapshotter), } for _, option := range options { @@ -1097,10 +1119,18 @@ func (e *Engine) WriteSnapshot() error { logEnd() }() - e.mu.Lock() - snapshot, err := e.Cache.Snapshot() - e.mu.Unlock() - if err != nil { + var ( + snapshot *Cache + segments []string + ) + if err := e.snapshotter.AcquireSegments(func(segs []string) (err error) { + segments = segs + + e.mu.Lock() + snapshot, err = e.Cache.Snapshot() + e.mu.Unlock() + return err + }); err != nil { return err } @@ -1118,11 +1148,11 @@ func (e *Engine) WriteSnapshot() error { zap.String("path", e.path), zap.Duration("duration", time.Since(dedup))) - return e.writeSnapshotAndCommit(log, snapshot) + return e.writeSnapshotAndCommit(log, snapshot, segments) } // writeSnapshotAndCommit will write the passed cache to a new TSM file and remove the closed WAL segments. -func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, snapshot *Cache) (err error) { +func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, snapshot *Cache, segments []string) (err error) { defer func() { if err != nil { e.Cache.ClearSnapshot(false) @@ -1136,19 +1166,20 @@ func (e *Engine) writeSnapshotAndCommit(log *zap.Logger, snapshot *Cache) (err e return err } - e.mu.RLock() - defer e.mu.RUnlock() + return e.snapshotter.CommitSegments(segments, func() error { + e.mu.RLock() + defer e.mu.RUnlock() - // update the file store with these new files - if err := e.FileStore.Replace(nil, newFiles); err != nil { - log.Info("Error adding new TSM files from snapshot", zap.Error(err)) - return err - } + // update the file store with these new files + if err := e.FileStore.Replace(nil, newFiles); err != nil { + log.Info("Error adding new TSM files from snapshot", zap.Error(err)) + return err + } - // clear the snapshot from the in-memory cache, then the old WAL files - e.Cache.ClearSnapshot(true) - - return nil + // clear the snapshot from the in-memory cache + e.Cache.ClearSnapshot(true) + return nil + }) } // compactCache continually checks if the WAL cache should be written to disk. From aa12144fc79cd746720c88a260814e5a6fbe0bbd Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Sun, 20 Jan 2019 16:03:06 -0700 Subject: [PATCH 24/95] storage: replay the WAL through the whole engine --- models/points.go | 9 +++ storage/engine.go | 113 +++++++++++++++++++++++++++++++------ storage/series_iterator.go | 46 +++++++++++++++ tsdb/tsm1/value.go | 16 ++++++ 4 files changed, 168 insertions(+), 16 deletions(-) create mode 100644 storage/series_iterator.go diff --git a/models/points.go b/models/points.go index a11b2df18e..dd985a6c4a 100644 --- a/models/points.go +++ b/models/points.go @@ -1353,6 +1353,15 @@ func NewPoint(name string, tags Tags, fields Fields, t time.Time) (Point, error) }, nil } +// NewPointFromSeries returns a Point given the serialized key, some fields, and a time. +func NewPointFromSeries(key []byte, fields Fields, t time.Time) Point { + return &point{ + key: key, + time: t, + fields: fields.MarshalBinary(), + } +} + // pointKey checks some basic requirements for valid points, and returns the // key, along with an possible error. func pointKey(measurement string, tags Tags, fields Fields, t time.Time) ([]byte, error) { diff --git a/storage/engine.go b/storage/engine.go index f983a993fe..06e774ec54 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "math" + "os" "sync" "time" @@ -16,6 +17,7 @@ import ( "github.com/influxdata/influxdb/tsdb" "github.com/influxdata/influxdb/tsdb/tsi1" "github.com/influxdata/influxdb/tsdb/tsm1" + "github.com/influxdata/influxdb/tsdb/value" "github.com/influxdata/influxql" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" @@ -226,24 +228,86 @@ func (e *Engine) reloadCache() error { return err } - limit := e.engine.Cache.MaxSize() - defer func() { - e.engine.Cache.SetMaxSize(limit) - }() - // Disable the max size during loading + limit := e.engine.Cache.MaxSize() + defer func() { e.engine.Cache.SetMaxSize(limit) }() e.engine.Cache.SetMaxSize(0) - loader := tsm1.NewCacheLoader(files) - loader.WithLogger(e.logger) - if err := loader.Load(e.engine.Cache); err != nil { - return err + for _, file := range files { + if err := e.reloadWALFile(file); err != nil { + return err + } } - e.logger.Info("Reloaded WAL cache", zap.String("path", e.wal.Path()), zap.Duration("duration", time.Since(now))) + e.logger.Info("Reloaded WAL", + zap.String("path", e.wal.Path()), + zap.Duration("duration", time.Since(now))) return nil } +// reloadWALFile executes all of the actions in the WAL against the engine. +func (e *Engine) reloadWALFile(file string) error { + f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0666) + if err != nil { + return err + } + defer f.Close() + + stat, err := f.Stat() + if err != nil { + return err + } + e.logger.Info("Reading file", zap.String("path", file), zap.Int64("size", stat.Size())) + + if stat.Size() == 0 { + return nil + } + + r := wal.NewWALSegmentReader(f) + defer r.Close() + + for r.Next() { + entry, err := r.Read() + if err != nil { + n := r.Count() + e.logger.Info("File corrupt", zap.Error(err), zap.String("path", file), zap.Int64("pos", n)) + if err := f.Truncate(n); err != nil { + return err + } + break + } + + switch t := entry.(type) { + case *wal.WriteWALEntry: + points := tsm1.ValuesToPoints(t.Values) + err := e.writePointsLocked(tsdb.NewSeriesCollection(points), t.Values) + if _, ok := err.(tsdb.PartialWriteError); err != nil && !ok { + return err + } + + case *wal.DeleteRangeWALEntry: + err := e.engine.DeleteSeriesRangeWithPredicate(newFixedSeriesIterator(t.Keys), + func(name []byte, tags models.Tags) (int64, int64, bool) { + return t.Min, t.Max, true + }) + if err != nil { + return err + } + + case *wal.DeleteWALEntry: + err := e.engine.DeleteSeriesRangeWithPredicate(newFixedSeriesIterator(t.Keys), + func(name []byte, tags models.Tags) (int64, int64, bool) { + return math.MinInt64, math.MaxInt64, true + }) + if err != nil { + return err + } + } + } + + return r.Close() +} + // runRetentionEnforcer runs the retention enforcer in a separate goroutine. // // Currently this just runs on an interval, but in the future we will add the @@ -382,15 +446,25 @@ func (e *Engine) WritePoints(points []models.Point) error { return ErrEngineClosed } - // TODO(jeff): keep track of the values in the collection so that partail write + return e.writePointsLocked(collection, nil) +} + +// writePointsLocked does the work of writing points and must be called under some sort of lock. +func (e *Engine) writePointsLocked(collection *tsdb.SeriesCollection, values map[string][]value.Value) error { + // TODO(jeff): keep track of the values in the collection so that partial write // errors get tracked all the way. Right now, the engine doesn't drop any values // but if it ever did, the errors could end up missing some data. - // Add the write to the WAL to be replayed if there is a crash or shutdown. - values, err := tsm1.PointsToValues(collection.Points) - if err != nil { - return err + // Load up the values if they haven't been passed in. + var err error + if values == nil { + values, err = tsm1.PointsToValues(collection.Points) + if err != nil { + return err + } } + + // Add the write to the WAL to be replayed if there is a crash or shutdown. if _, err := e.wal.WriteMulti(values); err != nil { return err } @@ -403,7 +477,7 @@ func (e *Engine) WritePoints(points []models.Point) error { // If there was a PartialWriteError already, that means the values may contain // more than the points so we need to recreate them. if collection.PartialWriteError() != nil { - values, err = tsm1.PointsToValues(points) + values, err = tsm1.PointsToValues(collection.Points) if err != nil { return err } @@ -456,6 +530,8 @@ func (e *Engine) DeleteBucket(orgID, bucketID platform.ID) error { return ErrEngineClosed } + // TODO(jeff): write the DeleteBucket request to the WAL. + // TODO(edd): we need to clean up how we're encoding the prefix so that we // don't have to remember to get it right everywhere we need to touch TSM data. encoded := tsdb.EncodeName(orgID, bucketID) @@ -472,6 +548,11 @@ func (e *Engine) DeleteSeriesRangeWithPredicate(itr tsdb.SeriesIterator, fn func if e.closing == nil { return ErrEngineClosed } + + // TODO(jeff): this can't exist because we can't WAL a predicate. We'd have to run the + // iterator and predicate to completion, store the results in the WAL, and then run it + // again. + return e.engine.DeleteSeriesRangeWithPredicate(itr, fn) } diff --git a/storage/series_iterator.go b/storage/series_iterator.go new file mode 100644 index 0000000000..48f28dfc41 --- /dev/null +++ b/storage/series_iterator.go @@ -0,0 +1,46 @@ +package storage + +import ( + "github.com/influxdata/influxdb/models" + "github.com/influxdata/influxdb/tsdb" + "github.com/influxdata/influxql" +) + +// fixedSeriesIterator is a tsdb.SeriesIterator over a given set of keys. +type fixedSeriesIterator struct{ keys [][]byte } + +// newFixedSeriesIterator returns a tsdb.SeriesIterator over the given set of keys. +func newFixedSeriesIterator(keys [][]byte) *fixedSeriesIterator { + return &fixedSeriesIterator{ + keys: keys, + } +} + +// Close is required for the tsdb.SeriesIterator interface. +func (i *fixedSeriesIterator) Close() error { return nil } + +// Next advances the iterator and returns the current element. +func (i *fixedSeriesIterator) Next() (tsdb.SeriesElem, error) { + if len(i.keys) == 0 { + return nil, nil + } + key := i.keys[0] + i.keys = i.keys[1:] + + name, tags := models.ParseKeyBytes(key) + return &fixedSeriesIteratorElem{ + name: name, + tags: tags, + }, nil +} + +// fixedSeriesIteratorElem imlements tsdb.SeriesElem but only the name and tags. +type fixedSeriesIteratorElem struct { + name []byte + tags models.Tags +} + +func (i *fixedSeriesIteratorElem) Name() []byte { return i.name } +func (i *fixedSeriesIteratorElem) Tags() models.Tags { return i.tags } +func (i *fixedSeriesIteratorElem) Deleted() bool { return false } +func (i *fixedSeriesIteratorElem) Expr() influxql.Expr { return nil } diff --git a/tsdb/tsm1/value.go b/tsdb/tsm1/value.go index f42a3d521a..652dcdfa1d 100644 --- a/tsdb/tsm1/value.go +++ b/tsdb/tsm1/value.go @@ -2,6 +2,7 @@ package tsm1 import ( "fmt" + "time" "github.com/influxdata/influxdb/models" "github.com/influxdata/influxdb/tsdb/value" @@ -105,3 +106,18 @@ func PointsToValues(points []models.Point) (map[string][]Value, error) { return values, nil } + +// ValuesToPoints takes in a map of values and returns a slice of models.Point. +func ValuesToPoints(values map[string][]Value) []models.Point { + points := make([]models.Point, 0, len(values)) + for composite, vals := range values { + series, field := SeriesAndFieldFromCompositeKey([]byte(composite)) + strField := string(field) + for _, val := range vals { + t := time.Unix(0, val.UnixNano()) + fields := models.Fields{strField: val.Value()} + points = append(points, models.NewPointFromSeries(series, fields, t)) + } + } + return points +} From 7f54e816e3c64e7051600f8328409dca227884e2 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Mon, 21 Jan 2019 13:09:15 -0700 Subject: [PATCH 25/95] refactor: have retention use DeleteBucketRange --- storage/engine.go | 40 +- storage/retention.go | 154 +---- storage/retention_test.go | 134 ++--- tsdb/tsm1/engine.go | 354 ------------ ...measurement.go => engine_delete_bucket.go} | 4 +- ...t_test.go => engine_delete_bucket_test.go} | 6 +- tsdb/tsm1/engine_test.go | 543 +----------------- 7 files changed, 80 insertions(+), 1155 deletions(-) rename tsdb/tsm1/{engine_delete_measurement.go => engine_delete_bucket.go} (97%) rename tsdb/tsm1/{engine_delete_measurement_test.go => engine_delete_bucket_test.go} (94%) diff --git a/storage/engine.go b/storage/engine.go index 06e774ec54..5b8b4954c0 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -286,22 +286,11 @@ func (e *Engine) reloadWALFile(file string) error { } case *wal.DeleteRangeWALEntry: - err := e.engine.DeleteSeriesRangeWithPredicate(newFixedSeriesIterator(t.Keys), - func(name []byte, tags models.Tags) (int64, int64, bool) { - return t.Min, t.Max, true - }) - if err != nil { - return err - } + // TODO(jeff): implement? case *wal.DeleteWALEntry: - err := e.engine.DeleteSeriesRangeWithPredicate(newFixedSeriesIterator(t.Keys), - func(name []byte, tags models.Tags) (int64, int64, bool) { - return math.MinInt64, math.MaxInt64, true - }) - if err != nil { - return err - } + // TODO(jeff): implement? + } } @@ -524,6 +513,11 @@ func (e *Engine) CommitSegments(segs []string, fn func() error) error { // DeleteBucket deletes an entire bucket from the storage engine. func (e *Engine) DeleteBucket(orgID, bucketID platform.ID) error { + return e.DeleteBucketRange(orgID, bucketID, math.MinInt64, math.MaxInt64) +} + +// DeleteBucketRange deletes an entire bucket from the storage engine. +func (e *Engine) DeleteBucketRange(orgID, bucketID platform.ID, min, max int64) error { e.mu.RLock() defer e.mu.RUnlock() if e.closing == nil { @@ -537,23 +531,7 @@ func (e *Engine) DeleteBucket(orgID, bucketID platform.ID) error { encoded := tsdb.EncodeName(orgID, bucketID) name := models.EscapeMeasurement(encoded[:]) - return e.engine.DeleteBucket(name, math.MinInt64, math.MaxInt64) -} - -// DeleteSeriesRangeWithPredicate deletes all series data iterated over if fn returns -// true for that series. -func (e *Engine) DeleteSeriesRangeWithPredicate(itr tsdb.SeriesIterator, fn func([]byte, models.Tags) (int64, int64, bool)) error { - e.mu.RLock() - defer e.mu.RUnlock() - if e.closing == nil { - return ErrEngineClosed - } - - // TODO(jeff): this can't exist because we can't WAL a predicate. We'd have to run the - // iterator and predicate to completion, store the results in the WAL, and then run it - // again. - - return e.engine.DeleteSeriesRangeWithPredicate(itr, fn) + return e.engine.DeleteBucketRange(name, min, max) } // SeriesCardinality returns the number of series in the engine. diff --git a/storage/retention.go b/storage/retention.go index ed3a08282a..3951b4d7e3 100644 --- a/storage/retention.go +++ b/storage/retention.go @@ -4,15 +4,10 @@ import ( "context" "errors" "math" - "sync" - "sync/atomic" "time" platform "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/logger" - "github.com/influxdata/influxdb/models" - "github.com/influxdata/influxdb/tsdb" - "github.com/influxdata/influxql" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) @@ -24,8 +19,7 @@ const ( // A Deleter implementation is capable of deleting data from a storage engine. type Deleter interface { - CreateSeriesCursor(context.Context, SeriesCursorRequest, influxql.Expr) (SeriesCursor, error) - DeleteSeriesRangeWithPredicate(tsdb.SeriesIterator, func([]byte, models.Tags) (int64, int64, bool)) error + DeleteBucketRange(orgID, bucketID platform.ID, min, max int64) error } // A BucketFinder is responsible for providing access to buckets via a filter. @@ -78,9 +72,9 @@ func (s *retentionEnforcer) run() { log, logEnd := logger.NewOperation(s.logger, "Data retention check", "data_retention_check") defer logEnd() - rpByBucketID, err := s.getRetentionPeriodPerBucket() + buckets, err := s.getBucketInformation() if err != nil { - log.Error("Unable to determine bucket:RP mapping", zap.Error(err)) + log.Error("Unable to determine bucket information", zap.Error(err)) return } @@ -88,7 +82,7 @@ func (s *retentionEnforcer) run() { labels := s.metrics.Labels() labels["status"] = "ok" - if err := s.expireData(rpByBucketID, now); err != nil { + if err := s.expireData(buckets, now); err != nil { log.Error("Deletion not successful", zap.Error(err)) labels["status"] = "error" } @@ -98,149 +92,37 @@ func (s *retentionEnforcer) run() { // expireData runs a delete operation on the storage engine. // -// Any series data that (1) belongs to a bucket in the provided map and +// Any series data that (1) belongs to a bucket in the provided list and // (2) falls outside the bucket's indicated retention period will be deleted. -func (s *retentionEnforcer) expireData(rpByBucketID map[platform.ID]time.Duration, now time.Time) error { +func (s *retentionEnforcer) expireData(buckets []*platform.Bucket, now time.Time) error { _, logEnd := logger.NewOperation(s.logger, "Data deletion", "data_deletion") defer logEnd() - ctx, cancel := context.WithTimeout(context.Background(), engineAPITimeout) - defer cancel() - cur, err := s.Engine.CreateSeriesCursor(ctx, SeriesCursorRequest{}, nil) - if err != nil { - return err - } - defer cur.Close() - - var mu sync.Mutex - badMSketch := make(map[string]struct{}) // Badly formatted measurements. - missingBSketch := make(map[platform.ID]struct{}) // Missing buckets. - - var seriesDeleted uint64 // Number of series where a delete is attempted. - var seriesSkipped uint64 // Number of series that were skipped from delete. - - fn := func(name []byte, tags models.Tags) (int64, int64, bool) { - if len(name) != platform.IDLength { - mu.Lock() - badMSketch[string(name)] = struct{}{} - mu.Unlock() - atomic.AddUint64(&seriesSkipped, 1) - return 0, 0, false - + for _, b := range buckets { + if b.RetentionPeriod == 0 { + continue } - var n [16]byte - copy(n[:], name) - _, bucketID := tsdb.DecodeName(n) - - retentionPeriod, ok := rpByBucketID[bucketID] - if !ok { - mu.Lock() - missingBSketch[bucketID] = struct{}{} - mu.Unlock() - atomic.AddUint64(&seriesSkipped, 1) - return 0, 0, false + max := now.Add(-b.RetentionPeriod).UnixNano() + err := s.Engine.DeleteBucketRange(b.OrganizationID, b.ID, math.MinInt64, max) + if err != nil { + // TODO(jeff): metrics? } - if retentionPeriod == 0 { - return 0, 0, false - } - - atomic.AddUint64(&seriesDeleted, 1) - to := now.Add(-retentionPeriod).UnixNano() - return math.MinInt64, to, true } - defer func() { - if s.metrics == nil { - return - } - labels := s.metrics.Labels() - labels["status"] = "bad_measurement" - s.metrics.Unprocessable.With(labels).Add(float64(len(badMSketch))) - - labels["status"] = "missing_bucket" - s.metrics.Unprocessable.With(labels).Add(float64(len(missingBSketch))) - - labels["status"] = "ok" - s.metrics.Series.With(labels).Add(float64(atomic.LoadUint64(&seriesDeleted))) - - labels["status"] = "skipped" - s.metrics.Series.With(labels).Add(float64(atomic.LoadUint64(&seriesSkipped))) - }() - - return s.Engine.DeleteSeriesRangeWithPredicate(newSeriesIteratorAdapter(cur), fn) + return nil } -// getRetentionPeriodPerBucket returns a map of (bucket ID -> retention period) -// for all buckets. -func (s *retentionEnforcer) getRetentionPeriodPerBucket() (map[platform.ID]time.Duration, error) { +// getBucketInformation returns a slice of buckets to run retention on. +func (s *retentionEnforcer) getBucketInformation() ([]*platform.Bucket, error) { ctx, cancel := context.WithTimeout(context.Background(), bucketAPITimeout) defer cancel() + buckets, _, err := s.BucketService.FindBuckets(ctx, platform.BucketFilter{}) - if err != nil { - return nil, err - } - rpByBucketID := make(map[platform.ID]time.Duration, len(buckets)) - for _, bucket := range buckets { - rpByBucketID[bucket.ID] = bucket.RetentionPeriod - } - return rpByBucketID, nil + return buckets, err } // PrometheusCollectors satisfies the prom.PrometheusCollector interface. func (s *retentionEnforcer) PrometheusCollectors() []prometheus.Collector { return s.metrics.PrometheusCollectors() } - -type seriesIteratorAdapter struct { - itr SeriesCursor - ea seriesElemAdapter - elem tsdb.SeriesElem -} - -func newSeriesIteratorAdapter(itr SeriesCursor) *seriesIteratorAdapter { - si := &seriesIteratorAdapter{itr: itr} - si.elem = &si.ea - return si -} - -// Next returns the next tsdb.SeriesElem. -// -// The returned tsdb.SeriesElem is valid for use until Next is called again. -func (s *seriesIteratorAdapter) Next() (tsdb.SeriesElem, error) { - if s.itr == nil { - return nil, nil - } - - row, err := s.itr.Next() - if err != nil { - return nil, err - } - - if row == nil { - return nil, nil - } - - s.ea.name = row.Name - s.ea.tags = row.Tags - return s.elem, nil -} - -func (s *seriesIteratorAdapter) Close() error { - if s.itr != nil { - err := s.itr.Close() - s.itr = nil - return err - } - return nil -} - -type seriesElemAdapter struct { - name []byte - tags models.Tags -} - -func (e *seriesElemAdapter) Name() []byte { return e.name } -func (e *seriesElemAdapter) Tags() models.Tags { return e.tags } -func (e *seriesElemAdapter) Deleted() bool { return false } -func (e *seriesElemAdapter) Expr() influxql.Expr { return nil } diff --git a/storage/retention_test.go b/storage/retention_test.go index c4d2a8e9b2..9b4db3cf41 100644 --- a/storage/retention_test.go +++ b/storage/retention_test.go @@ -2,7 +2,6 @@ package storage import ( "context" - "fmt" "math" "math/rand" "reflect" @@ -10,103 +9,80 @@ import ( "time" platform "github.com/influxdata/influxdb" - "github.com/influxdata/influxdb/models" "github.com/influxdata/influxdb/tsdb" - "github.com/influxdata/influxql" ) -func TestService_expireData(t *testing.T) { +func TestRetentionService(t *testing.T) { engine := NewTestEngine() service := newRetentionEnforcer(engine, NewTestBucketFinder()) now := time.Date(2018, 4, 10, 23, 12, 33, 0, time.UTC) - t.Run("no rpByBucketID", func(t *testing.T) { + t.Run("no buckets", func(t *testing.T) { if err := service.expireData(nil, now); err != nil { t.Error(err) } - - if err := service.expireData(map[platform.ID]time.Duration{}, now); err != nil { + if err := service.expireData([]*platform.Bucket{}, now); err != nil { t.Error(err) } }) - // Generate some measurement names - var names [][]byte - rpByBucketID := map[platform.ID]time.Duration{} - expMatchedFrequencies := map[string]int{} // To be used for verifying test results. - expRejectedFrequencies := map[string]int{} // To be used for verifying test results. + // Generate some buckets to expire + buckets := []*platform.Bucket{} + expMatched := map[string]struct{}{} // To be used for verifying test results. + expRejected := map[string]struct{}{} // To be used for verifying test results. for i := 0; i < 15; i++ { - repeat := rand.Intn(10) + 1 // [1, 10] name := genMeasurementName() - for j := 0; j < repeat; j++ { - names = append(names, name) - } var n [16]byte copy(n[:], name) - _, bucketID := tsdb.DecodeName(n) + orgID, bucketID := tsdb.DecodeName(n) // Put 1/3rd in the rpByBucketID into the set to delete and 1/3rd into the set // to not delete because no rp, and 1/3rd into the set to not delete because 0 rp. if i%3 == 0 { - rpByBucketID[bucketID] = 3 * time.Hour - expMatchedFrequencies[string(name)] = repeat + buckets = append(buckets, &platform.Bucket{ + OrganizationID: orgID, + ID: bucketID, + RetentionPeriod: 3 * time.Hour, + }) + expMatched[string(name)] = struct{}{} } else if i%3 == 1 { - expRejectedFrequencies[string(name)] = repeat + expRejected[string(name)] = struct{}{} } else if i%3 == 2 { - rpByBucketID[bucketID] = 0 - expRejectedFrequencies[string(name)] = repeat + buckets = append(buckets, &platform.Bucket{ + OrganizationID: orgID, + ID: bucketID, + RetentionPeriod: 0, + }) + expRejected[string(name)] = struct{}{} } } - // Add a badly formatted measurement. - for i := 0; i < 5; i++ { - names = append(names, []byte("zyzwrong")) - } - expRejectedFrequencies["zyzwrong"] = 5 - - gotMatchedFrequencies := map[string]int{} - gotRejectedFrequencies := map[string]int{} - engine.DeleteSeriesRangeWithPredicateFn = func(_ tsdb.SeriesIterator, fn func([]byte, models.Tags) (int64, int64, bool)) error { - - // Iterate over the generated names updating the frequencies by which - // the predicate function in expireData matches or rejects them. - for _, name := range names { - from, to, shouldDelete := fn(name, nil) - if shouldDelete { - gotMatchedFrequencies[string(name)]++ - if from != math.MinInt64 { - return fmt.Errorf("got from %d, expected %d", from, math.MinInt64) - } - wantTo := now.Add(-3 * time.Hour).UnixNano() - if to != wantTo { - return fmt.Errorf("got to %d, expected %d", to, wantTo) - } - } else { - gotRejectedFrequencies[string(name)]++ - } + gotMatched := map[string]struct{}{} + engine.DeleteBucketRangeFn = func(orgID, bucketID platform.ID, from, to int64) error { + if from != math.MinInt64 { + t.Fatalf("got from %d, expected %d", from, math.MinInt64) } + wantTo := now.Add(-3 * time.Hour).UnixNano() + if to != wantTo { + t.Fatalf("got to %d, expected %d", to, wantTo) + } + + name := tsdb.EncodeName(orgID, bucketID) + if _, ok := expRejected[string(name[:])]; ok { + t.Fatalf("got a delete for %x", name) + } + gotMatched[string(name[:])] = struct{}{} return nil } - t.Run("multiple bucket", func(t *testing.T) { - if err := service.expireData(rpByBucketID, now); err != nil { + t.Run("multiple buckets", func(t *testing.T) { + if err := service.expireData(buckets, now); err != nil { t.Error(err) } - - // Verify that the correct series were marked to be deleted. - t.Run("matched", func(t *testing.T) { - if !reflect.DeepEqual(gotMatchedFrequencies, expMatchedFrequencies) { - t.Fatalf("got\n%#v\nexpected\n%#v", gotMatchedFrequencies, expMatchedFrequencies) - } - }) - - t.Run("rejected", func(t *testing.T) { - // Verify that badly formatted measurements were rejected. - if !reflect.DeepEqual(gotRejectedFrequencies, expRejectedFrequencies) { - t.Fatalf("got\n%#v\nexpected\n%#v", gotRejectedFrequencies, expRejectedFrequencies) - } - }) + if !reflect.DeepEqual(gotMatched, expMatched) { + t.Fatalf("got\n%#v\nexpected\n%#v", gotMatched, expMatched) + } }) } @@ -120,40 +96,18 @@ func genMeasurementName() []byte { return b } -type TestSeriesCursor struct { - CloseFn func() error - NextFn func() (*SeriesCursorRow, error) -} - -func (f *TestSeriesCursor) Close() error { return f.CloseFn() } -func (f *TestSeriesCursor) Next() (*SeriesCursorRow, error) { return f.NextFn() } - type TestEngine struct { - CreateSeriesCursorFn func(context.Context, SeriesCursorRequest, influxql.Expr) (SeriesCursor, error) - DeleteSeriesRangeWithPredicateFn func(tsdb.SeriesIterator, func([]byte, models.Tags) (int64, int64, bool)) error - - SeriesCursor *TestSeriesCursor + DeleteBucketRangeFn func(platform.ID, platform.ID, int64, int64) error } func NewTestEngine() *TestEngine { - cursor := &TestSeriesCursor{ - CloseFn: func() error { return nil }, - NextFn: func() (*SeriesCursorRow, error) { return nil, nil }, - } - return &TestEngine{ - SeriesCursor: cursor, - CreateSeriesCursorFn: func(context.Context, SeriesCursorRequest, influxql.Expr) (SeriesCursor, error) { return cursor, nil }, - DeleteSeriesRangeWithPredicateFn: func(tsdb.SeriesIterator, func([]byte, models.Tags) (int64, int64, bool)) error { return nil }, + DeleteBucketRangeFn: func(platform.ID, platform.ID, int64, int64) error { return nil }, } } -func (e *TestEngine) CreateSeriesCursor(ctx context.Context, req SeriesCursorRequest, cond influxql.Expr) (SeriesCursor, error) { - return e.CreateSeriesCursorFn(ctx, req, cond) -} - -func (e *TestEngine) DeleteSeriesRangeWithPredicate(itr tsdb.SeriesIterator, fn func([]byte, models.Tags) (int64, int64, bool)) error { - return e.DeleteSeriesRangeWithPredicateFn(itr, fn) +func (e *TestEngine) DeleteBucketRange(orgID, bucketID platform.ID, min, max int64) error { + return e.DeleteBucketRangeFn(orgID, bucketID, min, max) } type TestBucketFinder struct { diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index 34ea98b3c3..de37de6b55 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -4,11 +4,8 @@ package tsm1 // import "github.com/influxdata/influxdb/tsdb/tsm1" import ( "bytes" "context" - "errors" "fmt" - "io" "io/ioutil" - "math" "os" "path/filepath" "regexp" @@ -20,7 +17,6 @@ import ( "github.com/influxdata/influxdb/logger" "github.com/influxdata/influxdb/models" - "github.com/influxdata/influxdb/pkg/bytesutil" "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/metrics" "github.com/influxdata/influxdb/query" @@ -594,361 +590,11 @@ func (e *Engine) WriteValues(values map[string][]Value) error { return nil } -// DeleteSeriesRange removes the values between min and max (inclusive) from all series -func (e *Engine) DeleteSeriesRange(itr tsdb.SeriesIterator, min, max int64) error { - return e.DeleteSeriesRangeWithPredicate(itr, func(name []byte, tags models.Tags) (int64, int64, bool) { - return min, max, true - }) -} - -// DeleteSeriesRangeWithPredicate removes the values between min and max (inclusive) from all series -// for which predicate() returns true. If predicate() is nil, then all values in range are removed. -func (e *Engine) DeleteSeriesRangeWithPredicate(itr tsdb.SeriesIterator, predicate func(name []byte, tags models.Tags) (int64, int64, bool)) error { - var disableOnce bool - - // Ensure that the index does not compact away the measurement or series we're - // going to delete before we're done with them. - e.index.DisableCompactions() - defer e.index.EnableCompactions() - e.index.Wait() - - fs, err := e.index.RetainFileSet() - if err != nil { - return err - } - defer fs.Release() - - var ( - sz int - min, max int64 = math.MinInt64, math.MaxInt64 - - // Indicator that the min/max time for the current batch has changed and - // we need to flush the current batch before appending to it. - flushBatch bool - ) - - // These are reversed from min/max to ensure they are different the first time through. - newMin, newMax := int64(math.MaxInt64), int64(math.MinInt64) - - // There is no predicate, so setup newMin/newMax to delete the full time range. - if predicate == nil { - newMin = min - newMax = max - } - - batch := make([][]byte, 0, 10000) - for { - elem, err := itr.Next() - if err != nil { - return err - } else if elem == nil { - break - } - - // See if the series should be deleted and if so, what range of time. - if predicate != nil { - var shouldDelete bool - newMin, newMax, shouldDelete = predicate(elem.Name(), elem.Tags()) - if !shouldDelete { - continue - } - - // If the min/max happens to change for the batch, we need to flush - // the current batch and start a new one. - flushBatch = (min != newMin || max != newMax) && len(batch) > 0 - } - - if elem.Expr() != nil { - if v, ok := elem.Expr().(*influxql.BooleanLiteral); !ok || !v.Val { - return errors.New("fields not supported in WHERE clause during deletion") - } - } - - if !disableOnce { - // Disable and abort running compactions so that tombstones added existing tsm - // files don't get removed. This would cause deleted measurements/series to - // re-appear once the compaction completed. We only disable the level compactions - // so that snapshotting does not stop while writing out tombstones. If it is stopped, - // and writing tombstones takes a long time, writes can get rejected due to the cache - // filling up. - e.disableLevelCompactions(true) - defer e.enableLevelCompactions(true) - - e.sfile.DisableCompactions() - defer e.sfile.EnableCompactions() - e.sfile.Wait() - - disableOnce = true - } - - if sz >= deleteFlushThreshold || flushBatch { - // Delete all matching batch. - if err := e.deleteSeriesRange(batch, min, max); err != nil { - return err - } - batch = batch[:0] - sz = 0 - flushBatch = false - } - - // Use the new min/max time for the next iteration - min = newMin - max = newMax - - key := models.MakeKey(elem.Name(), elem.Tags()) - sz += len(key) - batch = append(batch, key) - } - - if len(batch) > 0 { - // Delete all matching batch. - if err := e.deleteSeriesRange(batch, min, max); err != nil { - return err - } - } - - e.index.Rebuild() - return nil -} - -// deleteSeriesRange removes the values between min and max (inclusive) from all series. This -// does not update the index or disable compactions. This should mainly be called by DeleteSeriesRange -// and not directly. -func (e *Engine) deleteSeriesRange(seriesKeys [][]byte, min, max int64) error { - if len(seriesKeys) == 0 { - return nil - } - - // Ensure keys are sorted since lower layers require them to be. - if !bytesutil.IsSorted(seriesKeys) { - bytesutil.Sort(seriesKeys) - } - - // Min and max time in the engine are slightly different from the query language values. - if min == influxql.MinTime { - min = math.MinInt64 - } - if max == influxql.MaxTime { - max = math.MaxInt64 - } - - // Run the delete on each TSM file in parallel - if err := e.FileStore.Apply(func(r TSMFile) error { - // See if this TSM file contains the keys and time range - minKey, maxKey := seriesKeys[0], seriesKeys[len(seriesKeys)-1] - tsmMin, tsmMax := r.KeyRange() - - tsmMin, _ = SeriesAndFieldFromCompositeKey(tsmMin) - tsmMax, _ = SeriesAndFieldFromCompositeKey(tsmMax) - - overlaps := bytes.Compare(tsmMin, maxKey) <= 0 && bytes.Compare(tsmMax, minKey) >= 0 - if !overlaps || !r.OverlapsTimeRange(min, max) { - return nil - } - - // Delete each key we find in the file. We seek to the min key and walk from there. - batch := r.BatchDelete() - iter := r.Iterator(minKey) - var j int - for iter.Next() { - indexKey := iter.Key() - seriesKey, _ := SeriesAndFieldFromCompositeKey(indexKey) - - for j < len(seriesKeys) && bytes.Compare(seriesKeys[j], seriesKey) < 0 { - j++ - } - - if j >= len(seriesKeys) { - break - } - if bytes.Equal(seriesKeys[j], seriesKey) { - if err := batch.DeleteRange([][]byte{indexKey}, min, max); err != nil { - batch.Rollback() - return err - } - } - } - if err := iter.Err(); err != nil { - batch.Rollback() - return err - } - - return batch.Commit() - }); err != nil { - return err - } - - // find the keys in the cache and remove them - deleteKeys := make([][]byte, 0, len(seriesKeys)) - - // ApplySerialEntryFn cannot return an error in this invocation. - _ = e.Cache.ApplyEntryFn(func(k []byte, _ *entry) error { - seriesKey, _ := SeriesAndFieldFromCompositeKey([]byte(k)) - - // Cache does not walk keys in sorted order, so search the sorted - // series we need to delete to see if any of the cache keys match. - i := bytesutil.SearchBytes(seriesKeys, seriesKey) - if i < len(seriesKeys) && bytes.Equal(seriesKey, seriesKeys[i]) { - // k is the measurement + tags + sep + field - deleteKeys = append(deleteKeys, k) - } - return nil - }) - - // Sort the series keys because ApplyEntryFn iterates over the keys randomly. - bytesutil.Sort(deleteKeys) - - e.Cache.DeleteRange(deleteKeys, min, max) - - // The series are deleted on disk, but the index may still say they exist. - // Depending on the the min,max time passed in, the series may or not actually - // exists now. To reconcile the index, we walk the series keys that still exists - // on disk and cross out any keys that match the passed in series. Any series - // left in the slice at the end do not exist and can be deleted from the index. - // Note: this is inherently racy if writes are occurring to the same measurement/series are - // being removed. A write could occur and exist in the cache at this point, but we - // would delete it from the index. - minKey := seriesKeys[0] - - // Apply runs this func concurrently. The seriesKeys slice is mutated concurrently - // by different goroutines setting positions to nil. - if err := e.FileStore.Apply(func(r TSMFile) error { - var j int - - // Start from the min deleted key that exists in this file. - iter := r.Iterator(minKey) - for iter.Next() { - if j >= len(seriesKeys) { - return nil - } - - indexKey := iter.Key() - seriesKey, _ := SeriesAndFieldFromCompositeKey(indexKey) - - // Skip over any deleted keys that are less than our tsm key - cmp := bytes.Compare(seriesKeys[j], seriesKey) - for j < len(seriesKeys) && cmp < 0 { - j++ - if j >= len(seriesKeys) { - return nil - } - cmp = bytes.Compare(seriesKeys[j], seriesKey) - } - - // We've found a matching key, cross it out so we do not remove it from the index. - if j < len(seriesKeys) && cmp == 0 { - seriesKeys[j] = emptyBytes - j++ - } - } - - return iter.Err() - }); err != nil { - return err - } - - // Have we deleted all values for the series? If so, we need to remove - // the series from the index. - if len(seriesKeys) > 0 { - buf := make([]byte, 1024) // For use when accessing series file. - ids := tsdb.NewSeriesIDSet() - measurements := make(map[string]struct{}, 1) - - for _, k := range seriesKeys { - if len(k) == 0 { - continue // This key was wiped because it shouldn't be removed from index. - } - - name, tags := models.ParseKeyBytes(k) - sid := e.sfile.SeriesID(name, tags, buf) - if sid.IsZero() { - continue - } - - // See if this series was found in the cache earlier - i := bytesutil.SearchBytes(deleteKeys, k) - - var hasCacheValues bool - // If there are multiple fields, they will have the same prefix. If any field - // has values, then we can't delete it from the index. - for i < len(deleteKeys) && bytes.HasPrefix(deleteKeys[i], k) { - if e.Cache.Values(deleteKeys[i]).Len() > 0 { - hasCacheValues = true - break - } - i++ - } - - if hasCacheValues { - continue - } - - measurements[string(name)] = struct{}{} - // Remove the series from the local index. - if err := e.index.DropSeries(sid, k, false); err != nil { - return err - } - - // Add the id to the set of delete ids. - ids.Add(sid) - } - - for k := range measurements { - if err := e.index.DropMeasurementIfSeriesNotExist([]byte(k)); err != nil { - return err - } - } - - // Remove the remaining ids from the series file as they no longer exist - // in any shard. - var err error - ids.ForEach(func(id tsdb.SeriesID) { - if err1 := e.sfile.DeleteSeriesID(id); err1 != nil { - err = err1 - } - }) - if err != nil { - return err - } - } - - return nil -} - -// DeleteMeasurement deletes a measurement and all related series. -func (e *Engine) DeleteMeasurement(name []byte) error { - // Delete the bulk of data outside of the fields lock. - if err := e.deleteMeasurement(name); err != nil { - return err - } - return nil -} - -// DeleteMeasurement deletes a measurement and all related series. -func (e *Engine) deleteMeasurement(name []byte) error { - // Attempt to find the series keys. - itr, err := e.index.MeasurementSeriesIDIterator(name) - if err != nil { - return err - } else if itr == nil { - return nil - } - defer itr.Close() - return e.DeleteSeriesRange(tsdb.NewSeriesIteratorAdapter(e.sfile, itr), math.MinInt64, math.MaxInt64) -} - // ForEachMeasurementName iterates over each measurement name in the engine. func (e *Engine) ForEachMeasurementName(fn func(name []byte) error) error { return e.index.ForEachMeasurementName(fn) } -func (e *Engine) CreateSeriesListIfNotExists(collection *tsdb.SeriesCollection) error { - return e.index.CreateSeriesListIfNotExists(collection) -} - -// WriteTo is not implemented. -func (e *Engine) WriteTo(w io.Writer) (n int64, err error) { panic("not implemented") } - // compactionLevel describes a snapshot or levelled compaction. type compactionLevel int diff --git a/tsdb/tsm1/engine_delete_measurement.go b/tsdb/tsm1/engine_delete_bucket.go similarity index 97% rename from tsdb/tsm1/engine_delete_measurement.go rename to tsdb/tsm1/engine_delete_bucket.go index 466716fc46..57957942ae 100644 --- a/tsdb/tsm1/engine_delete_measurement.go +++ b/tsdb/tsm1/engine_delete_bucket.go @@ -11,10 +11,10 @@ import ( "github.com/influxdata/influxql" ) -// DeleteBucket removes all TSM data belonging to a bucket, and removes all index +// DeleteBucketRange removes all TSM data belonging to a bucket, and removes all index // and series file data associated with the bucket. The provided time range ensures // that only bucket data for that range is removed. -func (e *Engine) DeleteBucket(name []byte, min, max int64) error { +func (e *Engine) DeleteBucketRange(name []byte, min, max int64) error { // TODO(jeff): we need to block writes to this prefix while deletes are in progress // otherwise we can end up in a situation where we have staged data in the cache or // WAL that was deleted from the index, or worse. This needs to happen at a higher diff --git a/tsdb/tsm1/engine_delete_measurement_test.go b/tsdb/tsm1/engine_delete_bucket_test.go similarity index 94% rename from tsdb/tsm1/engine_delete_measurement_test.go rename to tsdb/tsm1/engine_delete_bucket_test.go index c0b21bb378..755d116fd9 100644 --- a/tsdb/tsm1/engine_delete_measurement_test.go +++ b/tsdb/tsm1/engine_delete_bucket_test.go @@ -8,7 +8,7 @@ import ( "github.com/influxdata/influxdb/models" ) -func TestEngine_DeletePrefix(t *testing.T) { +func TestEngine_DeleteBucket(t *testing.T) { // Create a few points. p1 := MustParsePointString("cpu,host=0 value=1.1 6") p2 := MustParsePointString("cpu,host=A value=1.2 2") @@ -44,7 +44,7 @@ func TestEngine_DeletePrefix(t *testing.T) { t.Fatalf("series count mismatch: exp %v, got %v", exp, got) } - if err := e.DeleteBucket([]byte("cpu"), 0, 3); err != nil { + if err := e.DeleteBucketRange([]byte("cpu"), 0, 3); err != nil { t.Fatalf("failed to delete series: %v", err) } @@ -90,7 +90,7 @@ func TestEngine_DeletePrefix(t *testing.T) { iter.Close() // Deleting remaining series should remove them from the series. - if err := e.DeleteBucket([]byte("cpu"), 0, 9); err != nil { + if err := e.DeleteBucketRange([]byte("cpu"), 0, 9); err != nil { t.Fatalf("failed to delete series: %v", err) } diff --git a/tsdb/tsm1/engine_test.go b/tsdb/tsm1/engine_test.go index a1ab2674bb..b8f86d6d0d 100644 --- a/tsdb/tsm1/engine_test.go +++ b/tsdb/tsm1/engine_test.go @@ -1,7 +1,6 @@ package tsm1_test import ( - "bytes" "fmt" "io/ioutil" "math" @@ -59,8 +58,9 @@ func TestIndex_SeriesIDSet(t *testing.T) { } // Drop all the series for the gpu measurement and they should no longer - // be in the series ID set. - if err := engine.DeleteMeasurement([]byte("gpu")); err != nil { + // be in the series ID set. This relies on the fact that DeleteBucketRange is really + // operating on prefixes. + if err := engine.DeleteBucketRange([]byte("gpu"), math.MinInt64, math.MaxInt64); err != nil { t.Fatal(err) } @@ -72,17 +72,6 @@ func TestIndex_SeriesIDSet(t *testing.T) { delete(seriesIDMap, "gpu") delete(seriesIDMap, "gpu,host=b") - // Drop the specific mem series - ditr := &seriesIterator{keys: [][]byte{[]byte("mem,host=z")}} - if err := engine.DeleteSeriesRange(ditr, math.MinInt64, math.MaxInt64); err != nil { - t.Fatal(err) - } - - if engine.SeriesIDSet().Contains(seriesIDMap["mem,host=z"]) { - t.Fatalf("bitmap does not contain ID: %d for key %s, but should", seriesIDMap["mem,host=z"], "mem,host=z") - } - delete(seriesIDMap, "mem,host=z") - // The rest of the keys should still be in the set. for key, id := range seriesIDMap { if !engine.SeriesIDSet().Contains(id) { @@ -106,530 +95,6 @@ func TestIndex_SeriesIDSet(t *testing.T) { } } -// Ensures that deleting series from TSM files with multiple fields removes all the -/// series -func TestEngine_DeleteSeries(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 1000000000") - p2 := MustParsePointString("cpu,host=B value=1.2 2000000000") - p3 := MustParsePointString("cpu,host=A sum=1.3 3000000000") - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 3, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A")}} - if err := e.DeleteSeriesRange(itr, math.MinInt64, math.MaxInt64); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 1, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - exp := "cpu,host=B#!~#value" - if _, ok := keys[exp]; !ok { - t.Fatalf("wrong series deleted: exp %v, got %v", exp, keys) - } -} - -func TestEngine_DeleteSeriesRange(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=0 value=1.1 6000000000") // Should not be deleted - p2 := MustParsePointString("cpu,host=A value=1.2 2000000000") - p3 := MustParsePointString("cpu,host=A value=1.3 3000000000") - p4 := MustParsePointString("cpu,host=B value=1.3 4000000000") // Should not be deleted - p5 := MustParsePointString("cpu,host=B value=1.3 5000000000") // Should not be deleted - p6 := MustParsePointString("cpu,host=C value=1.3 1000000000") - p7 := MustParsePointString("mem,host=C value=1.3 1000000000") // Should not be deleted - p8 := MustParsePointString("disk,host=C value=1.3 1000000000") // Should not be deleted - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3, p4, p5, p6, p7, p8); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 6, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=0"), []byte("cpu,host=A"), []byte("cpu,host=B"), []byte("cpu,host=C")}} - if err := e.DeleteSeriesRange(itr, 0, 3000000000); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 4, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - exp := "cpu,host=B#!~#value" - if _, ok := keys[exp]; !ok { - t.Fatalf("wrong series deleted: exp %v, got %v", exp, keys) - } - - // Check that the series still exists in the index - iter, err := e.index.MeasurementSeriesIDIterator([]byte("cpu")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } - defer iter.Close() - - elem, err := iter.Next() - if err != nil { - t.Fatal(err) - } - if elem.SeriesID.IsZero() { - t.Fatalf("series index mismatch: EOF, exp 2 series") - } - - // Lookup series. - name, tags := e.sfile.Series(elem.SeriesID) - if got, exp := name, []byte("cpu"); !bytes.Equal(got, exp) { - t.Fatalf("series mismatch: got %s, exp %s", got, exp) - } - - if !tags.Equal(models.NewTags(map[string]string{"host": "0"})) && !tags.Equal(models.NewTags(map[string]string{"host": "B"})) { - t.Fatalf(`series mismatch: got %s, exp either "host=0" or "host=B"`, tags) - } - iter.Close() - - // Deleting remaining series should remove them from the series. - itr = &seriesIterator{keys: [][]byte{[]byte("cpu,host=0"), []byte("cpu,host=B")}} - if err := e.DeleteSeriesRange(itr, 0, 9000000000); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - if iter, err = e.index.MeasurementSeriesIDIterator([]byte("cpu")); err != nil { - t.Fatalf("iterator error: %v", err) - } - if iter == nil { - return - } - - defer iter.Close() - if elem, err = iter.Next(); err != nil { - t.Fatal(err) - } - if !elem.SeriesID.IsZero() { - t.Fatalf("got an undeleted series id, but series should be dropped from index") - } -} - -func TestEngine_DeleteSeriesRangeWithPredicate(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 6000000000") // Should not be deleted - p2 := MustParsePointString("cpu,host=A value=1.2 2000000000") // Should not be deleted - p3 := MustParsePointString("cpu,host=B value=1.3 3000000000") - p4 := MustParsePointString("cpu,host=B value=1.3 4000000000") - p5 := MustParsePointString("cpu,host=C value=1.3 5000000000") // Should not be deleted - p6 := MustParsePointString("mem,host=B value=1.3 1000000000") - p7 := MustParsePointString("mem,host=C value=1.3 1000000000") - p8 := MustParsePointString("disk,host=C value=1.3 1000000000") // Should not be deleted - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3, p4, p5, p6, p7, p8); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 6, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A"), []byte("cpu,host=B"), []byte("cpu,host=C"), []byte("mem,host=B"), []byte("mem,host=C")}} - predicate := func(name []byte, tags models.Tags) (int64, int64, bool) { - if bytes.Equal(name, []byte("mem")) { - return math.MinInt64, math.MaxInt64, true - } - if bytes.Equal(name, []byte("cpu")) { - for _, tag := range tags { - if bytes.Equal(tag.Key, []byte("host")) && bytes.Equal(tag.Value, []byte("B")) { - return math.MinInt64, math.MaxInt64, true - } - } - } - return math.MinInt64, math.MaxInt64, false - } - if err := e.DeleteSeriesRangeWithPredicate(itr, predicate); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 3, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - exps := []string{"cpu,host=A#!~#value", "cpu,host=C#!~#value", "disk,host=C#!~#value"} - for _, exp := range exps { - if _, ok := keys[exp]; !ok { - t.Fatalf("wrong series deleted: exp %v, got %v", exps, keys) - } - } - - // Check that the series still exists in the index - iter, err := e.index.MeasurementSeriesIDIterator([]byte("cpu")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } - defer iter.Close() - - elem, err := iter.Next() - if err != nil { - t.Fatal(err) - } - if elem.SeriesID.IsZero() { - t.Fatalf("series index mismatch: EOF, exp 2 series") - } - - // Lookup series. - name, tags := e.sfile.Series(elem.SeriesID) - if got, exp := name, []byte("cpu"); !bytes.Equal(got, exp) { - t.Fatalf("series mismatch: got %s, exp %s", got, exp) - } - - if !tags.Equal(models.NewTags(map[string]string{"host": "A"})) && !tags.Equal(models.NewTags(map[string]string{"host": "C"})) { - t.Fatalf(`series mismatch: got %s, exp either "host=A" or "host=C"`, tags) - } - iter.Close() - - // Deleting remaining series should remove them from the series. - itr = &seriesIterator{keys: [][]byte{[]byte("cpu,host=A"), []byte("cpu,host=C")}} - if err := e.DeleteSeriesRange(itr, 0, 9000000000); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - if iter, err = e.index.MeasurementSeriesIDIterator([]byte("cpu")); err != nil { - t.Fatalf("iterator error: %v", err) - } - if iter == nil { - return - } - - defer iter.Close() - if elem, err = iter.Next(); err != nil { - t.Fatal(err) - } - if !elem.SeriesID.IsZero() { - t.Fatalf("got an undeleted series id, but series should be dropped from index") - } -} - -// Tests that a nil predicate deletes all values returned from the series iterator. -func TestEngine_DeleteSeriesRangeWithPredicate_Nil(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 6000000000") // Should not be deleted - p2 := MustParsePointString("cpu,host=A value=1.2 2000000000") // Should not be deleted - p3 := MustParsePointString("cpu,host=B value=1.3 3000000000") - p4 := MustParsePointString("cpu,host=B value=1.3 4000000000") - p5 := MustParsePointString("cpu,host=C value=1.3 5000000000") // Should not be deleted - p6 := MustParsePointString("mem,host=B value=1.3 1000000000") - p7 := MustParsePointString("mem,host=C value=1.3 1000000000") - p8 := MustParsePointString("disk,host=C value=1.3 1000000000") // Should not be deleted - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3, p4, p5, p6, p7, p8); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 6, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A"), []byte("cpu,host=B"), []byte("cpu,host=C"), []byte("mem,host=B"), []byte("mem,host=C")}} - if err := e.DeleteSeriesRangeWithPredicate(itr, nil); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 1, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - // Check that the series still exists in the index - iter, err := e.index.MeasurementSeriesIDIterator([]byte("cpu")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } else if iter == nil { - return - } - defer iter.Close() - - if elem, err := iter.Next(); err != nil { - t.Fatal(err) - } else if !elem.SeriesID.IsZero() { - t.Fatalf("got an undeleted series id, but series should be dropped from index") - } - - // Check that disk series still exists - iter, err = e.index.MeasurementSeriesIDIterator([]byte("disk")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } else if iter == nil { - return - } - defer iter.Close() - - if elem, err := iter.Next(); err != nil { - t.Fatal(err) - } else if elem.SeriesID.IsZero() { - t.Fatalf("got an undeleted series id, but series should be dropped from index") - } -} - -func TestEngine_DeleteSeriesRangeWithPredicate_FlushBatch(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 6000000000") // Should not be deleted - p2 := MustParsePointString("cpu,host=A value=1.2 2000000000") // Should not be deleted - p3 := MustParsePointString("cpu,host=B value=1.3 3000000000") - p4 := MustParsePointString("cpu,host=B value=1.3 4000000000") - p5 := MustParsePointString("cpu,host=C value=1.3 5000000000") // Should not be deleted - p6 := MustParsePointString("mem,host=B value=1.3 1000000000") - p7 := MustParsePointString("mem,host=C value=1.3 1000000000") - p8 := MustParsePointString("disk,host=C value=1.3 1000000000") // Should not be deleted - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1, p2, p3, p4, p5, p6, p7, p8); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 6, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A"), []byte("cpu,host=B"), []byte("cpu,host=C"), []byte("mem,host=B"), []byte("mem,host=C")}} - predicate := func(name []byte, tags models.Tags) (int64, int64, bool) { - if bytes.Equal(name, []byte("mem")) { - return 1000000000, 1000000000, true - } - - if bytes.Equal(name, []byte("cpu")) { - for _, tag := range tags { - if bytes.Equal(tag.Key, []byte("host")) && bytes.Equal(tag.Value, []byte("B")) { - return 3000000000, 4000000000, true - } - } - } - return math.MinInt64, math.MaxInt64, false - } - if err := e.DeleteSeriesRangeWithPredicate(itr, predicate); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 3, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - exps := []string{"cpu,host=A#!~#value", "cpu,host=C#!~#value", "disk,host=C#!~#value"} - for _, exp := range exps { - if _, ok := keys[exp]; !ok { - t.Fatalf("wrong series deleted: exp %v, got %v", exps, keys) - } - } - - // Check that the series still exists in the index - iter, err := e.index.MeasurementSeriesIDIterator([]byte("cpu")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } - defer iter.Close() - - elem, err := iter.Next() - if err != nil { - t.Fatal(err) - } - if elem.SeriesID.IsZero() { - t.Fatalf("series index mismatch: EOF, exp 2 series") - } - - // Lookup series. - name, tags := e.sfile.Series(elem.SeriesID) - if got, exp := name, []byte("cpu"); !bytes.Equal(got, exp) { - t.Fatalf("series mismatch: got %s, exp %s", got, exp) - } - - if !tags.Equal(models.NewTags(map[string]string{"host": "A"})) && !tags.Equal(models.NewTags(map[string]string{"host": "C"})) { - t.Fatalf(`series mismatch: got %s, exp either "host=A" or "host=C"`, tags) - } - iter.Close() - - // Deleting remaining series should remove them from the series. - itr = &seriesIterator{keys: [][]byte{[]byte("cpu,host=A"), []byte("cpu,host=C")}} - if err := e.DeleteSeriesRange(itr, 0, 9000000000); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - if iter, err = e.index.MeasurementSeriesIDIterator([]byte("cpu")); err != nil { - t.Fatalf("iterator error: %v", err) - } - if iter == nil { - return - } - - defer iter.Close() - if elem, err = iter.Next(); err != nil { - t.Fatal(err) - } - if !elem.SeriesID.IsZero() { - t.Fatalf("got an undeleted series id, but series should be dropped from index") - } -} - -func TestEngine_DeleteSeriesRange_OutsideTime(t *testing.T) { - // Create a few points. - p1 := MustParsePointString("cpu,host=A value=1.1 1000000000") // Should not be deleted - - e, err := NewEngine() - if err != nil { - t.Fatal(err) - } - - // mock the planner so compactions don't run during the test - e.CompactionPlan = &mockPlanner{} - if err := e.Open(); err != nil { - t.Fatal(err) - } - defer e.Close() - - if err := e.writePoints(p1); err != nil { - t.Fatalf("failed to write points: %s", err.Error()) - } - - if err := e.WriteSnapshot(); err != nil { - t.Fatalf("failed to snapshot: %s", err.Error()) - } - - keys := e.FileStore.Keys() - if exp, got := 1, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - itr := &seriesIterator{keys: [][]byte{[]byte("cpu,host=A")}} - if err := e.DeleteSeriesRange(itr, 0, 0); err != nil { - t.Fatalf("failed to delete series: %v", err) - } - - keys = e.FileStore.Keys() - if exp, got := 1, len(keys); exp != got { - t.Fatalf("series count mismatch: exp %v, got %v", exp, got) - } - - exp := "cpu,host=A#!~#value" - if _, ok := keys[exp]; !ok { - t.Fatalf("wrong series deleted: exp %v, got %v", exp, keys) - } - - // Check that the series still exists in the index - iter, err := e.index.MeasurementSeriesIDIterator([]byte("cpu")) - if err != nil { - t.Fatalf("iterator error: %v", err) - } - defer iter.Close() - - elem, err := iter.Next() - if err != nil { - t.Fatal(err) - } - if elem.SeriesID.IsZero() { - t.Fatalf("series index mismatch: EOF, exp 1 series") - } - - // Lookup series. - name, tags := e.sfile.Series(elem.SeriesID) - if got, exp := name, []byte("cpu"); !bytes.Equal(got, exp) { - t.Fatalf("series mismatch: got %s, exp %s", got, exp) - } - - if got, exp := tags, models.NewTags(map[string]string{"host": "A"}); !got.Equal(exp) { - t.Fatalf("series mismatch: got %s, exp %s", got, exp) - } -} - func TestEngine_SnapshotsDisabled(t *testing.T) { sfile := MustOpenSeriesFile() defer sfile.Close() @@ -968,7 +433,7 @@ func (e *Engine) WritePointsString(ptstr ...string) error { func (e *Engine) writePoints(points ...models.Point) error { // Write into the index. collection := tsdb.NewSeriesCollection(points) - if err := e.CreateSeriesListIfNotExists(collection); err != nil { + if err := e.index.CreateSeriesListIfNotExists(collection); err != nil { return err } // Write the points into the cache/wal. From 376b347d56d6b04c637b27ca4f7e7b33ca1e8489 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Mon, 21 Jan 2019 13:30:18 -0700 Subject: [PATCH 26/95] wal: change deletes to be based on DeleteBucket --- storage/engine.go | 135 +++++++--------- storage/wal/reader.go | 86 ++++++++++ storage/wal/wal.go | 210 +++++++----------------- storage/wal/wal_test.go | 348 ++++------------------------------------ tsdb/tsm1/cache.go | 84 ++-------- tsdb/tsm1/cache_test.go | 67 -------- 6 files changed, 245 insertions(+), 685 deletions(-) create mode 100644 storage/wal/reader.go diff --git a/storage/engine.go b/storage/engine.go index 5b8b4954c0..d7416bf4ac 100644 --- a/storage/engine.go +++ b/storage/engine.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "math" - "os" "sync" "time" @@ -200,12 +199,10 @@ func (e *Engine) Open() (err error) { return err } - if err := e.reloadCache(); err != nil { + if err := e.replayWAL(); err != nil { return err } - e.engine.SetCompactionsEnabled(true) // TODO(edd):is this needed? - e.closing = make(chan struct{}) // TODO(edd) background tasks will be run in priority order via a scheduler. @@ -216,85 +213,52 @@ func (e *Engine) Open() (err error) { return nil } -// reloadCache reads the WAL segment files and loads them into the cache. -func (e *Engine) reloadCache() error { +// replayWAL reads the WAL segment files and replays them. +func (e *Engine) replayWAL() error { if !e.config.WAL.Enabled { return nil } - now := time.Now() - files, err := wal.SegmentFileNames(e.wal.Path()) + + walPaths, err := wal.SegmentFileNames(e.wal.Path()) if err != nil { return err } + // TODO(jeff): we should just do snapshots and wait for them so that we don't hit + // OOM situations when reloading huge WALs. + // Disable the max size during loading limit := e.engine.Cache.MaxSize() defer func() { e.engine.Cache.SetMaxSize(limit) }() e.engine.Cache.SetMaxSize(0) - for _, file := range files { - if err := e.reloadWALFile(file); err != nil { + // Execute all the entries in the WAL again + reader := wal.NewWALReader(walPaths) + reader.WithLogger(e.logger) + err = reader.Read(func(entry wal.WALEntry) error { + switch en := entry.(type) { + case *wal.WriteWALEntry: + points := tsm1.ValuesToPoints(en.Values) + err := e.writePointsLocked(tsdb.NewSeriesCollection(points), en.Values) + if _, ok := err.(tsdb.PartialWriteError); ok { + err = nil + } return err + + case *wal.DeleteBucketRangeWALEntry: + return e.deleteBucketRangeLocked(en.OrgID, en.BucketID, en.Min, en.Max) } - } + + return nil + }) e.logger.Info("Reloaded WAL", zap.String("path", e.wal.Path()), - zap.Duration("duration", time.Since(now))) - return nil -} + zap.Duration("duration", time.Since(now)), + zap.Error(err)) -// reloadWALFile executes all of the actions in the WAL against the engine. -func (e *Engine) reloadWALFile(file string) error { - f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0666) - if err != nil { - return err - } - defer f.Close() - - stat, err := f.Stat() - if err != nil { - return err - } - e.logger.Info("Reading file", zap.String("path", file), zap.Int64("size", stat.Size())) - - if stat.Size() == 0 { - return nil - } - - r := wal.NewWALSegmentReader(f) - defer r.Close() - - for r.Next() { - entry, err := r.Read() - if err != nil { - n := r.Count() - e.logger.Info("File corrupt", zap.Error(err), zap.String("path", file), zap.Int64("pos", n)) - if err := f.Truncate(n); err != nil { - return err - } - break - } - - switch t := entry.(type) { - case *wal.WriteWALEntry: - points := tsm1.ValuesToPoints(t.Values) - err := e.writePointsLocked(tsdb.NewSeriesCollection(points), t.Values) - if _, ok := err.(tsdb.PartialWriteError); err != nil && !ok { - return err - } - - case *wal.DeleteRangeWALEntry: - // TODO(jeff): implement? - - case *wal.DeleteWALEntry: - // TODO(jeff): implement? - - } - } - - return r.Close() + return err } // runRetentionEnforcer runs the retention enforcer in a separate goroutine. @@ -365,6 +329,7 @@ func (e *Engine) Close() error { return ch.Done() } +// CreateSeriesCursor creates a SeriesCursor for usage with the read service. func (e *Engine) CreateSeriesCursor(ctx context.Context, req SeriesCursorRequest, cond influxql.Expr) (SeriesCursor, error) { e.mu.RLock() defer e.mu.RUnlock() @@ -374,6 +339,7 @@ func (e *Engine) CreateSeriesCursor(ctx context.Context, req SeriesCursorRequest return newSeriesCursor(req, e.index, cond) } +// CreateCursorIterator creates a CursorIterator for usage with the read service. func (e *Engine) CreateCursorIterator(ctx context.Context) (tsdb.CursorIterator, error) { e.mu.RLock() defer e.mu.RUnlock() @@ -435,7 +401,18 @@ func (e *Engine) WritePoints(points []models.Point) error { return ErrEngineClosed } - return e.writePointsLocked(collection, nil) + // Convert the points to values for adding to the WAL/Cache. + values, err := tsm1.PointsToValues(collection.Points) + if err != nil { + return err + } + + // Add the write to the WAL to be replayed if there is a crash or shutdown. + if _, err := e.wal.WriteMulti(values); err != nil { + return err + } + + return e.writePointsLocked(collection, values) } // writePointsLocked does the work of writing points and must be called under some sort of lock. @@ -444,28 +421,15 @@ func (e *Engine) writePointsLocked(collection *tsdb.SeriesCollection, values map // errors get tracked all the way. Right now, the engine doesn't drop any values // but if it ever did, the errors could end up missing some data. - // Load up the values if they haven't been passed in. - var err error - if values == nil { - values, err = tsm1.PointsToValues(collection.Points) - if err != nil { - return err - } - } - - // Add the write to the WAL to be replayed if there is a crash or shutdown. - if _, err := e.wal.WriteMulti(values); err != nil { - return err - } - // Add new series to the index and series file. if err := e.index.CreateSeriesListIfNotExists(collection); err != nil { return err } - // If there was a PartialWriteError already, that means the values may contain + // If there was a PartialWriteError, that means the passed in values may contain // more than the points so we need to recreate them. if collection.PartialWriteError() != nil { + var err error values, err = tsm1.PointsToValues(collection.Points) if err != nil { return err @@ -524,8 +488,17 @@ func (e *Engine) DeleteBucketRange(orgID, bucketID platform.ID, min, max int64) return ErrEngineClosed } - // TODO(jeff): write the DeleteBucket request to the WAL. + // Add the delete to the WAL to be replayed if there is a crash or shutdown. + if _, err := e.wal.DeleteBucketRange(orgID, bucketID, min, max); err != nil { + return err + } + return e.deleteBucketRangeLocked(orgID, bucketID, min, max) +} + +// deleteBucketRangeLocked does the work of deleting a bucket range and must be called under +// some sort of lock. +func (e *Engine) deleteBucketRangeLocked(orgID, bucketID platform.ID, min, max int64) error { // TODO(edd): we need to clean up how we're encoding the prefix so that we // don't have to remember to get it right everywhere we need to touch TSM data. encoded := tsdb.EncodeName(orgID, bucketID) diff --git a/storage/wal/reader.go b/storage/wal/reader.go new file mode 100644 index 0000000000..2ebf126b18 --- /dev/null +++ b/storage/wal/reader.go @@ -0,0 +1,86 @@ +package wal + +import ( + "os" + "sort" + + "go.uber.org/zap" +) + +// WALReader helps one read out the WAL into entries. +type WALReader struct { + files []string + logger *zap.Logger + r *WALSegmentReader +} + +// NewWALReader constructs a WALReader over the given set of files. +func NewWALReader(files []string) *WALReader { + sort.Strings(files) + return &WALReader{ + files: files, + logger: zap.NewNop(), + r: nil, + } +} + +// WithLogger sets the logger for the WALReader. +func (r *WALReader) WithLogger(logger *zap.Logger) { r.logger = logger } + +// Read calls the callback with every entry in the WAL files. If, during +// reading of a segment file, corruption is encountered, that segment file +// is truncated up to and including the last valid byte, and processing +// continues with the next segment file. +func (r *WALReader) Read(cb func(WALEntry) error) error { + for _, file := range r.files { + if err := r.readFile(file, cb); err != nil { + return err + } + } + return nil +} + +// readFile reads the file and calls the callback with each WAL entry. +// It uses the provided logger for information about progress and corruptions. +func (r *WALReader) readFile(file string, cb func(WALEntry) error) error { + f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0666) + if err != nil { + return err + } + defer f.Close() + + stat, err := f.Stat() + if err != nil { + return err + } + r.logger.Info("Reading file", zap.String("path", file), zap.Int64("size", stat.Size())) + + if stat.Size() == 0 { + return nil + } + + if r.r == nil { + r.r = NewWALSegmentReader(f) + } else { + r.r.Reset(f) + } + defer r.r.Close() + + for r.r.Next() { + entry, err := r.r.Read() + if err != nil { + n := r.r.Count() + r.logger.Info("File corrupt", zap.Error(err), zap.String("path", file), zap.Int64("pos", n)) + if err := f.Truncate(n); err != nil { + return err + } + break + } + + if err := cb(entry); err != nil { + return err + } + } + + return r.r.Close() +} diff --git a/storage/wal/wal.go b/storage/wal/wal.go index f3aa6be757..cb63303345 100644 --- a/storage/wal/wal.go +++ b/storage/wal/wal.go @@ -2,7 +2,6 @@ package wal import ( "bufio" - "bytes" "encoding/binary" "fmt" "io" @@ -18,6 +17,7 @@ import ( "time" "github.com/golang/snappy" + "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/pkg/limiter" "github.com/influxdata/influxdb/pkg/pool" "github.com/influxdata/influxdb/tsdb/value" @@ -52,11 +52,14 @@ const ( // WriteWALEntryType indicates a write entry. WriteWALEntryType WalEntryType = 0x01 - // DeleteWALEntryType indicates a delete entry. - DeleteWALEntryType WalEntryType = 0x02 + // DeleteWALEntryType indicates a delete entry. Deprecated. + _ WalEntryType = 0x02 - // DeleteRangeWALEntryType indicates a delete range entry. - DeleteRangeWALEntryType WalEntryType = 0x03 + // DeleteRangeWALEntryType indicates a delete range entry. Deprecated. + _ WalEntryType = 0x03 + + // DeleteBucketRangeWALEntryType indicates a delete bucket range entry. + DeleteBucketRangeWALEntryType WalEntryType = 0x04 ) var ( @@ -517,32 +520,18 @@ func (l *WAL) CloseSegment() error { return nil } -// Delete deletes the given keys, returning the segment ID for the operation. -func (l *WAL) Delete(keys [][]byte) (int, error) { - if len(keys) == 0 { - return 0, nil - } - entry := &DeleteWALEntry{ - Keys: keys, +// DeleteBucketRange deletes the data inside of the bucket between the two times, returning +// the segment ID for the operation. +func (l *WAL) DeleteBucketRange(orgID, bucketID influxdb.ID, min, max int64) (int, error) { + if !l.enabled { + return -1, nil } - id, err := l.writeToLog(entry) - if err != nil { - return -1, err - } - return id, nil -} - -// DeleteRange deletes the given keys within the given time range, -// returning the segment ID for the operation. -func (l *WAL) DeleteRange(keys [][]byte, min, max int64) (int, error) { - if len(keys) == 0 { - return 0, nil - } - entry := &DeleteRangeWALEntry{ - Keys: keys, - Min: min, - Max: max, + entry := &DeleteBucketRangeWALEntry{ + OrgID: orgID, + BucketID: bucketID, + Min: min, + Max: max, } id, err := l.writeToLog(entry) @@ -708,6 +697,7 @@ type WriteWALEntry struct { sz int } +// MarshalSize returns the number of bytes the entry takes when marshaled. func (w *WriteWALEntry) MarshalSize() int { if w.sz > 0 || len(w.Values) == 0 { return w.sz @@ -999,152 +989,70 @@ func (w *WriteWALEntry) Type() WalEntryType { return WriteWALEntryType } -// DeleteWALEntry represents the deletion of multiple series. -type DeleteWALEntry struct { - Keys [][]byte - sz int -} - -// MarshalBinary returns a binary representation of the entry in a new byte slice. -func (w *DeleteWALEntry) MarshalBinary() ([]byte, error) { - b := make([]byte, w.MarshalSize()) - return w.Encode(b) -} - -// UnmarshalBinary deserializes the byte slice into w. -func (w *DeleteWALEntry) UnmarshalBinary(b []byte) error { - if len(b) == 0 { - return nil - } - - // b originates from a pool. Copy what needs to be retained. - buf := make([]byte, len(b)) - copy(buf, b) - w.Keys = bytes.Split(buf, []byte("\n")) - return nil -} - -func (w *DeleteWALEntry) MarshalSize() int { - if w.sz > 0 || len(w.Keys) == 0 { - return w.sz - } - - encLen := len(w.Keys) // newlines - for _, k := range w.Keys { - encLen += len(k) - } - - w.sz = encLen - - return encLen -} - -// Encode converts the DeleteWALEntry into a byte slice, appending to dst. -func (w *DeleteWALEntry) Encode(dst []byte) ([]byte, error) { - sz := w.MarshalSize() - - if len(dst) < sz { - dst = make([]byte, sz) - } - - var n int - for _, k := range w.Keys { - n += copy(dst[n:], k) - n += copy(dst[n:], "\n") - } - - // We return n-1 to strip off the last newline so that unmarshalling the value - // does not produce an empty string - return []byte(dst[:n-1]), nil -} - -// Type returns DeleteWALEntryType. -func (w *DeleteWALEntry) Type() WalEntryType { - return DeleteWALEntryType -} - -// DeleteRangeWALEntry represents the deletion of multiple series. -type DeleteRangeWALEntry struct { - Keys [][]byte +// DeleteBucketRangeWALEntry represents the deletion of data in a bucket. +type DeleteBucketRangeWALEntry struct { + OrgID influxdb.ID + BucketID influxdb.ID Min, Max int64 - sz int } // MarshalBinary returns a binary representation of the entry in a new byte slice. -func (w *DeleteRangeWALEntry) MarshalBinary() ([]byte, error) { +func (w *DeleteBucketRangeWALEntry) MarshalBinary() ([]byte, error) { b := make([]byte, w.MarshalSize()) return w.Encode(b) } // UnmarshalBinary deserializes the byte slice into w. -func (w *DeleteRangeWALEntry) UnmarshalBinary(b []byte) error { - if len(b) < 16 { +func (w *DeleteBucketRangeWALEntry) UnmarshalBinary(b []byte) error { + if len(b) != 2*influxdb.IDLength+16 { return ErrWALCorrupt } - w.Min = int64(binary.BigEndian.Uint64(b[:8])) - w.Max = int64(binary.BigEndian.Uint64(b[8:16])) - - i := 16 - for i < len(b) { - if i+4 > len(b) { - return ErrWALCorrupt - } - sz := int(binary.BigEndian.Uint32(b[i : i+4])) - i += 4 - - if i+sz > len(b) { - return ErrWALCorrupt - } - - // b originates from a pool. Copy what needs to be retained. - buf := make([]byte, sz) - copy(buf, b[i:i+sz]) - w.Keys = append(w.Keys, buf) - i += sz + if err := w.OrgID.Decode(b[0:influxdb.IDLength]); err != nil { + return err } + if err := w.BucketID.Decode(b[influxdb.IDLength : 2*influxdb.IDLength]); err != nil { + return err + } + w.Min = int64(binary.BigEndian.Uint64(b[2*influxdb.IDLength : 2*influxdb.IDLength+8])) + w.Max = int64(binary.BigEndian.Uint64(b[2*influxdb.IDLength+8 : 2*influxdb.IDLength+16])) + return nil } -func (w *DeleteRangeWALEntry) MarshalSize() int { - if w.sz > 0 { - return w.sz - } - - sz := 16 + len(w.Keys)*4 - for _, k := range w.Keys { - sz += len(k) - } - - w.sz = sz - - return sz +// MarshalSize returns the number of bytes the entry takes when marshaled. +func (w *DeleteBucketRangeWALEntry) MarshalSize() int { + return 2*influxdb.IDLength + 16 } -// Encode converts the DeleteRangeWALEntry into a byte slice, appending to b. -func (w *DeleteRangeWALEntry) Encode(b []byte) ([]byte, error) { +// Encode converts the entry into a byte stream using b if it is large enough. +// If b is too small, a newly allocated slice is returned. +func (w *DeleteBucketRangeWALEntry) Encode(b []byte) ([]byte, error) { sz := w.MarshalSize() - if len(b) < sz { b = make([]byte, sz) } - binary.BigEndian.PutUint64(b[:8], uint64(w.Min)) - binary.BigEndian.PutUint64(b[8:16], uint64(w.Max)) - - i := 16 - for _, k := range w.Keys { - binary.BigEndian.PutUint32(b[i:i+4], uint32(len(k))) - i += 4 - i += copy(b[i:], k) + orgID, err := w.OrgID.Encode() + if err != nil { + return nil, err + } + bucketID, err := w.BucketID.Encode() + if err != nil { + return nil, err } - return b[:i], nil + copy(b, orgID) + copy(b[influxdb.IDLength:], bucketID) + binary.BigEndian.PutUint64(b[2*influxdb.IDLength:], uint64(w.Min)) + binary.BigEndian.PutUint64(b[2*influxdb.IDLength+8:], uint64(w.Max)) + + return b[:sz], nil } -// Type returns DeleteRangeWALEntryType. -func (w *DeleteRangeWALEntry) Type() WalEntryType { - return DeleteRangeWALEntryType +// Type returns DeleteBucketRangeWALEntryType. +func (w *DeleteBucketRangeWALEntry) Type() WalEntryType { + return DeleteBucketRangeWALEntryType } // WALSegmentWriter writes WAL segments. @@ -1290,10 +1198,8 @@ func (r *WALSegmentReader) Next() bool { r.entry = &WriteWALEntry{ Values: make(map[string][]value.Value), } - case DeleteWALEntryType: - r.entry = &DeleteWALEntry{} - case DeleteRangeWALEntryType: - r.entry = &DeleteRangeWALEntry{} + case DeleteBucketRangeWALEntryType: + r.entry = &DeleteBucketRangeWALEntry{} default: r.err = fmt.Errorf("unknown wal entry type: %v", entryType) return true diff --git a/storage/wal/wal_test.go b/storage/wal/wal_test.go index b7590cf98d..8347510375 100644 --- a/storage/wal/wal_test.go +++ b/storage/wal/wal_test.go @@ -3,12 +3,13 @@ package wal import ( "fmt" "io" + "math/rand" "os" "reflect" "testing" "github.com/golang/snappy" - "github.com/influxdata/influxdb/pkg/slices" + "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/tsdb/value" ) @@ -137,6 +138,7 @@ func TestWALWriter_WriteMulti_LargeBatch(t *testing.T) { t.Fatalf("wrong count of bytes read, got %d, exp %d", n, MustReadFileSize(f)) } } + func TestWALWriter_WriteMulti_Multiple(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) @@ -211,14 +213,17 @@ func TestWALWriter_WriteMulti_Multiple(t *testing.T) { } } -func TestWALWriter_WriteDelete_Single(t *testing.T) { +func TestWALWriter_DeleteBucketRange(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) f := MustTempFile(dir) w := NewWALSegmentWriter(f) - entry := &DeleteWALEntry{ - Keys: [][]byte{[]byte("cpu")}, + entry := &DeleteBucketRangeWALEntry{ + OrgID: influxdb.ID(1), + BucketID: influxdb.ID(2), + Min: 3, + Max: 4, } if err := w.Write(mustMarshalEntry(entry)); err != nil { @@ -244,220 +249,14 @@ func TestWALWriter_WriteDelete_Single(t *testing.T) { fatal(t, "read entry", err) } - e, ok := we.(*DeleteWALEntry) + e, ok := we.(*DeleteBucketRangeWALEntry) if !ok { t.Fatalf("expected WriteWALEntry: got %#v", e) } - if got, exp := len(e.Keys), len(entry.Keys); got != exp { - t.Fatalf("key length mismatch: got %v, exp %v", got, exp) + if !reflect.DeepEqual(entry, e) { + t.Fatalf("expected %+v but got %+v", entry, e) } - - if got, exp := string(e.Keys[0]), string(entry.Keys[0]); got != exp { - t.Fatalf("key mismatch: got %v, exp %v", got, exp) - } -} - -func TestWALWriter_WriteMultiDelete_Multiple(t *testing.T) { - dir := MustTempDir() - defer os.RemoveAll(dir) - f := MustTempFile(dir) - w := NewWALSegmentWriter(f) - - p1 := value.NewValue(1, true) - values := map[string][]value.Value{ - "cpu,host=A#!~#value": []value.Value{p1}, - } - - writeEntry := &WriteWALEntry{ - Values: values, - } - - if err := w.Write(mustMarshalEntry(writeEntry)); err != nil { - fatal(t, "write points", err) - } - - if err := w.Flush(); err != nil { - fatal(t, "flush", err) - } - - // Write the delete entry - deleteEntry := &DeleteWALEntry{ - Keys: [][]byte{[]byte("cpu,host=A#!~value")}, - } - - if err := w.Write(mustMarshalEntry(deleteEntry)); err != nil { - fatal(t, "write points", err) - } - - if err := w.Flush(); err != nil { - fatal(t, "flush", err) - } - - // Seek back to the beinning of the file for reading - if _, err := f.Seek(0, io.SeekStart); err != nil { - fatal(t, "seek", err) - } - - r := NewWALSegmentReader(f) - - // Read the write points first - if !r.Next() { - t.Fatalf("expected next, got false") - } - - we, err := r.Read() - if err != nil { - fatal(t, "read entry", err) - } - - e, ok := we.(*WriteWALEntry) - if !ok { - t.Fatalf("expected WriteWALEntry: got %#v", e) - } - - for k, v := range e.Values { - if got, exp := len(v), len(values[k]); got != exp { - t.Fatalf("values length mismatch: got %v, exp %v", got, exp) - } - - for i, vv := range v { - if got, exp := vv.String(), values[k][i].String(); got != exp { - t.Fatalf("points mismatch: got %v, exp %v", got, exp) - } - } - } - - // Read the delete second - if !r.Next() { - t.Fatalf("expected next, got false") - } - - we, err = r.Read() - if err != nil { - fatal(t, "read entry", err) - } - - de, ok := we.(*DeleteWALEntry) - if !ok { - t.Fatalf("expected DeleteWALEntry: got %#v", e) - } - - if got, exp := len(de.Keys), len(deleteEntry.Keys); got != exp { - t.Fatalf("key length mismatch: got %v, exp %v", got, exp) - } - - if got, exp := string(de.Keys[0]), string(deleteEntry.Keys[0]); got != exp { - t.Fatalf("key mismatch: got %v, exp %v", got, exp) - } -} - -func TestWALWriter_WriteMultiDeleteRange_Multiple(t *testing.T) { - dir := MustTempDir() - defer os.RemoveAll(dir) - f := MustTempFile(dir) - w := NewWALSegmentWriter(f) - - p1 := value.NewValue(1, 1.0) - p2 := value.NewValue(2, 2.0) - p3 := value.NewValue(3, 3.0) - - values := map[string][]value.Value{ - "cpu,host=A#!~#value": []value.Value{p1, p2, p3}, - } - - writeEntry := &WriteWALEntry{ - Values: values, - } - - if err := w.Write(mustMarshalEntry(writeEntry)); err != nil { - fatal(t, "write points", err) - } - - if err := w.Flush(); err != nil { - fatal(t, "flush", err) - } - - // Write the delete entry - deleteEntry := &DeleteRangeWALEntry{ - Keys: [][]byte{[]byte("cpu,host=A#!~value")}, - Min: 2, - Max: 3, - } - - if err := w.Write(mustMarshalEntry(deleteEntry)); err != nil { - fatal(t, "write points", err) - } - - if err := w.Flush(); err != nil { - fatal(t, "flush", err) - } - - // Seek back to the beinning of the file for reading - if _, err := f.Seek(0, io.SeekStart); err != nil { - fatal(t, "seek", err) - } - - r := NewWALSegmentReader(f) - - // Read the write points first - if !r.Next() { - t.Fatalf("expected next, got false") - } - - we, err := r.Read() - if err != nil { - fatal(t, "read entry", err) - } - - e, ok := we.(*WriteWALEntry) - if !ok { - t.Fatalf("expected WriteWALEntry: got %#v", e) - } - - for k, v := range e.Values { - if got, exp := len(v), len(values[k]); got != exp { - t.Fatalf("values length mismatch: got %v, exp %v", got, exp) - } - - for i, vv := range v { - if got, exp := vv.String(), values[k][i].String(); got != exp { - t.Fatalf("points mismatch: got %v, exp %v", got, exp) - } - } - } - - // Read the delete second - if !r.Next() { - t.Fatalf("expected next, got false") - } - - we, err = r.Read() - if err != nil { - fatal(t, "read entry", err) - } - - de, ok := we.(*DeleteRangeWALEntry) - if !ok { - t.Fatalf("expected DeleteWALEntry: got %#v", e) - } - - if got, exp := len(de.Keys), len(deleteEntry.Keys); got != exp { - t.Fatalf("key length mismatch: got %v, exp %v", got, exp) - } - - if got, exp := string(de.Keys[0]), string(deleteEntry.Keys[0]); got != exp { - t.Fatalf("key mismatch: got %v, exp %v", got, exp) - } - - if got, exp := de.Min, int64(2); got != exp { - t.Fatalf("min time mismatch: got %v, exp %v", got, exp) - } - - if got, exp := de.Max, int64(3); got != exp { - t.Fatalf("min time mismatch: got %v, exp %v", got, exp) - } - } func TestWAL_ClosedSegments(t *testing.T) { @@ -506,48 +305,6 @@ func TestWAL_ClosedSegments(t *testing.T) { } } -func TestWAL_Delete(t *testing.T) { - dir := MustTempDir() - defer os.RemoveAll(dir) - - w := NewWAL(dir) - if err := w.Open(); err != nil { - t.Fatalf("error opening WAL: %v", err) - } - - files, err := w.ClosedSegments() - if err != nil { - t.Fatalf("error getting closed segments: %v", err) - } - - if got, exp := len(files), 0; got != exp { - t.Fatalf("close segment length mismatch: got %v, exp %v", got, exp) - } - - if _, err := w.Delete([][]byte{[]byte("cpu")}); err != nil { - t.Fatalf("error writing points: %v", err) - } - - if err := w.Close(); err != nil { - t.Fatalf("error closing wal: %v", err) - } - - // Re-open the WAL - w = NewWAL(dir) - defer w.Close() - if err := w.Open(); err != nil { - t.Fatalf("error opening WAL: %v", err) - } - - files, err = w.ClosedSegments() - if err != nil { - t.Fatalf("error getting closed segments: %v", err) - } - if got, exp := len(files), 0; got != exp { - t.Fatalf("close segment length mismatch: got %v, exp %v", got, exp) - } -} - func TestWALWriter_Corrupt(t *testing.T) { dir := MustTempDir() defer os.RemoveAll(dir) @@ -687,78 +444,37 @@ func TestWriteWALSegment_UnmarshalBinary_WriteWALCorrupt(t *testing.T) { } } -func TestDeleteWALEntry_UnmarshalBinary(t *testing.T) { - examples := []struct { - In []string - Out [][]byte - }{ - { - In: []string{""}, - Out: nil, - }, - { - In: []string{"foo"}, - Out: [][]byte{[]byte("foo")}, - }, - { - In: []string{"foo", "bar"}, - Out: [][]byte{[]byte("foo"), []byte("bar")}, - }, - { - In: []string{"foo", "bar", "z", "abc"}, - Out: [][]byte{[]byte("foo"), []byte("bar"), []byte("z"), []byte("abc")}, - }, - { - In: []string{"foo", "bar", "z", "a"}, - Out: [][]byte{[]byte("foo"), []byte("bar"), []byte("z"), []byte("a")}, - }, - } +func TestDeleteBucketRangeWALEntry_UnmarshalBinary(t *testing.T) { + for i := 0; i < 1000; i++ { + in := &DeleteBucketRangeWALEntry{ + OrgID: influxdb.ID(rand.Int63()) + 1, + BucketID: influxdb.ID(rand.Int63()) + 1, + Min: rand.Int63(), + Max: rand.Int63(), + } - for i, example := range examples { - w := &DeleteWALEntry{Keys: slices.StringsToBytes(example.In...)} - b, err := w.MarshalBinary() + b, err := in.MarshalBinary() if err != nil { - t.Fatalf("[example %d] unexpected error, got %v", i, err) + t.Fatalf("unexpected error, got %v", err) } - out := &DeleteWALEntry{} + out := &DeleteBucketRangeWALEntry{} if err := out.UnmarshalBinary(b); err != nil { - t.Fatalf("[example %d] %v", i, err) + t.Fatalf("%v", err) } - if !reflect.DeepEqual(example.Out, out.Keys) { - t.Errorf("[example %d] got %v, expected %v", i, out.Keys, example.Out) + if !reflect.DeepEqual(in, out) { + t.Errorf("got %+v, expected %+v", out, in) } } } -func TestWriteWALSegment_UnmarshalBinary_DeleteWALCorrupt(t *testing.T) { - w := &DeleteWALEntry{ - Keys: [][]byte{[]byte("foo"), []byte("bar")}, - } - - b, err := w.MarshalBinary() - if err != nil { - t.Fatalf("unexpected error, got %v", err) - } - - // Test every possible truncation of a write WAL entry - for i := 0; i < len(b); i++ { - // re-allocated to ensure capacity would be exceed if slicing - truncated := make([]byte, i) - copy(truncated, b[:i]) - err := w.UnmarshalBinary(truncated) - if err != nil && err != ErrWALCorrupt { - t.Fatalf("unexpected error: %v", err) - } - } -} - -func TestWriteWALSegment_UnmarshalBinary_DeleteRangeWALCorrupt(t *testing.T) { - w := &DeleteRangeWALEntry{ - Keys: [][]byte{[]byte("foo"), []byte("bar")}, - Min: 1, - Max: 2, +func TestWriteWALSegment_UnmarshalBinary_DeleteBucketRangeWALCorrupt(t *testing.T) { + w := &DeleteBucketRangeWALEntry{ + OrgID: influxdb.ID(1), + BucketID: influxdb.ID(2), + Min: 3, + Max: 4, } b, err := w.MarshalBinary() diff --git a/tsdb/tsm1/cache.go b/tsdb/tsm1/cache.go index 89981d6111..dab9a362dd 100644 --- a/tsdb/tsm1/cache.go +++ b/tsdb/tsm1/cache.go @@ -3,7 +3,6 @@ package tsm1 import ( "fmt" "math" - "os" "sync" "sync/atomic" "time" @@ -625,92 +624,39 @@ func (c *Cache) ApplyEntryFn(f func(key []byte, entry *entry) error) error { } // CacheLoader processes a set of WAL segment files, and loads a cache with the data -// contained within those files. Processing of the supplied files take place in the -// order they exist in the files slice. +// contained within those files. type CacheLoader struct { - files []string - - Logger *zap.Logger + reader *wal.WALReader } // NewCacheLoader returns a new instance of a CacheLoader. func NewCacheLoader(files []string) *CacheLoader { return &CacheLoader{ - files: files, - Logger: zap.NewNop(), + reader: wal.NewWALReader(files), } } // Load returns a cache loaded with the data contained within the segment files. -// If, during reading of a segment file, corruption is encountered, that segment -// file is truncated up to and including the last valid byte, and processing -// continues with the next segment file. func (cl *CacheLoader) Load(cache *Cache) error { + return cl.reader.Read(func(entry wal.WALEntry) error { + switch en := entry.(type) { + case *wal.WriteWALEntry: + return cache.WriteMulti(en.Values) - var r *wal.WALSegmentReader - for _, fn := range cl.files { - if err := func() error { - f, err := os.OpenFile(fn, os.O_CREATE|os.O_RDWR, 0666) - if err != nil { - return err - } - defer f.Close() - - // Log some information about the segments. - stat, err := os.Stat(f.Name()) - if err != nil { - return err - } - cl.Logger.Info("Reading file", zap.String("path", f.Name()), zap.Int64("size", stat.Size())) - - // Nothing to read, skip it - if stat.Size() == 0 { - return nil - } - - if r == nil { - r = wal.NewWALSegmentReader(f) - defer r.Close() - } else { - r.Reset(f) - } - - for r.Next() { - entry, err := r.Read() - if err != nil { - n := r.Count() - cl.Logger.Info("File corrupt", zap.Error(err), zap.String("path", f.Name()), zap.Int64("pos", n)) - if err := f.Truncate(n); err != nil { - return err - } - break - } - - switch t := entry.(type) { - case *wal.WriteWALEntry: - if err := cache.WriteMulti(t.Values); err != nil { - return err - } - case *wal.DeleteRangeWALEntry: - cache.DeleteRange(t.Keys, t.Min, t.Max) - case *wal.DeleteWALEntry: - cache.Delete(t.Keys) - } - } - - return r.Close() - }(); err != nil { - return err + case *wal.DeleteBucketRangeWALEntry: + // TODO(jeff): delete bucket range } - } - return nil + + return nil + }) } // WithLogger sets the logger on the CacheLoader. -func (cl *CacheLoader) WithLogger(log *zap.Logger) { - cl.Logger = log.With(zap.String("service", "cacheloader")) +func (cl *CacheLoader) WithLogger(logger *zap.Logger) { + cl.reader.WithLogger(logger.With(zap.String("service", "cacheloader"))) } +// LastWriteTime returns the time that the cache was last written to. func (c *Cache) LastWriteTime() time.Time { c.mu.RLock() defer c.mu.RUnlock() diff --git a/tsdb/tsm1/cache_test.go b/tsdb/tsm1/cache_test.go index ecc0347703..b5547e2e70 100644 --- a/tsdb/tsm1/cache_test.go +++ b/tsdb/tsm1/cache_test.go @@ -737,73 +737,6 @@ func TestCacheLoader_LoadDouble(t *testing.T) { } } -// Ensure the CacheLoader can load deleted series -func TestCacheLoader_LoadDeleted(t *testing.T) { - // Create a WAL segment. - dir := mustTempDir() - defer os.RemoveAll(dir) - f := mustTempFile(dir) - w := wal.NewWALSegmentWriter(f) - - p1 := NewValue(1, 1.0) - p2 := NewValue(2, 2.0) - p3 := NewValue(3, 3.0) - - values := map[string][]Value{ - "foo": {p1, p2, p3}, - } - - entry := &wal.WriteWALEntry{ - Values: values, - } - - if err := w.Write(mustMarshalEntry(entry)); err != nil { - t.Fatal("write points", err) - } - - if err := w.Flush(); err != nil { - t.Fatalf("flush error: %v", err) - } - - dentry := &wal.DeleteRangeWALEntry{ - Keys: [][]byte{[]byte("foo")}, - Min: 2, - Max: 3, - } - - if err := w.Write(mustMarshalEntry(dentry)); err != nil { - t.Fatal("write points", err) - } - - if err := w.Flush(); err != nil { - t.Fatalf("flush error: %v", err) - } - - // Load the cache using the segment. - cache := NewCache(1024) - loader := NewCacheLoader([]string{f.Name()}) - if err := loader.Load(cache); err != nil { - t.Fatalf("failed to load cache: %s", err.Error()) - } - - // Check the cache. - if values := cache.Values([]byte("foo")); !reflect.DeepEqual(values, Values{p1}) { - t.Fatalf("cache key foo not as expected, got %v, exp %v", values, Values{p1}) - } - - // Reload the cache using the segment. - cache = NewCache(1024) - loader = NewCacheLoader([]string{f.Name()}) - if err := loader.Load(cache); err != nil { - t.Fatalf("failed to load cache: %s", err.Error()) - } - - // Check the cache. - if values := cache.Values([]byte("foo")); !reflect.DeepEqual(values, Values{p1}) { - t.Fatalf("cache key foo not as expected, got %v, exp %v", values, Values{p1}) - } -} - func TestCache_Split(t *testing.T) { v0 := NewValue(1, 1.0) v1 := NewValue(2, 2.0) From a424bf3e4c3951433588e6ccd6b9c66230aefa00 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Mon, 21 Jan 2019 17:23:58 -0700 Subject: [PATCH 27/95] tsm1: implement DeleteBucketRange for the Cache --- tsdb/tsm1/cache.go | 66 +++++++++++++++++-------------- tsdb/tsm1/cache_test.go | 55 ++++---------------------- tsdb/tsm1/engine_delete_bucket.go | 7 +--- 3 files changed, 47 insertions(+), 81 deletions(-) diff --git a/tsdb/tsm1/cache.go b/tsdb/tsm1/cache.go index dab9a362dd..e7aa60d166 100644 --- a/tsdb/tsm1/cache.go +++ b/tsdb/tsm1/cache.go @@ -1,6 +1,7 @@ package tsm1 import ( + "bytes" "fmt" "math" "sync" @@ -545,50 +546,51 @@ func (c *Cache) Values(key []byte) Values { return values } -// Delete removes all values for the given keys from the cache. -func (c *Cache) Delete(keys [][]byte) { - c.DeleteRange(keys, math.MinInt64, math.MaxInt64) -} - -// DeleteRange removes the values for all keys containing points -// with timestamps between between min and max from the cache. -// -// TODO(edd): Lock usage could possibly be optimised if necessary. -func (c *Cache) DeleteRange(keys [][]byte, min, max int64) { +// DeleteBucketRange removes values for all keys containing points +// with timestamps between min and max contained in the bucket identified +// by name from the cache. +func (c *Cache) DeleteBucketRange(name []byte, min, max int64) { c.init() c.mu.Lock() defer c.mu.Unlock() + // TODO(jeff): could optimzie lock usage, and figure a way out to + // avoid storing all of the entry keys to delete. + var toDelete [][]byte var total uint64 - for _, k := range keys { - // Make sure key exist in the cache, skip if it does not - e := c.store.entry(k) - if e == nil { - continue - } + // applySerial only errors if the closure returns an error. + _ = c.store.applySerial(func(k []byte, e *entry) error { + if !bytes.HasPrefix(k, name) { + return nil + } total += uint64(e.size()) - // Everything is being deleted. + + // if everything is being deleted, just stage it to be deleted and move on. if min == math.MinInt64 && max == math.MaxInt64 { - total += uint64(len(k)) // all entries and the key. - c.store.remove(k) - continue + toDelete = append(toDelete, k) + return nil } - // Filter what to delete by time range. + // filter the values and subtract out the remaining bytes from the reduction. e.filter(min, max) + total -= uint64(e.size()) + + // if it has no entries left, flag it to be deleted. if e.count() == 0 { - // Nothing left in cache for that key - total += uint64(len(k)) // all entries and the key. - c.store.remove(k) - continue + toDelete = append(toDelete, k) } - // Just update what is being deleted by the size of the filtered entries. - total -= uint64(e.size()) + return nil + }) + + for _, k := range toDelete { + total += uint64(len(k)) + c.store.remove(k) } - c.tracker.DecCacheSize(total) // Decrease the live cache size. + + c.tracker.DecCacheSize(total) c.tracker.SetMemBytes(uint64(c.Size())) } @@ -644,7 +646,13 @@ func (cl *CacheLoader) Load(cache *Cache) error { return cache.WriteMulti(en.Values) case *wal.DeleteBucketRangeWALEntry: - // TODO(jeff): delete bucket range + // TODO(edd): we need to clean up how we're encoding the prefix so that we + // don't have to remember to get it right everywhere we need to touch TSM data. + encoded := tsdb.EncodeName(en.OrgID, en.BucketID) + name := models.EscapeMeasurement(encoded[:]) + + cache.DeleteBucketRange(name, en.Min, en.Max) + return nil } return nil diff --git a/tsdb/tsm1/cache_test.go b/tsdb/tsm1/cache_test.go index b5547e2e70..4626ce2ed9 100644 --- a/tsdb/tsm1/cache_test.go +++ b/tsdb/tsm1/cache_test.go @@ -169,7 +169,7 @@ func TestCache_CacheWriteMulti_TypeConflict(t *testing.T) { } } -func TestCache_Cache_DeleteRange(t *testing.T) { +func TestCache_Cache_DeleteBucketRange(t *testing.T) { v0 := NewValue(1, 1.0) v1 := NewValue(2, 2.0) v2 := NewValue(3, 3.0) @@ -189,7 +189,7 @@ func TestCache_Cache_DeleteRange(t *testing.T) { t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) } - c.DeleteRange([][]byte{[]byte("bar")}, 2, math.MaxInt64) + c.DeleteBucketRange([]byte("bar"), 2, math.MaxInt64) if exp, keys := [][]byte{[]byte("bar"), []byte("foo")}, c.Keys(); !reflect.DeepEqual(keys, exp) { t.Fatalf("cache keys incorrect after delete, exp %v, got %v", exp, keys) @@ -208,7 +208,7 @@ func TestCache_Cache_DeleteRange(t *testing.T) { } } -func TestCache_DeleteRange_NoValues(t *testing.T) { +func TestCache_DeleteBucketRange_NoValues(t *testing.T) { v0 := NewValue(1, 1.0) v1 := NewValue(2, 2.0) v2 := NewValue(3, 3.0) @@ -228,7 +228,7 @@ func TestCache_DeleteRange_NoValues(t *testing.T) { t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) } - c.DeleteRange([][]byte{[]byte("foo")}, math.MinInt64, math.MaxInt64) + c.DeleteBucketRange([]byte("foo"), math.MinInt64, math.MaxInt64) if exp, keys := 0, len(c.Keys()); !reflect.DeepEqual(keys, exp) { t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) @@ -243,7 +243,7 @@ func TestCache_DeleteRange_NoValues(t *testing.T) { } } -func TestCache_DeleteRange_NotSorted(t *testing.T) { +func TestCache_DeleteBucketRange_NotSorted(t *testing.T) { v0 := NewValue(1, 1.0) v1 := NewValue(3, 3.0) v2 := NewValue(2, 2.0) @@ -263,7 +263,7 @@ func TestCache_DeleteRange_NotSorted(t *testing.T) { t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) } - c.DeleteRange([][]byte{[]byte("foo")}, 1, 3) + c.DeleteBucketRange([]byte("foo"), 1, 3) if exp, keys := 0, len(c.Keys()); !reflect.DeepEqual(keys, exp) { t.Fatalf("cache keys incorrect after delete, exp %v, got %v", exp, keys) @@ -278,49 +278,10 @@ func TestCache_DeleteRange_NotSorted(t *testing.T) { } } -func TestCache_Cache_Delete(t *testing.T) { - v0 := NewValue(1, 1.0) - v1 := NewValue(2, 2.0) - v2 := NewValue(3, 3.0) - values := Values{v0, v1, v2} - valuesSize := uint64(v0.Size() + v1.Size() + v2.Size()) - - c := NewCache(30 * valuesSize) - - if err := c.WriteMulti(map[string][]Value{"foo": values, "bar": values}); err != nil { - t.Fatalf("failed to write key foo to cache: %s", err.Error()) - } - if n := c.Size(); n != 2*valuesSize+6 { - t.Fatalf("cache size incorrect after 2 writes, exp %d, got %d", 2*valuesSize, n) - } - - if exp, keys := [][]byte{[]byte("bar"), []byte("foo")}, c.Keys(); !reflect.DeepEqual(keys, exp) { - t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) - } - - c.Delete([][]byte{[]byte("bar")}) - - if exp, keys := [][]byte{[]byte("foo")}, c.Keys(); !reflect.DeepEqual(keys, exp) { - t.Fatalf("cache keys incorrect after 2 writes, exp %v, got %v", exp, keys) - } - - if got, exp := c.Size(), valuesSize+3; exp != got { - t.Fatalf("cache size incorrect after 2 writes, exp %d, got %d", exp, got) - } - - if got, exp := len(c.Values([]byte("bar"))), 0; got != exp { - t.Fatalf("cache values mismatch: got %v, exp %v", got, exp) - } - - if got, exp := len(c.Values([]byte("foo"))), 3; got != exp { - t.Fatalf("cache values mismatch: got %v, exp %v", got, exp) - } -} - -func TestCache_Cache_Delete_NonExistent(t *testing.T) { +func TestCache_DeleteBucketRange_NonExistent(t *testing.T) { c := NewCache(1024) - c.Delete([][]byte{[]byte("bar")}) + c.DeleteBucketRange([]byte("bar"), math.MinInt64, math.MaxInt64) if got, exp := c.Size(), uint64(0); exp != got { t.Fatalf("cache size incorrect exp %d, got %d", exp, got) diff --git a/tsdb/tsm1/engine_delete_bucket.go b/tsdb/tsm1/engine_delete_bucket.go index 57957942ae..7842a3b8b6 100644 --- a/tsdb/tsm1/engine_delete_bucket.go +++ b/tsdb/tsm1/engine_delete_bucket.go @@ -76,9 +76,6 @@ func (e *Engine) DeleteBucketRange(name []byte, min, max int64) error { return err } - // TODO(jeff): add a DeletePrefix to the Cache and WAL. - // TODO(jeff): add a Tombstone entry into the WAL for deletes. - var deleteKeys [][]byte // ApplySerialEntryFn cannot return an error in this invocation. @@ -99,8 +96,8 @@ func (e *Engine) DeleteBucketRange(name []byte, min, max int64) error { // Sort the series keys because ApplyEntryFn iterates over the keys randomly. bytesutil.Sort(deleteKeys) - // Delete from the cache and WAL. - e.Cache.DeleteRange(deleteKeys, min, max) + // Delete from the cache. + e.Cache.DeleteBucketRange(name, min, max) // Now that all of the data is purged, we need to find if some keys are fully deleted // and if so, remove them from the index. From 3014733b2098e6cdb26a57e9cd4afddef4f77786 Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Tue, 22 Jan 2019 10:31:35 -0700 Subject: [PATCH 28/95] chore: fix staticcheck issues --- storage/retention.go | 7 ++++-- storage/series_iterator.go | 46 -------------------------------------- tsdb/tsm1/engine.go | 4 ---- tsdb/tsm1/engine_test.go | 27 ---------------------- 4 files changed, 5 insertions(+), 79 deletions(-) delete mode 100644 storage/series_iterator.go diff --git a/storage/retention.go b/storage/retention.go index 3951b4d7e3..72b908981c 100644 --- a/storage/retention.go +++ b/storage/retention.go @@ -14,7 +14,6 @@ import ( const ( bucketAPITimeout = 10 * time.Second - engineAPITimeout = time.Minute ) // A Deleter implementation is capable of deleting data from a storage engine. @@ -95,7 +94,7 @@ func (s *retentionEnforcer) run() { // Any series data that (1) belongs to a bucket in the provided list and // (2) falls outside the bucket's indicated retention period will be deleted. func (s *retentionEnforcer) expireData(buckets []*platform.Bucket, now time.Time) error { - _, logEnd := logger.NewOperation(s.logger, "Data deletion", "data_deletion") + logger, logEnd := logger.NewOperation(s.logger, "Data deletion", "data_deletion") defer logEnd() for _, b := range buckets { @@ -107,6 +106,10 @@ func (s *retentionEnforcer) expireData(buckets []*platform.Bucket, now time.Time err := s.Engine.DeleteBucketRange(b.OrganizationID, b.ID, math.MinInt64, max) if err != nil { // TODO(jeff): metrics? + logger.Info("unable to delete bucket range", + zap.String("bucket id", b.ID.String()), + zap.String("org id", b.OrganizationID.String()), + zap.Error(err)) } } diff --git a/storage/series_iterator.go b/storage/series_iterator.go deleted file mode 100644 index 48f28dfc41..0000000000 --- a/storage/series_iterator.go +++ /dev/null @@ -1,46 +0,0 @@ -package storage - -import ( - "github.com/influxdata/influxdb/models" - "github.com/influxdata/influxdb/tsdb" - "github.com/influxdata/influxql" -) - -// fixedSeriesIterator is a tsdb.SeriesIterator over a given set of keys. -type fixedSeriesIterator struct{ keys [][]byte } - -// newFixedSeriesIterator returns a tsdb.SeriesIterator over the given set of keys. -func newFixedSeriesIterator(keys [][]byte) *fixedSeriesIterator { - return &fixedSeriesIterator{ - keys: keys, - } -} - -// Close is required for the tsdb.SeriesIterator interface. -func (i *fixedSeriesIterator) Close() error { return nil } - -// Next advances the iterator and returns the current element. -func (i *fixedSeriesIterator) Next() (tsdb.SeriesElem, error) { - if len(i.keys) == 0 { - return nil, nil - } - key := i.keys[0] - i.keys = i.keys[1:] - - name, tags := models.ParseKeyBytes(key) - return &fixedSeriesIteratorElem{ - name: name, - tags: tags, - }, nil -} - -// fixedSeriesIteratorElem imlements tsdb.SeriesElem but only the name and tags. -type fixedSeriesIteratorElem struct { - name []byte - tags models.Tags -} - -func (i *fixedSeriesIteratorElem) Name() []byte { return i.name } -func (i *fixedSeriesIteratorElem) Tags() models.Tags { return i.tags } -func (i *fixedSeriesIteratorElem) Deleted() bool { return false } -func (i *fixedSeriesIteratorElem) Expr() influxql.Expr { return nil } diff --git a/tsdb/tsm1/engine.go b/tsdb/tsm1/engine.go index de37de6b55..fbe751397b 100644 --- a/tsdb/tsm1/engine.go +++ b/tsdb/tsm1/engine.go @@ -37,7 +37,6 @@ import ( var ( // Static objects to prevent small allocs. keyFieldSeparatorBytes = []byte(keyFieldSeparator) - emptyBytes = []byte{} ) var ( @@ -63,9 +62,6 @@ const ( // that identifies a specific field in series keyFieldSeparator = "#!~#" - // deleteFlushThreshold is the size in bytes of a batch of series keys to delete. - deleteFlushThreshold = 50 * 1024 * 1024 - // MaxPointsPerBlock is the maximum number of points in an encoded block in a TSM file MaxPointsPerBlock = 1000 ) diff --git a/tsdb/tsm1/engine_test.go b/tsdb/tsm1/engine_test.go index b8f86d6d0d..26e94b5e8e 100644 --- a/tsdb/tsm1/engine_test.go +++ b/tsdb/tsm1/engine_test.go @@ -518,30 +518,3 @@ func (m *mockPlanner) Release(groups []tsm1.CompactionGroup) {} func (m *mockPlanner) FullyCompacted() bool { return false } func (m *mockPlanner) ForceFull() {} func (m *mockPlanner) SetFileStore(fs *tsm1.FileStore) {} - -type seriesIterator struct { - keys [][]byte -} - -type series struct { - name []byte - tags models.Tags - deleted bool -} - -func (s series) Name() []byte { return s.name } -func (s series) Tags() models.Tags { return s.tags } -func (s series) Deleted() bool { return s.deleted } -func (s series) Expr() influxql.Expr { return nil } - -func (itr *seriesIterator) Close() error { return nil } - -func (itr *seriesIterator) Next() (tsdb.SeriesElem, error) { - if len(itr.keys) == 0 { - return nil, nil - } - name, tags := models.ParseKeyBytes(itr.keys[0]) - s := series{name: name, tags: tags} - itr.keys = itr.keys[1:] - return s, nil -} From b4823d11bfc71335b44cdd4f3642b488642cae8a Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Mon, 4 Feb 2019 10:16:38 -0700 Subject: [PATCH 29/95] storage: double check the cache to avoid deleting keys that still exist --- tsdb/tsm1/engine_delete_bucket.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tsdb/tsm1/engine_delete_bucket.go b/tsdb/tsm1/engine_delete_bucket.go index 7842a3b8b6..ee379a1673 100644 --- a/tsdb/tsm1/engine_delete_bucket.go +++ b/tsdb/tsm1/engine_delete_bucket.go @@ -132,6 +132,14 @@ func (e *Engine) DeleteBucketRange(name []byte, min, max int64) error { return err } + // ApplySerialEntryFn cannot return an error in this invocation. + _ = e.Cache.ApplyEntryFn(func(k []byte, _ *entry) error { + if bytes.HasPrefix(k, name) { + delete(possiblyDead.keys, string(k)) + } + return nil + }) + if len(possiblyDead.keys) > 0 { buf := make([]byte, 1024) From 0bc0568a804145a418fd2a0b3ba689e4b805fb9e Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Fri, 25 Jan 2019 17:53:09 -0800 Subject: [PATCH 30/95] Move collectors data loading into separate wizard --- .../components/DataLoaderSwitcher.test.tsx | 47 ++++ .../components/DataLoaderSwitcher.tsx | 62 +++++ .../components/DataLoadersWizard.tsx | 133 ++--------- .../dataLoaders/components/StepSwitcher.tsx | 73 +----- .../CollectorsStepSwitcher.tsx | 43 ++++ .../collectorsWizard/CollectorsWizard.tsx | 215 ++++++++++++++++++ .../configure/ConfigFieldHandler.test.tsx | 65 ++++++ .../configure}/ConfigFieldHandler.tsx | 33 ++- .../configure}/PluginConfigForm.test.tsx | 32 +-- .../configure}/PluginConfigForm.tsx | 83 ++++--- .../configure}/PluginConfigSwitcher.test.tsx | 23 +- .../configure/PluginConfigSwitcher.tsx | 65 ++++++ .../configure}/TelegrafPluginInstructions.tsx | 34 ++- .../select/SelectCollectorsStep.test.tsx | 79 +++++++ .../select/SelectCollectorsStep.tsx} | 137 +++++------ .../select}/StreamingSelector.test.tsx | 2 +- .../select}/StreamingSelector.tsx | 5 +- .../verify/VerifyCollectorsStep.tsx | 104 +++++++++ .../configureStep/ConfigureDataSourceStep.tsx | 82 +------ .../ConfigureDataSourceSwitcher.tsx | 49 +--- .../streaming/PluginConfigSwitcher.tsx | 83 ------- .../SelectDataSourceStep.test.tsx | 109 --------- .../components/selectionStep/TypeSelector.tsx | 69 ------ .../components/verifyStep/VerifyDataStep.tsx | 65 +----- .../verifyStep/VerifyDataSwitcher.tsx | 33 +-- .../VerifyDataSwitcher.test.tsx.snap | 9 +- .../organizations/components/BucketList.tsx | 65 ++++-- .../organizations/components/Collectors.tsx | 41 +++- ui/src/types/v2/dataLoaders.ts | 5 + 29 files changed, 985 insertions(+), 860 deletions(-) create mode 100644 ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx create mode 100644 ui/src/dataLoaders/components/DataLoaderSwitcher.tsx create mode 100644 ui/src/dataLoaders/components/collectorsWizard/CollectorsStepSwitcher.tsx create mode 100644 ui/src/dataLoaders/components/collectorsWizard/CollectorsWizard.tsx create mode 100644 ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.test.tsx rename ui/src/dataLoaders/components/{configureStep/streaming => collectorsWizard/configure}/ConfigFieldHandler.tsx (83%) rename ui/src/dataLoaders/components/{configureStep/streaming => collectorsWizard/configure}/PluginConfigForm.test.tsx (58%) rename ui/src/dataLoaders/components/{configureStep/streaming => collectorsWizard/configure}/PluginConfigForm.tsx (50%) rename ui/src/dataLoaders/components/{configureStep/streaming => collectorsWizard/configure}/PluginConfigSwitcher.test.tsx (60%) create mode 100644 ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.tsx rename ui/src/dataLoaders/components/{configureStep/streaming => collectorsWizard/configure}/TelegrafPluginInstructions.tsx (75%) create mode 100644 ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.test.tsx rename ui/src/dataLoaders/components/{selectionStep/SelectDataSourceStep.tsx => collectorsWizard/select/SelectCollectorsStep.tsx} (52%) rename ui/src/dataLoaders/components/{selectionStep => collectorsWizard/select}/StreamingSelector.test.tsx (92%) rename ui/src/dataLoaders/components/{selectionStep => collectorsWizard/select}/StreamingSelector.tsx (96%) create mode 100644 ui/src/dataLoaders/components/collectorsWizard/verify/VerifyCollectorsStep.tsx delete mode 100644 ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.tsx delete mode 100644 ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.test.tsx delete mode 100644 ui/src/dataLoaders/components/selectionStep/TypeSelector.tsx diff --git a/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx b/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx new file mode 100644 index 0000000000..eeb2af52bb --- /dev/null +++ b/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx @@ -0,0 +1,47 @@ +// Libraries +import React from 'react' +import {shallow} from 'enzyme' + +// Components +import DataLoaderSwitcher from 'src/dataLoaders/components/DataLoaderSwitcher' +import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' +import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' + +// Types +import {DataLoaderType} from 'src/types/v2/dataLoaders' + +const setup = (override = {}) => { + const props = { + type: DataLoaderType.Empty, + onCompleteSetup: jest.fn(), + visible: true, + buckets: [], + ...override, + } + + const wrapper = shallow() + + return {wrapper} +} + +describe('DataLoading.Components.DataLoaderSwitcher', () => { + it('renders data loaders wizard', () => { + const {wrapper} = setup() + + const wizard = wrapper.find(DataLoadersWizard) + + expect(wrapper.exists()).toBe(true) + expect(wizard.exists()).toBe(true) + }) + + describe('if type is streaming', () => { + it('renders collectors wizard', () => { + const {wrapper} = setup({type: DataLoaderType.Streaming}) + + const wizard = wrapper.find(CollectorsWizard) + + expect(wrapper.exists()).toBe(true) + expect(wizard.exists()).toBe(true) + }) + }) +}) diff --git a/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx b/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx new file mode 100644 index 0000000000..9e92cfc171 --- /dev/null +++ b/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx @@ -0,0 +1,62 @@ +// Libraries +import React, {PureComponent} from 'react' +import _ from 'lodash' + +// Components +import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' +import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' + +// Types +import {Substep, DataLoaderType} from 'src/types/v2/dataLoaders' +import {Bucket} from 'src/api' + +interface Props { + type: DataLoaderType + onCompleteSetup: () => void + visible: boolean + buckets: Bucket[] + startingType?: DataLoaderType + startingStep?: number + startingSubstep?: Substep +} + +class DataLoaderSwitcher extends PureComponent { + public render() { + const { + buckets, + type, + visible, + onCompleteSetup, + startingStep, + startingSubstep, + startingType, + } = this.props + + switch (type) { + case DataLoaderType.LineProtocol: + case DataLoaderType.Scraping: + case DataLoaderType.Empty: + return ( + + ) + case DataLoaderType.Streaming: + return ( + + ) + } + } +} + +export default DataLoaderSwitcher diff --git a/ui/src/dataLoaders/components/DataLoadersWizard.tsx b/ui/src/dataLoaders/components/DataLoadersWizard.tsx index 4606777786..5e1df56828 100644 --- a/ui/src/dataLoaders/components/DataLoadersWizard.tsx +++ b/ui/src/dataLoaders/components/DataLoadersWizard.tsx @@ -21,29 +21,15 @@ import { import { setDataLoadersType, - updateTelegrafPluginConfig, - addConfigValue, - removeConfigValue, - setActiveTelegrafPlugin, - setPluginConfiguration, - addPluginBundleWithPlugins, - removePluginBundleWithPlugins, - setConfigArrayValue, clearDataLoaders, } from 'src/dataLoaders/actions/dataLoaders' // Types import {Links} from 'src/types/v2/links' -import { - DataLoadersState, - DataLoaderType, - Substep, - DataLoaderStep, -} from 'src/types/v2/dataLoaders' +import {DataLoaderType, Substep} from 'src/types/v2/dataLoaders' import {Notification, NotificationFunc} from 'src/types' import {AppState} from 'src/types/v2' import {Bucket} from 'src/api' -import PluginsSideBar from 'src/dataLoaders/components/PluginsSideBar' export interface DataLoaderStepProps { links: Links @@ -61,7 +47,6 @@ export interface DataLoaderStepProps { interface OwnProps { onCompleteSetup: () => void visible: boolean - bucket?: Bucket buckets: Bucket[] startingType?: DataLoaderType startingStep?: number @@ -72,14 +57,6 @@ interface DispatchProps { notify: (message: Notification | NotificationFunc) => void onSetBucketInfo: typeof setBucketInfo onSetDataLoadersType: typeof setDataLoadersType - onAddPluginBundle: typeof addPluginBundleWithPlugins - onRemovePluginBundle: typeof removePluginBundleWithPlugins - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin - onSetPluginConfiguration: typeof setPluginConfiguration - onSetConfigArrayValue: typeof setConfigArrayValue onIncrementCurrentStepIndex: typeof incrementCurrentStepIndex onDecrementCurrentStepIndex: typeof decrementCurrentStepIndex onSetCurrentStepIndex: typeof setCurrentStepIndex @@ -90,11 +67,12 @@ interface DispatchProps { interface StateProps { links: Links - dataLoaders: DataLoadersState currentStepIndex: number substep: Substep username: string - selectedBucket: string + bucket: string + org: string + type: DataLoaderType } type Props = OwnProps & StateProps & DispatchProps @@ -118,23 +96,12 @@ class DataLoadersWizard extends PureComponent { public render() { const { currentStepIndex, - dataLoaders, - dataLoaders: {telegrafPlugins}, - onSetDataLoadersType, - onSetActiveTelegrafPlugin, - onSetPluginConfiguration, - onUpdateTelegrafPluginConfig, - onAddConfigValue, - onRemoveConfigValue, - onAddPluginBundle, - onRemovePluginBundle, - onSetConfigArrayValue, visible, bucket, - username, + org, onSetBucketInfo, buckets, - selectedBucket, + type, } = this.props return ( @@ -144,32 +111,14 @@ class DataLoadersWizard extends PureComponent { onDismis={this.handleDismiss} >
-
@@ -180,9 +129,9 @@ class DataLoadersWizard extends PureComponent { private handleSetBucketInfo = () => { const {bucket, buckets} = this.props - if (bucket || (buckets && buckets.length)) { - const b = bucket || buckets[0] - const {organization, organizationID, name, id} = b + + if (!bucket && (buckets && buckets.length)) { + const {organization, organizationID, name, id} = buckets[0] this.props.onSetBucketInfo(organization, organizationID, name, id) } @@ -216,47 +165,6 @@ class DataLoadersWizard extends PureComponent { this.props.onClearSteps() } - private get sideBarVisible() { - const {dataLoaders, currentStepIndex} = this.props - const {telegrafPlugins, type} = dataLoaders - - const isStreaming = type === DataLoaderType.Streaming - const isNotEmpty = telegrafPlugins.length > 0 - const isConfigStep = currentStepIndex > 0 - - return isStreaming && isNotEmpty && isConfigStep - } - - private handleClickSideBarTab = (tabID: string) => { - const { - onSetSubstepIndex, - onSetActiveTelegrafPlugin, - dataLoaders: {telegrafPlugins}, - substep, - onSetPluginConfiguration, - } = this.props - - if (!_.isNaN(Number(substep))) { - onSetPluginConfiguration(_.get(telegrafPlugins, `${substep}.name`, '')) - } - - if (tabID === 'config') { - onSetSubstepIndex(DataLoaderStep.Configure, tabID) - onSetActiveTelegrafPlugin('') - return - } - - const index = Math.max( - _.findIndex(telegrafPlugins, plugin => { - return plugin.name === tabID - }), - 0 - ) - - onSetSubstepIndex(DataLoaderStep.Configure, index) - onSetActiveTelegrafPlugin(tabID) - } - private get stepProps(): DataLoaderStepProps { const { links, @@ -288,31 +196,24 @@ class DataLoadersWizard extends PureComponent { const mstp = ({ links, dataLoading: { - dataLoaders, - steps: {currentStep, substep, bucket}, + dataLoaders: {type}, + steps: {currentStep, substep, bucket, org}, }, me: {name}, }: AppState): StateProps => ({ links, - dataLoaders, + type, currentStepIndex: currentStep, substep, username: name, - selectedBucket: bucket, + bucket, + org, }) const mdtp: DispatchProps = { notify: notifyAction, onSetBucketInfo: setBucketInfo, onSetDataLoadersType: setDataLoadersType, - onUpdateTelegrafPluginConfig: updateTelegrafPluginConfig, - onAddConfigValue: addConfigValue, - onRemoveConfigValue: removeConfigValue, - onSetActiveTelegrafPlugin: setActiveTelegrafPlugin, - onAddPluginBundle: addPluginBundleWithPlugins, - onRemovePluginBundle: removePluginBundleWithPlugins, - onSetPluginConfiguration: setPluginConfiguration, - onSetConfigArrayValue: setConfigArrayValue, onIncrementCurrentStepIndex: incrementCurrentStepIndex, onDecrementCurrentStepIndex: decrementCurrentStepIndex, onSetCurrentStepIndex: setCurrentStepIndex, diff --git a/ui/src/dataLoaders/components/StepSwitcher.tsx b/ui/src/dataLoaders/components/StepSwitcher.tsx index 7459d87452..93a231b3d7 100644 --- a/ui/src/dataLoaders/components/StepSwitcher.tsx +++ b/ui/src/dataLoaders/components/StepSwitcher.tsx @@ -3,49 +3,26 @@ import React, {PureComponent} from 'react' import _ from 'lodash' // Components -import SelectDataSourceStep from 'src/dataLoaders/components/selectionStep/SelectDataSourceStep' import ConfigureDataSourceStep from 'src/dataLoaders/components/configureStep/ConfigureDataSourceStep' import VerifyDataStep from 'src/dataLoaders/components/verifyStep/VerifyDataStep' import {ErrorHandling} from 'src/shared/decorators/errors' // Actions -import { - updateTelegrafPluginConfig, - setDataLoadersType, - setActiveTelegrafPlugin, - addConfigValue, - removeConfigValue, - addPluginBundleWithPlugins, - removePluginBundleWithPlugins, - setPluginConfiguration, - setConfigArrayValue, -} from 'src/dataLoaders/actions/dataLoaders' import {setBucketInfo} from 'src/dataLoaders/actions/steps' // Types -import {DataLoadersState, DataLoaderStep} from 'src/types/v2/dataLoaders' +import {DataLoaderType, DataLoaderStep} from 'src/types/v2/dataLoaders' import {DataLoaderStepProps} from 'src/dataLoaders/components/DataLoadersWizard' import {Bucket} from 'src/api' interface Props { onboardingStepProps: DataLoaderStepProps - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - onSetDataLoadersType: typeof setDataLoadersType - onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin - onSetPluginConfiguration: typeof setPluginConfiguration bucketName: string buckets: Bucket[] - dataLoaders: DataLoadersState + type: DataLoaderType currentStepIndex: number - onAddPluginBundle: typeof addPluginBundleWithPlugins - onRemovePluginBundle: typeof removePluginBundleWithPlugins - onSetConfigArrayValue: typeof setConfigArrayValue onSetBucketInfo: typeof setBucketInfo org: string - username: string - selectedBucket: string } @ErrorHandling @@ -54,68 +31,28 @@ class StepSwitcher extends PureComponent { const { currentStepIndex, onboardingStepProps, - dataLoaders, - onSetDataLoadersType, - onUpdateTelegrafPluginConfig, - onSetActiveTelegrafPlugin, - onSetPluginConfiguration, - onAddConfigValue, - onRemoveConfigValue, - onAddPluginBundle, - onRemovePluginBundle, - onSetConfigArrayValue, bucketName, - username, org, buckets, - onSetBucketInfo, - selectedBucket, + type, } = this.props switch (currentStepIndex) { - case DataLoaderStep.Select: - return ( - - ) case DataLoaderStep.Configure: return ( ) case DataLoaderStep.Verify: return ( ) diff --git a/ui/src/dataLoaders/components/collectorsWizard/CollectorsStepSwitcher.tsx b/ui/src/dataLoaders/components/collectorsWizard/CollectorsStepSwitcher.tsx new file mode 100644 index 0000000000..923c42bc77 --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/CollectorsStepSwitcher.tsx @@ -0,0 +1,43 @@ +// Libraries +import React, {PureComponent} from 'react' +import _ from 'lodash' + +// Components +import SelectCollectorsStep from 'src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep' +import PluginConfigSwitcher from 'src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher' +import VerifyCollectorsStep from 'src/dataLoaders/components/collectorsWizard/verify/VerifyCollectorsStep' +import {ErrorHandling} from 'src/shared/decorators/errors' + +// Types +import {CollectorsStep} from 'src/types/v2/dataLoaders' +import {CollectorsStepProps} from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' +import {Bucket} from 'src/api' + +interface Props { + stepProps: CollectorsStepProps + buckets: Bucket[] +} + +@ErrorHandling +class StepSwitcher extends PureComponent { + public render() { + const {stepProps, buckets} = this.props + + switch (stepProps.currentStepIndex) { + case CollectorsStep.Select: + return + case CollectorsStep.Configure: + return ( +
+ +
+ ) + case CollectorsStep.Verify: + return + default: + return
+ } + } +} + +export default StepSwitcher diff --git a/ui/src/dataLoaders/components/collectorsWizard/CollectorsWizard.tsx b/ui/src/dataLoaders/components/collectorsWizard/CollectorsWizard.tsx new file mode 100644 index 0000000000..a8588bb7c3 --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/CollectorsWizard.tsx @@ -0,0 +1,215 @@ +// Libraries +import React, {PureComponent} from 'react' +import {connect} from 'react-redux' +import _ from 'lodash' + +// Components +import {ErrorHandling} from 'src/shared/decorators/errors' +import WizardOverlay from 'src/clockface/components/wizard/WizardOverlay' +import CollectorsStepSwitcher from 'src/dataLoaders/components/collectorsWizard/CollectorsStepSwitcher' +import PluginsSideBar from 'src/dataLoaders/components/PluginsSideBar' + +// Actions +import {notify as notifyAction} from 'src/shared/actions/notifications' +import { + setBucketInfo, + incrementCurrentStepIndex, + decrementCurrentStepIndex, + setCurrentStepIndex, + clearSteps, +} from 'src/dataLoaders/actions/steps' + +import { + clearDataLoaders, + setActiveTelegrafPlugin, + setPluginConfiguration, +} from 'src/dataLoaders/actions/dataLoaders' + +// Types +import {Links} from 'src/types/v2/links' +import {Substep, TelegrafPlugin} from 'src/types/v2/dataLoaders' +import {Notification, NotificationFunc} from 'src/types' +import {AppState} from 'src/types/v2' +import {Bucket} from 'src/api' + +export interface CollectorsStepProps { + currentStepIndex: number + onIncrementCurrentStepIndex: () => void + onDecrementCurrentStepIndex: () => void + notify: (message: Notification | NotificationFunc) => void + onExit: () => void +} + +interface OwnProps { + onCompleteSetup: () => void + visible: boolean + buckets: Bucket[] + startingStep?: number +} + +interface DispatchProps { + notify: (message: Notification | NotificationFunc) => void + onSetBucketInfo: typeof setBucketInfo + onIncrementCurrentStepIndex: typeof incrementCurrentStepIndex + onDecrementCurrentStepIndex: typeof decrementCurrentStepIndex + onSetCurrentStepIndex: typeof setCurrentStepIndex + onClearDataLoaders: typeof clearDataLoaders + onClearSteps: typeof clearSteps + onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin + onSetPluginConfiguration: typeof setPluginConfiguration +} + +interface StateProps { + links: Links + telegrafPlugins: TelegrafPlugin[] + currentStepIndex: number + substep: Substep + username: string + bucket: string +} + +type Props = OwnProps & StateProps & DispatchProps + +@ErrorHandling +class CollectorsWizard extends PureComponent { + public componentDidMount() { + this.handleSetBucketInfo() + this.handleSetStartingValues() + } + + public componentDidUpdate(prevProps: Props) { + const hasBecomeVisible = !prevProps.visible && this.props.visible + + if (hasBecomeVisible) { + this.handleSetBucketInfo() + this.handleSetStartingValues() + } + } + + public render() { + const {visible, buckets, telegrafPlugins, currentStepIndex} = this.props + + return ( + +
+ +
+ +
+
+
+ ) + } + + private handleSetBucketInfo = () => { + const {bucket, buckets} = this.props + if (!bucket && (buckets && buckets.length)) { + const {organization, organizationID, name, id} = buckets[0] + + this.props.onSetBucketInfo(organization, organizationID, name, id) + } + } + + private handleSetStartingValues = () => { + const {startingStep} = this.props + + const hasStartingStep = startingStep || startingStep === 0 + + if (hasStartingStep) { + this.props.onSetCurrentStepIndex(startingStep) + } + } + + private handleDismiss = () => { + this.props.onCompleteSetup() + this.props.onClearDataLoaders() + this.props.onClearSteps() + } + + private get sideBarVisible() { + const {telegrafPlugins, currentStepIndex} = this.props + + const isNotEmpty = telegrafPlugins.length > 0 + const isConfigStep = currentStepIndex > 0 + + return isNotEmpty && isConfigStep + } + + private handleClickSideBarTab = (tabID: string) => { + const { + onSetActiveTelegrafPlugin, + telegrafPlugins, + onSetPluginConfiguration, + } = this.props + + const activeTelegrafPlugin = telegrafPlugins.find(tp => tp.active) + if (!!activeTelegrafPlugin) { + onSetPluginConfiguration(activeTelegrafPlugin.name) + } + + onSetActiveTelegrafPlugin(tabID) + } + + private get stepProps(): CollectorsStepProps { + const { + notify, + currentStepIndex, + onDecrementCurrentStepIndex, + onIncrementCurrentStepIndex, + } = this.props + + return { + currentStepIndex, + onIncrementCurrentStepIndex, + onDecrementCurrentStepIndex, + notify, + onExit: this.handleDismiss, + } + } +} + +const mstp = ({ + links, + dataLoading: { + dataLoaders: {telegrafPlugins}, + steps: {currentStep, substep, bucket}, + }, + me: {name}, +}: AppState): StateProps => ({ + links, + telegrafPlugins, + currentStepIndex: currentStep, + substep, + username: name, + bucket, +}) + +const mdtp: DispatchProps = { + notify: notifyAction, + onSetBucketInfo: setBucketInfo, + onIncrementCurrentStepIndex: incrementCurrentStepIndex, + onDecrementCurrentStepIndex: decrementCurrentStepIndex, + onSetCurrentStepIndex: setCurrentStepIndex, + onClearDataLoaders: clearDataLoaders, + onClearSteps: clearSteps, + onSetActiveTelegrafPlugin: setActiveTelegrafPlugin, + onSetPluginConfiguration: setPluginConfiguration, +} + +export default connect( + mstp, + mdtp +)(CollectorsWizard) diff --git a/ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.test.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.test.tsx new file mode 100644 index 0000000000..2a457b304f --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.test.tsx @@ -0,0 +1,65 @@ +// Libraries +import React from 'react' +import {shallow} from 'enzyme' + +// Components +import {ConfigFieldHandler} from 'src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler' + +// Constants +import {telegrafPluginsInfo} from 'src/dataLoaders/constants/pluginConfigs' +import {telegrafPlugin} from 'mocks/dummyData' + +// Types +import {TelegrafPluginInputCpu, TelegrafPluginInputRedis} from 'src/api' +import ConfigFieldSwitcher from '../../configureStep/streaming/ConfigFieldSwitcher' + +const setup = (override = {}) => { + const props = { + telegrafPlugin, + configFields: + telegrafPluginsInfo[TelegrafPluginInputCpu.NameEnum.Cpu].fields, + onUpdateTelegrafPluginConfig: jest.fn(), + onAddConfigValue: jest.fn(), + onRemoveConfigValue: jest.fn(), + onSetConfigArrayValue: jest.fn(), + ...override, + } + + const wrapper = shallow() + + return {wrapper} +} + +describe('DataLoaders.Components.CollectorsWizard.Configure.ConfigFieldHandler', () => { + describe('if configFields have no keys', () => { + it('renders no config text', () => { + const {wrapper} = setup({ + telegrafPlugin, + configFields: + telegrafPluginsInfo[TelegrafPluginInputCpu.NameEnum.Cpu].fields, + }) + const noConfig = wrapper.find({ + 'data-test': 'no-config', + }) + + expect(wrapper.exists()).toBe(true) + expect(noConfig.exists()).toBe(true) + }) + }) + + describe('if configFields have keys', () => { + it('renders correct number of switchers', () => { + const configFields = + telegrafPluginsInfo[TelegrafPluginInputRedis.NameEnum.Redis].fields + const {wrapper} = setup({ + telegrafPlugin, + configFields, + }) + + const switchers = wrapper.find(ConfigFieldSwitcher) + + expect(wrapper.exists()).toBe(true) + expect(switchers.length).toBe(Object.keys(configFields).length) + }) + }) +}) diff --git a/ui/src/dataLoaders/components/configureStep/streaming/ConfigFieldHandler.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.tsx similarity index 83% rename from ui/src/dataLoaders/components/configureStep/streaming/ConfigFieldHandler.tsx rename to ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.tsx index a523b4b1c5..4f8b38eb5a 100644 --- a/ui/src/dataLoaders/components/configureStep/streaming/ConfigFieldHandler.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler.tsx @@ -1,5 +1,6 @@ // Libraries import React, {PureComponent, ChangeEvent} from 'react' +import {connect} from 'react-redux' import _ from 'lodash' // Components @@ -20,16 +21,21 @@ import { ConfigFieldType, } from 'src/types/v2/dataLoaders' -interface Props { +interface OwnProps { configFields: ConfigFields telegrafPlugin: TelegrafPlugin - onSetConfigArrayValue: typeof setConfigArrayValue - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig } -class ConfigFieldHandler extends PureComponent { +interface DispatchProps { + onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig + onAddConfigValue: typeof addConfigValue + onRemoveConfigValue: typeof removeConfigValue + onSetConfigArrayValue: typeof setConfigArrayValue +} + +type Props = OwnProps & DispatchProps + +export class ConfigFieldHandler extends PureComponent { public render() { return <>{this.formFields} } @@ -38,7 +44,7 @@ class ConfigFieldHandler extends PureComponent { const {configFields, telegrafPlugin, onSetConfigArrayValue} = this.props if (!configFields) { - return

No configuration required.

+ return

No configuration required.

} return Object.entries(configFields).map( @@ -101,4 +107,15 @@ class ConfigFieldHandler extends PureComponent { onUpdateTelegrafPluginConfig(telegrafPlugin.name, name, value) } } -export default ConfigFieldHandler + +const mdtp: DispatchProps = { + onUpdateTelegrafPluginConfig: updateTelegrafPluginConfig, + onAddConfigValue: addConfigValue, + onRemoveConfigValue: removeConfigValue, + onSetConfigArrayValue: setConfigArrayValue, +} + +export default connect( + null, + mdtp +)(ConfigFieldHandler) diff --git a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.test.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.test.tsx similarity index 58% rename from ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.test.tsx rename to ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.test.tsx index af8cb97dfa..2364df6493 100644 --- a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.test.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.test.tsx @@ -1,10 +1,9 @@ // Libraries import React from 'react' -import {mount} from 'enzyme' +import {shallow} from 'enzyme' // Components -import ConfigFieldSwitcher from 'src/dataLoaders/components/configureStep/streaming/ConfigFieldSwitcher' -import PluginConfigForm from 'src/dataLoaders/components/configureStep/streaming/PluginConfigForm' +import {PluginConfigForm} from 'src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm' import {Form} from 'src/clockface' import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' @@ -13,7 +12,7 @@ import {telegrafPluginsInfo} from 'src/dataLoaders/constants/pluginConfigs' import {telegrafPlugin} from 'mocks/dummyData' // Types -import {TelegrafPluginInputCpu, TelegrafPluginInputRedis} from 'src/api' +import {TelegrafPluginInputCpu} from 'src/api' const setup = (override = {}) => { const props = { @@ -26,20 +25,22 @@ const setup = (override = {}) => { authToken: '', onSetConfigArrayValue: jest.fn(), telegrafPluginName: TelegrafPluginInputCpu.NameEnum.Cpu, + onSetActiveTelegrafPlugin: jest.fn(), onClickPrevious: jest.fn(), onClickSkip: jest.fn(), onClickNext: jest.fn(), telegrafPlugins: [], currentIndex: 3, + onSetPluginConfiguration: jest.fn(), ...override, } - const wrapper = mount() + const wrapper = shallow() return {wrapper} } -describe('Onboarding.Components.ConfigureStep.Streaming.PluginConfigForm', () => { +describe('DataLoaders.Components.CollectorsWizard.Configure.PluginConfigForm', () => { describe('if configFields have no keys', () => { it('renders text and buttons', () => { const {wrapper} = setup({ @@ -57,23 +58,4 @@ describe('Onboarding.Components.ConfigureStep.Streaming.PluginConfigForm', () => expect(onboardingButtons.exists()).toBe(true) }) }) - - describe('if configFields have keys', () => { - it('renders switcher', () => { - const configFields = - telegrafPluginsInfo[TelegrafPluginInputRedis.NameEnum.Redis].fields - const {wrapper} = setup({ - telegrafPlugin, - configFields, - }) - const form = wrapper.find(Form) - const configFieldSwitchers = wrapper.find(ConfigFieldSwitcher) - - const fields = Object.keys(configFields) - - expect(wrapper.exists()).toBe(true) - expect(form.exists()).toBe(true) - expect(configFieldSwitchers.length).toBe(fields.length) - }) - }) }) diff --git a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.tsx similarity index 50% rename from ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.tsx rename to ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.tsx index d821add4ae..cb6b04e86d 100644 --- a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigForm.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm.tsx @@ -1,52 +1,51 @@ // Libraries import React, {PureComponent} from 'react' +import {connect} from 'react-redux' import _ from 'lodash' // Components import {Form} from 'src/clockface' -import ConfigFieldHandler from 'src/dataLoaders/components/configureStep/streaming/ConfigFieldHandler' +import ConfigFieldHandler from 'src/dataLoaders/components/collectorsWizard/configure/ConfigFieldHandler' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' // Actions import { - updateTelegrafPluginConfig, - addConfigValue, - removeConfigValue, - setConfigArrayValue, + setActiveTelegrafPlugin, + setPluginConfiguration, } from 'src/dataLoaders/actions/dataLoaders' // Types import {TelegrafPlugin, ConfigFields} from 'src/types/v2/dataLoaders' import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' +import {AppState} from 'src/types/v2' -interface Props { +interface OwnProps { telegrafPlugin: TelegrafPlugin configFields: ConfigFields - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - onSetConfigArrayValue: typeof setConfigArrayValue - onClickNext: () => void +} + +interface DispatchProps { + onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin + onSetPluginConfiguration: typeof setPluginConfiguration +} + +interface StateProps { telegrafPlugins: TelegrafPlugin[] } -class PluginConfigForm extends PureComponent { +type Props = OwnProps & StateProps & DispatchProps + +export class PluginConfigForm extends PureComponent { public render() { - const { - telegrafPlugin: {name}, - configFields, - telegrafPlugin, - onSetConfigArrayValue, - onAddConfigValue, - onRemoveConfigValue, - onUpdateTelegrafPluginConfig, - } = this.props + const {configFields, telegrafPlugin} = this.props return ( -
+
-

{_.startCase(name)}

+

+ {_.startCase(telegrafPlugin.name)} +

For more information about this plugin, see{' '} {
@@ -71,10 +66,42 @@ class PluginConfigForm extends PureComponent { ) } + private get autoFocus(): boolean { const {configFields} = this.props return !configFields } + + private handleSubmitForm = () => { + const { + telegrafPlugins, + onSetPluginConfiguration, + onSetActiveTelegrafPlugin, + } = this.props + + const activeTelegrafPlugin = telegrafPlugins.find(tp => tp.active) + if (!!activeTelegrafPlugin) { + onSetPluginConfiguration(activeTelegrafPlugin.name) + } + + onSetActiveTelegrafPlugin('') + } } -export default PluginConfigForm +const mstp = ({ + dataLoading: { + dataLoaders: {telegrafPlugins}, + }, +}: AppState): StateProps => ({ + telegrafPlugins, +}) + +const mdtp: DispatchProps = { + onSetActiveTelegrafPlugin: setActiveTelegrafPlugin, + onSetPluginConfiguration: setPluginConfiguration, +} + +export default connect( + mstp, + mdtp +)(PluginConfigForm) diff --git a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.test.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.test.tsx similarity index 60% rename from ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.test.tsx rename to ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.test.tsx index 37b4718371..6e00146034 100644 --- a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.test.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.test.tsx @@ -3,9 +3,10 @@ import React from 'react' import {shallow} from 'enzyme' // Components -import PluginConfigSwitcher from 'src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher' +import {PluginConfigSwitcher} from 'src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher' +import TelegrafPluginInstructions from 'src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions' import EmptyDataSourceState from 'src/dataLoaders/components/configureStep/EmptyDataSourceState' -import PluginConfigForm from 'src/dataLoaders/components/configureStep/streaming/PluginConfigForm' +import PluginConfigForm from 'src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm' // Constants import {telegrafPlugin, token} from 'mocks/dummyData' @@ -32,7 +33,7 @@ const setup = (override = {}) => { return {wrapper} } -describe('Onboarding.Components.ConfigureStep.Streaming.PluginConfigSwitcher', () => { +describe('DataLoading.Components.Collectors.Configure.PluginConfigSwitcher', () => { describe('if no telegraf plugins', () => { it('renders empty data source state', () => { const {wrapper} = setup() @@ -43,10 +44,10 @@ describe('Onboarding.Components.ConfigureStep.Streaming.PluginConfigSwitcher', ( }) }) - describe('if has telegraf plugins', () => { + describe('if has active telegraf plugin', () => { it('renders plugin config form', () => { const {wrapper} = setup({ - telegrafPlugins: [telegrafPlugin], + telegrafPlugins: [{...telegrafPlugin, active: true}], }) const form = wrapper.find(PluginConfigForm) @@ -54,4 +55,16 @@ describe('Onboarding.Components.ConfigureStep.Streaming.PluginConfigSwitcher', ( expect(form.exists()).toBe(true) }) }) + + describe('if has no active telegraf plugin', () => { + it('renders telegraf instructions', () => { + const {wrapper} = setup({ + telegrafPlugins: [{...telegrafPlugin, active: false}], + }) + const form = wrapper.find(TelegrafPluginInstructions) + + expect(wrapper.exists()).toBe(true) + expect(form.exists()).toBe(true) + }) + }) }) diff --git a/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.tsx new file mode 100644 index 0000000000..db99032e00 --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/PluginConfigSwitcher.tsx @@ -0,0 +1,65 @@ +// Libraries +import React, {PureComponent} from 'react' +import {connect} from 'react-redux' +import _ from 'lodash' + +// Components +import PluginConfigForm from 'src/dataLoaders/components/collectorsWizard/configure/PluginConfigForm' +import EmptyDataSourceState from 'src/dataLoaders/components/configureStep/EmptyDataSourceState' + +// Utils +import {getConfigFields} from 'src/dataLoaders/utils/pluginConfigs' + +// Types +import {TelegrafPlugin, ConfigFields} from 'src/types/v2/dataLoaders' +import {AppState} from 'src/types/v2' +import TelegrafPluginInstructions from 'src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions' + +interface StateProps { + telegrafPlugins: TelegrafPlugin[] +} + +type Props = StateProps + +export class PluginConfigSwitcher extends PureComponent { + public render() { + const {telegrafPlugins} = this.props + + if (this.activeTelegrafPlugin) { + return ( + + ) + } else if (!telegrafPlugins || !telegrafPlugins.length) { + return + } + + return + } + + private get activeTelegrafPlugin(): TelegrafPlugin { + const {telegrafPlugins} = this.props + return telegrafPlugins.find(tp => tp.active) + } + + private get configFields(): ConfigFields { + if (this.activeTelegrafPlugin) { + return getConfigFields(this.activeTelegrafPlugin.name) + } + } +} + +const mstp = ({ + dataLoading: { + dataLoaders: {telegrafPlugins}, + }, +}: AppState): StateProps => ({ + telegrafPlugins, +}) + +export default connect( + mstp, + null +)(PluginConfigSwitcher) diff --git a/ui/src/dataLoaders/components/configureStep/streaming/TelegrafPluginInstructions.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx similarity index 75% rename from ui/src/dataLoaders/components/configureStep/streaming/TelegrafPluginInstructions.tsx rename to ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx index 4d086c29de..651b38619c 100644 --- a/ui/src/dataLoaders/components/configureStep/streaming/TelegrafPluginInstructions.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx @@ -1,32 +1,39 @@ // Libraries import React, {PureComponent, ChangeEvent} from 'react' import {connect} from 'react-redux' -import {AppState} from 'src/types/v2/index' + +// Components import {Form, Input, InputType, ComponentSize} from 'src/clockface' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' -import {setTelegrafConfigName} from 'src/dataLoaders/actions/dataLoaders' -interface OwnProps { - onClickNext: () => void - onClickPrevious: () => void -} +// Actions +import {setTelegrafConfigName} from 'src/dataLoaders/actions/dataLoaders' +import { + incrementCurrentStepIndex, + decrementCurrentStepIndex, +} from 'src/dataLoaders/actions/steps' + +// Types +import {AppState} from 'src/types/v2/index' interface DispatchProps { onSetTelegrafConfigName: typeof setTelegrafConfigName + onIncrementStep: typeof incrementCurrentStepIndex + onDecrementStep: typeof decrementCurrentStepIndex } interface StateProps { telegrafConfigName: string } -type Props = OwnProps & DispatchProps & StateProps +type Props = DispatchProps & StateProps -class TelegrafPluginInstructions extends PureComponent { +export class TelegrafPluginInstructions extends PureComponent { public render() { - const {onClickPrevious, onClickNext, telegrafConfigName} = this.props + const {telegrafConfigName, onDecrementStep, onIncrementStep} = this.props return ( -
+
@@ -52,10 +59,11 @@ class TelegrafPluginInstructions extends PureComponent {
- + ) } + private handleNameInput = (e: ChangeEvent) => { this.props.onSetTelegrafConfigName(e.target.value) } @@ -73,8 +81,10 @@ const mstp = ({ const mdtp: DispatchProps = { onSetTelegrafConfigName: setTelegrafConfigName, + onIncrementStep: incrementCurrentStepIndex, + onDecrementStep: decrementCurrentStepIndex, } -export default connect( +export default connect( mstp, mdtp )(TelegrafPluginInstructions) diff --git a/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.test.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.test.tsx new file mode 100644 index 0000000000..a8d36ac630 --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.test.tsx @@ -0,0 +1,79 @@ +// Libraries +import React from 'react' +import {shallow} from 'enzyme' + +// Components +import {SelectCollectorsStep} from 'src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep' +import StreamingSelector from 'src/dataLoaders/components/collectorsWizard/select/StreamingSelector' +import {ComponentStatus} from 'src/clockface' + +// Types +import {DataLoaderType} from 'src/types/v2/dataLoaders' + +// Dummy Data +import { + defaultOnboardingStepProps, + cpuTelegrafPlugin, + bucket, +} from 'mocks/dummyData' +import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' + +const setup = (override = {}) => { + const props = { + ...defaultOnboardingStepProps, + bucket: '', + telegrafPlugins: [], + pluginBundles: [], + type: DataLoaderType.Empty, + onAddPluginBundle: jest.fn(), + onRemovePluginBundle: jest.fn(), + onSetDataLoadersType: jest.fn(), + onSetActiveTelegrafPlugin: jest.fn(), + currentStepIndex: 2, + substep: undefined, + location: null, + router: null, + routes: [], + selectedBucket: '', + onSetBucketInfo: jest.fn(), + buckets: [], + ...override, + } + + return shallow() +} + +describe('DataLoaders.Components.CollectorsWizard.Select.SelectCollectorsStep', () => { + describe('if there are no plugins selected', () => { + it('renders streaming selector with buttons', () => { + const wrapper = setup({ + type: DataLoaderType.Streaming, + currentStepIndex: 0, + substep: 'streaming', + }) + const streamingSelector = wrapper.find(StreamingSelector) + const onboardingButtons = wrapper.find(OnboardingButtons) + + expect(streamingSelector.exists()).toBe(true) + expect(onboardingButtons.prop('nextButtonStatus')).toBe( + ComponentStatus.Disabled + ) + }) + }) + + describe('if there are plugins selected', () => { + it('renders next button with correct status', () => { + const wrapper = setup({ + type: DataLoaderType.Streaming, + currentStepIndex: 0, + substep: 'streaming', + telegrafPlugins: [cpuTelegrafPlugin], + buckets: [bucket], + }) + const onboardingButtons = wrapper.find(OnboardingButtons) + expect(onboardingButtons.prop('nextButtonStatus')).toBe( + ComponentStatus.Default + ) + }) + }) +}) diff --git a/ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx similarity index 52% rename from ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.tsx rename to ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx index 949633bf14..2d7cbe19db 100644 --- a/ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx @@ -1,50 +1,57 @@ // Libraries import React, {PureComponent} from 'react' +import {connect} from 'react-redux' import _ from 'lodash' // Components import {ErrorHandling} from 'src/shared/decorators/errors' import {ComponentStatus, Form} from 'src/clockface' -import TypeSelector from 'src/dataLoaders/components/selectionStep/TypeSelector' -import StreamingSelector from 'src/dataLoaders/components/selectionStep/StreamingSelector' +import StreamingSelector from 'src/dataLoaders/components/collectorsWizard/select/StreamingSelector' import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' // Actions import { - setActiveTelegrafPlugin, addPluginBundleWithPlugins, removePluginBundleWithPlugins, + setDataLoadersType, } from 'src/dataLoaders/actions/dataLoaders' import {setBucketInfo} from 'src/dataLoaders/actions/steps' // Types -import {DataLoaderStepProps} from 'src/dataLoaders/components/DataLoadersWizard' +import {CollectorsStepProps} from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' import { TelegrafPlugin, DataLoaderType, BundleName, } from 'src/types/v2/dataLoaders' import {Bucket} from 'src/api' +import {AppState} from 'src/types/v2' -export interface Props extends DataLoaderStepProps { +export interface OwnProps extends CollectorsStepProps { + buckets: Bucket[] +} + +export interface StateProps { + type: DataLoaderType bucket: string telegrafPlugins: TelegrafPlugin[] pluginBundles: BundleName[] - type: DataLoaderType - onAddPluginBundle: typeof addPluginBundleWithPlugins - onRemovePluginBundle: typeof removePluginBundleWithPlugins - onSetDataLoadersType: (type: DataLoaderType) => void - onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin - onSetBucketInfo: typeof setBucketInfo - buckets: Bucket[] - selectedBucket: string } +export interface DispatchProps { + onAddPluginBundle: typeof addPluginBundleWithPlugins + onRemovePluginBundle: typeof removePluginBundleWithPlugins + onSetDataLoadersType: typeof setDataLoadersType + onSetBucketInfo: typeof setBucketInfo +} + +type Props = OwnProps & StateProps & DispatchProps + @ErrorHandling -export class SelectDataSourceStep extends PureComponent { +export class SelectCollectorsStep extends PureComponent { public componentDidMount() { - if (this.isStreaming && this.props.type !== DataLoaderType.Streaming) { + if (this.props.type !== DataLoaderType.Streaming) { this.props.onSetDataLoadersType(DataLoaderType.Streaming) } } @@ -52,7 +59,7 @@ export class SelectDataSourceStep extends PureComponent { public render() { return (
-
+
@@ -60,7 +67,14 @@ export class SelectDataSourceStep extends PureComponent {
Telegraf collects and writes metrics to a bucket in InfluxDB.
- {this.selector} +
@@ -82,9 +96,7 @@ export class SelectDataSourceStep extends PureComponent { const isTypeEmpty = type === DataLoaderType.Empty const isStreamingWithoutPlugin = - type === DataLoaderType.Streaming && - this.isStreaming && - !telegrafPlugins.length + type === DataLoaderType.Streaming && !telegrafPlugins.length if (isTypeEmpty || isStreamingWithoutPlugin) { return ComponentStatus.Disabled @@ -95,32 +107,7 @@ export class SelectDataSourceStep extends PureComponent { private get title(): string { const {bucket} = this.props - if (this.isStreaming) { - return `Select Telegraf Plugins to add to ${bucket || 'your bucket'}` - } - return `Select a Data Source to add to ${bucket || 'your bucket'}` - } - - private get selector(): JSX.Element { - if (this.props.type === DataLoaderType.Streaming && this.isStreaming) { - return ( - - ) - } - return ( - - ) + return `Select Telegraf Plugins to add to ${bucket || 'your bucket'}` } private handleSelectBucket = (bucket: Bucket) => { @@ -129,36 +116,6 @@ export class SelectDataSourceStep extends PureComponent { this.props.onSetBucketInfo(organization, organizationID, name, id) } - private handleClickNext = () => { - const { - currentStepIndex, - onSetActiveTelegrafPlugin, - onSetSubstepIndex, - } = this.props - - const isTypeSelectionStep = - this.props.type === DataLoaderType.Streaming && !this.isStreaming - if (isTypeSelectionStep) { - onSetSubstepIndex(currentStepIndex, 'streaming') - onSetActiveTelegrafPlugin('') - return - } - - if (this.isStreaming) { - onSetSubstepIndex(currentStepIndex + 1, 'config') - return - } - - this.props.onIncrementCurrentStepIndex() - } - - private handleSelectDataLoaderType = async (type: DataLoaderType) => { - await this.props.onSetDataLoadersType(type) - this.handleClickNext() - - return - } - private handleTogglePluginBundle = ( bundle: BundleName, isSelected: boolean @@ -171,10 +128,28 @@ export class SelectDataSourceStep extends PureComponent { this.props.onAddPluginBundle(bundle) } - - private get isStreaming(): boolean { - return this.props.substep === 'streaming' - } } -export default SelectDataSourceStep +const mstp = ({ + dataLoading: { + dataLoaders: {telegrafPlugins, pluginBundles, type}, + steps: {bucket}, + }, +}: AppState): StateProps => ({ + type, + telegrafPlugins, + bucket, + pluginBundles, +}) + +const mdtp: DispatchProps = { + onSetDataLoadersType: setDataLoadersType, + onAddPluginBundle: addPluginBundleWithPlugins, + onRemovePluginBundle: removePluginBundleWithPlugins, + onSetBucketInfo: setBucketInfo, +} + +export default connect( + mstp, + mdtp +)(SelectCollectorsStep) diff --git a/ui/src/dataLoaders/components/selectionStep/StreamingSelector.test.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.test.tsx similarity index 92% rename from ui/src/dataLoaders/components/selectionStep/StreamingSelector.test.tsx rename to ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.test.tsx index 7249c4adb9..369b0c087b 100644 --- a/ui/src/dataLoaders/components/selectionStep/StreamingSelector.test.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import {shallow} from 'enzyme' // Components -import StreamingSelector from 'src/dataLoaders/components/selectionStep/StreamingSelector' +import StreamingSelector from 'src/dataLoaders/components/collectorsWizard/select/StreamingSelector' import CardSelectCard from 'src/clockface/components/card_select/CardSelectCard' import {Input} from 'src/clockface' diff --git a/ui/src/dataLoaders/components/selectionStep/StreamingSelector.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx similarity index 96% rename from ui/src/dataLoaders/components/selectionStep/StreamingSelector.tsx rename to ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx index 90f5986016..517dd30a79 100644 --- a/ui/src/dataLoaders/components/selectionStep/StreamingSelector.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx @@ -30,7 +30,6 @@ import {Bucket} from 'src/api' export interface Props { buckets: Bucket[] bucket: string - selectedBucket: string pluginBundles: BundleName[] telegrafPlugins: TelegrafPlugin[] onTogglePluginBundle: (telegrafPlugin: string, isSelected: boolean) => void @@ -128,9 +127,7 @@ class StreamingSelector extends PureComponent { } private get selectedBucketID(): string { - const {bucket, selectedBucket, buckets} = this.props - - return selectedBucket || bucket || _.get(buckets, '0.name', 'empty') + return this.props.bucket || 'empty' } private get dropdownBuckets(): JSX.Element[] { diff --git a/ui/src/dataLoaders/components/collectorsWizard/verify/VerifyCollectorsStep.tsx b/ui/src/dataLoaders/components/collectorsWizard/verify/VerifyCollectorsStep.tsx new file mode 100644 index 0000000000..0069136b74 --- /dev/null +++ b/ui/src/dataLoaders/components/collectorsWizard/verify/VerifyCollectorsStep.tsx @@ -0,0 +1,104 @@ +// Libraries +import React, {PureComponent} from 'react' +import {connect} from 'react-redux' +import _ from 'lodash' + +// Components +import {ErrorHandling} from 'src/shared/decorators/errors' +import DataStreaming from 'src/dataLoaders/components/verifyStep/DataStreaming' +import FetchAuthToken from 'src/dataLoaders/components/verifyStep/FetchAuthToken' +import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' +import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' + +// Actions +import { + setActiveTelegrafPlugin, + setPluginConfiguration, +} from 'src/dataLoaders/actions/dataLoaders' + +// Types +import {CollectorsStepProps} from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' +import {Form} from 'src/clockface' +import {AppState} from 'src/types/v2' + +type OwnProps = CollectorsStepProps + +interface StateProps { + username: string + telegrafConfigID: string + bucket: string + org: string +} + +interface DispatchProps { + onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin + onSetPluginConfiguration: typeof setPluginConfiguration +} + +export type Props = DispatchProps & StateProps & OwnProps + +@ErrorHandling +export class VerifyDataStep extends PureComponent { + public render() { + const { + username, + telegrafConfigID, + bucket, + notify, + org, + onDecrementCurrentStepIndex, + onExit, + } = this.props + + return ( +
+ +
+ +
+ + {authToken => ( + + )} + +
+
+
+ + +
+ ) + } +} + +const mstp = ({ + dataLoading: { + dataLoaders: {telegrafConfigID}, + steps: {bucket, org}, + }, + me: {name}, +}: AppState): StateProps => ({ + username: name, + telegrafConfigID, + bucket, + org, +}) + +const mdtp: DispatchProps = { + onSetActiveTelegrafPlugin: setActiveTelegrafPlugin, + onSetPluginConfiguration: setPluginConfiguration, +} + +export default connect( + mstp, + mdtp +)(VerifyDataStep) diff --git a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceStep.tsx b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceStep.tsx index 06112e2700..e7d4cf0caa 100644 --- a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceStep.tsx +++ b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceStep.tsx @@ -6,33 +6,15 @@ import _ from 'lodash' import {ErrorHandling} from 'src/shared/decorators/errors' import ConfigureDataSourceSwitcher from 'src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher' -// Actions -import {setActiveTelegrafPlugin} from 'src/dataLoaders/actions/dataLoaders' -import { - updateTelegrafPluginConfig, - setPluginConfiguration, - addConfigValue, - removeConfigValue, - setConfigArrayValue, -} from 'src/dataLoaders/actions/dataLoaders' - // Types import {DataLoaderStepProps} from 'src/dataLoaders/components/DataLoadersWizard' -import {TelegrafPlugin, DataLoaderType} from 'src/types/v2/dataLoaders' +import {DataLoaderType} from 'src/types/v2/dataLoaders' import {Bucket} from 'src/api' export interface OwnProps extends DataLoaderStepProps { - telegrafPlugins: TelegrafPlugin[] - onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onSetPluginConfiguration: typeof setPluginConfiguration type: DataLoaderType - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - onSetConfigArrayValue: typeof setConfigArrayValue bucket: string org: string - username: string buckets: Bucket[] } @@ -45,87 +27,29 @@ export class ConfigureDataSourceStep extends PureComponent { } public render() { - const { - telegrafPlugins, - type, - substep, - onUpdateTelegrafPluginConfig, - onAddConfigValue, - onRemoveConfigValue, - onSetConfigArrayValue, - bucket, - org, - username, - buckets, - } = this.props + const {type, bucket, org, buckets} = this.props return ( ) } private handleNext = async () => { - const { - onIncrementCurrentStepIndex, - onSetActiveTelegrafPlugin, - onSetPluginConfiguration, - telegrafPlugins, - substep, - currentStepIndex, - type, - onExit, - onSetSubstepIndex, - } = this.props + const {onIncrementCurrentStepIndex, type, onExit} = this.props if (type === DataLoaderType.Scraping) { onExit() return } - if (type === DataLoaderType.Streaming && !_.isNaN(Number(substep))) { - const index = +substep - const telegrafPlugin = _.get(telegrafPlugins, `${index}.name`) - onSetPluginConfiguration(telegrafPlugin) - onSetActiveTelegrafPlugin('') - onSetSubstepIndex(currentStepIndex, 'config') - return - } - onIncrementCurrentStepIndex() } - - private handlePrevious = () => { - const { - type, - substep, - currentStepIndex, - onSetSubstepIndex, - onDecrementCurrentStepIndex, - } = this.props - - if (type === DataLoaderType.Streaming) { - if (substep === 'config') { - onSetSubstepIndex(+currentStepIndex - 1, 'streaming') - } - return - } - - onDecrementCurrentStepIndex() - } } export default ConfigureDataSourceStep diff --git a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx index 167dc94e60..7eafb7f814 100644 --- a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx +++ b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx @@ -5,72 +5,27 @@ import _ from 'lodash' // Components import {ErrorHandling} from 'src/shared/decorators/errors' import LineProtocol from 'src/dataLoaders/components/configureStep/lineProtocol/LineProtocol' -import PluginConfigSwitcher from 'src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher' import EmptyDataSourceState from 'src/dataLoaders/components/configureStep/EmptyDataSourceState' import Scraping from 'src/dataLoaders/components/configureStep/Scraping' -// Actions -import { - updateTelegrafPluginConfig, - addConfigValue, - removeConfigValue, - setConfigArrayValue, -} from 'src/dataLoaders/actions/dataLoaders' - // Types -import {TelegrafPlugin, DataLoaderType, Substep} from 'src/types/v2/dataLoaders' +import {DataLoaderType} from 'src/types/v2/dataLoaders' import {Bucket} from 'src/api' export interface Props { - telegrafPlugins: TelegrafPlugin[] - substepIndex: Substep - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue dataLoaderType: DataLoaderType buckets: Bucket[] bucket: string org: string - username: string - onSetConfigArrayValue: typeof setConfigArrayValue onClickNext: () => void - onClickPrevious: () => void } @ErrorHandling class ConfigureDataSourceSwitcher extends PureComponent { public render() { - const { - bucket, - org, - telegrafPlugins, - substepIndex, - dataLoaderType, - onUpdateTelegrafPluginConfig, - onAddConfigValue, - onRemoveConfigValue, - onSetConfigArrayValue, - onClickNext, - onClickPrevious, - buckets, - } = this.props + const {bucket, org, dataLoaderType, onClickNext, buckets} = this.props switch (dataLoaderType) { - case DataLoaderType.Streaming: - return ( -
- -
- ) case DataLoaderType.LineProtocol: return (
diff --git a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.tsx b/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.tsx deleted file mode 100644 index 83d1c1a904..0000000000 --- a/ui/src/dataLoaders/components/configureStep/streaming/PluginConfigSwitcher.tsx +++ /dev/null @@ -1,83 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' -import _ from 'lodash' - -// Components -import PluginConfigForm from 'src/dataLoaders/components/configureStep/streaming/PluginConfigForm' -import EmptyDataSourceState from 'src/dataLoaders/components/configureStep/EmptyDataSourceState' - -// Utils -import {getConfigFields} from 'src/dataLoaders/utils/pluginConfigs' - -// Actions -import { - updateTelegrafPluginConfig, - addConfigValue, - removeConfigValue, - setConfigArrayValue, -} from 'src/dataLoaders/actions/dataLoaders' - -// Types -import {TelegrafPlugin, Substep} from 'src/types/v2/dataLoaders' -import TelegrafPluginInstructions from 'src/dataLoaders/components/configureStep/streaming/TelegrafPluginInstructions' - -interface Props { - telegrafPlugins: TelegrafPlugin[] - onUpdateTelegrafPluginConfig: typeof updateTelegrafPluginConfig - onAddConfigValue: typeof addConfigValue - onRemoveConfigValue: typeof removeConfigValue - substepIndex: Substep - onSetConfigArrayValue: typeof setConfigArrayValue - onClickNext: () => void - onClickPrevious: () => void -} - -class PluginConfigSwitcher extends PureComponent { - public render() { - const { - onUpdateTelegrafPluginConfig, - onAddConfigValue, - onRemoveConfigValue, - onSetConfigArrayValue, - onClickNext, - telegrafPlugins, - substepIndex, - onClickPrevious, - } = this.props - - if (substepIndex === 'config') { - return ( - - ) - } else if (this.currentTelegrafPlugin) { - return ( - - ) - } else { - return - } - } - - private get currentTelegrafPlugin(): TelegrafPlugin { - const {substepIndex, telegrafPlugins} = this.props - return _.get(telegrafPlugins, `${substepIndex}`, null) - } - - private get configFields() { - return getConfigFields(this.currentTelegrafPlugin.name) - } -} - -export default PluginConfigSwitcher diff --git a/ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.test.tsx b/ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.test.tsx deleted file mode 100644 index 2dc83338ea..0000000000 --- a/ui/src/dataLoaders/components/selectionStep/SelectDataSourceStep.test.tsx +++ /dev/null @@ -1,109 +0,0 @@ -// Libraries -import React from 'react' -import {shallow} from 'enzyme' - -// Components -import {SelectDataSourceStep} from 'src/dataLoaders/components/selectionStep/SelectDataSourceStep' -import StreamingSelector from 'src/dataLoaders/components/selectionStep/StreamingSelector' -import TypeSelector from 'src/dataLoaders/components/selectionStep/TypeSelector' -import {ComponentStatus} from 'src/clockface' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' - -// Dummy Data -import { - defaultOnboardingStepProps, - cpuTelegrafPlugin, - bucket, -} from 'mocks/dummyData' -import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' - -const setup = (override = {}) => { - const props = { - ...defaultOnboardingStepProps, - bucket: '', - telegrafPlugins: [], - pluginBundles: [], - type: DataLoaderType.Empty, - onAddPluginBundle: jest.fn(), - onRemovePluginBundle: jest.fn(), - onSetDataLoadersType: jest.fn(), - onSetActiveTelegrafPlugin: jest.fn(), - currentStepIndex: 2, - substep: undefined, - location: null, - router: null, - routes: [], - selectedBucket: '', - onSetBucketInfo: jest.fn(), - buckets: [], - ...override, - } - - return shallow() -} - -describe('Onboarding.Components.SelectionStep.SelectDataSourceStep', () => { - describe('if type is empty', () => { - it('renders type selector and buttons', async () => { - const wrapper = setup() - const typeSelector = wrapper.find(TypeSelector) - const onboardingButtons = wrapper.find(OnboardingButtons) - - expect(wrapper.exists()).toBe(true) - expect(typeSelector.exists()).toBe(true) - expect(onboardingButtons.prop('nextButtonStatus')).toBe( - ComponentStatus.Disabled - ) - }) - }) - - describe('if type is line protocol', () => { - it('renders back and next buttons with correct status', () => { - const wrapper = setup({ - type: DataLoaderType.LineProtocol, - buckets: [bucket], - }) - const onboardingButtons = wrapper.find(OnboardingButtons) - expect(onboardingButtons.prop('nextButtonStatus')).toBe( - ComponentStatus.Default - ) - }) - }) - - describe('if type and substep is streaming', () => { - describe('if there are no plugins selected', () => { - it('renders streaming selector with buttons', () => { - const wrapper = setup({ - type: DataLoaderType.Streaming, - currentStepIndex: 0, - substep: 'streaming', - }) - const streamingSelector = wrapper.find(StreamingSelector) - const onboardingButtons = wrapper.find(OnboardingButtons) - - expect(streamingSelector.exists()).toBe(true) - expect(onboardingButtons.prop('nextButtonStatus')).toBe( - ComponentStatus.Disabled - ) - }) - }) - - describe('if there are plugins selected', () => { - it('renders back and next button with correct status', () => { - const wrapper = setup({ - type: DataLoaderType.Streaming, - currentStepIndex: 0, - substep: 'streaming', - telegrafPlugins: [cpuTelegrafPlugin], - buckets: [bucket], - }) - const onboardingButtons = wrapper.find(OnboardingButtons) - expect(onboardingButtons.prop('nextButtonStatus')).toBe( - ComponentStatus.Default - ) - }) - }) - }) -}) diff --git a/ui/src/dataLoaders/components/selectionStep/TypeSelector.tsx b/ui/src/dataLoaders/components/selectionStep/TypeSelector.tsx deleted file mode 100644 index cbb2d6b281..0000000000 --- a/ui/src/dataLoaders/components/selectionStep/TypeSelector.tsx +++ /dev/null @@ -1,69 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' - -// Components -import {ErrorHandling} from 'src/shared/decorators/errors' -import CardSelectCard from 'src/clockface/components/card_select/CardSelectCard' -import {GridSizer} from 'src/clockface' -import { - IconCSV, - IconLineProtocol, - IconStreaming, -} from 'src/dataLoaders/graphics' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' - -export interface Props { - onSelectDataLoaderType: (type: string) => void - type: DataLoaderType -} - -const DATA_SOURCES_OPTIONS = [ - DataLoaderType.Streaming, - DataLoaderType.LineProtocol, - DataLoaderType.Scraping, -] - -const DATA_SOURCES_LOGOS = { - [DataLoaderType.CSV]: IconCSV, - [DataLoaderType.Streaming]: IconStreaming, - [DataLoaderType.LineProtocol]: IconLineProtocol, -} - -@ErrorHandling -class TypeSelector extends PureComponent { - public render() { - return ( -
- - {DATA_SOURCES_OPTIONS.map(ds => { - return ( - - ) - })} - -
- ) - } - - private isCardChecked(dataLoaderType: DataLoaderType) { - const {type} = this.props - - return dataLoaderType === type - } - - private handleClick = (type: string) => () => { - this.props.onSelectDataLoaderType(type) - } -} - -export default TypeSelector diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx index da15c895d9..80c4127ccd 100644 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx +++ b/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx @@ -9,31 +9,16 @@ import VerifyDataSwitcher from 'src/dataLoaders/components/verifyStep/VerifyData import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' -// Actions -import { - setActiveTelegrafPlugin, - setPluginConfiguration, -} from 'src/dataLoaders/actions/dataLoaders' - // Types -import {DataLoaderType, TelegrafPlugin} from 'src/types/v2/dataLoaders' +import {DataLoaderType} from 'src/types/v2/dataLoaders' import {Form} from 'src/clockface' -import {NotificationAction, RemoteDataState} from 'src/types' +import {RemoteDataState} from 'src/types' import {AppState} from 'src/types/v2' import {DataLoaderStepProps} from 'src/dataLoaders/components/DataLoadersWizard' export interface OwnProps extends DataLoaderStepProps { - notify: NotificationAction type: DataLoaderType - telegrafConfigID: string - telegrafPlugins: TelegrafPlugin[] - onSetActiveTelegrafPlugin: typeof setActiveTelegrafPlugin - onSetPluginConfiguration: typeof setPluginConfiguration stepIndex: number - bucket: string - username: string - org: string - selectedBucket: string } interface StateProps { @@ -44,26 +29,8 @@ export type Props = OwnProps & StateProps @ErrorHandling export class VerifyDataStep extends PureComponent { - public componentDidMount() { - const {type, onSetPluginConfiguration, telegrafPlugins} = this.props - - if (type === DataLoaderType.Streaming) { - telegrafPlugins.forEach(tp => { - onSetPluginConfiguration(tp.name) - }) - } - } - public render() { - const { - username, - telegrafConfigID, - type, - onDecrementCurrentStepIndex, - notify, - lpStatus, - org, - } = this.props + const {type, onDecrementCurrentStepIndex, lpStatus} = this.props return (
@@ -72,12 +39,7 @@ export class VerifyDataStep extends PureComponent {
@@ -93,32 +55,15 @@ export class VerifyDataStep extends PureComponent { ) } - private get bucket(): string { - const {bucket, selectedBucket} = this.props - - return selectedBucket || bucket - } - private handleIncrementStep = () => { const {onExit} = this.props onExit() } private handleDecrementStep = () => { - const { - onSetActiveTelegrafPlugin, - onDecrementCurrentStepIndex, - onSetSubstepIndex, - stepIndex, - type, - } = this.props + const {onDecrementCurrentStepIndex} = this.props - if (type === DataLoaderType.Streaming) { - onSetSubstepIndex(stepIndex - 1, 'config') - } else { - onDecrementCurrentStepIndex() - } - onSetActiveTelegrafPlugin('') + onDecrementCurrentStepIndex() } } diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx index 989c2ee2d1..ba2beb297a 100644 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx +++ b/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx @@ -3,21 +3,14 @@ import React, {PureComponent} from 'react' // Components import {ErrorHandling} from 'src/shared/decorators/errors' -import DataStreaming from 'src/dataLoaders/components/verifyStep/DataStreaming' -import FetchAuthToken from 'src/dataLoaders/components/verifyStep/FetchAuthToken' // Types import {DataLoaderType} from 'src/types/v2/dataLoaders' -import {NotificationAction, RemoteDataState} from 'src/types' +import {RemoteDataState} from 'src/types' import StatusIndicator from 'src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator' interface Props { - notify: NotificationAction type: DataLoaderType - org: string - bucket: string - username: string - telegrafConfigID: string onDecrementCurrentStep: () => void lpStatus: RemoteDataState } @@ -25,31 +18,9 @@ interface Props { @ErrorHandling export class VerifyDataSwitcher extends PureComponent { public render() { - const { - org, - bucket, - username, - type, - telegrafConfigID, - notify, - lpStatus, - } = this.props + const {type, lpStatus} = this.props switch (type) { - case DataLoaderType.Streaming: - return ( - - {authToken => ( - - )} - - ) case DataLoaderType.LineProtocol: return ( - - -`; +exports[`Onboarding.Components.VerifyStep.VerifyDataSwitcher If data type is streaming renders the DataStreaming component 1`] = `
`; diff --git a/ui/src/organizations/components/BucketList.tsx b/ui/src/organizations/components/BucketList.tsx index c9f781f47e..5fa311d3cb 100644 --- a/ui/src/organizations/components/BucketList.tsx +++ b/ui/src/organizations/components/BucketList.tsx @@ -1,30 +1,46 @@ // Libraries import React, {PureComponent} from 'react' import {withRouter, WithRouterProps} from 'react-router' +import {connect} from 'react-redux' import _ from 'lodash' // Components import UpdateBucketOverlay from 'src/organizations/components/UpdateBucketOverlay' import BucketRow, {PrettyBucket} from 'src/organizations/components/BucketRow' import {OverlayTechnology, IndexList} from 'src/clockface' +import DataLoaderSwitcher from 'src/dataLoaders/components/DataLoaderSwitcher' + +// Actions +import {setBucketInfo} from 'src/dataLoaders/actions/steps' // Types import {OverlayState} from 'src/types/v2' -import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' import {Substep, DataLoaderStep, DataLoaderType} from 'src/types/v2/dataLoaders' +import {setDataLoadersType} from 'src/dataLoaders/actions/dataLoaders' +import {AppState} from 'src/types/v2' -interface Props { +interface OwnProps { buckets: PrettyBucket[] emptyState: JSX.Element onUpdateBucket: (b: PrettyBucket) => Promise onDeleteBucket: (b: PrettyBucket) => Promise } +interface DispatchProps { + onSetBucketInfo: typeof setBucketInfo + onSetDataLoadersType: typeof setDataLoadersType +} + +interface StateProps { + dataLoaderType: DataLoaderType +} + +type Props = OwnProps & StateProps & DispatchProps + interface State { bucketID: string bucketOverlayState: OverlayState dataLoadersOverlayState: OverlayState - dataLoaderType: DataLoaderType } class BucketList extends PureComponent { @@ -45,12 +61,11 @@ class BucketList extends PureComponent { dataLoadersOverlayState: openDataLoaderOverlay ? OverlayState.Open : OverlayState.Closed, - dataLoaderType: DataLoaderType.Empty, } } public render() { - const {buckets, emptyState, onDeleteBucket} = this.props + const {dataLoaderType, buckets, emptyState, onDeleteBucket} = this.props return ( <> @@ -79,10 +94,10 @@ class BucketList extends PureComponent { onUpdateBucket={this.handleUpdateBucket} /> - @@ -99,15 +114,9 @@ class BucketList extends PureComponent { startingStep: number startingSubstep?: Substep } { - const {dataLoaderType} = this.state + const {dataLoaderType} = this.props switch (dataLoaderType) { - case DataLoaderType.Streaming: - return { - startingType: DataLoaderType.Streaming, - startingStep: DataLoaderStep.Select, - startingSubstep: 'streaming', - } case DataLoaderType.Scraping: return { startingType: DataLoaderType.Scraping, @@ -133,10 +142,18 @@ class BucketList extends PureComponent { bucket: PrettyBucket, dataLoaderType: DataLoaderType ) => { + this.props.onSetBucketInfo( + bucket.organization, + bucket.organizationID, + bucket.name, + bucket.id + ) + + this.props.onSetDataLoadersType(dataLoaderType) + this.setState({ bucketID: bucket.id, dataLoadersOverlayState: OverlayState.Open, - dataLoaderType, }) } @@ -163,4 +180,20 @@ class BucketList extends PureComponent { } } -export default withRouter(BucketList) +const mstp = ({ + dataLoading: { + dataLoaders: {type}, + }, +}: AppState): StateProps => ({ + dataLoaderType: type, +}) + +const mdtp: DispatchProps = { + onSetBucketInfo: setBucketInfo, + onSetDataLoadersType: setDataLoadersType, +} + +export default connect( + mstp, + mdtp +)(withRouter(BucketList)) diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index 106adb02f9..12f60a7794 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -1,6 +1,7 @@ // Libraries import _ from 'lodash' import React, {PureComponent, ChangeEvent} from 'react' +import {connect} from 'react-redux' // Utils import {downloadTextFile} from 'src/shared/utils/download' @@ -20,7 +21,7 @@ import { Input, InputType, } from 'src/clockface' -import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' +import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' import FilterList from 'src/shared/components/Filter' // APIS @@ -29,6 +30,7 @@ import {client} from 'src/utils/api' // Actions import * as NotificationsActions from 'src/types/actions/notifications' import {notify} from 'src/shared/actions/notifications' +import {setBucketInfo} from 'src/dataLoaders/actions/steps' // Constants import {getTelegrafConfigFailed} from 'src/shared/copy/v2/notifications' @@ -38,10 +40,9 @@ import {ErrorHandling} from 'src/shared/decorators/errors' // Types import {Telegraf, Bucket} from 'src/api' -import {DataLoaderType, DataLoaderStep} from 'src/types/v2/dataLoaders' import {OverlayState} from 'src/types/v2' -interface Props { +interface OwnProps { collectors: Telegraf[] onChange: () => void notify: NotificationsActions.PublishNotificationActionCreator @@ -49,13 +50,19 @@ interface Props { buckets: Bucket[] } +interface DispatchProps { + onSetBucketInfo: typeof setBucketInfo +} + +type Props = OwnProps & DispatchProps + interface State { overlayState: OverlayState searchTerm: string } @ErrorHandling -export default class Collectors extends PureComponent { +export class Collectors extends PureComponent { constructor(props: Props) { super(props) @@ -111,12 +118,10 @@ export default class Collectors extends PureComponent { - @@ -133,12 +138,18 @@ export default class Collectors extends PureComponent { text="Create Configuration" icon={IconFont.Plus} color={ComponentColor.Primary} - onClick={this.handleAddScraper} + onClick={this.handleAddCollector} /> ) } - private handleAddScraper = () => { + private handleAddCollector = () => { + const {buckets, onSetBucketInfo} = this.props + + if (buckets && buckets.length) { + const {organization, organizationID, name, id} = buckets[0] + onSetBucketInfo(organization, organizationID, name, id) + } this.setState({overlayState: OverlayState.Open}) } @@ -181,6 +192,7 @@ export default class Collectors extends PureComponent { notify(getTelegrafConfigFailed()) } } + private handleDeleteTelegraf = async (telegrafID: string) => { await client.telegrafConfigs.delete(telegrafID) this.props.onChange() @@ -194,3 +206,12 @@ export default class Collectors extends PureComponent { this.setState({searchTerm: e.target.value}) } } + +const mdtp: DispatchProps = { + onSetBucketInfo: setBucketInfo, +} + +export default connect( + null, + mdtp +)(Collectors) diff --git a/ui/src/types/v2/dataLoaders.ts b/ui/src/types/v2/dataLoaders.ts index fdb55e60c6..41030bd0f9 100644 --- a/ui/src/types/v2/dataLoaders.ts +++ b/ui/src/types/v2/dataLoaders.ts @@ -38,6 +38,11 @@ import {RemoteDataState} from 'src/types' import {WritePrecision} from 'src/api' export enum DataLoaderStep { + 'Configure', + 'Verify', +} + +export enum CollectorsStep { 'Select', 'Configure', 'Verify', From 3bb765279bf4a29c9ff910895bcdd0869c92d10f Mon Sep 17 00:00:00 2001 From: Jeff Wendling Date: Mon, 4 Feb 2019 12:26:21 -0700 Subject: [PATCH 31/95] storage: respond to review comments --- storage/metrics.go | 26 +++++--------------------- storage/retention.go | 24 +++++++++++------------- storage/retention_test.go | 12 +++--------- tsdb/tsm1/cache.go | 3 +-- 4 files changed, 20 insertions(+), 45 deletions(-) diff --git a/storage/metrics.go b/storage/metrics.go index 277386ab40..cf22be1acf 100644 --- a/storage/metrics.go +++ b/storage/metrics.go @@ -16,8 +16,6 @@ type retentionMetrics struct { labels prometheus.Labels Checks *prometheus.CounterVec CheckDuration *prometheus.HistogramVec - Unprocessable *prometheus.CounterVec - Series *prometheus.CounterVec } func newRetentionMetrics(labels prometheus.Labels) *retentionMetrics { @@ -25,17 +23,19 @@ func newRetentionMetrics(labels prometheus.Labels) *retentionMetrics { for k := range labels { names = append(names, k) } - names = append(names, "status") // All metrics include status sort.Strings(names) + checksNames := append(append([]string(nil), names...), "status", "org_id", "bucket_id") + sort.Strings(checksNames) + return &retentionMetrics{ labels: labels, Checks: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Subsystem: retentionSubsystem, Name: "checks_total", - Help: "Number of retention check operations performed.", - }, names), + Help: "Number of retention check operations performed by org/bucket id.", + }, checksNames), CheckDuration: prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: namespace, @@ -45,20 +45,6 @@ func newRetentionMetrics(labels prometheus.Labels) *retentionMetrics { // 25 buckets spaced exponentially between 10s and ~2h Buckets: prometheus.ExponentialBuckets(10, 1.32, 25), }, names), - - Unprocessable: prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: retentionSubsystem, - Name: "unprocessable_buckets_total", - Help: "Number of buckets that could not be operated on.", - }, names), - - Series: prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: retentionSubsystem, - Name: "series_total", - Help: "Number of series that a delete was applied to.", - }, names), } } @@ -76,7 +62,5 @@ func (rm *retentionMetrics) PrometheusCollectors() []prometheus.Collector { return []prometheus.Collector{ rm.Checks, rm.CheckDuration, - rm.Unprocessable, - rm.Series, } } diff --git a/storage/retention.go b/storage/retention.go index 72b908981c..323f8882b7 100644 --- a/storage/retention.go +++ b/storage/retention.go @@ -78,42 +78,40 @@ func (s *retentionEnforcer) run() { } now := time.Now().UTC() - labels := s.metrics.Labels() - labels["status"] = "ok" - - if err := s.expireData(buckets, now); err != nil { - log.Error("Deletion not successful", zap.Error(err)) - labels["status"] = "error" - } - s.metrics.CheckDuration.With(labels).Observe(time.Since(now).Seconds()) - s.metrics.Checks.With(labels).Inc() + s.expireData(buckets, now) + s.metrics.CheckDuration.With(s.metrics.Labels()).Observe(time.Since(now).Seconds()) } // expireData runs a delete operation on the storage engine. // // Any series data that (1) belongs to a bucket in the provided list and // (2) falls outside the bucket's indicated retention period will be deleted. -func (s *retentionEnforcer) expireData(buckets []*platform.Bucket, now time.Time) error { +func (s *retentionEnforcer) expireData(buckets []*platform.Bucket, now time.Time) { logger, logEnd := logger.NewOperation(s.logger, "Data deletion", "data_deletion") defer logEnd() + labels := s.metrics.Labels() for _, b := range buckets { if b.RetentionPeriod == 0 { continue } + labels["status"] = "ok" + labels["org_id"] = b.OrganizationID.String() + labels["bucket_id"] = b.ID.String() + max := now.Add(-b.RetentionPeriod).UnixNano() err := s.Engine.DeleteBucketRange(b.OrganizationID, b.ID, math.MinInt64, max) if err != nil { - // TODO(jeff): metrics? + labels["status"] = "error" logger.Info("unable to delete bucket range", zap.String("bucket id", b.ID.String()), zap.String("org id", b.OrganizationID.String()), zap.Error(err)) } - } - return nil + s.metrics.Checks.With(labels).Inc() + } } // getBucketInformation returns a slice of buckets to run retention on. diff --git a/storage/retention_test.go b/storage/retention_test.go index 9b4db3cf41..988426706b 100644 --- a/storage/retention_test.go +++ b/storage/retention_test.go @@ -18,12 +18,8 @@ func TestRetentionService(t *testing.T) { now := time.Date(2018, 4, 10, 23, 12, 33, 0, time.UTC) t.Run("no buckets", func(t *testing.T) { - if err := service.expireData(nil, now); err != nil { - t.Error(err) - } - if err := service.expireData([]*platform.Bucket{}, now); err != nil { - t.Error(err) - } + service.expireData(nil, now) + service.expireData([]*platform.Bucket{}, now) }) // Generate some buckets to expire @@ -77,9 +73,7 @@ func TestRetentionService(t *testing.T) { } t.Run("multiple buckets", func(t *testing.T) { - if err := service.expireData(buckets, now); err != nil { - t.Error(err) - } + service.expireData(buckets, now) if !reflect.DeepEqual(gotMatched, expMatched) { t.Fatalf("got\n%#v\nexpected\n%#v", gotMatched, expMatched) } diff --git a/tsdb/tsm1/cache.go b/tsdb/tsm1/cache.go index e7aa60d166..ea5868a97d 100644 --- a/tsdb/tsm1/cache.go +++ b/tsdb/tsm1/cache.go @@ -552,11 +552,10 @@ func (c *Cache) Values(key []byte) Values { func (c *Cache) DeleteBucketRange(name []byte, min, max int64) { c.init() + // TODO(edd/jeff): find a way to optimize lock usage c.mu.Lock() defer c.mu.Unlock() - // TODO(jeff): could optimzie lock usage, and figure a way out to - // avoid storing all of the entry keys to delete. var toDelete [][]byte var total uint64 From cb70b8eacb31cc1b2f307ee21d991a59b422e830 Mon Sep 17 00:00:00 2001 From: alexpaxton Date: Mon, 4 Feb 2019 13:01:32 -0800 Subject: [PATCH 32/95] Make Fancy Scrollbars Fancier (#11661) * WIP * Goodbye yarn * Use latest scrollbar package * Use default colors * Expose custom thumb color props * Use latest package * Remove unused package * Update test snapshots * Organize exernal styles into separate section --- ui/package-lock.json | 20 +- ui/package.json | 2 +- .../ViewTokenOverlay.test.tsx.snap | 66 +- .../fancy_scrollbar/FancyScrollbar.scss | 87 - .../fancy_scrollbar/FancyScrollbar.tsx | 19 +- ui/src/style/chronograf.scss | 4 +- ui/yarn.lock | 9316 ----------------- 7 files changed, 64 insertions(+), 9450 deletions(-) delete mode 100644 ui/src/shared/components/fancy_scrollbar/FancyScrollbar.scss delete mode 100644 ui/yarn.lock diff --git a/ui/package-lock.json b/ui/package-lock.json index a7ded7d3c5..116bbccf6f 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -836,6 +836,16 @@ "axios": "^0.18.0" } }, + "@influxdata/react-custom-scrollbars": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@influxdata/react-custom-scrollbars/-/react-custom-scrollbars-4.3.8.tgz", + "integrity": "sha512-tfBCP+L69nCqq/HgFDBmkvo0l6++6NnVZ2vj7vP5gHLenbTgODGNa9FLoaA3x5QQ8+OzvTt98UkVCAjKuY6aRg==", + "requires": { + "dom-css": "^2.0.0", + "prop-types": "^15.5.10", + "raf": "^3.1.0" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -10487,16 +10497,6 @@ "prop-types": "^15.5.8" } }, - "react-custom-scrollbars": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz", - "integrity": "sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts=", - "requires": { - "dom-css": "^2.0.0", - "prop-types": "^15.5.10", - "raf": "^3.1.0" - } - }, "react-dimensions": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/react-dimensions/-/react-dimensions-1.3.1.tgz", diff --git a/ui/package.json b/ui/package.json index 7337f572cd..4941631c29 100644 --- a/ui/package.json +++ b/ui/package.json @@ -116,6 +116,7 @@ "typescript": "^3.1.3" }, "dependencies": { + "@influxdata/react-custom-scrollbars": "4.3.8", "@influxdata/influx": "^0.1.7", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", @@ -143,7 +144,6 @@ "react": "^15.0.0 || ^16.0.0", "react-codemirror2": "^4.2.1", "react-copy-to-clipboard": "^5.0.1", - "react-custom-scrollbars": "^4.1.1", "react-dimensions": "^1.2.0", "react-dnd": "^2.6.0", "react-dnd-html5-backend": "^2.6.0", diff --git a/ui/src/me/components/account/__snapshots__/ViewTokenOverlay.test.tsx.snap b/ui/src/me/components/account/__snapshots__/ViewTokenOverlay.test.tsx.snap index 2ff8c4d455..a2757ef026 100644 --- a/ui/src/me/components/account/__snapshots__/ViewTokenOverlay.test.tsx.snap +++ b/ui/src/me/components/account/__snapshots__/ViewTokenOverlay.test.tsx.snap @@ -88,14 +88,11 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--container" hideTracksWhenNotNeeded={false} onScroll={[Function]} - renderThumbHorizontal={[Function]} - renderThumbVertical={[Function]} - renderTrackHorizontal={[Function]} - renderTrackVertical={[Function]} - renderView={[Function]} style={Object {}} tagName="div" thumbMinSize={30} + thumbStartColor="#22ADF6" + thumbStopColor="#9394FF" universal={false} >
@@ -149,8 +150,10 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--thumb-h" style={ Object { + "background": "linear-gradient(to right, #22ADF6 0%, #9394FF 100%)", + "borderRadius": "3px", "display": "block", - "height": "100%", + "height": "6px", "position": "relative", } } @@ -161,9 +164,13 @@ exports[`Account rendering renders! 1`] = ` key="trackVertical" style={ Object { - "display": "none", + "cursor": "pointer", + "height": "100%", + "padding": "3px", "position": "absolute", - "width": 6, + "right": "0", + "top": "0", + "width": "12px", } } > @@ -171,9 +178,11 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--thumb-v" style={ Object { + "background": "linear-gradient(to bottom, #22ADF6 0%, #9394FF 100%)", + "borderRadius": "3px", "display": "block", "position": "relative", - "width": "100%", + "width": "6px", } } /> @@ -248,14 +257,11 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--container" hideTracksWhenNotNeeded={false} onScroll={[Function]} - renderThumbHorizontal={[Function]} - renderThumbVertical={[Function]} - renderTrackHorizontal={[Function]} - renderTrackVertical={[Function]} - renderView={[Function]} style={Object {}} tagName="div" thumbMinSize={30} + thumbStartColor="#22ADF6" + thumbStopColor="#9394FF" universal={false} >
@@ -450,8 +460,10 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--thumb-h" style={ Object { + "background": "linear-gradient(to right, #22ADF6 0%, #9394FF 100%)", + "borderRadius": "3px", "display": "block", - "height": "100%", + "height": "6px", "position": "relative", } } @@ -462,9 +474,13 @@ exports[`Account rendering renders! 1`] = ` key="trackVertical" style={ Object { - "display": "none", + "cursor": "pointer", + "height": "100%", + "padding": "3px", "position": "absolute", - "width": 6, + "right": "0", + "top": "0", + "width": "12px", } } > @@ -472,9 +488,11 @@ exports[`Account rendering renders! 1`] = ` className="fancy-scroll--thumb-v" style={ Object { + "background": "linear-gradient(to bottom, #22ADF6 0%, #9394FF 100%)", + "borderRadius": "3px", "display": "block", "position": "relative", - "width": "100%", + "width": "6px", } } /> diff --git a/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.scss b/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.scss deleted file mode 100644 index a30c0575a8..0000000000 --- a/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.scss +++ /dev/null @@ -1,87 +0,0 @@ -/* - Fancy Scrollbars - ------------------------------------------------------ -*/ - -$scrollbar-track-size: 12px; -$scrollbar-thumb-size: 6px; - -$scrollbar-color-a: $c-pool; -$scrollbar-color-b: $c-comet; - -.fancy-scroll--track-h, -.fancy-scroll--track-v { - &:hover { - cursor: pointer; - } -} -/* Horizontal Scrollbar Styles */ -.fancy-scroll--track-h { - padding: ($scrollbar-track-size - $scrollbar-thumb-size) / 2; - width: 100%; - height: $scrollbar-track-size !important; - bottom: 0; - left: 0; -} -.fancy-scroll--thumb-h { - height: $scrollbar-thumb-size !important; - border-radius: ($scrollbar-thumb-size / 2); - @include gradient-h($scrollbar-color-a, $scrollbar-color-b); -} -/* Vertical Scrollbar Styles */ -.fancy-scroll--track-v { - padding: ($scrollbar-track-size - $scrollbar-thumb-size) / 2; - width: $scrollbar-track-size !important; - height: 100%; - top: 0; - right: 0; -} -.fancy-scroll--thumb-v { - width: $scrollbar-thumb-size !important; - border-radius: ($scrollbar-thumb-size / 2); - @include gradient-v($scrollbar-color-a, $scrollbar-color-b); -} - -/* Kapacitor Theme Scrollbars */ -$scrollbar-color-kap-a: $c-rainforest; -$scrollbar-color-kap-b: $c-pool; - -.fancy-scroll--kapacitor { - .fancy-scroll--thumb-h { - @include gradient-h($scrollbar-color-kap-a, $scrollbar-color-kap-b); - } - .fancy-scroll--thumb-v { - @include gradient-v($scrollbar-color-kap-a, $scrollbar-color-kap-b); - } -} - -/* Kapacitor Theme Scrollbars */ -$scrollbar-color-kap-a: $c-rainforest; -$scrollbar-color-kap-b: $c-pool; - -.fancy-scroll--func-selector { - .fancy-scroll--thumb-h { - @include gradient-h($c-neutrino, $c-hydrogen); - } - .fancy-scroll--thumb-v { - @include gradient-v($c-neutrino, $c-hydrogen); - } -} - -/* Dropdown Theme Scrollbars */ -ul.dropdown-menu { - .fancy-scroll--thumb-h { - @include gradient-h($c-neutrino, $c-laser); - } - .fancy-scroll--thumb-v { - @include gradient-v($c-neutrino, $c-laser); - } -} -/* Hacky Fix to make fancy scrollbars work in Safari */ -.query-builder--list { - position: relative; - - .fancy-scroll--container { - position: absolute !important; - } -} diff --git a/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.tsx b/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.tsx index c984e958ea..ecd1d49a11 100644 --- a/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.tsx +++ b/ui/src/shared/components/fancy_scrollbar/FancyScrollbar.tsx @@ -2,7 +2,7 @@ import React, {Component} from 'react' import _ from 'lodash' import classnames from 'classnames' -import {Scrollbars} from 'react-custom-scrollbars' +import {Scrollbars} from '@influxdata/react-custom-scrollbars' // Decorators import {ErrorHandling} from 'src/shared/decorators/errors' @@ -19,11 +19,13 @@ interface Props { className?: string scrollTop?: number scrollLeft?: number + thumbStartColor?: string + thumbStopColor?: string } @ErrorHandling class FancyScrollbar extends Component> { - public static defaultProps = { + public static defaultProps: DefaultProps = { autoHide: true, autoHeight: false, maxHeight: null, @@ -57,10 +59,6 @@ class FancyScrollbar extends Component> { this.updateScroll() } - public handleMakeDiv = (className: string) => (props): JSX.Element => { - return
- } - public render() { const { autoHide, @@ -70,6 +68,8 @@ class FancyScrollbar extends Component> { maxHeight, setScrollTop, style, + thumbStartColor, + thumbStopColor, } = this.props return ( @@ -85,11 +85,8 @@ class FancyScrollbar extends Component> { autoHideDuration={250} autoHeight={autoHeight} autoHeightMax={maxHeight} - renderTrackHorizontal={this.handleMakeDiv('track-h')} - renderTrackVertical={this.handleMakeDiv('track-v')} - renderThumbHorizontal={this.handleMakeDiv('thumb-h')} - renderThumbVertical={this.handleMakeDiv('thumb-v')} - renderView={this.handleMakeDiv('view')} + thumbStartColor={thumbStartColor} + thumbStopColor={thumbStopColor} > {children} diff --git a/ui/src/style/chronograf.scss b/ui/src/style/chronograf.scss index c22907229c..3639c9473a 100644 --- a/ui/src/style/chronograf.scss +++ b/ui/src/style/chronograf.scss @@ -18,7 +18,6 @@ @import 'src/shared/components/ColorDropdown'; @import 'src/shared/components/avatar/Avatar'; @import 'src/shared/components/tables/TableGraphs'; -@import 'src/shared/components/fancy_scrollbar/FancyScrollbar'; @import 'src/shared/components/notifications/Notifications'; @import 'src/shared/components/threesizer/Threesizer'; @import 'src/shared/components/graph_tips/GraphTips'; @@ -42,3 +41,6 @@ @import 'src/logs/components/logs_table/LogsTable'; @import 'src/logs/components/expandable_message/ExpandableMessage'; @import 'src/logs/components/logs_message/LogsMessage'; + +// External +@import '../../node_modules/@influxdata/react-custom-scrollbars/dist/styles.css'; diff --git a/ui/yarn.lock b/ui/yarn.lock deleted file mode 100644 index 345609e951..0000000000 --- a/ui/yarn.lock +++ /dev/null @@ -1,9316 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/core@^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e" - integrity sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.1.2" - "@babel/helpers" "^7.1.2" - "@babel/parser" "^7.1.2" - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.1.2" - convert-source-map "^1.1.0" - debug "^3.1.0" - json5 "^0.5.0" - lodash "^4.17.10" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.0.0", "@babel/generator@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.2.tgz#fde75c072575ce7abbd97322e8fef5bae67e4630" - integrity sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig== - dependencies: - "@babel/types" "^7.1.2" - jsesc "^2.5.1" - lodash "^4.17.10" - source-map "^0.5.0" - trim-right "^1.0.1" - -"@babel/helper-annotate-as-pure@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" - integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f" - integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-builder-react-jsx@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0.tgz#fa154cb53eb918cf2a9a7ce928e29eb649c5acdb" - integrity sha512-ebJ2JM6NAKW0fQEqN8hOLxK84RbRz9OkUhGS/Xd5u56ejMfVbayJ4+LykERZCOUM6faa6Fp3SZNX3fcT16MKHw== - dependencies: - "@babel/types" "^7.0.0" - esutils "^2.0.0" - -"@babel/helper-call-delegate@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" - integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ== - dependencies: - "@babel/helper-hoist-variables" "^7.0.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-define-map@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c" - integrity sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.0.0" - lodash "^4.17.10" - -"@babel/helper-explode-assignable-expression@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6" - integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA== - dependencies: - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-hoist-variables@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88" - integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-member-expression-to-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" - integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-transforms@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787" - integrity sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - lodash "^4.17.10" - -"@babel/helper-optimise-call-expression@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5" - integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27" - integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg== - dependencies: - lodash "^4.17.10" - -"@babel/helper-remap-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f" - integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-wrap-function" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362" - integrity sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-simple-access@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" - integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w== - dependencies: - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-wrap-function@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz#8cf54e9190706067f016af8f75cb3df829cc8c66" - integrity sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/template" "^7.1.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" - -"@babel/helpers@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.1.2.tgz#ab752e8c35ef7d39987df4e8586c63b8846234b5" - integrity sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA== - dependencies: - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.1.2" - -"@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.2.tgz#85c5c47af6d244fab77bce6b9bd830e38c978409" - integrity sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ== - -"@babel/plugin-proposal-async-generator-functions@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz#41c1a702e10081456e23a7b74d891922dd1bb6ce" - integrity sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" - -"@babel/plugin-proposal-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e" - integrity sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.0.0" - -"@babel/plugin-proposal-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e" - integrity sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425" - integrity sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33" - integrity sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.2.0" - -"@babel/plugin-syntax-async-generators@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c" - integrity sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-flow@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0.tgz#70638aeaad9ee426bc532e51523cff8ff02f6f17" - integrity sha512-zGcuZWiWWDa5qTZ6iAnpG0fnX/GOu49pGR5PFvkQ9GmKNaSphXQnlNXh/LG20sqWtNrx/eB6krzfEzcwvUyeFA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd" - integrity sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-jsx@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0.tgz#034d5e2b4e14ccaea2e4c137af7e4afb39375ffd" - integrity sha512-PdmL2AoPsCLWxhIr3kG2+F9v4WH06Q3z+NoGVpQgnUNGcagXHq5sB3OXxkSahKq9TLdNMN/AJzFYSOo8UKDMHg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b" - integrity sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475" - integrity sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749" - integrity sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz#109e036496c51dd65857e16acab3bafdf3c57811" - integrity sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.1.0" - -"@babel/plugin-transform-block-scoped-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07" - integrity sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-block-scoping@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc" - integrity sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.10" - -"@babel/plugin-transform-classes@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz#ab3f8a564361800cbc8ab1ca6f21108038432249" - integrity sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.1.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31" - integrity sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.2.tgz#5fa77d473f5a0a3f5266ad7ce2e8c995a164d60a" - integrity sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-dotall-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58" - integrity sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" - -"@babel/plugin-transform-duplicate-keys@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86" - integrity sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-exponentiation-operator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz#9c34c2ee7fd77e02779cfa37e403a2e1003ccc73" - integrity sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-flow-strip-types@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0.tgz#c40ced34c2783985d90d9f9ac77a13e6fb396a01" - integrity sha512-WhXUNb4It5a19RsgKKbQPrjmy4yWOY1KynpEbNw7bnd1QTcrT/EIl3MJvnGgpgvrKyKbqX7nUNOJfkpLOnoDKA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.0.0" - -"@babel/plugin-transform-for-of@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39" - integrity sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz#29c5550d5c46208e7f730516d41eeddd4affadbb" - integrity sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg== - dependencies: - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86" - integrity sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-amd@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz#f9e0a7072c12e296079b5a59f408ff5b97bf86a8" - integrity sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz#0a9d86451cbbfb29bd15186306897c67f6f9a05c" - integrity sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.1.0" - -"@babel/plugin-transform-modules-systemjs@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz#8873d876d4fee23209decc4d1feab8f198cf2df4" - integrity sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g== - dependencies: - "@babel/helper-hoist-variables" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-umd@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz#a29a7d85d6f28c3561c33964442257cc6a21f2a8" - integrity sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig== - dependencies: - "@babel/helper-module-transforms" "^7.1.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-new-target@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" - integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-object-super@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz#b1ae194a054b826d8d4ba7ca91486d4ada0f91bb" - integrity sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.1.0" - -"@babel/plugin-transform-parameters@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz#44f492f9d618c9124026e62301c296bf606a7aed" - integrity sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw== - dependencies: - "@babel/helper-call-delegate" "^7.1.0" - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-react-jsx@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.0.0.tgz#524379e4eca5363cd10c4446ba163f093da75f3e" - integrity sha512-0TMP21hXsSUjIQJmu/r7RiVxeFrXRcMUigbKu0BLegJK9PkYodHstaszcig7zxXfaBji2LYUdtqIkHs+hgYkJQ== - dependencies: - "@babel/helper-builder-react-jsx" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.0.0" - -"@babel/plugin-transform-regenerator@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1" - integrity sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw== - dependencies: - regenerator-transform "^0.13.3" - -"@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15" - integrity sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b" - integrity sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366" - integrity sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - -"@babel/plugin-transform-template-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65" - integrity sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-typeof-symbol@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9" - integrity sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc" - integrity sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" - -"@babel/preset-env@^7.0.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11" - integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.1.0" - "@babel/plugin-proposal-json-strings" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.0.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.1.0" - "@babel/plugin-transform-block-scoped-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.1.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-dotall-regex" "^7.0.0" - "@babel/plugin-transform-duplicate-keys" "^7.0.0" - "@babel/plugin-transform-exponentiation-operator" "^7.1.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.1.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-amd" "^7.1.0" - "@babel/plugin-transform-modules-commonjs" "^7.1.0" - "@babel/plugin-transform-modules-systemjs" "^7.0.0" - "@babel/plugin-transform-modules-umd" "^7.1.0" - "@babel/plugin-transform-new-target" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.1.0" - "@babel/plugin-transform-parameters" "^7.1.0" - "@babel/plugin-transform-regenerator" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typeof-symbol" "^7.0.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - browserslist "^4.1.0" - invariant "^2.2.2" - js-levenshtein "^1.1.3" - semver "^5.3.0" - -"@babel/runtime@^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.2.tgz#81c89935f4647706fc54541145e6b4ecfef4b8e3" - integrity sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg== - dependencies: - regenerator-runtime "^0.12.0" - -"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" - integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.1.2" - "@babel/types" "^7.1.2" - -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.0.tgz#503ec6669387efd182c3888c4eec07bcc45d91b2" - integrity sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.0.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - debug "^3.1.0" - globals "^11.1.0" - lodash "^4.17.10" - -"@babel/types@^7.0.0", "@babel/types@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.2.tgz#183e7952cf6691628afdc2e2b90d03240bac80c0" - integrity sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg== - dependencies: - esutils "^2.0.2" - lodash "^4.17.10" - to-fast-properties "^2.0.0" - -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.stat@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz#54c5a964462be3d4d78af631363c18d6fa91ac26" - integrity sha512-yprFYuno9FtNsSHVlSWd+nRlmGoAbqbeCwOryP6sC/zoCjhpArcRMYp19EvpSUSizJAlsXEwJv+wcWS9XaXdMw== - -"@types/abstract-leveldown@*": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz#3c7750d0186b954c7f2d2f6acc8c3c7ba0c3412e" - integrity sha512-wYxU3kp5zItbxKmeRYCEplS2MW7DzyBnxPGj+GJVHZEUZiK/nn5Ei1sUFgURDh+X051+zsGe28iud3oHjrYWQQ== - -"@types/cheerio@*": - version "0.22.9" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.9.tgz#b5990152604c2ada749b7f88cab3476f21f39d7b" - integrity sha512-q6LuBI0t5u04f0Q4/R+cGBqIbZMtJkVvCSF+nTfFBBdQqQvJR/mNHeWjRkszyLl7oyf2rDoKUYMEjTw5AV0hiw== - -"@types/chroma-js@^1.3.4": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-1.4.0.tgz#1d215474b54e227bd0204572c0483b98593eabd0" - integrity sha512-pY0EVvIUizkmvSZo9c74hska0Gv1vXzdGCQ8FoBBNpV8jtMUstu55VVa+AKtaQyUZOPRBralYzzqFRXVk4Iznw== - -"@types/codemirror@^0.0.56": - version "0.0.56" - resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.56.tgz#1fcf68df0d0a49791d843dadda7d94891ac88669" - integrity sha512-OMtPqg2wFOEcNeVga+m+UXpYJw8ugISPCQOtShdFUho/k91Ms1oWOozoDT1I87Phv6IdwLfMLtIOahh1tO1cJQ== - -"@types/commander@^2.11.0": - version "2.12.2" - resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae" - integrity sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q== - dependencies: - commander "*" - -"@types/d3-color@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-1.2.1.tgz#26141c3c554e320edd40726b793570a3ae57397e" - integrity sha512-xwb1tqvYNWllbHuhMFhiXk63Imf+QNq/dJdmbXmr2wQVnwGenCuj3/0IWJ9hdIFQIqzvhT7T37cvx93jtAsDbQ== - -"@types/d3-scale@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-2.0.2.tgz#61145948aa1a52ab31384766cd013308699112b3" - integrity sha512-pnmZsEVwTyX+68bjG9r3XXUBASUF6z3Ir2nlrv81mWCH9yqeRscR98myMNP5OwDd9urUnvjNabJul5B9K0+F2w== - dependencies: - "@types/d3-time" "*" - -"@types/d3-time@*": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.0.9.tgz#c2cf05a3cd51f810b8d8a9bbca0c74030d4e535e" - integrity sha512-m+D4NbQdDlTVaO7QgXAnatR3IDxQYDMBtRhgSCi5rs9R1LPq1y7/2aqa1FJ2IWjFm1mOV63swDxonnCDlHgHMA== - -"@types/dygraphs@^1.1.6": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@types/dygraphs/-/dygraphs-1.1.8.tgz#e32b6aa367a86f469888e0c34cc62343fc3ffcbb" - integrity sha512-qoSvrmDb83ll0hM3ANs6x5Xa163osIKrstX6Vgg1l9A8HPz72IHEOY+4EPb6jW+B25i6NCR+Dv7O9D0p2m4b6A== - dependencies: - "@types/google.visualization" "*" - -"@types/encoding-down@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/encoding-down/-/encoding-down-5.0.0.tgz#0b5b90b93ac3aa75148f19508044e7bd36463557" - integrity sha512-G0MlS/+/U2RIQLcSEhhAcoMrXw3hXUCFSKbhbeEljoKMra2kq+NPX6tfOveSWQLX2hJXBo+YrvKgAGe+tFL1Aw== - dependencies: - "@types/abstract-leveldown" "*" - "@types/level-codec" "*" - -"@types/enzyme@^3.1.14": - version "3.1.14" - resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.1.14.tgz#379c26205f6e0e272f3a51d6bbdd50071a9d03a6" - integrity sha512-jvAbagrpoSNAXeZw2kRpP10eTsSIH8vW1IBLCXbN0pbZsYZU8FvTPMMd5OzSWUKWTQfrbXFUY8e6un/W4NpqIA== - dependencies: - "@types/cheerio" "*" - "@types/react" "*" - -"@types/events@*": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" - integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA== - -"@types/google.visualization@*": - version "0.0.43" - resolved "https://registry.yarnpkg.com/@types/google.visualization/-/google.visualization-0.0.43.tgz#d4172f94292b68a49a5666033386ce177f0ead9d" - integrity sha512-SmQWGJ4UykOzChj+AVo5JB8vC0hDnI3hUT6auRD34mnyO/s9ll1i4cT1hSmng3ZXbxG7qAdOctNElOpD9xqJZQ== - -"@types/history@3.2.2", "@types/history@^3": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@types/history/-/history-3.2.2.tgz#b6affa240cb10b5f841c6443d8a24d7f3fc8bb0c" - integrity sha512-DMvBzeA2dp1uZZftXkoqPC4TrdHlyuuTabCOxHY6EAKOJRMaPVu8b6lvX0QxEGKZq3cK/h3JCSxgfKmbDOYmRw== - -"@types/jest@^23.3.2": - version "23.3.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.3.tgz#246ebcc52771d2327bb8e37aa971b412d9dc4237" - integrity sha512-G6EBrbjWDfmIpYu8UcRBOhwtDiYaLj5N5jUR5rx0YvbKxRBhXPZVLUmtfShewSUNKiQwpHavpML69a2WMbIlEQ== - -"@types/level-codec@*": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@types/level-codec/-/level-codec-9.0.0.tgz#9f1dc7f9017b6fba094a450602ec0b91cc384059" - integrity sha512-SWYkVJylo1dqblkhrr7UtmsQh4wdZA9bV1y3QJSywMPSqGfW0p1w37N1EayZtKbg1dGReIIQEEOtxk4wZvGrWQ== - -"@types/levelup@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-3.1.0.tgz#e04f6a8eaf707f88d7c6e043a9067dda431f4538" - integrity sha512-Y2SC5PskYsE8+dELuWLCMG+UcUrkhhIz5wV55yX73AAVqr3kDXLYlj6k/vuchXUt1L1b/P1Frt4Dcc3WmWcbLA== - dependencies: - "@types/abstract-leveldown" "*" - "@types/events" "*" - "@types/node" "*" - -"@types/lodash@^4.14.116": - version "4.14.116" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.116.tgz#5ccf215653e3e8c786a58390751033a9adca0eb9" - integrity sha512-lRnAtKnxMXcYYXqOiotTmJd74uawNWuPnsnPrrO7HiFuE3npE2iQhfABatbYDyxTNqZNuXzcKGhw37R7RjBFLg== - -"@types/node@*": - version "10.11.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.11.4.tgz#e8bd933c3f78795d580ae41d86590bfc1f4f389d" - integrity sha512-ojnbBiKkZFYRfQpmtnnWTMw+rzGp/JiystjluW9jgN3VzRwilXddJ6aGQ9V/7iuDG06SBgn7ozW9k3zcAnYjYQ== - -"@types/node@^9.4.6": - version "9.6.34" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.34.tgz#e03f9008f5fba43feb21223a82d3983531e004a2" - integrity sha512-PzJpSs2afoYqBA4yLBgaKUdZRk8+1yvkxcUBW6958h4vYOC+pc4k4C+QmQ6AO5Pt7uA4EIIboFog6YNCuITD0g== - -"@types/papaparse@^4.1.34": - version "4.5.4" - resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-4.5.4.tgz#3c52c95fe31688ffe3c21c892791f981223cc821" - integrity sha512-Zpgl4HpeiKAs3i1gIsHJZrH6zhS7OLI8JAbkl0vjno08glm9uJ78m4KvqOBz1OsfoO+jQWj4d6g9ET9l1d7bgw== - dependencies: - "@types/node" "*" - -"@types/prop-types@*", "@types/prop-types@^15.5.2": - version "15.5.6" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.6.tgz#9c03d3fed70a8d517c191b7734da2879b50ca26c" - integrity sha512-ZBFR7TROLVzCkswA3Fmqq+IIJt62/T7aY/Dmz+QkU7CaW2QFqAitCE8Ups7IzmGhcN1YWMBT4Qcoc07jU9hOJQ== - -"@types/qs@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.1.tgz#a38f69c62528d56ba7bd1f91335a8004988d72f7" - integrity sha512-mNhVdZHdtKHMMxbqzNK3RzkBcN1cux3AvuCYGTvjEIQT2uheH3eCAyYsbMbh2Bq8nXkeOWs1kyDiF7geWRFQ4Q== - -"@types/react-dnd-html5-backend@^2.1.9": - version "2.1.9" - resolved "https://registry.yarnpkg.com/@types/react-dnd-html5-backend/-/react-dnd-html5-backend-2.1.9.tgz#dfc9efe2a68bd12407815a2d61ddfd18bb8686fb" - integrity sha512-o42zIpcgXXj04xYDT9o9kXoldqDa81ie5XAKKCo7/fOWEhOCRt9UYu+LzOXC308eKKf8v0HzbJaDTr93j3JrTw== - dependencies: - "@types/react-dnd" "*" - -"@types/react-dnd@*": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/react-dnd/-/react-dnd-3.0.2.tgz#939e5a8ca5b83f847c3f64dabbe2f49a9fefb192" - integrity sha512-Z1BqHYGFtfSPfWs+kgX4b6wQmwwtqq4/pLo4zdO9xcDUB1ZQP8iWTAYNf3EJ2f0WiVQpSLN8UytP+ILzZHDLYw== - dependencies: - react-dnd "*" - -"@types/react-dnd@^2.0.36": - version "2.0.36" - resolved "https://registry.yarnpkg.com/@types/react-dnd/-/react-dnd-2.0.36.tgz#67e08a3608f112a3af27201d1fb6f79334d43214" - integrity sha512-jA95HjQxuHNSnr0PstVBjRwVcFJZoinxbtsS4bpi5nwAL5GUOtjrLrq1bDi4WNYxW+77KHvqSAZ2EgA2q9evdA== - dependencies: - "@types/react" "*" - -"@types/react-grid-layout@^0.16.5": - version "0.16.5" - resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.5.tgz#ee23e1f9a0f2d00fc0bf91a5ad12b5c9c6b548df" - integrity sha512-nhezg1cggpckAfo+VASaAa8CtQBWIo/APTTW/RAusCAPFfrxxbC9EHqgUXcYac+Q9vxaSy348t/v+HTRSG9omA== - dependencies: - "@types/react" "*" - -"@types/react-redux@^6.0.9": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-6.0.9.tgz#96aa7f5b0716bcc3bfb36ceaa1223118d509f79a" - integrity sha512-LatgnnZ7bG63SmzEqGMjAIP1bN36iaXpb4G7UW3SqpHyo+OQ97MnMXm9BoNi720r61+PvseyIUJN4el4GVhAAg== - dependencies: - "@types/react" "*" - redux "^4.0.0" - -"@types/react-router-redux@^4.0.0": - version "4.0.51" - resolved "https://registry.yarnpkg.com/@types/react-router-redux/-/react-router-redux-4.0.51.tgz#047e8c206892790bc2462f30d8b346d5b4f24fa0" - integrity sha512-XkWpcG1xSnD0+MG1f19FbKu8c7jmasFacdgFzN/FPG6oIIQIFqz8H2tJL2i7eSa4Cp2qCFAowAKILhAORXtH1g== - dependencies: - "@types/history" "^3" - redux "^3.6.0" - -"@types/react-router@^3.0.15": - version "3.0.19" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-3.0.19.tgz#c7fc0d1feaec5fdff513337f203301de7a27b752" - integrity sha512-079+T/Elvlds2Nr2CX6H17c3JUy0J95EUzjFlcF6wissyOisOL23R/Ci7prugPDVT4x2dpGwR+fxpOTitUgIZA== - dependencies: - "@types/history" "^3" - "@types/react" "*" - -"@types/react-virtualized@^9.18.3": - version "9.18.7" - resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.7.tgz#8703d8904236819facff90b8b320f29233160c90" - integrity sha512-zFLpFJjj5r8MUHf0O5xSWLlv/QYkSkBsYCaYaZbn87d7bb45HP0fZI0IEn9FhvFmt4kgfJhstX2bIkxoOWadYw== - dependencies: - "@types/prop-types" "*" - "@types/react" "*" - -"@types/react@*", "@types/react@^16.4.14": - version "16.4.16" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.4.16.tgz#99f91b1200ae8c2062030402006d3b3c3a177043" - integrity sha512-lxyoipLWweAnLnSsV4Ho2NAZTKKmxeYgkTQ6PaDiPDU9JJBUY2zJVVGiK1smzYv8+ZgbqEmcm5xM74GCpunSEA== - dependencies: - "@types/prop-types" "*" - csstype "^2.2.0" - -"@types/semver@^5.4.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" - integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== - -"@types/text-encoding@^0.0.32": - version "0.0.32" - resolved "https://registry.yarnpkg.com/@types/text-encoding/-/text-encoding-0.0.32.tgz#52289b320a406850b14f08f48b475ca021218048" - integrity sha512-kQ79aFmYcD/DR3QKo6wXyvNrKi7PunY0KYTBUhHjHl0SXwWuLRl9Leh73YtnsSJMBi9qSiK+fxWhdJNQPbhc9A== - -"@types/uuid@^3.4.3": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5" - integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw== - dependencies: - "@types/node" "*" - -abab@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" - integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= - -abab@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" - integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -accepts@~1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I= - dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" - -acorn-globals@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" - integrity sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8= - dependencies: - acorn "^4.0.4" - -acorn-globals@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" - integrity sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw== - dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" - -acorn-walk@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.0.tgz#c957f4a1460da46af4a0388ce28b4c99355b0cbc" - integrity sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg== - -acorn@^4.0.4: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c= - -acorn@^5.0.0, acorn@^5.5.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - -acorn@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.2.tgz#6a459041c320ab17592c6317abbfdf4bbaa98ca4" - integrity sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg== - -add-px-to-style@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a" - integrity sha1-0ME1RB+oAUqBN5BFMQlvZ/KPJjo= - -ajv@^5.1.0, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-to-html@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.6.tgz#58a8d04b87ec9a85e3ad273c12a5fbc7147b9c42" - integrity sha512-90M/2sZna3OsoOEbSyXK46poFnlClBC53Rx6etNKQK7iShsX5fI5E/M9Ld6FurtLaxAWLuAPi0Jp8p3y5oAkxg== - dependencies: - entities "^1.1.1" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - integrity sha1-126/jKlNJ24keja61EpLdKthGZE= - dependencies: - default-require-extensions "^1.0.0" - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arity-n@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745" - integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U= - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= - dependencies: - arr-flatten "^1.0.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -array.prototype.flat@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4" - integrity sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw== - dependencies: - define-properties "^1.1.2" - es-abstract "^1.10.0" - function-bind "^1.1.1" - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asap@^2.0.6, asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= - dependencies: - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= - -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== - -async@^2.1.4, async@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atoa@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/atoa/-/atoa-1.0.0.tgz#0cc0e91a480e738f923ebc103676471779b34a49" - integrity sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autoprefixer@^6.3.1: - version "6.7.7" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" - integrity sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ= - dependencies: - browserslist "^1.7.6" - caniuse-db "^1.0.30000634" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^5.2.16" - postcss-value-parser "^3.2.3" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.6.0, aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== - -axios@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" - integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI= - dependencies: - follow-redirects "^1.3.0" - is-buffer "^1.1.5" - -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.0, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.18.0, babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-jest@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1" - integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew== - dependencies: - babel-plugin-istanbul "^4.1.6" - babel-preset-jest "^23.2.0" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-istanbul@^4.1.6: - version "4.1.6" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" - integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ== - dependencies: - babel-plugin-syntax-object-rest-spread "^6.13.0" - find-up "^2.1.0" - istanbul-lib-instrument "^1.10.1" - test-exclude "^4.2.1" - -babel-plugin-jest-hoist@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167" - integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc= - -babel-plugin-syntax-object-rest-spread@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-polyfill@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - integrity sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM= - dependencies: - babel-runtime "^6.26.0" - core-js "^2.5.0" - regenerator-runtime "^0.10.5" - -babel-preset-jest@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46" - integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY= - dependencies: - babel-plugin-jest-hoist "^23.2.0" - babel-plugin-syntax-object-rest-spread "^6.13.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.11.6, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.0.0, babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon-walk@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" - integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4= - dependencies: - babel-runtime "^6.11.6" - babel-types "^6.15.0" - lodash.clone "^4.5.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -bail@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" - integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg== - -balanced-match@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -bignumber.js@^4.0.2, bignumber.js@^4.0.4: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - integrity sha512-eJzYkFYy9L4JzXsbymsFn3p54D+llV27oTQ+ziJG7WFRheJcNZilgVXMG0LoZtlQSKBsJdWtLFqOD0u+U0jZKA== - -binary-extensions@^1.0.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== - -bindings@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" - integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - -body-parser@1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" - integrity sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ= - dependencies: - bytes "3.0.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.1" - http-errors "~1.6.2" - iconv-lite "0.4.19" - on-finished "~2.3.0" - qs "6.5.1" - raw-body "2.3.2" - type-is "~1.6.15" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.3.0, braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -brfs@^1.2.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" - integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== - dependencies: - quote-stream "^1.0.1" - resolve "^1.1.5" - static-module "^2.2.0" - through2 "^2.0.0" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-process-hrtime@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" - integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== - -browser-resolve@^1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= - dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - -browserslist@^4.0.0, browserslist@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.2.0.tgz#3e5e5edf7fa9758ded0885cf88c1e4be753a591c" - integrity sha512-Berls1CHL7qfQz8Lct6QxYA5d2Tvt4doDWHcjvAISybpd+EKZVppNtXgXhaN6SdrPKo7YLTSZuYBs5cYrSWN8w== - dependencies: - caniuse-lite "^1.0.30000889" - electron-to-chromium "^1.3.73" - node-releases "^1.0.0-alpha.12" - -bs-logger@0.x: - version "0.2.5" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.5.tgz#1d82f0cf88864e1341cd9262237f8d0748a49b22" - integrity sha512-uFLE0LFMxrH8Z5Hd9QgivvRbrl/NFkOTHzGhlqQxsnmx5JBLrp4bc249afLL+GccyY/8hkcGi2LpVaOzaEY0nQ== - dependencies: - fast-json-stable-stringify "^2.0.0" - -bser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" - integrity sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk= - dependencies: - node-int64 "^0.4.0" - -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= - -buffer-from@1.x, buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^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" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bullseye@1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/bullseye/-/bullseye-1.4.6.tgz#b73f606f7b4273be80ac65acd75295d62606fe24" - integrity sha1-tz9gb3tCc76ArGWs11KV1iYG/iQ= - dependencies: - crossvent "^1.3.1" - seleccion "2.0.0" - sell "^1.0.0" - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -calculate-size@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/calculate-size/-/calculate-size-1.1.1.tgz#ae7caa1c7795f82c4f035dc7be270e3581dae3ee" - integrity sha1-rnyqHHeV+CxPA13HvicONYHa4+4= - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -caniuse-api@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" - integrity sha1-tTTnxzTE+B7F++isoq0kNUuWLGw= - dependencies: - browserslist "^1.3.6" - caniuse-db "^1.0.30000529" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000890" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000890.tgz#b406595db8b631975b8dc5fa174f32925c23778b" - integrity sha512-aO5uw1Taw8GkNMMXIWOz/WJz3y6tR1ETUAdH/pvO5EoJ3I1Po9vNJd9aMjY1GKucS/OXWMiQbXRbk3O1sgCbRA== - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000889: - version "1.0.30000890" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000890.tgz#86a18ffcc65d79ec6a437e985761b8bf1c4efeaf" - integrity sha512-4NI3s4Y6ROm+SgZN5sLUG4k7nVWQnedis3c/RWkynV5G6cHSY7+a8fwFyn2yoBDE3E6VswhTNNwR3PvzGqlTkg== - -capture-exit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" - integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= - dependencies: - rsvp "^3.3.3" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -change-emitter@^0.1.2: - version "0.1.6" - resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515" - integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU= - -character-entities-legacy@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" - integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA== - -character-entities@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" - integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ== - -character-reference-invalid@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" - integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ== - -cheerio@^1.0.0-rc.2: - version "1.0.0-rc.2" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" - integrity sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash "^4.15.0" - parse5 "^3.0.1" - -chickencurry@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chickencurry/-/chickencurry-1.1.1.tgz#02655f2b26b3bc2ee1ae1e5316886de38eb79738" - integrity sha1-AmVfKyazvC7hrh5TFoht4463lzg= - -chokidar@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - lodash.debounce "^4.0.8" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.5" - optionalDependencies: - fsevents "^1.2.2" - -chownr@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== - -chroma-js@^1.3.6: - version "1.4.0" - resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-1.4.0.tgz#695c52e7c97617e5f687db31913503d410481ae4" - integrity sha512-5vBYGJkhSnK2SRZ0XkxwTL+TSRyP7PHIxjeg+1uce5qpNDRLLwAXcF12kIztas/BYakWPQhchzV4TKkiwKNd8Q== - -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - integrity sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA== - dependencies: - chalk "^1.1.3" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -classnames@2.x, classnames@^2.2.3, classnames@^2.2.5: - version "2.2.6" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" - integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-spinners@^1.1.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" - integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -clones@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/clones/-/clones-1.1.0.tgz#87e904132d6140c5c0b72006c08c0d05bd7b63b3" - integrity sha1-h+kEEy1hQMXAtyAGwIwNBb17Y7M= - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= - dependencies: - q "^1.1.2" - -coa@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" - integrity sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ== - dependencies: - q "^1.1.2" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -codemirror@^5.36.0: - version "5.40.2" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.40.2.tgz#f4a41fee2d84e679543591b3680af259d903330b" - integrity sha512-yoWuvEiD3v5vTwdoMc/wu/Ld6dh9K/yEiEBTKOPGM+/pN0gTAqFNtrLHv1IJ1UJvzFpNRvMi92XCi3+8/iIaEw== - -collapse-white-space@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" - integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw== - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" - integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= - dependencies: - color-name "^1.0.0" - -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" - integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= - dependencies: - clone "^1.0.2" - color-convert "^1.3.0" - color-string "^0.3.0" - -color@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" - integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - -colormin@^1.0.5: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" - integrity sha1-6i90IKcrlogaOKrlnsEkpvcpgTM= - dependencies: - color "^0.11.0" - css-color-names "0.0.4" - has "^1.0.1" - -colors@0.5.x: - version "0.5.1" - resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774" - integrity sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q= - -colors@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= - -combined-stream@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= - dependencies: - delayed-stream "~1.0.0" - -combined-stream@~1.0.5, combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== - dependencies: - delayed-stream "~1.0.0" - -command-exists@^1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.7.tgz#16828f0c3ff2b0c58805861ef211b64fc15692a8" - integrity sha512-doWDvhXCcW5LK0cIUWrOQ8oMFXJv3lEQCkJpGVjM8v9SV0uhqYXB943538tEA2CiaWqSyuYUGAm5ezDwEx9xlw== - -commander@*, commander@^2.11.0, commander@^2.12.1: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -compose-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-2.0.0.tgz#e642fa7e1da21529720031476776fc24691ac0b0" - integrity sha1-5kL6fh2iFSlyADFHZ3b8JGkawLA= - dependencies: - arity-n "^1.0.4" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@~1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -config-chain@~1.1.5: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= - -content-type-parser@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" - integrity sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ== - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -contra@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/contra/-/contra-1.9.1.tgz#60e498274b3d2d332896d60f82900aefa2ecac8c" - integrity sha1-YOSYJ0s9LTMoltYPgpAK76LsrIw= - dependencies: - atoa "1.0.0" - ticky "1.0.0" - -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-to-clipboard@^3: - version "3.0.8" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9" - integrity sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw== - dependencies: - toggle-selection "^1.0.3" - -core-decorators@^0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/core-decorators/-/core-decorators-0.20.0.tgz#605896624053af8c28efbe735c25a301a61c65c5" - integrity sha1-YFiWYkBTr4wo775zXCWjAaYcZcU= - -core-js@^1.0.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" - integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= - -core-js@^2.4.0, core-js@^2.5.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - require-from-string "^2.0.1" - -cosmiconfig@^5.0.0: - version "5.0.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - integrity sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ== - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -create-jest-runner@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/create-jest-runner/-/create-jest-runner-0.4.1.tgz#eeda15bc0f9dc622ef2de5a7fd9a0f1a2c2eb62d" - integrity sha512-JOy675JMZ3b05F3VfAAi6Igme3pVBWu7Rt+gbW9ujAiX/Dua7+G47O7IbfiUU/FZjXhtipu/tz930b++UMGQEA== - dependencies: - jest-worker "^23.2.0" - throat "^4.1.0" - -create-react-class@^15.5.1: - version "15.6.3" - resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" - integrity sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg== - dependencies: - fbjs "^0.8.9" - loose-envify "^1.3.1" - object-assign "^4.1.1" - -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.4: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crossvent@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/crossvent/-/crossvent-1.5.0.tgz#3779c1242699e19417f0414e61b144753a52fd6d" - integrity sha1-N3nBJCaZ4ZQX8EFOYbFEdTpS/W0= - dependencies: - custom-event "1.0.0" - -crossvent@^1.3.1: - version "1.5.5" - resolved "https://registry.yarnpkg.com/crossvent/-/crossvent-1.5.5.tgz#ad20878e4921e9be73d9d6976f8b2ecd0f71a0b1" - integrity sha1-rSCHjkkh6b5z2daXb4suzQ9xoLE= - dependencies: - custom-event "^1.0.0" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-select-base-adapter@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz#0102b3d14630df86c3eb9fa9f5456270106cf990" - integrity sha1-AQKz0UYw34bD65+p9UVicBBs+ZA= - -css-select@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.0.tgz#7aa2921392114831f68db175c0b6a555df74bbd5" - integrity sha512-MGhoq1S9EyPgZIGnts8Yz5WwUOyHmPMdlqeifsYs/xFX7AAm3hY0RJe1dqVlXtYPI66Nsk39R/sa5/ree6L2qg== - dependencies: - boolbase "^1.0.0" - css-what "2.1" - domutils "^1.7.0" - nth-check "^1.0.1" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-tree@1.0.0-alpha.28: - version "1.0.0-alpha.28" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= - -css-what@2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" - integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= - -cssnano-preset-default@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.2.tgz#1de3f27e73b7f0fbf87c1d7fd7a63ae980ac3774" - integrity sha512-zO9PeP84l1E4kbrdyF7NSLtA/JrJY1paX5FHy5+w/ziIXO2kDqDMfJ/mosXkaHHSa3RPiIY3eB6aEgwx3IiGqA== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^6.0.2" - postcss-colormin "^4.0.2" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.1" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.6" - postcss-merge-rules "^4.0.2" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.1" - postcss-minify-params "^4.0.1" - postcss-minify-selectors "^4.0.1" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.1" - postcss-normalize-positions "^4.0.1" - postcss-normalize-repeat-style "^4.0.1" - postcss-normalize-string "^4.0.1" - postcss-normalize-timing-functions "^4.0.1" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.1" - postcss-ordered-values "^4.1.1" - postcss-reduce-initial "^4.0.2" - postcss-reduce-transforms "^4.0.1" - postcss-svgo "^4.0.1" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^3.4.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" - integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg= - dependencies: - autoprefixer "^6.3.1" - decamelize "^1.1.2" - defined "^1.0.0" - has "^1.0.1" - object-assign "^4.0.1" - postcss "^5.0.14" - postcss-calc "^5.2.0" - postcss-colormin "^2.1.8" - postcss-convert-values "^2.3.4" - postcss-discard-comments "^2.0.4" - postcss-discard-duplicates "^2.0.1" - postcss-discard-empty "^2.0.1" - postcss-discard-overridden "^0.1.1" - postcss-discard-unused "^2.2.1" - postcss-filter-plugins "^2.0.0" - postcss-merge-idents "^2.1.5" - postcss-merge-longhand "^2.0.1" - postcss-merge-rules "^2.0.3" - postcss-minify-font-values "^1.0.2" - postcss-minify-gradients "^1.0.1" - postcss-minify-params "^1.0.4" - postcss-minify-selectors "^2.0.4" - postcss-normalize-charset "^1.1.0" - postcss-normalize-url "^3.0.7" - postcss-ordered-values "^2.1.0" - postcss-reduce-idents "^2.2.2" - postcss-reduce-initial "^1.0.0" - postcss-reduce-transforms "^1.0.3" - postcss-svgo "^2.1.1" - postcss-unique-selectors "^2.0.2" - postcss-value-parser "^3.2.3" - postcss-zindex "^2.0.1" - -cssnano@^4.0.0: - version "4.1.4" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.4.tgz#55b71e3d8f5451dd3edc7955673415c98795788f" - integrity sha512-wP0wbOM9oqsek14CiNRYrK9N3w3jgadtGZKHXysgC/OMVpy0KZgWVPdNqODSZbz7txO9Gekr9taOfcCgL0pOOw== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.2" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^3.5.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" - -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= - dependencies: - clap "^1.0.9" - source-map "^0.5.3" - -cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797" - integrity sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog== - -"cssstyle@>= 0.2.37 < 0.3.0": - version "0.2.37" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" - integrity sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ= - dependencies: - cssom "0.3.x" - -cssstyle@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.1.1.tgz#18b038a9c44d65f7a8e428a653b9f6fe42faf5fb" - integrity sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog== - dependencies: - cssom "0.3.x" - -csstype@^2.2.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.7.tgz#bf9235d5872141eccfb2d16d82993c6b149179ff" - integrity sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw== - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - -custom-event@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.0.tgz#2e4628be19dc4b214b5c02630c5971e811618062" - integrity sha1-LkYovhncSyFLXAJjDFlx6BFhgGI= - -custom-event@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= - -d3-array@^1.2.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" - integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw== - -d3-collection@1: - version "1.0.7" - resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e" - integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A== - -d3-color@1, d3-color@^1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.2.3.tgz#6c67bb2af6df3cc8d79efcc4d3a3e83e28c8048f" - integrity sha512-x37qq3ChOTLd26hnps36lexMRhNXEtVxZ4B25rL0DVdDsGQIJGB18S7y9XDwlDD6MD/ZBzITCf4JjGMM10TZkw== - -d3-format@1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562" - integrity sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ== - -d3-interpolate@1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.3.2.tgz#417d3ebdeb4bc4efcc8fd4361c55e4040211fd68" - integrity sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w== - dependencies: - d3-color "1" - -d3-scale@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.1.2.tgz#4e932b7b60182aee9073ede8764c98423e5f9a94" - integrity sha512-bESpd64ylaKzCDzvULcmHKZTlzA/6DGSVwx7QSDj/EnX9cpSevsdiwdHFYI9ouo9tNBbV3v5xztHS2uFeOzh8Q== - dependencies: - d3-array "^1.2.0" - d3-collection "1" - d3-format "1" - d3-interpolate "1" - d3-time "1" - d3-time-format "2" - -d3-time-format@2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b" - integrity sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA== - dependencies: - d3-time "1" - -d3-time@1: - version "1.0.10" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.10.tgz#8259dd71288d72eeacfd8de281c4bf5c7393053c" - integrity sha512-hF+NTLCaJHF/JqHN5hE8HVGAXPStEq6/omumPE/SxyHVrR7/qQxusFDo0t0c/44+sCGHthC7yNGFZIEgju0P8g== - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -data-urls@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.1.tgz#d416ac3896918f29ca84d81085bc3705834da579" - integrity sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg== - dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.1.0" - whatwg-url "^7.0.0" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - -deasync@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.13.tgz#815c2b69bbd1117cae570152cd895661c09f20ea" - integrity sha512-/6ngYM7AapueqLtvOzjv9+11N2fHDSrkxeMF1YPE20WIfaaawiBg+HZH1E5lHrcJxlKR42t6XPOEmMmqcAsU1g== - dependencies: - bindings "~1.2.1" - nan "^2.0.7" - -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407" - integrity sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg== - dependencies: - ms "^2.1.1" - -decamelize@^1.1.1, decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg= - dependencies: - strip-bom "^2.0.0" - -defaults@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k= - -depd@~1.1.1, depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -detect-newline@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= - -diff@^3.2.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -discontinuous-range@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" - integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= - -disposables@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/disposables/-/disposables-1.0.2.tgz#36c6a674475f55a2d6913567a601444e487b4b6e" - integrity sha1-NsamdEdfVaLWkTVnpgFETkh7S24= - -dnd-core@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-2.6.0.tgz#12bad66d58742c6e5f7cf2943fb6859440f809c4" - integrity sha1-ErrWbVh0LG5ffPKUP7aFlED4CcQ= - dependencies: - asap "^2.0.6" - invariant "^2.0.0" - lodash "^4.2.0" - redux "^3.7.1" - -dnd-core@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-4.0.5.tgz#3b83d138d0d5e265c73ec978dec5e1ed441dc665" - integrity sha1-O4PRONDV4mXHPsl43sXh7UQdxmU= - dependencies: - asap "^2.0.6" - invariant "^2.2.4" - lodash "^4.17.10" - redux "^4.0.0" - -dom-css@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/dom-css/-/dom-css-2.1.0.tgz#fdbc2d5a015d0a3e1872e11472bbd0e7b9e6a202" - integrity sha1-/bwtWgFdCj4YcuEUcrvQ57nmogI= - dependencies: - add-px-to-style "1.0.0" - prefix-style "2.0.1" - to-camel-case "1.0.0" - -"dom-helpers@^2.4.0 || ^3.0.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" - integrity sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg== - -dom-serializer@0, dom-serializer@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= - -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.0.0" - -dotenv-expand@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" - integrity sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU= - -dotenv@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" - integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== - -duplexer2@~0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - dependencies: - readable-stream "^2.0.2" - -dygraphs@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/dygraphs/-/dygraphs-2.1.0.tgz#2fbfd2c803ead02307df3faf8d4dd3ef55cb2075" - integrity sha1-L7/SyAPq0CMH3z+vjU3T71XLIHU= - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -editorconfig@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.0.tgz#b6dd4a0b6b9e76ce48e066bdc15381aebb8804fd" - integrity sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg== - dependencies: - "@types/commander" "^2.11.0" - "@types/semver" "^5.4.0" - commander "^2.11.0" - lru-cache "^4.1.1" - semver "^5.4.1" - sigmund "^1.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.73: - version "1.3.75" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.75.tgz#dd04551739e7371862b0ac7f4ddaa9f3f95b7e68" - integrity sha512-nLo03Qpw++8R6BxDZL/B1c8SQvUe/htdgc5LWYHe5YotV2jVvRUMP5AlOmxOsyeOzgMiXrNln2mC05Ixz6vuUQ== - -element-resize-event@^2.0.4: - version "2.0.9" - resolved "https://registry.yarnpkg.com/element-resize-event/-/element-resize-event-2.0.9.tgz#2f5e1581a296eb5275210c141bc56342e218f876" - integrity sha1-L14VgaKW61J1IQwUG8VjQuIY+HY= - -elliptic@^6.0.0: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - integrity sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -encoding-down@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= - -enzyme-adapter-react-16@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.6.0.tgz#3fca28d3c32f3ff427495380fe2dd51494689073" - integrity sha512-ay9eGFpChyUDnjTFMMJHzrb681LF3hPWJLEA7RoLFG9jSWAdAm2V50pGmFV9dYGJgh5HfdiqM+MNvle41Yf/PA== - dependencies: - enzyme-adapter-utils "^1.8.0" - function.prototype.name "^1.1.0" - object.assign "^4.1.0" - object.values "^1.0.4" - prop-types "^15.6.2" - react-is "^16.5.2" - react-test-renderer "^16.0.0-0" - -enzyme-adapter-utils@^1.8.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.1.tgz#a927d840ce2c14b42892a533aec836809d4e022b" - integrity sha512-s3QB3xQAowaDS2sHhmEqrT13GJC4+n5bG015ZkLv60n9k5vhxxHTQRIneZmQ4hmdCZEBrvUJ89PG6fRI5OEeuQ== - dependencies: - function.prototype.name "^1.1.0" - object.assign "^4.1.0" - prop-types "^15.6.2" - -enzyme-to-json@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.4.tgz#67c6040e931182f183418af2eb9f4323258aa77f" - integrity sha1-Z8YEDpMRgvGDQYry659DIyWKp38= - dependencies: - lodash "^4.17.4" - -enzyme@^3.6.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.7.0.tgz#9b499e8ca155df44fef64d9f1558961ba1385a46" - integrity sha512-QLWx+krGK6iDNyR1KlH5YPZqxZCQaVF6ike1eDJAOg0HvSkSCVImPsdWaNw6v+VrnK92Kg8jIOYhuOSS9sBpyg== - dependencies: - array.prototype.flat "^1.2.1" - cheerio "^1.0.0-rc.2" - function.prototype.name "^1.1.0" - has "^1.0.3" - is-boolean-object "^1.0.0" - is-callable "^1.1.4" - is-number-object "^1.0.3" - is-string "^1.0.4" - is-subset "^0.1.1" - lodash.escape "^4.0.1" - lodash.isequal "^4.5.0" - object-inspect "^1.6.0" - object-is "^1.0.1" - object.assign "^4.1.0" - object.entries "^1.0.4" - object.values "^1.0.4" - raf "^3.4.0" - rst-selector-parser "^2.2.3" - string.prototype.trim "^1.1.2" - -errno@~0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.10.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.6.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -es-to-primitive@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escodegen@^1.6.1, escodegen@^1.8.1, escodegen@^1.9.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escodegen@~1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" - integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-plugin-prettier@^2.2.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz#b4312dcf2c1d965379d7f9d5b5f8aaadc6a45904" - integrity sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA== - dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" - -esprima@^2.6.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - -esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - -esutils@^2.0.0, esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" - integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA== - -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -expect@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98" - integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w== - dependencies: - ansi-styles "^3.2.0" - jest-diff "^23.6.0" - jest-get-type "^22.1.0" - jest-matcher-utils "^23.6.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" - -express@^4.14.0: - version "4.16.3" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" - integrity sha1-avilAjUNsyRuzEvs9rWjTSL37VM= - dependencies: - accepts "~1.3.5" - array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.1" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - path-to-regexp "0.1.7" - proxy-addr "~2.0.3" - qs "6.5.1" - range-parser "~1.2.0" - safe-buffer "5.1.1" - send "0.16.2" - serve-static "1.13.2" - setprototypeof "1.1.0" - statuses "~1.4.0" - type-is "~1.6.16" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0, extend@~3.0.1, extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -falafel@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" - integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= - dependencies: - acorn "^5.0.0" - foreach "^2.0.5" - isarray "0.0.1" - object-keys "^1.0.6" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - -fast-diff@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== - -fast-glob@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.3.tgz#d09d378e9ef6b0076a0fa1ba7519d9d4d9699c28" - integrity sha512-NiX+JXjnx43RzvVFwRWfPKo4U+1BrK5pJPsHQdKMlLoFHrrGktXglQhHliSihWAq+m1z6fHk3uwGHrtRbS9vLA== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.0.1" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.1" - micromatch "^3.1.10" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fast.js@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/fast.js/-/fast.js-0.1.1.tgz#7c024d55ae144882fbcee44b79005fe2dcabd9fe" - integrity sha1-fAJNVa4USIL7zuRLeQBf4tyr2f4= - -fb-watchman@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= - dependencies: - bser "^2.0.0" - -fbjs@^0.8.1, fbjs@^0.8.9: - version "0.8.17" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd" - integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90= - dependencies: - core-js "^1.0.0" - isomorphic-fetch "^2.1.1" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^0.7.18" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fileset@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - -filesize@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" - integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.4.0" - unpipe "~1.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -flatten@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" - integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I= - -follow-redirects@^1.0.0, follow-redirects@^1.3.0: - version "1.5.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.8.tgz#1dbfe13e45ad969f813e86c00e5296f525c885a1" - integrity sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg== - dependencies: - debug "=3.1.0" - -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.1, form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== - dependencies: - minipass "^2.2.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.2, fsevents@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== - dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" - -fstream@^1.0.0, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -fswatcher-child@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fswatcher-child/-/fswatcher-child-1.1.1.tgz#264dd95f9c4b5f8615327d7d7567884591846b9b" - integrity sha512-FVDjVhR71TkJ+ud6vnRwCHvCgK9drGRdimWcTLqw8iN88uL5tTX+/xrwigJdcuQGrWYo3TRw9gRzk9xqR0UPPQ== - dependencies: - chokidar "^2.0.3" - -function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" - integrity sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - is-callable "^1.1.3" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-port@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globule@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" - integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ== - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= - -grapheme-breaker@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" - integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw= - dependencies: - brfs "^1.2.0" - unicode-trie "^0.3.1" - -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - -handlebars@^4.0.3: - version "4.0.12" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== - dependencies: - async "^2.5.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - -har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== - dependencies: - ajv "^5.3.0" - har-schema "^2.0.0" - -harmony-reflect@^1.4.6: - version "1.6.1" - resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" - integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA== - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.0, has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -history@^3.0.0, history@^3.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c" - integrity sha1-/O3M6PEpdTcVRdc1RhAzV5ptrpw= - dependencies: - invariant "^2.2.1" - loose-envify "^1.2.0" - query-string "^4.2.2" - warning "^3.0.0" - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoist-non-react-statics@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" - integrity sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs= - -hoist-non-react-statics@^2.1.0, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-comment-regex@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" - integrity sha1-ZouTd26q5V696POtRkswekljYl4= - -html-encoding-sniffer@^1.0.1, html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== - dependencies: - whatwg-encoding "^1.0.1" - -html-to-react@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/html-to-react/-/html-to-react-1.3.3.tgz#e41666a735f9997ed2372dcd21d8b0e42b334467" - integrity sha512-4Qi5/t8oBr6c1t1kBJKyxEeJu0lb7ctvq29oFZioiUHH0Wz88VWGwoXuH26HDt9v64bDHA4NMPNTH8bVrcaJWA== - dependencies: - domhandler "^2.3.0" - escape-string-regexp "^1.0.5" - htmlparser2 "^3.8.3" - ramda "^0.25.0" - underscore.string.fp "^1.0.4" - -htmlnano@^0.1.9: - version "0.1.10" - resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.1.10.tgz#a0a548eb4c76ae2cf2423ec7a25c881734d3dea6" - integrity sha512-eTEUzz8VdWYp+w/KUdb99kwao4reR64epUySyZkQeepcyzPQ2n2EPWzibf6QDxmkGy10Kr+CKxYqI3izSbmhJQ== - dependencies: - cssnano "^3.4.0" - object-assign "^4.0.1" - posthtml "^0.11.3" - posthtml-render "^1.1.4" - svgo "^1.0.5" - terser "^3.8.1" - -htmlparser2@^3.8.3: - version "3.10.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" - integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.0.6" - -htmlparser2@^3.9.0, htmlparser2@^3.9.1, htmlparser2@^3.9.2: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg= - dependencies: - domelementtype "^1.3.0" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^2.0.2" - -http-errors@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - integrity sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY= - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-proxy-middleware@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" - integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q== - dependencies: - http-proxy "^1.16.2" - is-glob "^4.0.0" - lodash "^4.17.5" - micromatch "^3.1.9" - -http-proxy@^1.16.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" - integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g== - dependencies: - eventemitter3 "^3.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== - -iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -identity-obj-proxy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= - dependencies: - harmony-reflect "^1.4.6" - -ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= - -import-local@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" - integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ== - dependencies: - pkg-dir "^2.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -in-publish@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" - integrity sha1-4g/146KvwmkDILbcVSaCqcf631E= - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= - dependencies: - repeating "^2.0.0" - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -ini@^1.3.4, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -ipaddr.js@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" - integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4= - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-alphabetical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" - integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg== - -is-alphanumerical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" - integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-boolean-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" - integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= - -is-buffer@^1.1.4, is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= - dependencies: - builtin-modules "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-ci@^1.0.10: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== - dependencies: - ci-info "^1.5.0" - -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-decimal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" - integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg== - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-generator-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" - integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" - integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A== - -is-number-object@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" - integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k= - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" - integrity sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ= - -is-subset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" - integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= - -is-svg@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" - integrity sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk= - dependencies: - html-comment-regex "^1.1.0" - -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-url@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-whitespace-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" - integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ== - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-word-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" - integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0, isobject@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isomorphic-fetch@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -istanbul-api@^1.3.1: - version "1.3.7" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa" - integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA== - dependencies: - async "^2.1.4" - fileset "^2.0.2" - istanbul-lib-coverage "^1.2.1" - istanbul-lib-hook "^1.2.2" - istanbul-lib-instrument "^1.10.2" - istanbul-lib-report "^1.1.5" - istanbul-lib-source-maps "^1.2.6" - istanbul-reports "^1.5.1" - js-yaml "^3.7.0" - mkdirp "^0.5.1" - once "^1.4.0" - -istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" - integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ== - -istanbul-lib-hook@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86" - integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw== - dependencies: - append-transform "^0.4.0" - -istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" - integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A== - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.1" - semver "^5.3.0" - -istanbul-lib-report@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c" - integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw== - dependencies: - istanbul-lib-coverage "^1.2.1" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" - -istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f" - integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg== - dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.2.1" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" - -istanbul-reports@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a" - integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw== - dependencies: - handlebars "^4.0.3" - -jest-changed-files@^23.4.2: - version "23.4.2" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83" - integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA== - dependencies: - throat "^4.0.0" - -jest-cli@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4" - integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.1" - exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.1.11" - import-local "^1.0.0" - is-ci "^1.0.10" - istanbul-api "^1.3.1" - istanbul-lib-coverage "^1.2.0" - istanbul-lib-instrument "^1.10.1" - istanbul-lib-source-maps "^1.2.4" - jest-changed-files "^23.4.2" - jest-config "^23.6.0" - jest-environment-jsdom "^23.4.0" - jest-get-type "^22.1.0" - jest-haste-map "^23.6.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" - jest-resolve-dependencies "^23.6.0" - jest-runner "^23.6.0" - jest-runtime "^23.6.0" - jest-snapshot "^23.6.0" - jest-util "^23.4.0" - jest-validate "^23.6.0" - jest-watcher "^23.4.0" - jest-worker "^23.2.0" - micromatch "^2.3.11" - node-notifier "^5.2.1" - prompts "^0.1.9" - realpath-native "^1.0.0" - rimraf "^2.5.4" - slash "^1.0.0" - string-length "^2.0.0" - strip-ansi "^4.0.0" - which "^1.2.12" - yargs "^11.0.0" - -jest-config@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d" - integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ== - dependencies: - babel-core "^6.0.0" - babel-jest "^23.6.0" - chalk "^2.0.1" - glob "^7.1.1" - jest-environment-jsdom "^23.4.0" - jest-environment-node "^23.4.0" - jest-get-type "^22.1.0" - jest-jasmine2 "^23.6.0" - jest-regex-util "^23.3.0" - jest-resolve "^23.6.0" - jest-util "^23.4.0" - jest-validate "^23.6.0" - micromatch "^2.3.11" - pretty-format "^23.6.0" - -jest-diff@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d" - integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g== - dependencies: - chalk "^2.0.1" - diff "^3.2.0" - jest-get-type "^22.1.0" - pretty-format "^23.6.0" - -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== - -jest-docblock@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7" - integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c= - dependencies: - detect-newline "^2.1.0" - -jest-each@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575" - integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg== - dependencies: - chalk "^2.0.1" - pretty-format "^23.6.0" - -jest-environment-jsdom@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023" - integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM= - dependencies: - jest-mock "^23.2.0" - jest-util "^23.4.0" - jsdom "^11.5.1" - -jest-environment-node@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10" - integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA= - dependencies: - jest-mock "^23.2.0" - jest-util "^23.4.0" - -jest-get-type@^22.1.0: - version "22.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" - integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== - -jest-haste-map@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16" - integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg== - dependencies: - fb-watchman "^2.0.0" - graceful-fs "^4.1.11" - invariant "^2.2.4" - jest-docblock "^23.2.0" - jest-serializer "^23.0.1" - jest-worker "^23.2.0" - micromatch "^2.3.11" - sane "^2.0.0" - -jest-jasmine2@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0" - integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ== - dependencies: - babel-traverse "^6.0.0" - chalk "^2.0.1" - co "^4.6.0" - expect "^23.6.0" - is-generator-fn "^1.0.0" - jest-diff "^23.6.0" - jest-each "^23.6.0" - jest-matcher-utils "^23.6.0" - jest-message-util "^23.4.0" - jest-snapshot "^23.6.0" - jest-util "^23.4.0" - pretty-format "^23.6.0" - -jest-leak-detector@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de" - integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg== - dependencies: - pretty-format "^23.6.0" - -jest-matcher-utils@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80" - integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog== - dependencies: - chalk "^2.0.1" - jest-get-type "^22.1.0" - pretty-format "^23.6.0" - -jest-message-util@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f" - integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8= - dependencies: - "@babel/code-frame" "^7.0.0-beta.35" - chalk "^2.0.1" - micromatch "^2.3.11" - slash "^1.0.0" - stack-utils "^1.0.1" - -jest-mock@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134" - integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ= - -jest-regex-util@^23.3.0: - version "23.3.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5" - integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U= - -jest-resolve-dependencies@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d" - integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA== - dependencies: - jest-regex-util "^23.3.0" - jest-snapshot "^23.6.0" - -jest-resolve@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae" - integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA== - dependencies: - browser-resolve "^1.11.3" - chalk "^2.0.1" - realpath-native "^1.0.0" - -jest-runner-tslint@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/jest-runner-tslint/-/jest-runner-tslint-1.0.5.tgz#040fc508ceddbf629bdafc15de00b133a5d976ac" - integrity sha512-8r4PRt1/e9dCsQt6Bo1CxSWiCnEM+boPGdUD4iRk81QJ6X/Q3jF0SWyd1zPfJ335h1EdJ3kNDiatxNi+bR2fDA== - dependencies: - cosmiconfig "^4.0.0" - create-jest-runner "^0.4.0" - tslint "^5.8.0" - -jest-runner@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38" - integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA== - dependencies: - exit "^0.1.2" - graceful-fs "^4.1.11" - jest-config "^23.6.0" - jest-docblock "^23.2.0" - jest-haste-map "^23.6.0" - jest-jasmine2 "^23.6.0" - jest-leak-detector "^23.6.0" - jest-message-util "^23.4.0" - jest-runtime "^23.6.0" - jest-util "^23.4.0" - jest-worker "^23.2.0" - source-map-support "^0.5.6" - throat "^4.0.0" - -jest-runtime@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082" - integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw== - dependencies: - babel-core "^6.0.0" - babel-plugin-istanbul "^4.1.6" - chalk "^2.0.1" - convert-source-map "^1.4.0" - exit "^0.1.2" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.1.11" - jest-config "^23.6.0" - jest-haste-map "^23.6.0" - jest-message-util "^23.4.0" - jest-regex-util "^23.3.0" - jest-resolve "^23.6.0" - jest-snapshot "^23.6.0" - jest-util "^23.4.0" - jest-validate "^23.6.0" - micromatch "^2.3.11" - realpath-native "^1.0.0" - slash "^1.0.0" - strip-bom "3.0.0" - write-file-atomic "^2.1.0" - yargs "^11.0.0" - -jest-serializer@^23.0.1: - version "23.0.1" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165" - integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU= - -jest-snapshot@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a" - integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg== - dependencies: - babel-types "^6.0.0" - chalk "^2.0.1" - jest-diff "^23.6.0" - jest-matcher-utils "^23.6.0" - jest-message-util "^23.4.0" - jest-resolve "^23.6.0" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - pretty-format "^23.6.0" - semver "^5.5.0" - -jest-util@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561" - integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE= - dependencies: - callsites "^2.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.11" - is-ci "^1.0.10" - jest-message-util "^23.4.0" - mkdirp "^0.5.1" - slash "^1.0.0" - source-map "^0.6.0" - -jest-validate@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" - integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A== - dependencies: - chalk "^2.0.1" - jest-get-type "^22.1.0" - leven "^2.1.0" - pretty-format "^23.6.0" - -jest-watcher@^23.4.0: - version "23.4.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c" - integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw= - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.1" - string-length "^2.0.0" - -jest-worker@^23.2.0: - version "23.2.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9" - integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk= - dependencies: - merge-stream "^1.0.1" - -jest@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d" - integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw== - dependencies: - import-local "^1.0.0" - jest-cli "^23.6.0" - -js-base64@^2.1.8, js-base64@^2.1.9: - version "2.4.9" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03" - integrity sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ== - -js-beautify@^1.7.5: - version "1.8.6" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.6.tgz#6a7e61e47a6e45fb58c5e22499eed350f8607d98" - integrity sha512-TYDZa+lg8vEC5U0OmGQEEwiZ0XFBfvZAUeNOtqflLe+woKuIqF4JzlsBx/C1KVYW5lUewZy2ODL4Obq6sH7a4Q== - dependencies: - config-chain "~1.1.5" - editorconfig "^0.15.0" - mkdirp "~0.5.0" - nopt "~4.0.1" - -js-levenshtein@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e" - integrity sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@~3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" - integrity sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A= - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^11.5.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" - integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== - dependencies: - abab "^2.0.0" - acorn "^5.5.3" - acorn-globals "^4.1.0" - array-equal "^1.0.0" - cssom ">= 0.3.2 < 0.4.0" - cssstyle "^1.0.0" - data-urls "^1.0.0" - domexception "^1.0.1" - escodegen "^1.9.1" - html-encoding-sniffer "^1.0.2" - left-pad "^1.3.0" - nwsapi "^2.0.7" - parse5 "4.0.0" - pn "^1.1.0" - request "^2.87.0" - request-promise-native "^1.0.5" - sax "^1.2.4" - symbol-tree "^3.2.2" - tough-cookie "^2.3.4" - w3c-hr-time "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.3" - whatwg-mimetype "^2.1.0" - whatwg-url "^6.4.1" - ws "^5.2.0" - xml-name-validator "^3.0.0" - -jsdom@^9.0.0: - version "9.12.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" - integrity sha1-6MVG//ywbADUgzyoRBD+1/igl9Q= - dependencies: - abab "^1.0.3" - acorn "^4.0.4" - acorn-globals "^3.1.0" - array-equal "^1.0.0" - content-type-parser "^1.0.1" - cssom ">= 0.3.2 < 0.4.0" - cssstyle ">= 0.2.37 < 0.3.0" - escodegen "^1.6.1" - html-encoding-sniffer "^1.0.1" - nwmatcher ">= 1.3.9 < 2.0.0" - parse5 "^1.5.1" - request "^2.79.0" - sax "^1.2.1" - symbol-tree "^3.2.1" - tough-cookie "^2.3.2" - webidl-conversions "^4.0.0" - whatwg-encoding "^1.0.1" - whatwg-url "^4.3.0" - xml-name-validator "^2.0.1" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - -jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4= - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json5@2.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== - dependencies: - minimist "^1.2.0" - -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -kleur@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300" - integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ== - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -left-pad@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" - integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== - -level-codec@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.0.tgz#2d3a0e835c4aa8339ec63de3f5a37480b74a5f87" - integrity sha512-OIpVvjCcZNP5SdhcNupnsI1zo5Y9Vpm+k/F1gfG5kXrtctlrwanisakweJtE0uA0OpLukRfOQae+Fg0M5Debhg== - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.0.tgz#2de5b566b62eef92f99e19be74397fbc512563fa" - integrity sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg== - dependencies: - errno "~0.1.1" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-js@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/level-js/-/level-js-3.0.0.tgz#e6c066fb529b23eec230849c0751e4f6d548c865" - integrity sha512-e2dVpjCWNwIcyboZUsLqx2vERM0I5OPZOE9wfD22fk8b8OeuZRoV4scr0Y+YIyDXE5cwOsO/1LyjsdJ36o+9Ag== - dependencies: - abstract-leveldown "~5.0.0" - immediate "~3.2.3" - inherits "^2.0.3" - ltgt "^2.1.2" - typedarray-to-buffer "~3.1.5" - -levelup@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - -leven@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -lodash-es@^4.17.5, lodash-es@^4.2.1: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.11.tgz#145ab4a7ac5c5e52a3531fb4f310255a152b4be0" - integrity sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q== - -lodash.assign@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= - -lodash.clone@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= - -lodash.clonedeep@^4.3.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.escape@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" - integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg= - -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - -lodash.isempty@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" - integrity sha1-b4bL7di+TsmHvpqvM8loTbGzHn4= - -lodash.isequal@^4.0.0, lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.mergewith@^4.6.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" - integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ== - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.0.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.10: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== - -log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lru-cache@^4.0.1, lru-cache@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -ltgt@^2.1.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= - -magic-string@^0.22.4: - version "0.22.5" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" - integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== - dependencies: - vlq "^0.2.2" - -make-error@1.x: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" - integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== - -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= - dependencies: - tmpl "1.0.x" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-or-similar@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" - integrity sha1-beJlMXSt+12e3DPGnT6Sobdvrwg= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -markdown-escapes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" - integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA== - -math-expression-evaluator@^1.2.14: - version "1.2.17" - resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" - integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= - -math-random@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdast-add-list-metadata@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz#95e73640ce2fc1fa2dcb7ec443d09e2bfe7db4cf" - integrity sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA== - dependencies: - unist-util-visit-parents "1.1.2" - -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - -memoize-one@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.0.2.tgz#3fb8db695aa14ab9c0f1644e1585a8806adc1aee" - integrity sha512-ucx2DmXTeZTsS4GPPUZCbULAN7kdPT1G+H49Y34JjbQ5ESc6OGhVxKvb1iKhr9v19ZB9OtnHwNnhUnNR/7Wteg== - -memoizerific@^1.11.2: - version "1.11.3" - resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" - integrity sha1-fIekZGREwy11Q4VwkF8tvRsagFo= - dependencies: - map-or-similar "^1.5.0" - -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-source-map@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" - integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8= - dependencies: - source-map "^0.5.6" - -merge-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -merge2@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" - integrity sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg== - -merge@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da" - integrity sha1-dTHjnUlJwoGma4xabgJl6LBYlNo= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.9: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== - dependencies: - mime-db "~1.36.0" - -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -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" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minipass@^2.2.1, minipass@^2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" - integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" - integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA== - dependencies: - minipass "^2.2.1" - -mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -moment@^2.13.0, moment@^2.8.2: - version "2.22.2" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= - -moo@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" - integrity sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -nan@^2.0.7, nan@^2.10.0, nan@^2.9.2: - version "2.11.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== - -nano-date@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nano-date/-/nano-date-2.1.0.tgz#bde8213d8a0f2ad1a3a16e8f455eee2475ffdbf9" - integrity sha1-veghPYoPKtGjoW6PRV7uJHX/2/k= - dependencies: - bignumber.js "^4.0.4" - core-decorators "^0.20.0" - memoizerific "^1.11.2" - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -nearley@^2.7.10: - version "2.15.1" - resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.15.1.tgz#965e4e6ec9ed6b80fc81453e161efbcebb36d247" - integrity sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw== - dependencies: - moo "^0.4.3" - nomnom "~1.6.2" - railroad-diagrams "^1.0.0" - randexp "0.4.6" - semver "^5.4.1" - -needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-fetch@^1.0.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-forge@^0.7.1: - version "0.7.6" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" - integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== - -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-libs-browser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^1.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.0" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" - -node-notifier@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" - integrity sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg== - dependencies: - growly "^1.3.0" - semver "^5.4.1" - shellwords "^0.1.1" - which "^1.3.0" - -node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.0.0-alpha.12: - version "1.0.0-alpha.12" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.12.tgz#32e461b879ea76ac674e511d9832cf29da345268" - integrity sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q== - dependencies: - semver "^5.3.0" - -node-sass@^4.9.3: - version "4.9.3" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.3.tgz#f407cf3d66f78308bb1e346b24fa428703196224" - integrity sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww== - dependencies: - async-foreach "^0.1.3" - chalk "^1.1.1" - cross-spawn "^3.0.0" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - in-publish "^2.0.0" - lodash.assign "^4.2.0" - lodash.clonedeep "^4.3.2" - lodash.mergewith "^4.6.0" - meow "^3.7.0" - mkdirp "^0.5.1" - nan "^2.10.0" - node-gyp "^3.8.0" - npmlog "^4.0.0" - request "2.87.0" - sass-graph "^2.2.4" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -nomnom@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971" - integrity sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE= - dependencies: - colors "0.5.x" - underscore "~1.4.4" - -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -nopt@^4.0.1, nopt@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.1, normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^1.4.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -npm-bundled@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== - -npm-packlist@^1.1.6: - version "1.1.11" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" - integrity sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nth-check@^1.0.1, nth-check@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" - integrity sha1-mSms32KPwsQQmN6rgqxYDPFJquQ= - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -"nwmatcher@>= 1.3.9 < 2.0.0": - version "1.4.4" - resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.4.tgz#2285631f34a95f0d0395cd900c96ed39b58f346e" - integrity sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ== - -nwsapi@^2.0.7: - version "2.0.9" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.9.tgz#77ac0cdfdcad52b6a1151a84e73254edc33ed016" - integrity sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ== - -oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -object-inspect@~1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" - integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== - -object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.entries@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" - integrity sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.values@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" - integrity sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -opn@^5.1.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" - integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw== - dependencies: - is-wsl "^1.1.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -ora@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" - integrity sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA== - dependencies: - chalk "^2.3.1" - cli-cursor "^2.1.0" - cli-spinners "^1.1.0" - log-symbols "^2.2.0" - strip-ansi "^4.0.0" - wcwidth "^1.0.1" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@0, osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -pako@^0.2.5: - version "0.2.9" - resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" - integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= - -pako@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== - -papaparse@^4.4.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-4.6.1.tgz#7b3c5bdf4f0fd12374e2d37f987e9d74a1834ca8" - integrity sha512-X9Ws5tnEQKRCZRfoojX3KvRZbLY1BbL0wqSHF3CKGmxD8Zr4E0WaipUuFweffkCN8RSQzHKhb/F+ATYdNcz1rg== - -parcel@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/parcel/-/parcel-1.10.2.tgz#0943b95634c25b719085d4ea5d9c8abdf7f557f4" - integrity sha512-OI7RKtkHnwhg/8Pd17UYq1Ca6NGwoWPgs55f/G/645qj34RviPQ6jESuHg2I3+EdtpmV3tyuXDoJRe1qZuPjyA== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/core" "^7.0.0" - "@babel/generator" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/plugin-transform-flow-strip-types" "^7.0.0" - "@babel/plugin-transform-modules-commonjs" "^7.0.0" - "@babel/plugin-transform-react-jsx" "^7.0.0" - "@babel/preset-env" "^7.0.0" - "@babel/runtime" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - ansi-to-html "^0.6.4" - babylon-walk "^1.0.2" - browserslist "^4.1.0" - chalk "^2.1.0" - clone "^2.1.1" - command-exists "^1.2.6" - commander "^2.11.0" - cross-spawn "^6.0.4" - cssnano "^4.0.0" - deasync "^0.1.13" - dotenv "^5.0.0" - dotenv-expand "^4.2.0" - fast-glob "^2.2.2" - filesize "^3.6.0" - fswatcher-child "^1.0.5" - get-port "^3.2.0" - grapheme-breaker "^0.3.2" - htmlnano "^0.1.9" - is-glob "^4.0.0" - is-url "^1.2.2" - js-yaml "^3.10.0" - json5 "^1.0.1" - micromatch "^3.0.4" - mkdirp "^0.5.1" - node-forge "^0.7.1" - node-libs-browser "^2.0.0" - opn "^5.1.0" - ora "^2.1.0" - physical-cpu-count "^2.0.0" - postcss "^6.0.19" - postcss-value-parser "^3.3.0" - posthtml "^0.11.2" - posthtml-parser "^0.4.0" - posthtml-render "^1.1.3" - resolve "^1.4.0" - semver "^5.4.1" - serialize-to-js "^1.1.1" - serve-static "^1.12.4" - source-map "0.6.1" - strip-ansi "^4.0.0" - terser "^3.7.3" - toml "^2.3.3" - tomlify-j0.4 "^3.0.0" - v8-compile-cache "^2.0.0" - ws "^5.1.1" - -parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - -parse-entities@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.0.tgz#9deac087661b2e36814153cb78d7e54a4c5fd6f4" - integrity sha512-XXtDdOPLSB0sHecbEapQi6/58U/ODj/KWfIXmmMCJF/eRn8laX6LZbOyioMoETOOJoWRW8/qTSl5VQkUIfKM5g== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" - integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== - -parse5@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" - integrity sha1-m387DeMr543CQBsXVzzK8Pb1nZQ= - -parse5@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" - integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA== - dependencies: - "@types/node" "*" - -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -physical-cpu-count@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" - integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-calc@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" - integrity sha1-d7rnypKK2FcW4v2kLyYb98HWW14= - dependencies: - postcss "^5.0.2" - postcss-message-helpers "^2.0.0" - reduce-css-calc "^1.2.6" - -postcss-calc@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.2.tgz#4d9a43e27dbbf27d095fecb021ac6896e2318337" - integrity sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA== - dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.2" - postcss-selector-parser "^2.2.2" - reduce-css-calc "^2.0.0" - -postcss-colormin@^2.1.8: - version "2.2.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" - integrity sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks= - dependencies: - colormin "^1.0.5" - postcss "^5.0.13" - postcss-value-parser "^3.2.3" - -postcss-colormin@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.2.tgz#93cd1fa11280008696887db1a528048b18e7ed99" - integrity sha512-1QJc2coIehnVFsz0otges8kQLsryi4lo19WD+U5xCWvXd0uw/Z+KKYnbiNDCnO9GP+PvErPHCG0jNvWTngk9Rw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^2.3.4: - version "2.6.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" - integrity sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0= - dependencies: - postcss "^5.0.11" - postcss-value-parser "^3.1.2" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-discard-comments@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" - integrity sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0= - dependencies: - postcss "^5.0.14" - -postcss-discard-comments@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.1.tgz#30697735b0c476852a7a11050eb84387a67ef55d" - integrity sha512-Ay+rZu1Sz6g8IdzRjUgG2NafSNpp2MSMOQUb+9kkzzzP+kh07fP0yNbhtFejURnyVXSX3FYy2nVNW1QTnNjgBQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" - integrity sha1-uavye4isGIFYpesSq8riAmO5GTI= - dependencies: - postcss "^5.0.4" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" - integrity sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU= - dependencies: - postcss "^5.0.14" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" - integrity sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg= - dependencies: - postcss "^5.0.16" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-discard-unused@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" - integrity sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM= - dependencies: - postcss "^5.0.14" - uniqs "^2.0.0" - -postcss-filter-plugins@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" - integrity sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ== - dependencies: - postcss "^5.0.4" - -postcss-merge-idents@^2.1.5: - version "2.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" - integrity sha1-TFUwMTwI4dWzu/PSu8dH4njuonA= - dependencies: - has "^1.0.1" - postcss "^5.0.10" - postcss-value-parser "^3.1.1" - -postcss-merge-longhand@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" - integrity sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg= - dependencies: - postcss "^5.0.4" - -postcss-merge-longhand@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.6.tgz#2b938fa3529c3d1657e53dc7ff0fd604dbc85ff1" - integrity sha512-JavnI+V4IHWsaUAfOoKeMEiJQGXTraEy1nHM0ILlE6NIQPEZrJDAnPh3lNGZ5HAk2mSSrwp66JoGhvjp6SqShA== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" - integrity sha1-0d9d+qexrMO+VT8OnhDofGG19yE= - dependencies: - browserslist "^1.5.2" - caniuse-api "^1.5.2" - postcss "^5.0.4" - postcss-selector-parser "^2.2.2" - vendors "^1.0.0" - -postcss-merge-rules@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.2.tgz#2be44401bf19856f27f32b8b12c0df5af1b88e74" - integrity sha512-UiuXwCCJtQy9tAIxsnurfF0mrNHKc4NnNx6NxqmzNNjXpQwLSukUxELHTRF0Rg1pAmcoKLih8PwvZbiordchag== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-message-helpers@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" - integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= - -postcss-minify-font-values@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" - integrity sha1-S1jttWZB66fIR0qzUmyv17vey2k= - dependencies: - object-assign "^4.0.1" - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" - integrity sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE= - dependencies: - postcss "^5.0.12" - postcss-value-parser "^3.3.0" - -postcss-minify-gradients@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.1.tgz#6da95c6e92a809f956bb76bf0c04494953e1a7dd" - integrity sha512-pySEW3E6Ly5mHm18rekbWiAjVi/Wj8KKt2vwSfVFAWdW6wOIekgqxKxLU7vJfb107o3FDNPkaYFCxGAJBFyogA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^1.0.4: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" - integrity sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM= - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.2" - postcss-value-parser "^3.0.2" - uniqs "^2.0.0" - -postcss-minify-params@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.1.tgz#5b2e2d0264dd645ef5d68f8fec0d4c38c1cf93d2" - integrity sha512-h4W0FEMEzBLxpxIVelRtMheskOKKp52ND6rJv+nBS33G1twu2tCyurYj/YtgU76+UDCvWeNs0hs8HFAWE2OUFg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" - integrity sha1-ssapjAByz5G5MtGkllCBFDEXNb8= - dependencies: - alphanum-sort "^1.0.2" - has "^1.0.1" - postcss "^5.0.14" - postcss-selector-parser "^2.0.0" - -postcss-minify-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.1.tgz#a891c197977cc37abf60b3ea06b84248b1c1e9cd" - integrity sha512-8+plQkomve3G+CodLCgbhAKrb5lekAnLYuL1d7Nz+/7RANpBEVdgBkPNwljfSKvZ9xkkZTZITd04KP+zeJTJqg== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-normalize-charset@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" - integrity sha1-757nEhLX/nWceO0WL2HtYrXLk/E= - dependencies: - postcss "^5.0.5" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz#d9a83d47c716e8a980f22f632c8b0458cfb48a4c" - integrity sha512-R5mC4vaDdvsrku96yXP7zak+O3Mm9Y8IslUobk7IMP+u/g+lXvcN4jngmHY5zeJnrQvE13dfAg5ViU05ZFDwdg== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.1.tgz#ee2d4b67818c961964c6be09d179894b94fd6ba1" - integrity sha512-GNoOaLRBM0gvH+ZRb2vKCIujzz4aclli64MBwDuYGU2EY53LwiP7MxOZGE46UGtotrSnmarPPZ69l2S/uxdaWA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.1.tgz#5293f234b94d7669a9f805495d35b82a581c50e5" - integrity sha512-fFHPGIjBUyUiswY2rd9rsFcC0t3oRta4wxE1h3lpwfQZwFeFjXFSiDtdJ7APCmHQOnUZnqYBADNRPKPwFAONgA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.1.tgz#23c5030c2cc24175f66c914fa5199e2e3c10fef3" - integrity sha512-IJoexFTkAvAq5UZVxWXAGE0yLoNN/012v7TQh5nDo6imZJl2Fwgbhy3J2qnIoaDBrtUP0H7JrXlX1jjn2YcvCQ== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.1.tgz#8be83e0b9cb3ff2d1abddee032a49108f05f95d7" - integrity sha512-1nOtk7ze36+63ONWD8RCaRDYsnzorrj+Q6fxkQV+mlY5+471Qx9kspqv0O/qQNMeApg8KNrRf496zHwJ3tBZ7w== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^3.0.7: - version "3.0.8" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" - integrity sha1-EI90s/L82viRov+j6kWSJ5/HgiI= - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^1.4.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.1.tgz#d14cb639b61238418ac8bc8d3b7bdd65fc86575e" - integrity sha512-U8MBODMB2L+nStzOk6VvWWjZgi5kQNShCyjRhMT3s+W9Jw93yIjOnrEkKYD3Ul7ChWbEcjDWmXq0qOL9MIAnAw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-ordered-values@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" - integrity sha1-7sbCpntsQSqNsgQud/6NpD+VwR0= - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.1" - -postcss-ordered-values@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.1.tgz#2e3b432ef3e489b18333aeca1f1295eb89be9fc2" - integrity sha512-PeJiLgJWPzkVF8JuKSBcylaU+hDJ/TX3zqAMIjlghgn1JBi6QwQaDZoDIlqWRcCAI8SxKrt3FCPSRmOgKRB97Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-reduce-idents@^2.2.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" - integrity sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM= - dependencies: - postcss "^5.0.4" - postcss-value-parser "^3.0.2" - -postcss-reduce-initial@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" - integrity sha1-aPgGlfBF0IJjqHmtJA343WT2ROo= - dependencies: - postcss "^5.0.4" - -postcss-reduce-initial@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.2.tgz#bac8e325d67510ee01fa460676dc8ea9e3b40f15" - integrity sha512-epUiC39NonKUKG+P3eAOKKZtm5OtAtQJL7Ye0CBN1f+UQTHzqotudp+hki7zxXm7tT0ZAKDMBj1uihpPjP25ug== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" - integrity sha1-/3b02CEkN7McKYpC0uFEQCV3GuE= - dependencies: - has "^1.0.1" - postcss "^5.0.8" - postcss-value-parser "^3.0.1" - -postcss-reduce-transforms@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.1.tgz#8600d5553bdd3ad640f43bff81eb52f8760d4561" - integrity sha512-sZVr3QlGs0pjh6JAIe6DzWvBaqYw05V1t3d9Tp+VnFRT5j+rsqoWsysh/iSD7YNsULjq9IAylCznIwVd5oU/zA== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" - integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= - dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^2.1.1: - version "2.1.6" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" - integrity sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0= - dependencies: - is-svg "^2.0.0" - postcss "^5.0.14" - postcss-value-parser "^3.2.3" - svgo "^0.7.0" - -postcss-svgo@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.1.tgz#5628cdb38f015de6b588ce6d0bf0724b492b581d" - integrity sha512-YD5uIk5NDRySy0hcI+ZJHwqemv2WiqqzDgtvgMzO8EGSkK5aONyX8HMVFRFJSdO8wUWTuisUFn/d7yRRbBr5Qw== - dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" - integrity sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0= - dependencies: - alphanum-sort "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" - integrity sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU= - -postcss-zindex@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" - integrity sha1-0hCd3AVbka9n/EyzsCWUZjnSryI= - dependencies: - has "^1.0.1" - postcss "^5.0.4" - uniqs "^2.0.0" - -postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: - version "5.2.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" - integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== - dependencies: - chalk "^1.1.3" - js-base64 "^2.1.9" - source-map "^0.5.6" - supports-color "^3.2.3" - -postcss@^6.0.19: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.5.tgz#70e6443e36a6d520b0fd4e7593fcca3635ee9f55" - integrity sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.5.0" - -posthtml-parser@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.3.3.tgz#3fe986fca9f00c0f109d731ba590b192f26e776d" - integrity sha512-H/Z/yXGwl49A7hYQLV1iQ3h87NE0aZ/PMZhFwhw3lKeCAN+Ti4idrHvVvh4/GX10I7u77aQw+QB4vV5/Lzvv5A== - dependencies: - htmlparser2 "^3.9.2" - isobject "^2.1.0" - object-assign "^4.1.1" - -posthtml-parser@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.1.tgz#95b78fef766fbbe0a6f861b6e95582bc3d1ff933" - integrity sha512-h7vXIQ21Ikz2w5wPClPakNP6mJeJCK6BT0GpqnQrNNABdR7/TchNlFyryL1Bz6Ww53YWCKkr6tdZuHlxY1AVdQ== - dependencies: - htmlparser2 "^3.9.2" - object-assign "^4.1.1" - -posthtml-render@^1.1.0, posthtml-render@^1.1.3, posthtml-render@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.4.tgz#95dac09892f4f183fad5ac823f08f42c0256551e" - integrity sha512-jL6eFIzoN3xUEvbo33OAkSDE2VIKU4JQ1wENOows1DpfnrdapR/K3Q1/fB43Mq7wQlcSgRm23nFrvoioufM7eA== - -posthtml@^0.11.2, posthtml@^0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.3.tgz#17ea2921b0555b7455f33c977bd16d8b8cb74f27" - integrity sha512-quMHnDckt2DQ9lRi6bYLnuyBDnVzK+McHa8+ar4kTdYbWEo/92hREOu3h70ZirudOOp/my2b3r0m5YtxY52yrA== - dependencies: - object-assign "^4.1.1" - posthtml-parser "^0.3.3" - posthtml-render "^1.1.0" - -prefix-style@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/prefix-style/-/prefix-style-2.0.1.tgz#66bba9a870cfda308a5dc20e85e9120932c95a06" - integrity sha1-ZrupqHDP2jCKXcIOhekSCTLJWgY= - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -prettier@^1.14.3: - version "1.14.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" - integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== - -pretty-format@^23.6.0: - version "23.6.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" - integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== - dependencies: - ansi-regex "^3.0.0" - ansi-styles "^3.2.0" - -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -prompts@^0.1.9: - version "0.1.14" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2" - integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w== - dependencies: - kleur "^2.0.1" - sisteransi "^0.1.1" - -prop-types@15.5.8: - version "15.5.8" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394" - integrity sha1-a3suFBCDvjjIWVqlH8VXdccZk5Q= - dependencies: - fbjs "^0.8.9" - -prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" - integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== - dependencies: - loose-envify "^1.3.1" - object-assign "^4.1.1" - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -proxy-addr@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" - integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.8.0" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" - integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== - -qs@^6.5.2, qs@~6.5.1, qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^4.1.0, query-string@^4.2.2: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -quote-stream@^1.0.1, quote-stream@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" - integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= - dependencies: - buffer-equal "0.0.1" - minimist "^1.1.3" - through2 "^2.0.0" - -raf@^3.1.0, raf@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - integrity sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw== - dependencies: - performance-now "^2.1.0" - -railroad-diagrams@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" - integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234= - -ramda@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" - integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== - -randexp@0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" - integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== - dependencies: - discontinuous-range "1.0.0" - ret "~0.1.10" - -randomatic@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" - integrity sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - integrity sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k= - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-codemirror2@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/react-codemirror2/-/react-codemirror2-4.3.0.tgz#e79aedca4da60d22402d2cd74f2885a3e5c009fd" - integrity sha512-tC0n9CHgrQYc976pUlKOaVJYEHAAYTVMers04gNy6jbkFf4rbPlw72y7bbOAfkHHvu6COG5S629Fek30bvHe8w== - -react-copy-to-clipboard@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz#8eae107bb400be73132ed3b6a7b4fb156090208e" - integrity sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA== - dependencies: - copy-to-clipboard "^3" - prop-types "^15.5.8" - -react-custom-scrollbars@^4.1.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db" - integrity sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts= - dependencies: - dom-css "^2.0.0" - prop-types "^15.5.10" - raf "^3.1.0" - -react-dimensions@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/react-dimensions/-/react-dimensions-1.3.1.tgz#89c29bcd48828a74faeb07da1e461e1a354ccc48" - integrity sha512-go5vMuGUxaB5PiTSIk+ZfAxLbHwcIgIfLhkBZ2SIMQjaCgnpttxa30z5ijEzfDjeOCTGRpxvkzcmE4Vt4Ppvyw== - dependencies: - element-resize-event "^2.0.4" - -react-dnd-html5-backend@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-2.6.0.tgz#590cd1cca78441bb274edd571fef4c0b16ddcf8e" - integrity sha1-WQzRzKeEQbsnTt1XH+9MCxbdz44= - dependencies: - lodash "^4.2.0" - -react-dnd@*: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-5.0.0.tgz#c4a17c70109e456dad8906be838e6ee8f32b06b5" - integrity sha1-xKF8cBCeRW2tiQa+g45u6PMrBrU= - dependencies: - dnd-core "^4.0.5" - hoist-non-react-statics "^2.5.0" - invariant "^2.1.0" - lodash "^4.17.10" - recompose "^0.27.1" - shallowequal "^1.0.2" - -react-dnd@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-2.6.0.tgz#7fa25676cf827d58a891293e3c1ab59da002545a" - integrity sha1-f6JWds+CfViokSk+PBq1naACVFo= - dependencies: - disposables "^1.0.1" - dnd-core "^2.6.0" - hoist-non-react-statics "^2.1.0" - invariant "^2.1.0" - lodash "^4.2.0" - prop-types "^15.5.10" - -react-dom@^16.3.1: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7" - integrity sha512-RC8LDw8feuZOHVgzEf7f+cxBr/DnKdqp56VU0lAs1f4UfKc4cU8wU4fTq/mgnvynLQo8OtlPC19NUFh/zjZPuA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - schedule "^0.5.0" - -react-draggable@3.x, "react-draggable@^2.2.6 || ^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.0.5.tgz#c031e0ed4313531f9409d6cd84c8ebcec0ddfe2d" - integrity sha512-qo76q6+pafyGllbmfc+CgWfOkwY9v3UoJa3jp6xG2vdsRY8uJTN1kqNievLj0uVNjEqCvZ0OFiEBxlAJNj3OTg== - dependencies: - classnames "^2.2.5" - prop-types "^15.6.0" - -react-grid-layout@^0.16.6: - version "0.16.6" - resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9b2407a2b946c2260ebaf66f13b556e1da4efeb2" - integrity sha512-h2EsYgsqcESLJeevQSJsEKp8hhh+phOlXDJoMhlV2e7T3VWQL+S6iCF3iD/LK19r4oyRyOMDEir0KV+eLXrAyw== - dependencies: - classnames "2.x" - lodash.isequal "^4.0.0" - prop-types "15.x" - react-draggable "3.x" - react-resizable "1.x" - -react-is@^16.5.2: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.5.2.tgz#e2a7b7c3f5d48062eb769fcb123505eb928722e3" - integrity sha512-hSl7E6l25GTjNEZATqZIuWOgSnpXb3kD0DVCujmg46K5zLxsbiKaaT6VO9slkSBDPZfYs30lwfJwbOFOnoEnKQ== - -react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - -react-markdown@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-4.0.3.tgz#8851f9265d0322bb5d60ab2766b3ab48cdbeb890" - integrity sha512-CIc3eLVpW5XocM1MCid2rS0vs9skhvdL/slAkY/a3Cr9y72b0J/25GiD70fGmStjuxsd5ROdm4ZYfiYYxPPyGA== - dependencies: - html-to-react "^1.3.3" - mdast-add-list-metadata "1.0.1" - prop-types "^15.6.1" - remark-parse "^5.0.0" - unified "^6.1.5" - unist-util-visit "^1.3.0" - xtend "^4.0.1" - -react-redux@^5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" - integrity sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg== - dependencies: - hoist-non-react-statics "^2.5.0" - invariant "^2.0.0" - lodash "^4.17.5" - lodash-es "^4.17.5" - loose-envify "^1.1.0" - prop-types "^15.6.0" - -react-resizable@1.x: - version "1.7.5" - resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-1.7.5.tgz#83eb75bb3684da6989bbbf4f826e1470f0af902e" - integrity sha512-lauPcBsLqmxMHXHpTeOBpYenGalbSikYr8hK+lwtNYMQX1pGd2iYE+pDvZEV97nCnzuCtWM9htp7OpsBIY2Sjw== - dependencies: - prop-types "15.x" - react-draggable "^2.2.6 || ^3.0.3" - -react-resize-detector@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c" - integrity sha512-oCAddEWWeFWYH5FAcHdBYcZjAw9fMzRUK9sWSx6WvSSOPVRxcHd5zTIGy/mOus+AhN/u6T4TMiWxvq79PywnJQ== - dependencies: - lodash.debounce "^4.0.8" - lodash.throttle "^4.1.1" - prop-types "^15.6.0" - resize-observer-polyfill "^1.5.0" - -react-router-redux@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-4.0.8.tgz#227403596b5151e182377dab835b5d45f0f8054e" - integrity sha1-InQDWWtRUeGCN32rg1tdRfD4BU4= - -react-router@^3.0.2: - version "3.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.2.1.tgz#b9a3279962bdfbe684c8bd0482b81ef288f0f244" - integrity sha512-SXkhC0nr3G0ltzVU07IN8jYl0bB6FsrDIqlLC9dK3SITXqyTJyM7yhXlUqs89w3Nqi5OkXsfRUeHX+P874HQrg== - dependencies: - create-react-class "^15.5.1" - history "^3.0.0" - hoist-non-react-statics "^2.3.1" - invariant "^2.2.1" - loose-envify "^1.2.0" - prop-types "^15.5.6" - warning "^3.0.0" - -react-test-renderer@^16.0.0-0: - version "16.5.2" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.5.2.tgz#92e9d2c6f763b9821b2e0b22f994ee675068b5ae" - integrity sha512-AGbJYbCVx1J6jdUgI4s0hNp+9LxlgzKvXl0ROA3DHTrtjAr00Po1RhDZ/eAq2VC/ww8AHgpDXULh5V2rhEqqJg== - dependencies: - object-assign "^4.1.1" - prop-types "^15.6.2" - react-is "^16.5.2" - schedule "^0.5.0" - -react-tooltip@^3.2.1: - version "3.8.4" - resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-3.8.4.tgz#7af7994d5a242c08f2a3cf0b86919fede6eb44f2" - integrity sha512-i9rP5eihRNXFqYtyw58fhy+oT7OAEox/WC7XJOSED57s31nLU+uOJai5TgADbwNzJ7xamPkijYF36IfrUGJgcQ== - dependencies: - classnames "^2.2.5" - prop-types "^15.6.0" - sanitize-html-react "^1.13.0" - -react-virtualized@^9.18.5: - version "9.20.1" - resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.20.1.tgz#02dc08fe9070386b8c48e2ac56bce7af0208d22d" - integrity sha512-xIWxBsyNAjceqD3hsE0nw5TcDVxKbIepsHhvS2XneHmNz0KlKxdLdGBmGZBM9ZesEmbZ5EO0Sw70TB1MeCmpbQ== - dependencies: - babel-runtime "^6.26.0" - classnames "^2.2.3" - dom-helpers "^2.4.0 || ^3.0.0" - loose-envify "^1.3.0" - prop-types "^15.6.0" - react-lifecycles-compat "^3.0.4" - -"react@^15.0.0 || ^16.0.0": - version "16.5.2" - resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42" - integrity sha512-FDCSVd3DjVTmbEAjUNX6FgfAmQ+ypJfHUsqUJOYNCBUp1h8lqmtC+0mXJ+JjsWx4KAVTkk1vKd1hLQPvEviSuw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - schedule "^0.5.0" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.0.6.tgz#351302e4c68b5abd6a2ed55376a7f9a25be3057a" - integrity sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -realpath-native@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.2.tgz#cd51ce089b513b45cf9b1516c82989b51ccc6560" - integrity sha512-+S3zTvVt9yTntFrBpm7TQmQ3tzpCrnA1a/y+3cUHAc9ZR6aIjG0WNLR+Rj79QpJktY+VeW/TQtFlQ1bzsehI8g== - dependencies: - util.promisify "^1.0.0" - -recompose@^0.27.1: - version "0.27.1" - resolved "https://registry.yarnpkg.com/recompose/-/recompose-0.27.1.tgz#1a49e931f183634516633bbb4f4edbfd3f38a7ba" - integrity sha512-p7xsyi/rfNjHfdP7vPU02uSFa+Q1eHhjKrvO+3+kRP4Ortj+MxEmpmd+UQtBGM2D2iNAjzNI5rCyBKp9Ob5McA== - dependencies: - babel-runtime "^6.26.0" - change-emitter "^0.1.2" - fbjs "^0.8.1" - hoist-non-react-statics "^2.3.1" - react-lifecycles-compat "^3.0.2" - symbol-observable "^1.0.4" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -reduce-css-calc@^1.2.6: - version "1.3.0" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" - integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= - dependencies: - balanced-match "^0.4.2" - math-expression-evaluator "^1.2.14" - reduce-function-call "^1.0.1" - -reduce-css-calc@^2.0.0: - version "2.1.5" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.5.tgz#f283712f0c9708ef952d328f4b16112d57b03714" - integrity sha512-AybiBU03FKbjYzyvJvwkJZY6NLN+80Ufc2EqEs+41yQH+8wqBEslD6eGiS0oIeq5TNLA5PrhBeYHXWdn8gtW7A== - dependencies: - css-unit-converter "^1.1.1" - postcss-value-parser "^3.3.0" - -reduce-function-call@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" - integrity sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk= - dependencies: - balanced-match "^0.4.2" - -redux-auth-wrapper@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/redux-auth-wrapper/-/redux-auth-wrapper-1.1.0.tgz#ccd4a753fe2134eb93c44f4e5781054577f6244a" - integrity sha1-zNSnU/4hNOuTxE9OV4EFRXf2JEo= - dependencies: - hoist-non-react-statics "1.2.0" - lodash.isempty "4.4.0" - prop-types "15.5.8" - -redux-thunk@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-1.0.3.tgz#778aa0099eea0595031ab6b39165f6670d8d26bd" - integrity sha1-d4qgCZ7qBZUDGrazkWX2Zw2NJr0= - -redux@^3.6.0, redux@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" - integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A== - dependencies: - lodash "^4.2.1" - lodash-es "^4.2.1" - loose-envify "^1.1.0" - symbol-observable "^1.0.3" - -redux@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" - integrity sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA== - dependencies: - loose-envify "^1.1.0" - symbol-observable "^1.2.0" - -regenerate-unicode-properties@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.10.5: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg= - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== - -regenerator-transform@^0.13.3: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb" - integrity sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA== - dependencies: - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp-quote@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/regexp-quote/-/regexp-quote-0.0.0.tgz#1e0f4650c862dcbfed54fd42b148e9bb1721fcf2" - integrity sha1-Hg9GUMhi3L/tVP1CsUjpuxch/PI= - -regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" - integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^7.0.0" - regjsgen "^0.4.0" - regjsparser "^0.3.0" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.0.2" - -regjsgen@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" - integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA== - -regjsparser@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" - integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA== - dependencies: - jsesc "~0.5.0" - -remark-parse@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" - integrity sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA== - dependencies: - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^1.1.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^1.0.0" - vfile-location "^2.0.0" - xtend "^4.0.1" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - -replace-ext@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= - dependencies: - lodash "^4.13.1" - -request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= - dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - -request@2.87.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@^2.79.0, request@^2.87.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resize-observer-polyfill@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69" - integrity sha512-M2AelyJDVR/oLnToJLtuDJRBBWUGUvvGigj1411hXhAdyFWqMaqHp7TixW3FpiLuVaikIcR1QL+zqoJoZlOgpg== - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - -resolve@^1.1.5, resolve@^1.3.2, resolve@^1.4.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== - dependencies: - path-parse "^1.0.5" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -reverse-arguments@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/reverse-arguments/-/reverse-arguments-1.0.0.tgz#c28095a3a921ac715d61834ddece9027992667cd" - integrity sha1-woCVo6khrHFdYYNN3s6QJ5kmZ80= - -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== - dependencies: - glob "^7.0.5" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rome@^2.1.22: - version "2.1.22" - resolved "https://registry.yarnpkg.com/rome/-/rome-2.1.22.tgz#4bf25318cc0522ae92dd090472ce7a6e0b1f5e02" - integrity sha1-S/JTGMwFIq6S3QkEcs56bgsfXgI= - dependencies: - bullseye "1.4.6" - contra "1.9.1" - crossvent "1.5.0" - moment "^2.8.2" - -rst-selector-parser@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" - integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE= - dependencies: - lodash.flattendeep "^4.4.0" - nearley "^2.7.10" - -rsvp@^3.3.3: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== - -safe-buffer@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -safer-eval@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.2.3.tgz#73ba74a34bc8a07d6a44135c815fd18a8eebe7a0" - integrity sha512-nDwXOhiheoaBT6op02n8wzsshjLXHhh4YAeqsDEoVmy1k2+lGv/ENLsGaWqkaKArUkUx48VO12/ZPa3sI/OEqQ== - dependencies: - clones "^1.1.0" - -sane@^2.0.0: - version "2.5.2" - resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa" - integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o= - dependencies: - anymatch "^2.0.0" - capture-exit "^1.2.0" - exec-sh "^0.2.0" - fb-watchman "^2.0.0" - micromatch "^3.1.4" - minimist "^1.1.1" - walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" - -sanitize-html-react@^1.13.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/sanitize-html-react/-/sanitize-html-react-1.13.0.tgz#e757b9adbaf2c8a762f3d2dff70138838e05420a" - integrity sha1-51e5rbryyKdi89Lf9wE4g44FQgo= - dependencies: - htmlparser2 "^3.9.0" - regexp-quote "0.0.0" - xtend "^4.0.0" - -sass-graph@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" - integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k= - dependencies: - glob "^7.0.0" - lodash "^4.0.0" - scss-tokenizer "^0.2.3" - yargs "^7.0.0" - -sax@^1.2.1, sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -schedule@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/schedule/-/schedule-0.5.0.tgz#c128fffa0b402488b08b55ae74bb9df55cc29cc8" - integrity sha512-HUcJicG5Ou8xfR//c2rPT0lPIRR09vVvN81T9fqfVgBmhERUbDEQoYKjpBxbueJnCPpSu2ujXzOnRQt6x9o/jw== - dependencies: - object-assign "^4.1.1" - -scss-tokenizer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" - integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE= - dependencies: - js-base64 "^2.1.8" - source-map "^0.4.2" - -seleccion@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/seleccion/-/seleccion-2.0.0.tgz#0984ac1e8df513e38b41a608e65042e8381e0a73" - integrity sha1-CYSsHo31E+OLQaYI5lBC6DgeCnM= - -sell@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sell/-/sell-1.0.0.tgz#3baca7e51f78ddee9e22eea1ac747a6368bd1630" - integrity sha1-O6yn5R943e6eIu6hrHR6Y2i9FjA= - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" - integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== - -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -serialize-to-js@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.1.tgz#2e87f61f938826d24c463a7cbd0dd2929ec38008" - integrity sha512-TK6d30GNkOLeFDPuP6Jfy1Q1V31GxzppYTt2lzr8KWmIUKomFj+260QP5o4AhHLu0pr6urgyS8i/Z1PqurjBoA== - dependencies: - js-beautify "^1.7.5" - safer-eval "^1.2.3" - -serve-static@1.13.2, serve-static@^1.12.4: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4, setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shallow-copy@~0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" - integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= - -shallowequal@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" - integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== - -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -sisteransi@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" - integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g== - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.6, source-map-support@~0.5.6: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - integrity sha1-66T12pwNyZneaAMti092FzZSA2s= - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -spdx-correct@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - integrity sha1-xvxhZIo9nE52T9P8306hBeSSupg= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stable@~0.1.6: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -stack-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" - integrity sha1-1PM6tU6OOHeLDKXP07OvsS22hiA= - -state-toggle@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" - integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og== - -static-eval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.0.tgz#0e821f8926847def7b4b50cda5d55c04a9b13864" - integrity sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw== - dependencies: - escodegen "^1.8.1" - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -static-module@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" - integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== - dependencies: - concat-stream "~1.6.0" - convert-source-map "^1.5.1" - duplexer2 "~0.1.4" - escodegen "~1.9.0" - falafel "^2.1.0" - has "^1.0.1" - magic-string "^0.22.4" - merge-source-map "1.0.4" - object-inspect "~1.4.0" - quote-stream "~1.0.2" - readable-stream "~2.3.3" - shallow-copy "~0.0.1" - static-eval "^2.0.0" - through2 "~2.0.3" - -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - -stealthy-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - -stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-length@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" - integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= - dependencies: - astral-regex "^1.0.0" - strip-ansi "^4.0.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.trim@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" - -string_decoder@^1.0.0, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-bom@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -stylehacks@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.1.tgz#3186595d047ab0df813d213e51c8b94e0b9010f2" - integrity sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^3.1.2, supports-color@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - -supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - 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" - integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= - dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" - mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" - -svgo@^1.0.0, svgo@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" - integrity sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g== - dependencies: - coa "~2.0.1" - colors "~1.1.2" - css-select "^2.0.0" - css-select-base-adapter "~0.1.0" - css-tree "1.0.0-alpha.28" - css-url-regex "^1.1.0" - csso "^3.5.0" - js-yaml "^3.12.0" - mkdirp "~0.5.1" - object.values "^1.0.4" - sax "~1.2.4" - stable "~0.1.6" - unquote "~1.1.1" - util.promisify "~1.0.0" - -symbol-observable@^1.0.3, symbol-observable@^1.0.4, symbol-observable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - -symbol-tree@^3.2.1, symbol-tree@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= - -tar@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -tar@^4: - version "4.4.6" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== - dependencies: - chownr "^1.0.1" - fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - -terser@^3.7.3, terser@^3.8.1: - version "3.9.3" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.9.3.tgz#14d13207f58b7a25ba7dd11def76c9e73cca5036" - integrity sha512-7CAUcdTRzfxvMUqhSDe95MQ/qVEV3JqiSB8mMGQZSe1CL7AKB1iMpF7Mj6DatC9YfG/4xxE25Egp1kxVNORdGQ== - dependencies: - commander "~2.17.1" - source-map "~0.6.1" - source-map-support "~0.5.6" - -test-exclude@^4.2.1: - version "4.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" - integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA== - dependencies: - arrify "^1.0.1" - micromatch "^2.3.11" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" - -throat@^4.0.0, throat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" - integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= - -through2@^2.0.0, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -ticky@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ticky/-/ticky-1.0.0.tgz#e87f38ee0491ea32f62e8f0567ba9638b29f049c" - integrity sha1-6H847gSR6jL2Lo8FZ7qWOLKfBJw= - -timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== - dependencies: - setimmediate "^1.0.4" - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-inflate@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" - integrity sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c= - -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-camel-case@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" - integrity sha1-GlYFSy+daWKYzmamCJcyK29CPkY= - dependencies: - to-space-case "^1.0.0" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-no-case@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a" - integrity sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -to-space-case@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17" - integrity sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc= - dependencies: - to-no-case "^1.0.0" - -toggle-selection@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" - integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= - -toml@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb" - integrity sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA== - -tomlify-j0.4@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz#99414d45268c3a3b8bf38be82145b7bba34b7473" - integrity sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ== - -tough-cookie@>=2.3.3, tough-cookie@^2.3.2, tough-cookie@^2.3.4, tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -trim-trailing-lines@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" - integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg== - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - -trough@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24" - integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw== - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - -ts-jest@^23.10.3: - version "23.10.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.10.4.tgz#a7a953f55c9165bcaa90ff91014a178e87fe0df8" - integrity sha512-oV/wBwGUS7olSk/9yWMiSIJWbz5xO4zhftnY3gwv6s4SMg6WHF1m8XZNBvQOKQRiTAexZ9754Z13dxBq3Zgssw== - dependencies: - bs-logger "0.x" - buffer-from "1.x" - fast-json-stable-stringify "2.x" - json5 "2.x" - make-error "1.x" - mkdirp "0.x" - semver "^5.5" - yargs-parser "10.x" - -tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - -tslint-config-prettier@^1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.15.0.tgz#76b9714399004ab6831fdcf76d89b73691c812cf" - integrity sha512-06CgrHJxJmNYVgsmeMoa1KXzQRoOdvfkqnJth6XUkNeOz707qxN0WfxfhYwhL5kXHHbYJRby2bqAPKwThlZPhw== - -tslint-plugin-prettier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tslint-plugin-prettier/-/tslint-plugin-prettier-2.0.0.tgz#ade328b26c71f37418d4d01187dca232a7447b49" - integrity sha512-nA8yM+1tS9dylirSajTxxFV6jCQrIMQ0Ykl//jjRgqmwwmGp3hqodG+rtr16S/OUwyQBfoFScFDK7nuHYPd4Gw== - dependencies: - eslint-plugin-prettier "^2.2.0" - tslib "^1.7.1" - -tslint-react@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.6.0.tgz#7f462c95c4a0afaae82507f06517ff02942196a1" - integrity sha512-AIv1QcsSnj7e9pFir6cJ6vIncTqxfqeFF3Lzh8SuuBljueYzEAtByuB6zMaD27BL0xhMEqsZ9s5eHuCONydjBw== - dependencies: - tsutils "^2.13.1" - -tslint@^5.8.0, tslint@^5.9.1: - version "5.11.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.11.0.tgz#98f30c02eae3cde7006201e4c33cb08b48581eed" - integrity sha1-mPMMAurjzecAYgHkwzywi0hYHu0= - dependencies: - babel-code-frame "^6.22.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^3.2.0" - glob "^7.1.1" - js-yaml "^3.7.0" - minimatch "^3.0.4" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.27.2" - -tsutils@^2.13.1, tsutils@^2.27.2: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-is@~1.6.15, type-is@~1.6.16: - version "1.6.16" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" - integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.18" - -typedarray-to-buffer@~3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5" - integrity sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA== - -ua-parser-js@^0.7.18: - version "0.7.18" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" - integrity sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA== - -uglify-js@^3.1.4: - version "3.4.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== - dependencies: - commander "~2.17.1" - source-map "~0.6.1" - -underscore.string.fp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/underscore.string.fp/-/underscore.string.fp-1.0.4.tgz#054b3f1843bcae561286c87de5e8879b4fc98364" - integrity sha1-BUs/GEO8rlYShsh95eiHm0/Jg2Q= - dependencies: - chickencurry "1.1.1" - compose-function "^2.0.0" - reverse-arguments "1.0.0" - underscore.string "3.0.3" - -underscore.string@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.0.3.tgz#4617b8c1a250cf6e5064fbbb363d0fa96cf14552" - integrity sha1-Rhe4waJQz25QZPu7Nj0PqWzxRVI= - -underscore@~1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604" - integrity sha1-YaajIBBiKvoHljvzJSA88SI51gQ= - -unherit@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" - integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g== - dependencies: - inherits "^2.0.1" - xtend "^4.0.1" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== - -unicode-trie@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" - integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU= - dependencies: - pako "^0.2.5" - tiny-inflate "^1.0.0" - -unified@^6.1.5: - version "6.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" - integrity sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^1.1.0" - trough "^1.0.0" - vfile "^2.0.0" - x-is-string "^0.1.0" - -union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - -unist-util-is@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" - integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw== - -unist-util-remove-position@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" - integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q== - dependencies: - unist-util-visit "^1.1.0" - -unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" - integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== - -unist-util-visit-parents@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06" - integrity sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q== - -unist-util-visit-parents@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" - integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== - dependencies: - unist-util-is "^2.1.2" - -unist-util-visit@^1.1.0, unist-util-visit@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1" - integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw== - dependencies: - unist-util-visit-parents "^2.0.0" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@^1.0.0, util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -v8-compile-cache@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vfile-location@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77" - integrity sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A== - -vfile-message@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677" - integrity sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug== - dependencies: - unist-util-stringify-position "^1.1.1" - -vfile@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" - integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== - dependencies: - is-buffer "^1.1.4" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" - -vlq@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" - -w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= - dependencies: - browser-process-hrtime "^0.1.2" - -walker@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= - dependencies: - makeerror "1.0.x" - -warning@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" - integrity sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w= - dependencies: - loose-envify "^1.0.0" - -watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= - dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" - -wcwidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= - dependencies: - defaults "^1.0.3" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -webidl-conversions@^4.0.0, webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== - -whatwg-mimetype@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz#a3d58ef10b76009b042d03e25591ece89b88d171" - integrity sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw== - -whatwg-url@^4.3.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.8.0.tgz#d2981aa9148c1e00a41c5a6131166ab4683bbcc0" - integrity sha1-0pgaqRSMHgCkHFphMRZqtGg7vMA= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -whatwg-url@^6.4.1: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -whatwg-url@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" - integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@1, which@^1.2.12, which@^1.2.9, which@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" - integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -ws@^5.1.1, ws@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== - dependencies: - async-limiter "~1.0.0" - -x-is-string@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= - -xml-name-validator@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" - integrity sha1-TYuPHszTQZqjYgYb7O9RXh5VljU= - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= - -yargs-parser@10.x: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" - -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= - dependencies: - camelcase "^4.1.0" - -yargs@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yargs@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" From ebfbe3ba3801d8349337375bc61e70f13e3048b3 Mon Sep 17 00:00:00 2001 From: alexpaxton Date: Mon, 4 Feb 2019 14:28:54 -0800 Subject: [PATCH 33/95] Polish/view spacing (#11665) * Make single-stat view take up entire cell * Decrease margin around tables * Make markdown views take up entire cell --- ui/src/shared/components/cells/Cell.scss | 11 ++++++++++- ui/src/shared/components/tables/TableGraphs.scss | 3 +-- ui/src/shared/components/views/Markdown.scss | 6 ++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ui/src/shared/components/cells/Cell.scss b/ui/src/shared/components/cells/Cell.scss index 3dadb05cdd..f7351030dc 100644 --- a/ui/src/shared/components/cells/Cell.scss +++ b/ui/src/shared/components/cells/Cell.scss @@ -25,7 +25,16 @@ $cell--header-size: 36px; z-index: $z--cell-view; > .single-stat { - border-radius: 0 0 $radius $radius; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: $radius; + } + + .time-machine-tables { + padding-top: 0; } } diff --git a/ui/src/shared/components/tables/TableGraphs.scss b/ui/src/shared/components/tables/TableGraphs.scss index b736aa510b..b4a685aab7 100644 --- a/ui/src/shared/components/tables/TableGraphs.scss +++ b/ui/src/shared/components/tables/TableGraphs.scss @@ -4,8 +4,7 @@ flex-wrap: none; width: 100%; height: 100%; - background-color: $g3-castle; - padding: 16px; + padding: 8px; } .time-machine-sidebar { diff --git a/ui/src/shared/components/views/Markdown.scss b/ui/src/shared/components/views/Markdown.scss index 93548167cc..fb6e191589 100644 --- a/ui/src/shared/components/views/Markdown.scss +++ b/ui/src/shared/components/views/Markdown.scss @@ -4,11 +4,13 @@ */ .markdown-cell { - height: calc(100% - 20px) !important; + position: absolute !important; + top: 0; + left: 0; } .markdown-cell--contents { - padding: 8px 16px; + padding: 16px; font-size: 13px; } From 211d28567dd26abb2ee455673048c4e5f6475393 Mon Sep 17 00:00:00 2001 From: Mark Rushakoff Date: Mon, 4 Feb 2019 14:26:00 -0800 Subject: [PATCH 34/95] fix(task): set run status to failed if execution fails Previously a run that started successfully and then failed, would be incorrectly marked as a success. --- task/backend/scheduler.go | 13 ++++++++++--- task/backend/scheduler_test.go | 20 +++++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/task/backend/scheduler.go b/task/backend/scheduler.go index dfb3deb4f7..1198b4c15d 100644 --- a/task/backend/scheduler.go +++ b/task/backend/scheduler.go @@ -10,7 +10,7 @@ import ( "time" platform "github.com/influxdata/influxdb" - "github.com/opentracing/opentracing-go" + opentracing "github.com/opentracing/opentracing-go" "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" ) @@ -659,8 +659,8 @@ func (r *runner) executeAndWait(ctx context.Context, qr QueuedRun, runLogger *za } }() - // TODO(mr): handle res.IsRetryable(). - _, err = rp.Wait() + // TODO(mr): handle rr.IsRetryable(). + rr, err := rp.Wait() close(ready) if err != nil { if err == ErrRunCanceled { @@ -678,6 +678,13 @@ func (r *runner) executeAndWait(ctx context.Context, qr QueuedRun, runLogger *za atomic.StoreUint32(r.state, runnerIdle) return } + if err := rr.Err(); err != nil { + runLogger.Info("Run failed to execute", zap.Error(err)) + // TODO(mr): retry? + r.updateRunState(qr, RunFail, runLogger) + atomic.StoreUint32(r.state, runnerIdle) + return + } if err := r.desiredState.FinishRun(r.ctx, qr.TaskID, qr.RunID); err != nil { runLogger.Info("Failed to finish run", zap.Error(err)) diff --git a/task/backend/scheduler_test.go b/task/backend/scheduler_test.go index 8d488193fe..2dbcb18ecc 100644 --- a/task/backend/scheduler_test.go +++ b/task/backend/scheduler_test.go @@ -483,7 +483,7 @@ func TestScheduler_RunLog(t *testing.T) { pollForRunStatus(t, rl, task.ID, 2, 1, backend.RunStarted.String()) - // Finish with failure. + // Finish with failure to create the run. promises[0].Finish(nil, errors.New("forced failure")) if _, err := e.PollForNumberRunning(task.ID, 0); err != nil { t.Fatal(err) @@ -491,7 +491,7 @@ func TestScheduler_RunLog(t *testing.T) { pollForRunStatus(t, rl, task.ID, 2, 1, backend.RunFail.String()) - // One more run, but cancel this time. + // Create a new run that starts but fails. s.Tick(8) promises, err = e.PollForNumberRunning(task.ID, 1) if err != nil { @@ -499,6 +499,20 @@ func TestScheduler_RunLog(t *testing.T) { } pollForRunStatus(t, rl, task.ID, 3, 2, backend.RunStarted.String()) + promises[0].Finish(mock.NewRunResult(errors.New("started but failed to finish properly"), false), nil) + if _, err := e.PollForNumberRunning(task.ID, 0); err != nil { + t.Fatal(err) + } + pollForRunStatus(t, rl, task.ID, 3, 2, backend.RunFail.String()) + + // One more run, but cancel this time. + s.Tick(9) + promises, err = e.PollForNumberRunning(task.ID, 1) + if err != nil { + t.Fatal(err) + } + + pollForRunStatus(t, rl, task.ID, 4, 3, backend.RunStarted.String()) // Finish with failure. promises[0].Cancel() @@ -506,7 +520,7 @@ func TestScheduler_RunLog(t *testing.T) { t.Fatal(err) } - pollForRunStatus(t, rl, task.ID, 3, 2, backend.RunCanceled.String()) + pollForRunStatus(t, rl, task.ID, 4, 3, backend.RunCanceled.String()) } func TestScheduler_Metrics(t *testing.T) { From 811fbd84ae14dd4f60f01a2d5e43d7635c823ba3 Mon Sep 17 00:00:00 2001 From: Palak Bhojani Date: Thu, 31 Jan 2019 09:41:39 -0800 Subject: [PATCH 35/95] Add the ability to inline-edit for Bucket, Dashboard, Tasks, Collectors and Scraper names --- .../organizations/components/BucketList.tsx | 1 + ui/src/organizations/components/BucketRow.tsx | 14 +- ui/src/organizations/components/Buckets.tsx | 1 + .../components/CollectorList.tsx | 4 +- .../organizations/components/CollectorRow.tsx | 14 +- .../organizations/components/Collectors.tsx | 6 + .../components/DashboardList.tsx | 4 +- .../organizations/components/DashboardRow.tsx | 13 +- .../organizations/components/Dashboards.tsx | 10 +- .../organizations/components/ScraperList.tsx | 4 +- .../organizations/components/ScraperRow.tsx | 14 +- ui/src/organizations/components/Scrapers.tsx | 6 + ui/src/organizations/components/TaskList.tsx | 10 +- ui/src/organizations/components/TaskRow.tsx | 16 +- ui/src/organizations/components/Tasks.tsx | 6 + ui/src/shared/components/EditableName.scss | 86 +++++++++++ ui/src/shared/components/EditableName.tsx | 139 ++++++++++++++++++ 17 files changed, 330 insertions(+), 18 deletions(-) create mode 100644 ui/src/shared/components/EditableName.scss create mode 100644 ui/src/shared/components/EditableName.tsx diff --git a/ui/src/organizations/components/BucketList.tsx b/ui/src/organizations/components/BucketList.tsx index 5fa311d3cb..1a88626984 100644 --- a/ui/src/organizations/components/BucketList.tsx +++ b/ui/src/organizations/components/BucketList.tsx @@ -83,6 +83,7 @@ class BucketList extends PureComponent { onEditBucket={this.handleStartEdit} onDeleteBucket={onDeleteBucket} onAddData={this.handleStartAddData} + onUpdateBucket={this.handleUpdateBucket} /> ))} diff --git a/ui/src/organizations/components/BucketRow.tsx b/ui/src/organizations/components/BucketRow.tsx index 571efff3fe..69ac4976c0 100644 --- a/ui/src/organizations/components/BucketRow.tsx +++ b/ui/src/organizations/components/BucketRow.tsx @@ -15,6 +15,7 @@ import { // Types import {Bucket} from 'src/api' import {DataLoaderType} from 'src/types/v2/dataLoaders' +import EditableName from 'src/shared/components/EditableName' export interface PrettyBucket extends Bucket { ruleString: string @@ -25,6 +26,7 @@ interface Props { onEditBucket: (b: PrettyBucket) => void onDeleteBucket: (b: PrettyBucket) => void onAddData: (b: PrettyBucket, d: DataLoaderType) => void + onUpdateBucket: (b: PrettyBucket) => void } export default class BucketRow extends PureComponent { @@ -34,9 +36,11 @@ export default class BucketRow extends PureComponent { <> - - {bucket.name} - + {bucket.ruleString} @@ -78,6 +82,10 @@ export default class BucketRow extends PureComponent { ) } + private handleUpdateBucketName = (value: string) => { + this.props.onUpdateBucket({...this.props.bucket, name: value}) + } + private handleEditBucket = (): void => { this.props.onEditBucket(this.props.bucket) } diff --git a/ui/src/organizations/components/Buckets.tsx b/ui/src/organizations/components/Buckets.tsx index 7c431b424a..1ac34aa829 100644 --- a/ui/src/organizations/components/Buckets.tsx +++ b/ui/src/organizations/components/Buckets.tsx @@ -112,6 +112,7 @@ export default class Buckets extends PureComponent { await client.buckets.update(updatedBucket.id, updatedBucket) this.props.onChange() } + private handleDeleteBucket = async (deletedBucket: PrettyBucket) => { const {onChange, notify} = this.props await client.buckets.delete(deletedBucket.id) diff --git a/ui/src/organizations/components/CollectorList.tsx b/ui/src/organizations/components/CollectorList.tsx index 28ee12aaf9..39da1f7544 100644 --- a/ui/src/organizations/components/CollectorList.tsx +++ b/ui/src/organizations/components/CollectorList.tsx @@ -15,6 +15,7 @@ interface Props { emptyState: JSX.Element onDownloadConfig: (telegrafID: string, telegrafName: string) => void onDelete: (telegrafID: string) => void + onUpdate: (telegraf: Telegraf) => void } export default class CollectorList extends PureComponent { @@ -37,7 +38,7 @@ export default class CollectorList extends PureComponent { } public get collectorsList(): JSX.Element[] { - const {collectors, onDownloadConfig, onDelete} = this.props + const {collectors, onDownloadConfig, onDelete, onUpdate} = this.props if (collectors !== undefined) { return collectors.map(collector => ( @@ -47,6 +48,7 @@ export default class CollectorList extends PureComponent { bucket={getDeep(collector, 'plugins.0.config.bucket', '')} onDownloadConfig={onDownloadConfig} onDelete={onDelete} + onUpdate={onUpdate} /> )) } diff --git a/ui/src/organizations/components/CollectorRow.tsx b/ui/src/organizations/components/CollectorRow.tsx index 956d47a271..b781221ea5 100644 --- a/ui/src/organizations/components/CollectorRow.tsx +++ b/ui/src/organizations/components/CollectorRow.tsx @@ -12,12 +12,14 @@ import { ComponentSpacer, } from 'src/clockface' import {Telegraf} from 'src/api' +import EditableName from 'src/shared/components/EditableName' interface Props { collector: Telegraf bucket: string onDownloadConfig: (telegrafID: string, telegrafName: string) => void onDelete: (telegrafID: string) => void + onUpdate: (telegraf: Telegraf) => void } export default class CollectorRow extends PureComponent { @@ -26,7 +28,12 @@ export default class CollectorRow extends PureComponent { return ( <> - {collector.name} + + + {bucket} @@ -49,6 +56,11 @@ export default class CollectorRow extends PureComponent { ) } + private handleUpdateConfig = (name: string) => { + const {onUpdate, collector} = this.props + onUpdate({...collector, name}) + } + private handleDownloadConfig = (): void => { this.props.onDownloadConfig( this.props.collector.id, diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index 12f60a7794..c19b714fa7 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -104,6 +104,7 @@ export class Collectors extends PureComponent { emptyState={this.emptyState} onDownloadConfig={this.handleDownloadConfig} onDelete={this.handleDeleteTelegraf} + onUpdate={this.handleUpdateTelegraf} /> )} @@ -198,6 +199,11 @@ export class Collectors extends PureComponent { this.props.onChange() } + private handleUpdateTelegraf = async (telegraf: Telegraf) => { + await client.telegrafConfigs.update(telegraf.id, telegraf) + this.props.onChange() + } + private handleFilterChange = (e: ChangeEvent): void => { this.setState({searchTerm: e.target.value}) } diff --git a/ui/src/organizations/components/DashboardList.tsx b/ui/src/organizations/components/DashboardList.tsx index d8b2ff41c2..6921eed24a 100644 --- a/ui/src/organizations/components/DashboardList.tsx +++ b/ui/src/organizations/components/DashboardList.tsx @@ -33,6 +33,7 @@ interface OwnProps { dashboards: Dashboard[] emptyState: JSX.Element onDeleteDashboard: (dashboard: Dashboard) => void + onUpdateDashboard: (dashboard: Dashboard) => void } type Props = DispatchProps & OwnProps @@ -73,13 +74,14 @@ class DashboardList extends PureComponent { } private get rows(): JSX.Element[] { - const {onDeleteDashboard} = this.props + const {onDeleteDashboard, onUpdateDashboard} = this.props return this.props.dashboards.map(d => ( )) diff --git a/ui/src/organizations/components/DashboardRow.tsx b/ui/src/organizations/components/DashboardRow.tsx index a623354aa9..54aa42541e 100644 --- a/ui/src/organizations/components/DashboardRow.tsx +++ b/ui/src/organizations/components/DashboardRow.tsx @@ -1,6 +1,5 @@ // Libraries import React, {PureComponent} from 'react' -import {Link} from 'react-router' import moment from 'moment' // Components @@ -21,10 +20,12 @@ import {Dashboard} from 'src/types/v2' // Constants import {UPDATED_AT_TIME_FORMAT} from 'src/dashboards/constants' +import EditableName from 'src/shared/components/EditableName' interface Props { dashboard: Dashboard onDeleteDashboard: (dashboard: Dashboard) => void + onUpdateDashboard: (dashboard: Dashboard) => void onCloneDashboard: (dashboard: Dashboard) => void } @@ -35,7 +36,11 @@ export default class DashboardRow extends PureComponent { return ( - {dashboard.name} + {this.lastModifiedCell} @@ -61,6 +66,10 @@ export default class DashboardRow extends PureComponent { ) } + private handleUpdateDashboard = (name: string) => { + this.props.onUpdateDashboard({...this.props.dashboard, name}) + } + private handleCloneDashboard = (): void => { const {dashboard, onCloneDashboard} = this.props diff --git a/ui/src/organizations/components/Dashboards.tsx b/ui/src/organizations/components/Dashboards.tsx index 84eaaa11dd..65925c4b33 100644 --- a/ui/src/organizations/components/Dashboards.tsx +++ b/ui/src/organizations/components/Dashboards.tsx @@ -3,9 +3,6 @@ import React, {PureComponent, ChangeEvent} from 'react' import {withRouter, WithRouterProps} from 'react-router' import _ from 'lodash' -// APIs -import {deleteDashboard} from 'src/dashboards/apis' - // Components import TabbedPageHeader from 'src/shared/components/tabbed_page/TabbedPageHeader' import {ComponentSize, EmptyState, Input, IconFont} from 'src/clockface' @@ -17,6 +14,7 @@ import {Dashboard} from 'src/types/v2' // Decorators import {ErrorHandling} from 'src/shared/decorators/errors' +import {deleteDashboard, updateDashboard} from 'src/dashboards/apis/v2' interface OwnProps { dashboards: Dashboard[] @@ -66,6 +64,7 @@ class Dashboards extends PureComponent { dashboards={ds} emptyState={this.emptyState} onDeleteDashboard={this.handleDeleteDashboard} + onUpdateDashboard={this.handleUpdateDashboard} orgID={orgID} router={router} /> @@ -75,6 +74,11 @@ class Dashboards extends PureComponent { ) } + private handleUpdateDashboard = async (dashboard: Dashboard) => { + await updateDashboard(dashboard) + this.props.onChange() + } + private handleFilterChange = (e: ChangeEvent): void => { this.setState({searchTerm: e.target.value}) } diff --git a/ui/src/organizations/components/ScraperList.tsx b/ui/src/organizations/components/ScraperList.tsx index 4c1f8c97c9..8ab4b82cb1 100644 --- a/ui/src/organizations/components/ScraperList.tsx +++ b/ui/src/organizations/components/ScraperList.tsx @@ -12,6 +12,7 @@ interface Props { scrapers: ScraperTargetResponse[] emptyState: JSX.Element onDeleteScraper: (scraper) => void + onUpdateScraper: (scraper: ScraperTargetResponse) => void } export default class ScraperList extends PureComponent { @@ -34,7 +35,7 @@ export default class ScraperList extends PureComponent { } public get scrapersList(): JSX.Element[] { - const {scrapers, onDeleteScraper} = this.props + const {scrapers, onDeleteScraper, onUpdateScraper} = this.props if (scrapers !== undefined) { return scrapers.map(scraper => ( @@ -42,6 +43,7 @@ export default class ScraperList extends PureComponent { key={scraper.id} scraper={scraper} onDeleteScraper={onDeleteScraper} + onUpdateScraper={onUpdateScraper} /> )) } diff --git a/ui/src/organizations/components/ScraperRow.tsx b/ui/src/organizations/components/ScraperRow.tsx index 2b0b932d59..10c02c2408 100644 --- a/ui/src/organizations/components/ScraperRow.tsx +++ b/ui/src/organizations/components/ScraperRow.tsx @@ -9,10 +9,12 @@ import { Alignment, } from 'src/clockface' import {ScraperTargetResponse} from 'src/api' +import EditableName from 'src/shared/components/EditableName' interface Props { scraper: ScraperTargetResponse onDeleteScraper: (scraper) => void + onUpdateScraper: (scraper: ScraperTargetResponse) => void } export default class ScraperRow extends PureComponent { @@ -21,7 +23,12 @@ export default class ScraperRow extends PureComponent { return ( <> - {scraper.url} + + + {scraper.bucket} { ) } + + private handleUpdateScraper = (name: string) => { + const {onUpdateScraper, scraper} = this.props + onUpdateScraper({...scraper, url: name}) + } } diff --git a/ui/src/organizations/components/Scrapers.tsx b/ui/src/organizations/components/Scrapers.tsx index 80127b39c6..effb8226e3 100644 --- a/ui/src/organizations/components/Scrapers.tsx +++ b/ui/src/organizations/components/Scrapers.tsx @@ -71,6 +71,7 @@ export default class Scrapers extends PureComponent { scrapers={this.configurations} emptyState={this.emptyState} onDeleteScraper={this.handleDeleteScraper} + onUpdateScraper={this.handleUpdateScraper} /> { ) } + private handleUpdateScraper = async (scraper: ScraperTargetResponse) => { + await client.scrapers.update(scraper.id, scraper) + this.props.onChange() + } + private handleDeleteScraper = async (scraper: ScraperTargetResponse) => { await client.scrapers.delete(scraper.id) this.props.onChange() diff --git a/ui/src/organizations/components/TaskList.tsx b/ui/src/organizations/components/TaskList.tsx index 3390e6b81e..b1e4dc907a 100644 --- a/ui/src/organizations/components/TaskList.tsx +++ b/ui/src/organizations/components/TaskList.tsx @@ -12,6 +12,7 @@ interface Props { tasks: Task[] emptyState: JSX.Element onDelete: (taskID: string) => void + onUpdate: (task: Task) => void } export default class TaskList extends PureComponent { @@ -31,9 +32,14 @@ export default class TaskList extends PureComponent { } private get rows(): JSX.Element[] { - const {tasks, onDelete} = this.props + const {tasks, onDelete, onUpdate} = this.props return tasks.map(task => ( - + )) } } diff --git a/ui/src/organizations/components/TaskRow.tsx b/ui/src/organizations/components/TaskRow.tsx index 03f6feb399..2e0241caa5 100644 --- a/ui/src/organizations/components/TaskRow.tsx +++ b/ui/src/organizations/components/TaskRow.tsx @@ -1,6 +1,5 @@ // Libraries import React, {PureComponent} from 'react' -import {Link} from 'react-router' // Components import { @@ -12,10 +11,12 @@ import { // Api import {Task} from 'src/api' +import EditableName from 'src/shared/components/EditableName' interface Props { task: Task onDelete: (taskID: string) => void + onUpdate: (task: Task) => void } export default class TaskRow extends PureComponent { @@ -26,9 +27,13 @@ export default class TaskRow extends PureComponent { <> - {task.name} + - {task.owner.name} + {task.name} { ) } + private handleUpdateTask = (name: string) => { + const {onUpdate, task} = this.props + onUpdate({...task, name}) + } + private handleDeleteTask = (): void => { this.props.onDelete(this.props.task.id) } diff --git a/ui/src/organizations/components/Tasks.tsx b/ui/src/organizations/components/Tasks.tsx index bca0a922e1..64f1e331e0 100644 --- a/ui/src/organizations/components/Tasks.tsx +++ b/ui/src/organizations/components/Tasks.tsx @@ -57,6 +57,7 @@ export default class Tasks extends PureComponent { tasks={ts} emptyState={this.emptyState} onDelete={this.handleDeleteTask} + onUpdate={this.handleUpdateTask} /> )} @@ -94,6 +95,11 @@ export default class Tasks extends PureComponent { ) } + private handleUpdateTask = async (task: Task) => { + await client.tasks.update(task.id, task) + this.props.onChange() + } + private handleDeleteTask = async (taskID: string) => { await client.tasks.delete(taskID) this.props.onChange() diff --git a/ui/src/shared/components/EditableName.scss b/ui/src/shared/components/EditableName.scss new file mode 100644 index 0000000000..5530883f17 --- /dev/null +++ b/ui/src/shared/components/EditableName.scss @@ -0,0 +1,86 @@ +/* + Editable Name Component Styles + ------------------------------------------------------------------------------ +*/ + +@import 'src/style/modules'; + +$rename-dash-title-padding: 5px; + +.editable-name { + height: $form-xs-height; + width: 100%; + margin-top: -3px; +} + +.editable-name--preview, +.input.editable-name--input > input { + font-size: $form-xs-font; + font-weight: 400; + font-family: $ix-text-font; + padding: 0 $rename-dash-title-padding; +} + +.editable-name--preview, +.editable-name--input { + position: relative; + width: 100%; +} + +.editable-name--preview { + display: inline-flex; + justify-content: flex-start; + align-items: center; + border-radius: $radius; + position: relative; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + @include no-user-select(); + color: $g13-mist; + transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease; + border: $ix-border solid transparent; + height: $form-xs-height; + line-height: $form-xs-height - ($ix-border * 2); + + .icon { + position: relative; + display: inline-block; + margin-left: $ix-marg-b; + opacity: 0; + transition: opacity 0.25s ease; + color: $g11-sidewalk; + } + + &:hover .icon { + opacity: 1; + } + + &.untitled { + color: $g9-mountain; + font-style: italic; + } + + &:hover { + cursor: text; + color: $g20-white; + // background-color: $g3-castle; + // border-color: $g3-castle; + } +} + +/* Ensure placeholder text matches font weight of title */ +.input.editable-name--input > input { + &::-webkit-input-placeholder { + font-weight: $page-title-weight !important; + } + &::-moz-placeholder { + font-weight: $page-title-weight !important; + } + &:-ms-input-placeholder { + font-weight: $page-title-weight !important; + } + &:-moz-placeholder { + font-weight: $page-title-weight !important; + } +} diff --git a/ui/src/shared/components/EditableName.tsx b/ui/src/shared/components/EditableName.tsx new file mode 100644 index 0000000000..078f3d4e15 --- /dev/null +++ b/ui/src/shared/components/EditableName.tsx @@ -0,0 +1,139 @@ +// Libraries +import React, {Component, KeyboardEvent, ChangeEvent} from 'react' +import classnames from 'classnames' + +// Components +import {Input, ComponentSize} from 'src/clockface' +import {ClickOutside} from 'src/shared/components/ClickOutside' + +// Decorators +import {ErrorHandling} from 'src/shared/decorators/errors' + +// Styles +import 'src/shared/components/EditableName.scss' + +interface Props { + onUpdate: (name: string) => void + name: string + onEditName: () => void + hrefValue?: string + placeholder?: string +} + +interface State { + isEditing: boolean + workingName: string +} + +@ErrorHandling +class EditableName extends Component { + public static defaultProps: Partial = { + hrefValue: '#', + } + constructor(props: Props) { + super(props) + + this.state = { + isEditing: false, + workingName: props.name, + } + } + + public render() { + const {name, onEditName, hrefValue} = this.props + const {isEditing} = this.state + + if (isEditing) { + return ( +
+ + {this.input} + +
+ ) + } + + return ( + <> +
+ {name || 'No name'} + +
+
+ +
+
+ + ) + } + + private get input(): JSX.Element { + const {placeholder} = this.props + const {workingName} = this.state + + return ( + + ) + } + + private handleStartEditing = (): void => { + this.setState({isEditing: true}) + } + + private handleStopEditing = async (): Promise => { + const {workingName} = this.state + const {onUpdate} = this.props + + await onUpdate(workingName) + + this.setState({isEditing: false}) + } + + private handleInputChange = (e: ChangeEvent): void => { + this.setState({workingName: e.target.value}) + } + + private handleKeyDown = async ( + e: KeyboardEvent + ): Promise => { + const {onUpdate, name} = this.props + const {workingName} = this.state + + if (e.key === 'Enter') { + await onUpdate(workingName) + this.setState({isEditing: false}) + } + + if (e.key === 'Escape') { + this.setState({isEditing: false, workingName: name}) + } + } + + private handleInputFocus = (e: ChangeEvent): void => { + e.currentTarget.select() + } + + private get previewClassName(): string { + const {name} = this.props + + return classnames('editable-name--preview', { + untitled: name === '', + }) + } +} + +export default EditableName From 8335b4234db76e9336208868319848e7b881be3e Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Mon, 4 Feb 2019 15:35:28 -0800 Subject: [PATCH 36/95] refactor(ui/dataLoaders): Move Line Protocol wizard into a separate wizard --- .../components/DataLoaderSwitcher.test.tsx | 12 ++ .../components/DataLoaderSwitcher.tsx | 11 +- .../dataLoaders/components/StepSwitcher.tsx | 9 - .../ConfigureDataSourceSwitcher.tsx | 9 +- .../__snapshots__/LineProtocol.test.tsx.snap | 53 ------ .../lineProtocolWizard/LineProtocolWizard.tsx | 165 ++++++++++++++++++ .../configure}/LineProtocol.test.tsx | 7 +- .../configure}/LineProtocol.tsx | 49 +++--- .../configure}/LineProtocolTabs.test.tsx | 2 +- .../configure}/LineProtocolTabs.tsx | 6 +- .../configure}/PrecisionDropdown.tsx | 0 .../configure}/Tab.tsx | 0 .../configure}/TabBody.tsx | 0 .../configure}/TabSelector.tsx | 2 +- .../__snapshots__/LineProtocol.test.tsx.snap | 57 ++++++ .../LineProtocolTabs.test.tsx.snap | 0 .../verify/LineProtocolStepSwitcher.tsx | 36 ++++ .../verify/LineProtocolVerifyStep.tsx | 42 +++++ .../verify}/StatusIndicator.test.tsx | 2 +- .../verify}/StatusIndicator.tsx | 22 ++- .../StatusIndicator.test.tsx.snap | 0 .../verifyStep/VerifyDataStep.test.tsx | 51 ------ .../components/verifyStep/VerifyDataStep.tsx | 78 --------- .../verifyStep/VerifyDataSwitcher.test.tsx | 47 ----- .../verifyStep/VerifyDataSwitcher.tsx | 41 ----- .../VerifyDataSwitcher.test.tsx.snap | 3 - ui/src/types/v2/dataLoaders.ts | 6 +- 27 files changed, 384 insertions(+), 326 deletions(-) delete mode 100644 ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocol.test.tsx.snap create mode 100644 ui/src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard.tsx rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/LineProtocol.test.tsx (72%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/LineProtocol.tsx (66%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/LineProtocolTabs.test.tsx (86%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/LineProtocolTabs.tsx (92%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/PrecisionDropdown.tsx (100%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/Tab.tsx (100%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/TabBody.tsx (100%) rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/TabSelector.tsx (91%) create mode 100644 ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocol.test.tsx.snap rename ui/src/dataLoaders/components/{configureStep/lineProtocol => lineProtocolWizard/configure}/__snapshots__/LineProtocolTabs.test.tsx.snap (100%) create mode 100644 ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolStepSwitcher.tsx create mode 100644 ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolVerifyStep.tsx rename ui/src/dataLoaders/components/{verifyStep/lineProtocol => lineProtocolWizard/verify}/StatusIndicator.test.tsx (84%) rename ui/src/dataLoaders/components/{verifyStep/lineProtocol => lineProtocolWizard/verify}/StatusIndicator.tsx (76%) rename ui/src/dataLoaders/components/{verifyStep/lineProtocol => lineProtocolWizard/verify}/__snapshots__/StatusIndicator.test.tsx.snap (100%) delete mode 100644 ui/src/dataLoaders/components/verifyStep/VerifyDataStep.test.tsx delete mode 100644 ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx delete mode 100644 ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.test.tsx delete mode 100644 ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx delete mode 100644 ui/src/dataLoaders/components/verifyStep/__snapshots__/VerifyDataSwitcher.test.tsx.snap diff --git a/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx b/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx index eeb2af52bb..22df769255 100644 --- a/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx +++ b/ui/src/dataLoaders/components/DataLoaderSwitcher.test.tsx @@ -6,6 +6,7 @@ import {shallow} from 'enzyme' import DataLoaderSwitcher from 'src/dataLoaders/components/DataLoaderSwitcher' import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' +import LineProtocolWizard from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard' // Types import {DataLoaderType} from 'src/types/v2/dataLoaders' @@ -44,4 +45,15 @@ describe('DataLoading.Components.DataLoaderSwitcher', () => { expect(wizard.exists()).toBe(true) }) }) + + describe('if type is line protocol', () => { + it('renders line protocol wizard', () => { + const {wrapper} = setup({type: DataLoaderType.LineProtocol}) + + const wizard = wrapper.find(LineProtocolWizard) + + expect(wrapper.exists()).toBe(true) + expect(wizard.exists()).toBe(true) + }) + }) }) diff --git a/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx b/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx index 9e92cfc171..ef50218fa2 100644 --- a/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx +++ b/ui/src/dataLoaders/components/DataLoaderSwitcher.tsx @@ -5,6 +5,7 @@ import _ from 'lodash' // Components import DataLoadersWizard from 'src/dataLoaders/components/DataLoadersWizard' import CollectorsWizard from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' +import LineProtocolWizard from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard' // Types import {Substep, DataLoaderType} from 'src/types/v2/dataLoaders' @@ -33,7 +34,6 @@ class DataLoaderSwitcher extends PureComponent { } = this.props switch (type) { - case DataLoaderType.LineProtocol: case DataLoaderType.Scraping: case DataLoaderType.Empty: return ( @@ -51,7 +51,14 @@ class DataLoaderSwitcher extends PureComponent { + ) + case DataLoaderType.LineProtocol: + return ( + ) diff --git a/ui/src/dataLoaders/components/StepSwitcher.tsx b/ui/src/dataLoaders/components/StepSwitcher.tsx index 93a231b3d7..810b0a2687 100644 --- a/ui/src/dataLoaders/components/StepSwitcher.tsx +++ b/ui/src/dataLoaders/components/StepSwitcher.tsx @@ -4,7 +4,6 @@ import _ from 'lodash' // Components import ConfigureDataSourceStep from 'src/dataLoaders/components/configureStep/ConfigureDataSourceStep' -import VerifyDataStep from 'src/dataLoaders/components/verifyStep/VerifyDataStep' import {ErrorHandling} from 'src/shared/decorators/errors' // Actions @@ -48,14 +47,6 @@ class StepSwitcher extends PureComponent { type={type} /> ) - case DataLoaderStep.Verify: - return ( - - ) default: return
} diff --git a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx index 7eafb7f814..dc48e7d7d8 100644 --- a/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx +++ b/ui/src/dataLoaders/components/configureStep/ConfigureDataSourceSwitcher.tsx @@ -4,7 +4,6 @@ import _ from 'lodash' // Components import {ErrorHandling} from 'src/shared/decorators/errors' -import LineProtocol from 'src/dataLoaders/components/configureStep/lineProtocol/LineProtocol' import EmptyDataSourceState from 'src/dataLoaders/components/configureStep/EmptyDataSourceState' import Scraping from 'src/dataLoaders/components/configureStep/Scraping' @@ -23,15 +22,9 @@ export interface Props { @ErrorHandling class ConfigureDataSourceSwitcher extends PureComponent { public render() { - const {bucket, org, dataLoaderType, onClickNext, buckets} = this.props + const {dataLoaderType, onClickNext, buckets} = this.props switch (dataLoaderType) { - case DataLoaderType.LineProtocol: - return ( -
- -
- ) case DataLoaderType.Scraping: return (
diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocol.test.tsx.snap b/ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocol.test.tsx.snap deleted file mode 100644 index 4c0ec59634..0000000000 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocol.test.tsx.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`LineProtocol rendering renders! 1`] = ` -
-
- -
-

- Add Data via Line Protocol -

-
- Need help writing InfluxDB Line Protocol? See Documentation -
- -
-
-
- - -`; diff --git a/ui/src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard.tsx new file mode 100644 index 0000000000..e7bf4f9490 --- /dev/null +++ b/ui/src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard.tsx @@ -0,0 +1,165 @@ +// Libraries +import React, {PureComponent} from 'react' +import {connect} from 'react-redux' +import _ from 'lodash' + +// Components +import {ErrorHandling} from 'src/shared/decorators/errors' +import WizardOverlay from 'src/clockface/components/wizard/WizardOverlay' +import LineProtocolStepSwitcher from 'src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolStepSwitcher' + +// Actions +import {notify as notifyAction} from 'src/shared/actions/notifications' +import { + setBucketInfo, + incrementCurrentStepIndex, + decrementCurrentStepIndex, + setCurrentStepIndex, + clearSteps, +} from 'src/dataLoaders/actions/steps' + +import {clearDataLoaders} from 'src/dataLoaders/actions/dataLoaders' + +// Types +import {Notification, NotificationFunc} from 'src/types' +import {AppState} from 'src/types/v2' +import {Bucket} from 'src/api' + +export interface LineProtocolStepProps { + currentStepIndex: number + onIncrementCurrentStepIndex: () => void + onDecrementCurrentStepIndex: () => void + notify: (message: Notification | NotificationFunc) => void + onExit: () => void +} + +interface OwnProps { + onCompleteSetup: () => void + visible: boolean + buckets: Bucket[] + startingStep?: number +} + +interface DispatchProps { + notify: (message: Notification | NotificationFunc) => void + onSetBucketInfo: typeof setBucketInfo + onIncrementCurrentStepIndex: typeof incrementCurrentStepIndex + onDecrementCurrentStepIndex: typeof decrementCurrentStepIndex + onSetCurrentStepIndex: typeof setCurrentStepIndex + onClearDataLoaders: typeof clearDataLoaders + onClearSteps: typeof clearSteps +} + +interface StateProps { + currentStepIndex: number + username: string + bucket: string +} + +type Props = OwnProps & StateProps & DispatchProps + +@ErrorHandling +class CollectorsWizard extends PureComponent { + public componentDidMount() { + this.handleSetBucketInfo() + this.handleSetStartingValues() + } + + public componentDidUpdate(prevProps: Props) { + const hasBecomeVisible = !prevProps.visible && this.props.visible + + if (hasBecomeVisible) { + this.handleSetBucketInfo() + this.handleSetStartingValues() + } + } + + public render() { + const {visible, buckets} = this.props + + return ( + +
+
+ +
+
+
+ ) + } + + private handleSetBucketInfo = () => { + const {bucket, buckets} = this.props + if (!bucket && (buckets && buckets.length)) { + const {organization, organizationID, name, id} = buckets[0] + + this.props.onSetBucketInfo(organization, organizationID, name, id) + } + } + + private handleSetStartingValues = () => { + const {startingStep} = this.props + + const hasStartingStep = startingStep || startingStep === 0 + + if (hasStartingStep) { + this.props.onSetCurrentStepIndex(startingStep) + } + } + + private handleDismiss = () => { + this.props.onCompleteSetup() + this.props.onClearDataLoaders() + this.props.onClearSteps() + } + + private get stepProps(): LineProtocolStepProps { + const { + notify, + currentStepIndex, + onDecrementCurrentStepIndex, + onIncrementCurrentStepIndex, + } = this.props + + return { + currentStepIndex, + onIncrementCurrentStepIndex, + onDecrementCurrentStepIndex, + notify, + onExit: this.handleDismiss, + } + } +} + +const mstp = ({ + dataLoading: { + steps: {currentStep, bucket}, + }, + me: {name}, +}: AppState): StateProps => ({ + currentStepIndex: currentStep, + username: name, + bucket, +}) + +const mdtp: DispatchProps = { + notify: notifyAction, + onSetBucketInfo: setBucketInfo, + onIncrementCurrentStepIndex: incrementCurrentStepIndex, + onDecrementCurrentStepIndex: decrementCurrentStepIndex, + onSetCurrentStepIndex: setCurrentStepIndex, + onClearDataLoaders: clearDataLoaders, + onClearSteps: clearSteps, +} + +export default connect( + mstp, + mdtp +)(CollectorsWizard) diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.test.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.test.tsx similarity index 72% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.test.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.test.tsx index af7cb603b5..a8c9b27265 100644 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.test.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import {shallow} from 'enzyme' // Components -import {LineProtocol} from 'src/dataLoaders/components/configureStep/lineProtocol/LineProtocol' +import {LineProtocol} from 'src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol' import {WritePrecision} from 'src/api' const setup = (override = {}) => { @@ -15,6 +15,11 @@ const setup = (override = {}) => { precision: WritePrecision.Ns, setLPStatus: jest.fn(), writeLineProtocolAction: jest.fn(), + currentStepIndex: 0, + onIncrementCurrentStepIndex: jest.fn(), + onDecrementCurrentStepIndex: jest.fn(), + notify: jest.fn(), + onExit: jest.fn(), ...override, } const wrapper = shallow() diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.tsx similarity index 66% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.tsx index c5958e82b3..6771617413 100644 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocol.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol.tsx @@ -5,7 +5,7 @@ import {connect} from 'react-redux' import _ from 'lodash' // Components -import LineProtocolTabs from 'src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs' +import LineProtocolTabs from 'src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs' import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' import {Form} from 'src/clockface' import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' @@ -24,16 +24,15 @@ import {LineProtocolTab} from 'src/types/v2/dataLoaders' import {AppState} from 'src/types/v2/index' import {WritePrecision} from 'src/api' import {RemoteDataState} from 'src/types' +import {LineProtocolStepProps} from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard' -interface OwnProps { - bucket: string - org: string - onClickNext: () => void -} +type OwnProps = LineProtocolStepProps interface StateProps { lineProtocolBody: string precision: WritePrecision + bucket: string + org: string } interface DispatchProps { @@ -52,20 +51,24 @@ export class LineProtocol extends PureComponent { public render() { return ( -
-
- -
-

Add Data via Line Protocol

-
- Need help writing InfluxDB Line Protocol? See Documentation -
- {this.content} -
-
-
- - +
+
+
+ +
+

+ Add Data via Line Protocol +

+
+ Need help writing InfluxDB Line Protocol? See Documentation +
+ {this.content} +
+
+
+ + +
) } @@ -92,19 +95,21 @@ export class LineProtocol extends PureComponent { writeLineProtocolAction, lineProtocolBody, precision, + onIncrementCurrentStepIndex, } = this.props writeLineProtocolAction(org, bucket, lineProtocolBody, precision) - this.props.onClickNext() + onIncrementCurrentStepIndex() } } const mstp = ({ dataLoading: { dataLoaders: {lineProtocolBody, precision}, + steps: {bucket, org}, }, }: AppState): StateProps => { - return {lineProtocolBody, precision} + return {lineProtocolBody, precision, bucket, org} } const mdtp: DispatchProps = { diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.test.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.test.tsx similarity index 86% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.test.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.test.tsx index 30e581a757..7d2ae2bb59 100644 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.test.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import {shallow} from 'enzyme' // Components -import {LineProtocolTabs} from 'src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs' +import {LineProtocolTabs} from 'src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs' import {LineProtocolTab} from 'src/types/v2/dataLoaders' diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.tsx similarity index 92% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.tsx index ed57474cf0..3be64e18b6 100644 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/LineProtocolTabs.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/LineProtocolTabs.tsx @@ -3,9 +3,9 @@ import React, {PureComponent} from 'react' import {connect} from 'react-redux' import _ from 'lodash' -import PrecisionDropdown from 'src/dataLoaders/components/configureStep/lineProtocol/PrecisionDropdown' -import TabSelector from 'src/dataLoaders/components/configureStep/lineProtocol/TabSelector' -import TabBody from 'src/dataLoaders/components/configureStep/lineProtocol/TabBody' +import PrecisionDropdown from 'src/dataLoaders/components/lineProtocolWizard/configure/PrecisionDropdown' +import TabSelector from 'src/dataLoaders/components/lineProtocolWizard/configure/TabSelector' +import TabBody from 'src/dataLoaders/components/lineProtocolWizard/configure/TabBody' // Types import {LineProtocolTab} from 'src/types/v2/dataLoaders' diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/PrecisionDropdown.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/PrecisionDropdown.tsx similarity index 100% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/PrecisionDropdown.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/PrecisionDropdown.tsx diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/Tab.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/Tab.tsx similarity index 100% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/Tab.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/Tab.tsx diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/TabBody.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/TabBody.tsx similarity index 100% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/TabBody.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/TabBody.tsx diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/TabSelector.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/configure/TabSelector.tsx similarity index 91% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/TabSelector.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/TabSelector.tsx index 0fae15057e..abfa747587 100644 --- a/ui/src/dataLoaders/components/configureStep/lineProtocol/TabSelector.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/TabSelector.tsx @@ -3,7 +3,7 @@ import React, {PureComponent} from 'react' import {Radio, ButtonShape} from 'src/clockface' import {LineProtocolTab} from 'src/types/v2/dataLoaders' -import Tab from 'src/dataLoaders/components/configureStep/lineProtocol/Tab' +import Tab from 'src/dataLoaders/components/lineProtocolWizard/configure/Tab' interface Props { tabs: LineProtocolTab[] diff --git a/ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocol.test.tsx.snap b/ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocol.test.tsx.snap new file mode 100644 index 0000000000..18d6e48da1 --- /dev/null +++ b/ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocol.test.tsx.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LineProtocol rendering renders! 1`] = ` +
+
+
+ +
+

+ Add Data via Line Protocol +

+
+ Need help writing InfluxDB Line Protocol? See Documentation +
+ +
+
+
+ + +
+`; diff --git a/ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocolTabs.test.tsx.snap b/ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocolTabs.test.tsx.snap similarity index 100% rename from ui/src/dataLoaders/components/configureStep/lineProtocol/__snapshots__/LineProtocolTabs.test.tsx.snap rename to ui/src/dataLoaders/components/lineProtocolWizard/configure/__snapshots__/LineProtocolTabs.test.tsx.snap diff --git a/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolStepSwitcher.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolStepSwitcher.tsx new file mode 100644 index 0000000000..c1daab89ae --- /dev/null +++ b/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolStepSwitcher.tsx @@ -0,0 +1,36 @@ +// Libraries +import React, {PureComponent} from 'react' +import _ from 'lodash' + +// Components +import {ErrorHandling} from 'src/shared/decorators/errors' +import LineProtocol from 'src/dataLoaders/components/lineProtocolWizard/configure/LineProtocol' +import LineProtocolVerifyStep from 'src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolVerifyStep' + +// Types +import {LineProtocolStep} from 'src/types/v2/dataLoaders' +import {LineProtocolStepProps} from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard' +import {Bucket} from 'src/api' + +interface Props { + stepProps: LineProtocolStepProps + buckets: Bucket[] +} + +@ErrorHandling +class StepSwitcher extends PureComponent { + public render() { + const {stepProps} = this.props + + switch (stepProps.currentStepIndex) { + case LineProtocolStep.Configure: + return + case LineProtocolStep.Verify: + return + default: + return
+ } + } +} + +export default StepSwitcher diff --git a/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolVerifyStep.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolVerifyStep.tsx new file mode 100644 index 0000000000..1d47d039bc --- /dev/null +++ b/ui/src/dataLoaders/components/lineProtocolWizard/verify/LineProtocolVerifyStep.tsx @@ -0,0 +1,42 @@ +// Libraries +import React, {PureComponent} from 'react' +import _ from 'lodash' + +// Components +import {ErrorHandling} from 'src/shared/decorators/errors' +import StatusIndicator from 'src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator' +import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' +import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' + +// Types +import {Form} from 'src/clockface' +import {LineProtocolStepProps} from 'src/dataLoaders/components/lineProtocolWizard/LineProtocolWizard' + +type Props = LineProtocolStepProps + +@ErrorHandling +export class VerifyLineProtocolStep extends PureComponent { + public render() { + const {onDecrementCurrentStepIndex, onExit} = this.props + + return ( +
+
+
+ +
+ +
+
+
+ + +
+ ) + } +} + +export default VerifyLineProtocolStep diff --git a/ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.test.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.test.tsx similarity index 84% rename from ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.test.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.test.tsx index 949878c921..382749404e 100644 --- a/ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.test.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import {shallow} from 'enzyme' // Components -import StatusIndicator from 'src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator' +import {StatusIndicator} from 'src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator' // Types import {RemoteDataState} from 'src/types' diff --git a/ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.tsx b/ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.tsx similarity index 76% rename from ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.tsx rename to ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.tsx index 2f2031eed3..755bd44842 100644 --- a/ui/src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator.tsx +++ b/ui/src/dataLoaders/components/lineProtocolWizard/verify/StatusIndicator.tsx @@ -1,18 +1,21 @@ // Libraries import React, {PureComponent} from 'react' import classnames from 'classnames' +import {connect} from 'react-redux' import {SparkleSpinner} from 'src/clockface' // Types import {RemoteDataState} from 'src/types' +import {AppState} from 'src/types/v2' -interface Props { +interface StateProps { status: RemoteDataState - onClickRetry: () => void } -class StatusIndicator extends PureComponent { +type Props = StateProps + +export class StatusIndicator extends PureComponent { public render() { const {status} = this.props return ( @@ -52,4 +55,15 @@ class StatusIndicator extends PureComponent { } } -export default StatusIndicator +const mstp = ({ + dataLoading: { + dataLoaders: {lpStatus}, + }, +}: AppState): StateProps => ({ + status: lpStatus, +}) + +export default connect( + mstp, + null +)(StatusIndicator) diff --git a/ui/src/dataLoaders/components/verifyStep/lineProtocol/__snapshots__/StatusIndicator.test.tsx.snap b/ui/src/dataLoaders/components/lineProtocolWizard/verify/__snapshots__/StatusIndicator.test.tsx.snap similarity index 100% rename from ui/src/dataLoaders/components/verifyStep/lineProtocol/__snapshots__/StatusIndicator.test.tsx.snap rename to ui/src/dataLoaders/components/lineProtocolWizard/verify/__snapshots__/StatusIndicator.test.tsx.snap diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.test.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.test.tsx deleted file mode 100644 index 8781673582..0000000000 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -// Libraries -import React from 'react' -import {shallow} from 'enzyme' - -// Components -import {VerifyDataStep} from 'src/dataLoaders/components/verifyStep/VerifyDataStep' -import VerifyDataSwitcher from 'src/dataLoaders/components/verifyStep/VerifyDataSwitcher' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' - -// Constants -import {defaultOnboardingStepProps} from 'mocks/dummyData' -import {RemoteDataState} from 'src/types' - -jest.mock('src/utils/api', () => require('src/onboarding/apis/mocks')) - -const setup = (override = {}) => { - const props = { - ...defaultOnboardingStepProps, - type: DataLoaderType.Empty, - telegrafPlugins: [], - stepIndex: 2, - substep: 0, - telegrafConfigID: '', - onSaveTelegrafConfig: jest.fn(), - onSetActiveTelegrafPlugin: jest.fn(), - onSetPluginConfiguration: jest.fn(), - lpStatus: RemoteDataState.NotStarted, - bucket: 'defbuck', - username: 'user', - org: '', - notify: jest.fn(), - selectedBucket: '', - ...override, - } - - const wrapper = shallow() - - return {wrapper} -} - -describe('Onboarding.Components.VerifyStep.VerifyDataStep', () => { - it('renders', () => { - const {wrapper} = setup() - const switcher = wrapper.find(VerifyDataSwitcher) - - expect(wrapper.exists()).toBe(true) - expect(switcher.exists()).toBe(true) - }) -}) diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx deleted file mode 100644 index 80c4127ccd..0000000000 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataStep.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' -import {connect} from 'react-redux' -import _ from 'lodash' - -// Components -import {ErrorHandling} from 'src/shared/decorators/errors' -import VerifyDataSwitcher from 'src/dataLoaders/components/verifyStep/VerifyDataSwitcher' -import OnboardingButtons from 'src/onboarding/components/OnboardingButtons' -import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' -import {Form} from 'src/clockface' -import {RemoteDataState} from 'src/types' -import {AppState} from 'src/types/v2' -import {DataLoaderStepProps} from 'src/dataLoaders/components/DataLoadersWizard' - -export interface OwnProps extends DataLoaderStepProps { - type: DataLoaderType - stepIndex: number -} - -interface StateProps { - lpStatus: RemoteDataState -} - -export type Props = OwnProps & StateProps - -@ErrorHandling -export class VerifyDataStep extends PureComponent { - public render() { - const {type, onDecrementCurrentStepIndex, lpStatus} = this.props - - return ( -
-
-
- -
- -
-
-
- - -
- ) - } - - private handleIncrementStep = () => { - const {onExit} = this.props - onExit() - } - - private handleDecrementStep = () => { - const {onDecrementCurrentStepIndex} = this.props - - onDecrementCurrentStepIndex() - } -} - -const mstp = ({ - dataLoading: { - dataLoaders: {lpStatus}, - }, -}: AppState): StateProps => ({ - lpStatus, -}) - -export default connect(mstp)(VerifyDataStep) diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.test.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.test.tsx deleted file mode 100644 index 8736dc527c..0000000000 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Libraries -import React from 'react' -import {shallow} from 'enzyme' - -// Components -import {VerifyDataSwitcher} from 'src/dataLoaders/components/verifyStep/VerifyDataSwitcher' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' -import {RemoteDataState} from 'src/types' - -const setup = (override = {}) => { - const props = { - notify: jest.fn(), - type: DataLoaderType.Empty, - org: '', - username: '', - bucket: '', - authToken: '', - telegrafConfigID: '', - onSaveTelegrafConfig: jest.fn(), - stepIndex: 4, - onDecrementCurrentStep: jest.fn(), - lpStatus: RemoteDataState.NotStarted, - ...override, - } - - const wrapper = shallow() - - return {wrapper} -} - -describe('Onboarding.Components.VerifyStep.VerifyDataSwitcher', () => { - it('renders', () => { - const {wrapper} = setup() - - expect(wrapper.exists()).toBe(true) - }) - - describe('If data type is streaming', () => { - it('renders the DataStreaming component', () => { - const {wrapper} = setup({type: DataLoaderType.Streaming}) - - expect(wrapper).toMatchSnapshot() - }) - }) -}) diff --git a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx b/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx deleted file mode 100644 index ba2beb297a..0000000000 --- a/ui/src/dataLoaders/components/verifyStep/VerifyDataSwitcher.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// Libraries -import React, {PureComponent} from 'react' - -// Components -import {ErrorHandling} from 'src/shared/decorators/errors' - -// Types -import {DataLoaderType} from 'src/types/v2/dataLoaders' -import {RemoteDataState} from 'src/types' -import StatusIndicator from 'src/dataLoaders/components/verifyStep/lineProtocol/StatusIndicator' - -interface Props { - type: DataLoaderType - onDecrementCurrentStep: () => void - lpStatus: RemoteDataState -} - -@ErrorHandling -export class VerifyDataSwitcher extends PureComponent { - public render() { - const {type, lpStatus} = this.props - - switch (type) { - case DataLoaderType.LineProtocol: - return ( - - ) - default: - return
- } - } - - private handleClickRetry = () => { - this.props.onDecrementCurrentStep() - } -} - -export default VerifyDataSwitcher diff --git a/ui/src/dataLoaders/components/verifyStep/__snapshots__/VerifyDataSwitcher.test.tsx.snap b/ui/src/dataLoaders/components/verifyStep/__snapshots__/VerifyDataSwitcher.test.tsx.snap deleted file mode 100644 index 7990daf000..0000000000 --- a/ui/src/dataLoaders/components/verifyStep/__snapshots__/VerifyDataSwitcher.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Onboarding.Components.VerifyStep.VerifyDataSwitcher If data type is streaming renders the DataStreaming component 1`] = `
`; diff --git a/ui/src/types/v2/dataLoaders.ts b/ui/src/types/v2/dataLoaders.ts index 41030bd0f9..845fbd4abb 100644 --- a/ui/src/types/v2/dataLoaders.ts +++ b/ui/src/types/v2/dataLoaders.ts @@ -39,7 +39,6 @@ import {WritePrecision} from 'src/api' export enum DataLoaderStep { 'Configure', - 'Verify', } export enum CollectorsStep { @@ -48,6 +47,11 @@ export enum CollectorsStep { 'Verify', } +export enum LineProtocolStep { + 'Configure', + 'Verify', +} + interface ScraperTarget { bucket: string url: string From 54353fb9640ad4c913f27685e81cfb995b74d90e Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Mon, 4 Feb 2019 17:27:17 -0800 Subject: [PATCH 37/95] refactor(ui/dataLoaders): Update dataLoaders bucket dropdowns to be the same component --- .../components/BucketsDropdown.test.tsx | 50 +++++++++++++ .../components/BucketsDropdown.tsx | 75 +++++++++++++++++++ .../select/StreamingSelector.tsx | 39 ++-------- .../configureStep/ScraperTarget.tsx | 46 +++--------- .../components/configureStep/Scraping.tsx | 27 ++----- .../__snapshots__/Scraper.test.tsx.snap | 27 ++----- 6 files changed, 155 insertions(+), 109 deletions(-) create mode 100644 ui/src/dataLoaders/components/BucketsDropdown.test.tsx create mode 100644 ui/src/dataLoaders/components/BucketsDropdown.tsx diff --git a/ui/src/dataLoaders/components/BucketsDropdown.test.tsx b/ui/src/dataLoaders/components/BucketsDropdown.test.tsx new file mode 100644 index 0000000000..80a856e5b5 --- /dev/null +++ b/ui/src/dataLoaders/components/BucketsDropdown.test.tsx @@ -0,0 +1,50 @@ +// Libraries +import React from 'react' +import {shallow} from 'enzyme' + +// Components +import BucketsDropdown from 'src/dataLoaders/components/BucketsDropdown' +import {Dropdown, ComponentStatus} from 'src/clockface' +import {bucket} from 'mocks/dummyData' + +// Mocks + +const setup = (override = {}) => { + const props = { + selected: '', + buckets: [], + onSelectBucket: jest.fn(), + ...override, + } + + const wrapper = shallow() + + return {wrapper} +} + +describe('DataLoading.Components.BucketsDropdown', () => { + describe('when no buckets', () => { + it('renders disabled dropdown', () => { + const {wrapper} = setup() + + const dropdown = wrapper.find(Dropdown) + + expect(wrapper.exists()).toBe(true) + expect(dropdown.exists()).toBe(true) + expect(dropdown.prop('status')).toBe(ComponentStatus.Disabled) + }) + }) + + describe('if buckets', () => { + it('renders dropdown', () => { + const buckets = [bucket] + const {wrapper} = setup({buckets}) + + const dropdown = wrapper.find(Dropdown) + + expect(wrapper.exists()).toBe(true) + expect(dropdown.exists()).toBe(true) + expect(dropdown.prop('status')).toBe(ComponentStatus.Default) + }) + }) +}) diff --git a/ui/src/dataLoaders/components/BucketsDropdown.tsx b/ui/src/dataLoaders/components/BucketsDropdown.tsx new file mode 100644 index 0000000000..2bdf40b1d3 --- /dev/null +++ b/ui/src/dataLoaders/components/BucketsDropdown.tsx @@ -0,0 +1,75 @@ +// Libraries +import React, {PureComponent} from 'react' + +// Components +import {Dropdown, ComponentStatus} from 'src/clockface' + +// Types +import {Bucket} from 'src/api' + +interface Props { + selected: string + buckets: Bucket[] + onSelectBucket: (bucket: Bucket) => void +} + +class BucketsDropdown extends PureComponent { + public render() { + return ( + + {this.dropdownBuckets} + + ) + } + + private get title(): string { + if (this.isBucketsEmpty) { + return 'No buckets found' + } + + return '' + } + + private get status(): ComponentStatus { + if (this.isBucketsEmpty) { + return ComponentStatus.Disabled + } + + return ComponentStatus.Default + } + + private get selectedID(): string { + return this.props.selected || '' + } + + private get isBucketsEmpty(): boolean { + const {buckets} = this.props + return !buckets || !buckets.length + } + + private get dropdownBuckets(): JSX.Element[] { + const {buckets} = this.props + if (this.isBucketsEmpty) { + return [] + } + + return buckets.map(b => ( + + {b.name} + + )) + } + + private handleSelectBucket = (bucketName: string) => { + const bucket = this.props.buckets.find(b => b.name === bucketName) + + this.props.onSelectBucket(bucket) + } +} + +export default BucketsDropdown diff --git a/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx index 517dd30a79..05b11e4066 100644 --- a/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/select/StreamingSelector.tsx @@ -11,7 +11,6 @@ import { Input, IconFont, ComponentSize, - Dropdown, FormElement, Grid, Columns, @@ -22,6 +21,7 @@ import { PLUGIN_BUNDLE_OPTIONS, BUNDLE_LOGOS, } from 'src/dataLoaders/constants/pluginConfigs' +import BucketDropdown from 'src/dataLoaders/components/BucketsDropdown' // Types import {TelegrafPlugin, BundleName} from 'src/types/v2/dataLoaders' @@ -69,6 +69,7 @@ class StreamingSelector extends PureComponent { } public render() { + const {bucket, buckets} = this.props const {gridSizerUpdateFlag, searchTerm} = this.state return ( @@ -76,12 +77,11 @@ class StreamingSelector extends PureComponent { - - {this.dropdownBuckets} - + @@ -120,33 +120,10 @@ class StreamingSelector extends PureComponent { ) } - private handleSelectBucket = (bucketName: string) => { - const bucket = this.props.buckets.find(b => b.name === bucketName) - + private handleSelectBucket = (bucket: Bucket) => { this.props.onSelectBucket(bucket) } - private get selectedBucketID(): string { - return this.props.bucket || 'empty' - } - - private get dropdownBuckets(): JSX.Element[] { - const {buckets} = this.props - if (!buckets || !buckets.length) { - return [ - - {'No buckets found'} - , - ] - } - - return buckets.map(b => ( - - {b.name} - - )) - } - private get filteredBundles(): BundleName[] { const {searchTerm} = this.state diff --git a/ui/src/dataLoaders/components/configureStep/ScraperTarget.tsx b/ui/src/dataLoaders/components/configureStep/ScraperTarget.tsx index 41d55bae13..aed7fcd007 100644 --- a/ui/src/dataLoaders/components/configureStep/ScraperTarget.tsx +++ b/ui/src/dataLoaders/components/configureStep/ScraperTarget.tsx @@ -8,15 +8,16 @@ import { Columns, Grid, ComponentSize, - Dropdown, InputType, ComponentStatus, } from 'src/clockface' +import BucketDropdown from 'src/dataLoaders/components/BucketsDropdown' +import {Bucket} from 'src/api' interface Props { bucket: string - buckets: string[] - onSelectBucket: (value: string) => void + buckets: Bucket[] + onSelectBucket: (bucket: Bucket) => void onChangeURL: (value: string) => void url: string } @@ -27,18 +28,17 @@ export class ScraperTarget extends PureComponent { } public render() { - const {onSelectBucket, url} = this.props + const {onSelectBucket, url, bucket, buckets} = this.props return ( - - {this.dropdownBuckets} - + @@ -69,32 +69,6 @@ export class ScraperTarget extends PureComponent { return ComponentStatus.Default } - private get selectedBucket(): string { - const {buckets, bucket} = this.props - - if (!buckets || !buckets.length) { - return 'empty' - } - return bucket - } - - private get dropdownBuckets(): JSX.Element[] { - const {buckets} = this.props - if (!buckets || !buckets.length) { - return [ - - {'No buckets found'} - , - ] - } - - return buckets.map(b => ( - - {b} - - )) - } - private get urlEmpty(): boolean { return !this.props.url } diff --git a/ui/src/dataLoaders/components/configureStep/Scraping.tsx b/ui/src/dataLoaders/components/configureStep/Scraping.tsx index 7473b9958d..96380cf40e 100644 --- a/ui/src/dataLoaders/components/configureStep/Scraping.tsx +++ b/ui/src/dataLoaders/components/configureStep/Scraping.tsx @@ -56,7 +56,7 @@ export class Scraping extends PureComponent { } public render() { - const {scraperBucket, onSetScraperTargetURL, url} = this.props + const {scraperBucket, onSetScraperTargetURL, url, buckets} = this.props return (
@@ -70,7 +70,7 @@ export class Scraping extends PureComponent { { ) } - private get buckets(): string[] { - const {buckets} = this.props + private handleSelectBucket = (bucket: Bucket) => { + const {onSetBucketInfo, onSetScraperTargetBucket} = this.props + const {organization, organizationID, id, name} = bucket - return buckets.map(b => b.name) - } - - private handleSelectBucket = (bucket: string) => { - const {buckets, onSetScraperTargetBucket, onSetBucketInfo} = this.props - if (!buckets || !buckets.length) { - return - } - - const findBucket = buckets.find(b => b.name === bucket) - const bucketID = findBucket.id - const org = findBucket.organization - const orgID = findBucket.organizationID - - onSetBucketInfo(org, orgID, bucket, bucketID) - onSetScraperTargetBucket(bucket) + onSetBucketInfo(organization, organizationID, name, id) + onSetScraperTargetBucket(bucket.name) } private get nextButtonStatus(): ComponentStatus { diff --git a/ui/src/dataLoaders/components/configureStep/__snapshots__/Scraper.test.tsx.snap b/ui/src/dataLoaders/components/configureStep/__snapshots__/Scraper.test.tsx.snap index 9e04e16489..d6d6bc84ec 100644 --- a/ui/src/dataLoaders/components/configureStep/__snapshots__/Scraper.test.tsx.snap +++ b/ui/src/dataLoaders/components/configureStep/__snapshots__/Scraper.test.tsx.snap @@ -10,28 +10,11 @@ exports[`ScraperTarget rendering renders! 1`] = ` - - - No buckets found - - + Date: Mon, 4 Feb 2019 17:40:01 -0800 Subject: [PATCH 38/95] fix(ui/dataLoaders): Set collectors data loading type in the correct place --- .../select/SelectCollectorsStep.tsx | 27 +++---------------- .../organizations/components/Collectors.tsx | 9 ++++++- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx index 2d7cbe19db..bef2023862 100644 --- a/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/select/SelectCollectorsStep.tsx @@ -14,17 +14,12 @@ import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar import { addPluginBundleWithPlugins, removePluginBundleWithPlugins, - setDataLoadersType, } from 'src/dataLoaders/actions/dataLoaders' import {setBucketInfo} from 'src/dataLoaders/actions/steps' // Types import {CollectorsStepProps} from 'src/dataLoaders/components/collectorsWizard/CollectorsWizard' -import { - TelegrafPlugin, - DataLoaderType, - BundleName, -} from 'src/types/v2/dataLoaders' +import {TelegrafPlugin, BundleName} from 'src/types/v2/dataLoaders' import {Bucket} from 'src/api' import {AppState} from 'src/types/v2' @@ -33,7 +28,6 @@ export interface OwnProps extends CollectorsStepProps { } export interface StateProps { - type: DataLoaderType bucket: string telegrafPlugins: TelegrafPlugin[] pluginBundles: BundleName[] @@ -42,7 +36,6 @@ export interface StateProps { export interface DispatchProps { onAddPluginBundle: typeof addPluginBundleWithPlugins onRemovePluginBundle: typeof removePluginBundleWithPlugins - onSetDataLoadersType: typeof setDataLoadersType onSetBucketInfo: typeof setBucketInfo } @@ -50,12 +43,6 @@ type Props = OwnProps & StateProps & DispatchProps @ErrorHandling export class SelectCollectorsStep extends PureComponent { - public componentDidMount() { - if (this.props.type !== DataLoaderType.Streaming) { - this.props.onSetDataLoadersType(DataLoaderType.Streaming) - } - } - public render() { return (
@@ -88,17 +75,13 @@ export class SelectCollectorsStep extends PureComponent { } private get nextButtonStatus(): ComponentStatus { - const {type, telegrafPlugins, buckets} = this.props + const {telegrafPlugins, buckets} = this.props if (!buckets || !buckets.length) { return ComponentStatus.Disabled } - const isTypeEmpty = type === DataLoaderType.Empty - const isStreamingWithoutPlugin = - type === DataLoaderType.Streaming && !telegrafPlugins.length - - if (isTypeEmpty || isStreamingWithoutPlugin) { + if (!telegrafPlugins.length) { return ComponentStatus.Disabled } @@ -132,18 +115,16 @@ export class SelectCollectorsStep extends PureComponent { const mstp = ({ dataLoading: { - dataLoaders: {telegrafPlugins, pluginBundles, type}, + dataLoaders: {telegrafPlugins, pluginBundles}, steps: {bucket}, }, }: AppState): StateProps => ({ - type, telegrafPlugins, bucket, pluginBundles, }) const mdtp: DispatchProps = { - onSetDataLoadersType: setDataLoadersType, onAddPluginBundle: addPluginBundleWithPlugins, onRemovePluginBundle: removePluginBundleWithPlugins, onSetBucketInfo: setBucketInfo, diff --git a/ui/src/organizations/components/Collectors.tsx b/ui/src/organizations/components/Collectors.tsx index c19b714fa7..3b74bb92c5 100644 --- a/ui/src/organizations/components/Collectors.tsx +++ b/ui/src/organizations/components/Collectors.tsx @@ -41,6 +41,8 @@ import {ErrorHandling} from 'src/shared/decorators/errors' // Types import {Telegraf, Bucket} from 'src/api' import {OverlayState} from 'src/types/v2' +import {setDataLoadersType} from 'src/dataLoaders/actions/dataLoaders' +import {DataLoaderType} from 'src/types/v2/dataLoaders' interface OwnProps { collectors: Telegraf[] @@ -52,6 +54,7 @@ interface OwnProps { interface DispatchProps { onSetBucketInfo: typeof setBucketInfo + onSetDataLoadersType: typeof setDataLoadersType } type Props = OwnProps & DispatchProps @@ -145,12 +148,15 @@ export class Collectors extends PureComponent { } private handleAddCollector = () => { - const {buckets, onSetBucketInfo} = this.props + const {buckets, onSetBucketInfo, onSetDataLoadersType} = this.props if (buckets && buckets.length) { const {organization, organizationID, name, id} = buckets[0] onSetBucketInfo(organization, organizationID, name, id) } + + onSetDataLoadersType(DataLoaderType.Scraping) + this.setState({overlayState: OverlayState.Open}) } @@ -215,6 +221,7 @@ export class Collectors extends PureComponent { const mdtp: DispatchProps = { onSetBucketInfo: setBucketInfo, + onSetDataLoadersType: setDataLoadersType, } export default connect( From ab2a7265a486705ec1e12f5d7f88667e67776455 Mon Sep 17 00:00:00 2001 From: Lyon Hill Date: Tue, 5 Feb 2019 08:26:26 -0800 Subject: [PATCH 39/95] Add user resource management to the task API (#11664) * Add user resource management to the task API step 1 and 2 of #11427 --- http/task_service.go | 38 +++++++++++++++++++++++++ http/task_service_test.go | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/http/task_service.go b/http/task_service.go index b9b0445809..4b6dca7509 100644 --- a/http/task_service.go +++ b/http/task_service.go @@ -350,6 +350,29 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) { return } + // add User resource map + urm := &platform.UserResourceMapping{ + UserID: auth.GetUserID(), + UserType: platform.Owner, + ResourceType: platform.TasksResourceType, + ResourceID: req.Task.ID, + } + if err := h.UserResourceMappingService.CreateUserResourceMapping(ctx, urm); err != nil { + // clean up the task if we fail to map the user and resource + // TODO(lh): Multi step creates could benefit from a service wide transactional request + if derr := h.TaskService.DeleteTask(ctx, req.Task.ID); derr != nil { + err = fmt.Errorf("%s: failed to clean up task: %s", err.Error(), derr.Error()) + } + + err = &platform.Error{ + Err: err, + Msg: "failed to add user permissions", + } + + EncodeError(ctx, err, w) + return + } + if err := encodeResponse(ctx, w, http.StatusCreated, newTaskResponse(*req.Task, []*platform.Label{})); err != nil { logEncodingError(h.logger, r, err) return @@ -554,6 +577,21 @@ func (h *TaskHandler) handleDeleteTask(w http.ResponseWriter, r *http.Request) { EncodeError(ctx, err, w) return } + // clean up resource maps for deleted task + urms, _, err := h.UserResourceMappingService.FindUserResourceMappings(ctx, platform.UserResourceMappingFilter{ + ResourceID: req.TaskID, + ResourceType: platform.TasksResourceType, + }) + + if err != nil { + h.logger.Warn("failed to pull user resource mapping", zap.Error(err)) + } else { + for _, m := range urms { + if err := h.UserResourceMappingService.DeleteUserResourceMapping(ctx, m.ResourceID, m.UserID); err != nil { + h.logger.Warn(fmt.Sprintf("failed to remove user resource mapping for task %s", m.ResourceID.String()), zap.Error(err)) + } + } + } w.WriteHeader(http.StatusNoContent) } diff --git a/http/task_service_test.go b/http/task_service_test.go index 56f128d8bd..e3d53ade23 100644 --- a/http/task_service_test.go +++ b/http/task_service_test.go @@ -760,3 +760,63 @@ func TestTaskHandler_NotFoundStatus(t *testing.T) { }) } } + +func TestTaskUserResourceMap(t *testing.T) { + task := platform.Task{ + Name: "task1", + OrganizationID: 1, + } + + b, err := json.Marshal(task) + if err != nil { + t.Fatalf("failed to unmarshal task: %v", err) + } + + r := httptest.NewRequest("POST", "http://any.url/v1", bytes.NewReader(b)) + ctx := pcontext.SetAuthorizer(context.Background(), &platform.Authorization{UserID: 2}) + r = r.WithContext(ctx) + + w := httptest.NewRecorder() + + var created *platform.UserResourceMapping + var deletedUser platform.ID + var deletedResource platform.ID + + urms := &mock.UserResourceMappingService{ + CreateMappingFn: func(_ context.Context, urm *platform.UserResourceMapping) error { created = urm; return nil }, + DeleteMappingFn: func(_ context.Context, rid platform.ID, uid platform.ID) error { + deletedUser = uid + deletedResource = rid + return nil + }, + FindMappingsFn: func(context.Context, platform.UserResourceMappingFilter) ([]*platform.UserResourceMapping, int, error) { + return []*platform.UserResourceMapping{created}, 1, nil + }, + } + + h := NewTaskHandler(urms, mock.NewLabelService(), zaptest.NewLogger(t), mock.NewUserService()) + h.OrganizationService = mockOrgService() + taskID := platform.ID(1) + + h.TaskService = &mock.TaskService{ + CreateTaskFn: func(ctx context.Context, t *platform.Task) error { + t.ID = taskID + return nil + }, + DeleteTaskFn: func(ctx context.Context, id platform.ID) error { + return nil + }, + } + h.handlePostTask(w, r) + r = httptest.NewRequest("DELETE", "http://any.url/api/v2/tasks/"+taskID.String(), nil) + + h.ServeHTTP(w, r) + + if created.UserID != deletedUser { + t.Fatalf("deleted user (%s) doesn't match created user (%s)", deletedUser, created.UserID) + } + + if created.ResourceID != deletedResource { + t.Fatalf("deleted resource (%s) doesn't match created resource (%s)", deletedResource, created.ResourceID) + } +} From 90236be3f01548adfd6cfda206602ac9ba5399d8 Mon Sep 17 00:00:00 2001 From: Delmer Date: Tue, 5 Feb 2019 13:38:06 -0500 Subject: [PATCH 40/95] fix(ui/onboarding): update Influx 2.0 -> InfluxDB 2.0 (#11654) --- ui/src/onboarding/components/CompletionStep.tsx | 2 +- .../components/__snapshots__/CompletionStep.test.tsx.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/onboarding/components/CompletionStep.tsx b/ui/src/onboarding/components/CompletionStep.tsx index f16605ed0b..74877d889e 100644 --- a/ui/src/onboarding/components/CompletionStep.tsx +++ b/ui/src/onboarding/components/CompletionStep.tsx @@ -121,7 +121,7 @@ class CompletionStep extends PureComponent { />
I've got this...
- Jump into Influx 2.0 and set up data collection when + Jump into InfluxDB 2.0 and set up data collection when you’re ready.
diff --git a/ui/src/onboarding/components/__snapshots__/CompletionStep.test.tsx.snap b/ui/src/onboarding/components/__snapshots__/CompletionStep.test.tsx.snap index ea46afe038..03ce7dcf14 100644 --- a/ui/src/onboarding/components/__snapshots__/CompletionStep.test.tsx.snap +++ b/ui/src/onboarding/components/__snapshots__/CompletionStep.test.tsx.snap @@ -101,7 +101,7 @@ exports[`Onboarding.Components.CompletionStep renders 1`] = ` I've got this...
- Jump into Influx 2.0 and set up data collection when you’re ready. + Jump into InfluxDB 2.0 and set up data collection when you’re ready.
From fd974fb6b6df14d83f91b6955ed5e7d5b809f531 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Tue, 5 Feb 2019 10:06:24 -0800 Subject: [PATCH 41/95] fix(ui/dataLoaders): Add swap to system bundle --- CHANGELOG.md | 10 ++++++++++ ui/mocks/dummyData.ts | 7 +++++++ ui/src/dataLoaders/constants/pluginConfigs.ts | 1 + ui/src/dataLoaders/reducers/dataLoaders.test.ts | 2 ++ 4 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a5011cf51..690822bdd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## v2.0.0-alpha.2 [unreleased] + +## Features + +## Bug Fixes +1. [11678](https://github.com/influxdata/influxdb/pull/11678): Update the System Telegraf Plugin bundle to include the swap plugin + +## UI Improvements + + ## v2.0.0-alpha.1 [2019-01-23] ### Release Notes diff --git a/ui/mocks/dummyData.ts b/ui/mocks/dummyData.ts index b534af907a..6aa8f17162 100644 --- a/ui/mocks/dummyData.ts +++ b/ui/mocks/dummyData.ts @@ -17,6 +17,7 @@ import { TelegrafPluginInputNet, TelegrafPluginInputProcstat, TelegrafPluginInputDocker, + TelegrafPluginInputSwap, Task as TaskApi, Organization, } from 'src/api' @@ -400,6 +401,12 @@ export const redisTelegrafPlugin = { name: TelegrafPluginInputRedis.NameEnum.Redis, } +export const swapTelegrafPlugin = { + ...telegrafPlugin, + name: TelegrafPluginInputSwap.NameEnum.Swap, + configured: ConfigurationState.Configured, +} + export const redisPlugin = { name: TelegrafPluginInputRedis.NameEnum.Redis, type: TelegrafPluginInputRedis.TypeEnum.Input, diff --git a/ui/src/dataLoaders/constants/pluginConfigs.ts b/ui/src/dataLoaders/constants/pluginConfigs.ts index d26b49bf7f..01f248b0f4 100644 --- a/ui/src/dataLoaders/constants/pluginConfigs.ts +++ b/ui/src/dataLoaders/constants/pluginConfigs.ts @@ -43,6 +43,7 @@ export const pluginsByBundle: PluginBundles = { TelegrafPluginInputMem.NameEnum.Mem, TelegrafPluginInputNet.NameEnum.Net, TelegrafPluginInputProcesses.NameEnum.Processes, + TelegrafPluginInputSwap.NameEnum.Swap, ], [BundleName.Docker]: [TelegrafPluginInputDocker.NameEnum.Docker], [BundleName.Kubernetes]: [TelegrafPluginInputKubernetes.NameEnum.Kubernetes], diff --git a/ui/src/dataLoaders/reducers/dataLoaders.test.ts b/ui/src/dataLoaders/reducers/dataLoaders.test.ts index d4859c2c1f..abd070870f 100644 --- a/ui/src/dataLoaders/reducers/dataLoaders.test.ts +++ b/ui/src/dataLoaders/reducers/dataLoaders.test.ts @@ -39,6 +39,7 @@ import { token, telegrafConfig, dockerTelegrafPlugin, + swapTelegrafPlugin, } from 'mocks/dummyData' import {QUICKSTART_SCRAPER_TARGET_URL} from 'src/dataLoaders/constants/pluginConfigs' @@ -506,6 +507,7 @@ describe('dataLoader reducer', () => { memTelegrafPlugin, netTelegrafPlugin, processesTelegrafPlugin, + swapTelegrafPlugin, ]) ) }) From d8e32cff4bed85cd0c70c4e9fa8ff5bbe48bb70e Mon Sep 17 00:00:00 2001 From: Deniz Kusefoglu Date: Mon, 4 Feb 2019 15:00:34 -0800 Subject: [PATCH 42/95] Add ability to clone tasks --- ui/src/organizations/components/TaskList.tsx | 4 +++- ui/src/organizations/components/TaskRow.tsx | 15 +++++++++++++++ ui/src/organizations/components/Tasks.tsx | 6 ++++++ ui/src/shared/copy/v2/notifications.ts | 13 +++++++++++++ ui/src/tasks/actions/v2/index.ts | 15 +++++++++++++++ ui/src/tasks/components/TaskRow.tsx | 14 ++++++++++++++ ui/src/tasks/components/TasksList.tsx | 4 +++- ui/src/tasks/containers/TasksPage.tsx | 12 +++++++++++- 8 files changed, 80 insertions(+), 3 deletions(-) diff --git a/ui/src/organizations/components/TaskList.tsx b/ui/src/organizations/components/TaskList.tsx index b1e4dc907a..935d3ac13e 100644 --- a/ui/src/organizations/components/TaskList.tsx +++ b/ui/src/organizations/components/TaskList.tsx @@ -13,6 +13,7 @@ interface Props { emptyState: JSX.Element onDelete: (taskID: string) => void onUpdate: (task: Task) => void + onClone: (task: Task) => void } export default class TaskList extends PureComponent { @@ -32,13 +33,14 @@ export default class TaskList extends PureComponent { } private get rows(): JSX.Element[] { - const {tasks, onDelete, onUpdate} = this.props + const {tasks, onDelete, onClone, onUpdate} = this.props return tasks.map(task => ( )) } diff --git a/ui/src/organizations/components/TaskRow.tsx b/ui/src/organizations/components/TaskRow.tsx index 2e0241caa5..91d3a87372 100644 --- a/ui/src/organizations/components/TaskRow.tsx +++ b/ui/src/organizations/components/TaskRow.tsx @@ -7,6 +7,9 @@ import { IndexList, ConfirmationButton, Alignment, + Button, + IconFont, + ComponentColor, } from 'src/clockface' // Api @@ -17,6 +20,7 @@ interface Props { task: Task onDelete: (taskID: string) => void onUpdate: (task: Task) => void + onClone: (task: Task) => void } export default class TaskRow extends PureComponent { @@ -35,6 +39,13 @@ export default class TaskRow extends PureComponent { {task.name} +
- + ) } From 3d6e253cf702da73d58b86633dfbcc2bc8a9c0e9 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Tue, 5 Feb 2019 13:09:54 -0800 Subject: [PATCH 49/95] fix(ui/dataLoaders): Update default telegraf config name to 'Name this Configuration' --- ui/src/dataLoaders/reducers/dataLoaders.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/dataLoaders/reducers/dataLoaders.ts b/ui/src/dataLoaders/reducers/dataLoaders.ts index f0faa9afa1..7e77390572 100644 --- a/ui/src/dataLoaders/reducers/dataLoaders.ts +++ b/ui/src/dataLoaders/reducers/dataLoaders.ts @@ -36,7 +36,7 @@ export const INITIAL_STATE: DataLoadersState = { telegrafConfigID: null, pluginBundles: [], scraperTarget: {bucket: '', url: QUICKSTART_SCRAPER_TARGET_URL}, - telegrafConfigName: 'new config', + telegrafConfigName: 'Name this Configuration', } export default (state = INITIAL_STATE, action: Action): DataLoadersState => { From 4893c5f451a75ccf572785b31ec74a1ca2f4c066 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 5 Feb 2019 13:09:10 -0800 Subject: [PATCH 50/95] Move cells api calls to client --- ui/package-lock.json | 6 +++--- ui/package.json | 2 +- ui/src/dashboards/apis/v2/index.ts | 16 +++++++--------- ui/src/utils/api.ts | 4 +--- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index 15bad63a4f..4a50ea5530 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.9.tgz", - "integrity": "sha512-AoOK71N/jUqAJxGVFZ2quPe79eeDvtZuzF0ITzg4HXeVDZJrdWL2c1HeF/gbS1OOQcMj4UGFMXUzzeSpRaXY4g==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.10.tgz", + "integrity": "sha512-KGVxR2tYzRSrfCJItHhR5e+1a6iuqq6Ted7PphgThm/v/zkqwRmc4EveoudjDFgcqyh34aRw1AY73jkXj7tJ1A==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index e9adc46416..3f52f6d3bc 100644 --- a/ui/package.json +++ b/ui/package.json @@ -117,7 +117,7 @@ }, "dependencies": { "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/influx": "^0.1.9", + "@influxdata/influx": "^0.1.10", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/dashboards/apis/v2/index.ts b/ui/src/dashboards/apis/v2/index.ts index 1f9e4f8d82..9e846579d0 100644 --- a/ui/src/dashboards/apis/v2/index.ts +++ b/ui/src/dashboards/apis/v2/index.ts @@ -1,5 +1,5 @@ // Libraries -import {dashboardsAPI, cellsAPI} from 'src/utils/api' +import {dashboardsAPI} from 'src/utils/api' import _ from 'lodash' // Utils @@ -18,6 +18,7 @@ import { } from 'src/types/v2' import {Cell as CellTypeAPI} from 'src/api' +import {client} from 'src/utils/api' // Utils import { @@ -101,12 +102,9 @@ export const addCell = async ( dashboardID: string, cell: NewCell ): Promise => { - const {data} = await cellsAPI.dashboardsDashboardIDCellsPost( - dashboardID, - cell - ) + const result = await client.dashboards.createCell(dashboardID, cell) - const cellWithID = {...data, dashboardID} + const cellWithID = {...result, dashboardID} return cellWithID } @@ -115,16 +113,16 @@ export const updateCells = async ( id: string, cells: Cell[] ): Promise => { - const {data} = await cellsAPI.dashboardsDashboardIDCellsPut(id, cells) + const result = await client.dashboards.updateAllCells(id, cells) - return addDashboardIDToCells(data.cells, id) + return addDashboardIDToCells(result, id) } export const deleteCell = async ( dashboardID: string, cell: Cell ): Promise => { - await cellsAPI.dashboardsDashboardIDCellsCellIDDelete(dashboardID, cell.id) + await client.dashboards.deleteCell(dashboardID, cell.id) } export const addDashboardLabels = async ( diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index e7a2614ca0..73dc2a66fa 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -1,4 +1,4 @@ -import {DashboardsApi, CellsApi, ViewsApi, QueryApi, ProtosApi} from 'src/api' +import {DashboardsApi, QueryApi, ProtosApi} from 'src/api' import Client from '@influxdata/influx' @@ -6,8 +6,6 @@ const basePath = '/api/v2' export const client = new Client(basePath) -export const viewsAPI = new ViewsApi({basePath}) export const dashboardsAPI = new DashboardsApi({basePath}) -export const cellsAPI = new CellsApi({basePath}) export const queryAPI = new QueryApi({basePath}) export const protosAPI = new ProtosApi({basePath}) From 04e36b18f0ce725cc92e57ff749b0c5a78ed066c Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Tue, 5 Feb 2019 13:25:32 -0800 Subject: [PATCH 51/95] fix(ui/dataLoaders): Update the collectors configure step button to 'Create and Verify' --- CHANGELOG.md | 1 + .../configure/TelegrafPluginInstructions.tsx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0224937c2a..4bc51a3381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ## UI Improvements 1. [11683](https://github.com/influxdata/influxdb/pull/11683): Change the wording for the plugin config form button to Done +1. [11689](https://github.com/influxdata/influxdb/pull/11689): Change the wording for the Collectors configure step button to Create and Verify ## v2.0.0-alpha.1 [2019-01-23] diff --git a/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx index 651b38619c..4e3da07b6b 100644 --- a/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx +++ b/ui/src/dataLoaders/components/collectorsWizard/configure/TelegrafPluginInstructions.tsx @@ -59,7 +59,10 @@ export class TelegrafPluginInstructions extends PureComponent {
- + ) } From 7b27c92a57e114c9d6f4d380aa64983da2efec76 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 5 Feb 2019 13:41:19 -0800 Subject: [PATCH 52/95] Move proto api to client library --- ui/package-lock.json | 6 +++--- ui/package.json | 2 +- ui/src/protos/actions/index.ts | 10 +++------- ui/src/protos/apis/index.ts | 20 -------------------- ui/src/utils/api.ts | 3 +-- 5 files changed, 8 insertions(+), 33 deletions(-) delete mode 100644 ui/src/protos/apis/index.ts diff --git a/ui/package-lock.json b/ui/package-lock.json index 4a50ea5530..6029a6f46d 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.10.tgz", - "integrity": "sha512-KGVxR2tYzRSrfCJItHhR5e+1a6iuqq6Ted7PphgThm/v/zkqwRmc4EveoudjDFgcqyh34aRw1AY73jkXj7tJ1A==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.11.tgz", + "integrity": "sha512-AXnYlAeRpw18E1HvLQcoslkP1jpsPJglxd9WhbeGxOEYx3Nma6TcEX1/5gtqG+wIMfJ2r9Or6pZFfFW9Pp2fHQ==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 3f52f6d3bc..8d985ea680 100644 --- a/ui/package.json +++ b/ui/package.json @@ -117,7 +117,7 @@ }, "dependencies": { "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/influx": "^0.1.10", + "@influxdata/influx": "^0.1.11", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/protos/actions/index.ts b/ui/src/protos/actions/index.ts index 801b38b93e..69b06b709d 100644 --- a/ui/src/protos/actions/index.ts +++ b/ui/src/protos/actions/index.ts @@ -1,11 +1,7 @@ // Libraries import {Dispatch} from 'redux' -// APIs -import { - getProtos as getProtosAJAX, - createDashFromProto as createDashFromProtoAJAX, -} from 'src/protos/apis/' +import {client} from 'src/utils/api' // Utils import {addDashboardIDToCells} from 'src/dashboards/apis/v2/' @@ -46,7 +42,7 @@ export const loadProto = (proto: Proto): LoadProtoAction => ({ export const getProtos = () => async (dispatch: Dispatch) => { try { - const {protos} = await getProtosAJAX() + const protos = await client.protos.getAll() protos.forEach(p => { dispatch(loadProto(p)) @@ -61,7 +57,7 @@ export const createDashFromProto = ( orgID: string ) => async dispatch => { try { - const {dashboards} = await createDashFromProtoAJAX(protoID, orgID) + const dashboards = await client.dashboards.createFromProto(protoID, orgID) dashboards.forEach((d: Dashboard) => { const updatedDashboard = { diff --git a/ui/src/protos/apis/index.ts b/ui/src/protos/apis/index.ts deleted file mode 100644 index 6d723ce2cc..0000000000 --- a/ui/src/protos/apis/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -// API funcs -import {protosAPI} from 'src/utils/api' - -// types -import {Protos, Dashboards} from 'src/api' - -export const getProtos = async (): Promise => { - const {data} = await protosAPI.protosGet() - - return data -} - -export const createDashFromProto = async ( - protoID: string, - orgID: string -): Promise => { - const {data} = await protosAPI.protosProtoIDDashboardsPost(protoID, {orgID}) - // might want to map dashboard[] to more one more useful to FE. - return data -} diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 73dc2a66fa..706956c9ab 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -1,4 +1,4 @@ -import {DashboardsApi, QueryApi, ProtosApi} from 'src/api' +import {DashboardsApi, QueryApi} from 'src/api' import Client from '@influxdata/influx' @@ -8,4 +8,3 @@ export const client = new Client(basePath) export const dashboardsAPI = new DashboardsApi({basePath}) export const queryAPI = new QueryApi({basePath}) -export const protosAPI = new ProtosApi({basePath}) From 26e2a15f3ade2667cbb05413608b0e0530e26c21 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Tue, 5 Feb 2019 14:11:32 -0800 Subject: [PATCH 53/95] feat(ui/dataLoaders): Use env var for telegraf config auth token instead of auth token --- CHANGELOG.md | 1 + ui/src/dataLoaders/actions/dataLoaders.ts | 4 ++-- .../components/verifyStep/CreateOrUpdateConfig.tsx | 4 +--- ui/src/dataLoaders/components/verifyStep/DataStreaming.tsx | 2 +- ui/src/dataLoaders/reducers/dataLoaders.test.ts | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc51a3381..78485fccf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## v2.0.0-alpha.2 [unreleased] ## Features +1. [11693](https://github.com/influxdata/influxdb/pull/11693): Save the $INFLUX_TOKEN environmental variable in telegraf configs ## Bug Fixes 1. [11678](https://github.com/influxdata/influxdb/pull/11678): Update the System Telegraf Plugin bundle to include the swap plugin diff --git a/ui/src/dataLoaders/actions/dataLoaders.ts b/ui/src/dataLoaders/actions/dataLoaders.ts index a8689b53f1..21a5efc9fa 100644 --- a/ui/src/dataLoaders/actions/dataLoaders.ts +++ b/ui/src/dataLoaders/actions/dataLoaders.ts @@ -283,7 +283,7 @@ export const removePluginBundleWithPlugins = ( dispatch(removeBundlePlugins(bundle)) } -export const createOrUpdateTelegrafConfigAsync = (authToken: string) => async ( +export const createOrUpdateTelegrafConfigAsync = () => async ( dispatch, getState: GetState ) => { @@ -299,7 +299,7 @@ export const createOrUpdateTelegrafConfigAsync = (authToken: string) => async ( type: TelegrafPluginOutputInfluxDBV2.TypeEnum.Output, config: { urls: ['http://127.0.0.1:9999'], - token: authToken, + token: '$INFLUX_TOKEN', organization: org, bucket, }, diff --git a/ui/src/dataLoaders/components/verifyStep/CreateOrUpdateConfig.tsx b/ui/src/dataLoaders/components/verifyStep/CreateOrUpdateConfig.tsx index fe0fdeb0e5..0065f7abbb 100644 --- a/ui/src/dataLoaders/components/verifyStep/CreateOrUpdateConfig.tsx +++ b/ui/src/dataLoaders/components/verifyStep/CreateOrUpdateConfig.tsx @@ -23,7 +23,6 @@ import {RemoteDataState, NotificationAction} from 'src/types' export interface OwnProps { org: string - authToken: string children: () => JSX.Element } @@ -50,7 +49,6 @@ export class CreateOrUpdateConfig extends PureComponent { public async componentDidMount() { const { onSaveTelegrafConfig, - authToken, notify, createDashboardsForPlugins, } = this.props @@ -58,7 +56,7 @@ export class CreateOrUpdateConfig extends PureComponent { this.setState({loading: RemoteDataState.Loading}) try { - await onSaveTelegrafConfig(authToken) + await onSaveTelegrafConfig() notify(TelegrafConfigCreationSuccess) await createDashboardsForPlugins() diff --git a/ui/src/dataLoaders/components/verifyStep/DataStreaming.tsx b/ui/src/dataLoaders/components/verifyStep/DataStreaming.tsx index 2056e41f50..c6c2217542 100644 --- a/ui/src/dataLoaders/components/verifyStep/DataStreaming.tsx +++ b/ui/src/dataLoaders/components/verifyStep/DataStreaming.tsx @@ -28,7 +28,7 @@ class DataStreaming extends PureComponent { return ( <> - + {() => ( { }, }, }) - await createOrUpdateTelegrafConfigAsync(token)(dispatch, getState) + await createOrUpdateTelegrafConfigAsync()(dispatch, getState) expect(dispatch).toBeCalledWith(setTelegrafConfigID(telegrafConfig.id)) }) From c8cc898a11bcb36e12b550c378cb1e4214f84d55 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 5 Feb 2019 14:28:19 -0800 Subject: [PATCH 54/95] Move ast call to client library --- ui/package-lock.json | 6 +-- ui/package.json | 2 +- ui/src/logs/actions/index.ts | 11 ---- ui/src/logs/api/v2/index.ts | 59 ---------------------- ui/src/logs/utils/fixtures/fluxResponse.ts | 3 +- ui/src/logs/utils/logQuery.ts | 36 +------------ ui/src/shared/apis/v2/ast.ts | 8 --- ui/src/shared/utils/renderQuery.ts | 6 +-- ui/src/utils/api.ts | 3 +- 9 files changed, 10 insertions(+), 124 deletions(-) delete mode 100644 ui/src/logs/api/v2/index.ts delete mode 100644 ui/src/shared/apis/v2/ast.ts diff --git a/ui/package-lock.json b/ui/package-lock.json index 6029a6f46d..f6c2f19783 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.11.tgz", - "integrity": "sha512-AXnYlAeRpw18E1HvLQcoslkP1jpsPJglxd9WhbeGxOEYx3Nma6TcEX1/5gtqG+wIMfJ2r9Or6pZFfFW9Pp2fHQ==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.12.tgz", + "integrity": "sha512-xq+XBvGwlvZVIGJmsJrdoT/KNtm+gFkQvi9tVTl2oWsCwpNanxWR1ED/xifzi0pq86blOKOgEq9vY59fFSaHeQ==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 8d985ea680..3d1fa322f0 100644 --- a/ui/package.json +++ b/ui/package.json @@ -117,7 +117,7 @@ }, "dependencies": { "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/influx": "^0.1.11", + "@influxdata/influx": "^0.1.12", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/logs/actions/index.ts b/ui/src/logs/actions/index.ts index dcc8d14281..fda8fa9e17 100644 --- a/ui/src/logs/actions/index.ts +++ b/ui/src/logs/actions/index.ts @@ -4,7 +4,6 @@ import uuid from 'uuid' import {getDeep} from 'src/utils/wrappers' import {serverToUIConfig} from 'src/logs/utils/config' import { - getTableData, buildTableQueryConfig, validateTailQuery, validateOlderQuery, @@ -12,7 +11,6 @@ import { // APIs import {client} from 'src/utils/api' -import {executeQueryAsync} from 'src/logs/api/v2' // Data import {logViewData as defaultLogView} from 'src/logs/data/logViewData' @@ -628,10 +626,6 @@ export const fetchLogTailAsync = (logTailID: number) => async ( const upperUTC = Date.parse(logQuery.upper) dispatch(setCurrentTailUpperBound(upperUTC)) - - const logSeries = await getTableData(executeQueryAsync, logQuery) - - dispatch(updateLogsTailData(logSeries, logTailID, upperUTC)) } export const updateLogsTailData = ( @@ -799,11 +793,6 @@ export const fetchOlderChunkAsync = (olderBatchID: string) => async ( } const nextOlderUpperBound = new Date(logQuery.lower).valueOf() await dispatch(setNextOlderUpperBound(nextOlderUpperBound)) - - const logSeries = await getTableData(executeQueryAsync, logQuery) - if (logSeries.values.length > 0) { - await dispatch(updateOlderLogs(logSeries, olderBatchID)) - } } export const updateOlderLogs = ( diff --git a/ui/src/logs/api/v2/index.ts b/ui/src/logs/api/v2/index.ts deleted file mode 100644 index b519c6d67a..0000000000 --- a/ui/src/logs/api/v2/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Utils -import {parseResponse} from 'src/shared/parsing/flux/response' - -// Types -import {FluxTable} from 'src/types' -import {SearchStatus} from 'src/types/logs' -import {queryAPI} from 'src/utils/api' -import {Query, Dialect} from 'src/api' - -export interface QueryResponse { - tables: FluxTable[] - status: SearchStatus -} - -export const executeQueryAsync = async ( - query: string, - type: Query.TypeEnum = Query.TypeEnum.Influxql -): Promise => { - try { - const dialect = { - header: true, - annotations: [ - Dialect.AnnotationsEnum.Datatype, - Dialect.AnnotationsEnum.Group, - Dialect.AnnotationsEnum.Default, - ], - delimiter: ',', - } - - const {data} = await queryAPI.queryPost( - 'text/csv', - 'application/json', - null, - null, - {type, query, dialect} - ) - - const tables = parseResponse(data) - const status = responseStatus(tables) - - return {tables, status} - } catch (error) { - console.error(error) - return { - tables: [], - status: SearchStatus.SourceError, - } - } -} - -const responseStatus = (tables: FluxTable[]): SearchStatus => { - if (tables.length === 0) { - return SearchStatus.NoResults - } else if (tables[0].name === 'Error') { - return SearchStatus.SourceError - } else { - return SearchStatus.Loaded - } -} diff --git a/ui/src/logs/utils/fixtures/fluxResponse.ts b/ui/src/logs/utils/fixtures/fluxResponse.ts index 7759d35a78..8f743b9799 100644 --- a/ui/src/logs/utils/fixtures/fluxResponse.ts +++ b/ui/src/logs/utils/fixtures/fluxResponse.ts @@ -1,7 +1,6 @@ -import {QueryResponse} from 'src/logs/api/v2' import {SearchStatus} from 'src/types/logs' -export const fluxResponse: QueryResponse = { +export const fluxResponse = { tables: [ { id: 'd7cc1e08-4b17-4309-885b-6798402bdae2', diff --git a/ui/src/logs/utils/logQuery.ts b/ui/src/logs/utils/logQuery.ts index eae1c0693f..c9bd5912c9 100644 --- a/ui/src/logs/utils/logQuery.ts +++ b/ui/src/logs/utils/logQuery.ts @@ -2,25 +2,14 @@ import uuid from 'uuid' import _ from 'lodash' -// APIs -import {executeQueryAsync} from 'src/logs/api/v2' - // Utils -import {fluxToTableData} from 'src/logs/utils/v2' import {buildFluxQuery} from 'src/logs/utils/v2/queryBuilder' import {buildInfluxQLQuery} from 'src/logs/utils/v1/queryBuilder' // Types import {Bucket, Query} from 'src/api' import {QueryConfig} from 'src/types' -import { - LogSearchParams, - LogQuery, - SearchStatus, - TableData, -} from 'src/types/logs' - -type FetchSeries = typeof executeQueryAsync +import {LogSearchParams, LogQuery} from 'src/types/logs' const defaultQueryConfig = { areTagsAccepted: false, @@ -101,29 +90,6 @@ export const buildLogQuery = ( } } -export const getTableData = async ( - executeQuery: FetchSeries, - logQuery: LogQuery -): Promise => { - const {source, ...searchParams} = logQuery - // TODO: get type from source - const type = Query.TypeEnum.Flux - const query = buildLogQuery(type, searchParams) - - const response = await executeQuery(query, type) - - const {config} = searchParams - const columnNames: string[] = config.fields.map(f => f.alias) - - if (response.status !== SearchStatus.Loaded) { - return fluxToTableData([], columnNames) - } - - const logSeries: TableData = fluxToTableData(response.tables, columnNames) - - return logSeries -} - export const validateTailQuery = ( logQuery: LogQuery, logTailID: number, diff --git a/ui/src/shared/apis/v2/ast.ts b/ui/src/shared/apis/v2/ast.ts deleted file mode 100644 index 6337eee856..0000000000 --- a/ui/src/shared/apis/v2/ast.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {queryAPI} from 'src/utils/api' -import {Package} from 'src/types/ast' - -export const getAST = async (query: string): Promise => { - const {data} = await queryAPI.queryAstPost(undefined, undefined, {query}) - - return data.ast -} diff --git a/ui/src/shared/utils/renderQuery.ts b/ui/src/shared/utils/renderQuery.ts index 7e8e4c23af..f91f46be1e 100644 --- a/ui/src/shared/utils/renderQuery.ts +++ b/ui/src/shared/utils/renderQuery.ts @@ -1,5 +1,5 @@ // APIs -import {getAST} from 'src/shared/apis/v2/ast' +import {client} from 'src/utils/api' // Utils import {getMinDurationFromAST} from 'src/shared/utils/getMinDurationFromAST' @@ -28,7 +28,7 @@ export async function renderQuery( let variableDeclarations = formatVariables(variables, query) if (query.includes(WINDOW_PERIOD)) { - const ast = await getAST(`${variableDeclarations}\n\n${query}`) + const ast = await client.queries.ast(`${variableDeclarations}\n\n${query}`) let windowPeriod: number @@ -47,7 +47,7 @@ export async function renderQuery( async function extractImports( query: string ): Promise<{imports: string; body: string}> { - const ast = await getAST(query) + const ast = await client.queries.ast(query) const {imports, body} = ast.files[0] const importStatements = (imports || []) .map(i => i.location.source) diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 706956c9ab..7dfbf1f595 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -1,4 +1,4 @@ -import {DashboardsApi, QueryApi} from 'src/api' +import {DashboardsApi} from 'src/api' import Client from '@influxdata/influx' @@ -7,4 +7,3 @@ const basePath = '/api/v2' export const client = new Client(basePath) export const dashboardsAPI = new DashboardsApi({basePath}) -export const queryAPI = new QueryApi({basePath}) From cb30f50e14f7fb907ebd2d507ce23aa98f230231 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 5 Feb 2019 16:20:42 -0800 Subject: [PATCH 55/95] Update dashboard api calls to use client --- ui/package-lock.json | 6 +- ui/package.json | 2 +- ui/src/dashboards/actions/v2/index.ts | 3 +- ui/src/dashboards/apis/v2/index.ts | 124 ++++-------------- .../dashboards/components/DashboardHeader.tsx | 2 - .../dashboards/components/DashboardPage.tsx | 47 +------ ui/src/organizations/apis/index.ts | 8 +- ui/src/types/v2/dashboards.ts | 2 +- ui/src/utils/api.ts | 4 - 9 files changed, 38 insertions(+), 160 deletions(-) diff --git a/ui/package-lock.json b/ui/package-lock.json index f6c2f19783..ade579bfbd 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.12.tgz", - "integrity": "sha512-xq+XBvGwlvZVIGJmsJrdoT/KNtm+gFkQvi9tVTl2oWsCwpNanxWR1ED/xifzi0pq86blOKOgEq9vY59fFSaHeQ==", + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.16.tgz", + "integrity": "sha512-L5gVs6Fe0JD5LxZuFlv0POBGoifi13syqhJmVLGoFmkWKpVVQ/k0ugY8hGwY/1Ub3nbBK/nUnBvr7+kdrxEhHQ==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index 3d1fa322f0..edd9981332 100644 --- a/ui/package.json +++ b/ui/package.json @@ -117,7 +117,7 @@ }, "dependencies": { "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/influx": "^0.1.12", + "@influxdata/influx": "^0.1.16", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/dashboards/actions/v2/index.ts b/ui/src/dashboards/actions/v2/index.ts index 21222e9447..e33e2e99e5 100644 --- a/ui/src/dashboards/actions/v2/index.ts +++ b/ui/src/dashboards/actions/v2/index.ts @@ -39,7 +39,8 @@ import * as copy from 'src/shared/copy/notifications' import {RemoteDataState} from 'src/types' import {PublishNotificationAction} from 'src/types/actions/notifications' import {CreateCell} from 'src/api' -import {Dashboard, NewView, Cell, Label} from 'src/types/v2' +import {Dashboard, NewView, Cell} from 'src/types/v2' +import {Label} from '@influxdata/influx' export enum ActionTypes { LoadDashboards = 'LOAD_DASHBOARDS', diff --git a/ui/src/dashboards/apis/v2/index.ts b/ui/src/dashboards/apis/v2/index.ts index 9e846579d0..08e105c360 100644 --- a/ui/src/dashboards/apis/v2/index.ts +++ b/ui/src/dashboards/apis/v2/index.ts @@ -1,5 +1,4 @@ // Libraries -import {dashboardsAPI} from 'src/utils/api' import _ from 'lodash' // Utils @@ -8,24 +7,12 @@ import {incrementCloneName} from 'src/utils/naming' // Types -import { - DashboardSwitcherLinks, - Cell, - NewCell, - Dashboard, - View, - Label, -} from 'src/types/v2' +import {Cell, NewCell, Dashboard, View} from 'src/types/v2' +import {Label} from '@influxdata/influx' import {Cell as CellTypeAPI} from 'src/api' import {client} from 'src/utils/api' -// Utils -import { - linksFromDashboards, - updateDashboardLinks, -} from 'src/dashboards/utils/dashboardSwitcherLinks' - export const addDashboardIDToCells = ( cells: CellTypeAPI[], dashboardID: string @@ -37,9 +24,9 @@ export const addDashboardIDToCells = ( // TODO(desa): what to do about getting dashboards from another v2 source export const getDashboards = async (): Promise => { - const {data} = await dashboardsAPI.dashboardsGet() + const dashboards = await client.dashboards.getAll() - return data.dashboards.map(d => ({ + return dashboards.map(d => ({ ...d, labels: d.labels.map(addLabelDefaults), cells: addDashboardIDToCells(d.cells, d.id), @@ -47,57 +34,43 @@ export const getDashboards = async (): Promise => { } export const getDashboard = async (id: string): Promise => { - const {data} = await dashboardsAPI.dashboardsDashboardIDGet(id) + const dashboard = await client.dashboards.get(id) return { - ...data, - labels: data.labels.map(addLabelDefaults), - cells: addDashboardIDToCells(data.cells, data.id), + ...dashboard, + labels: dashboard.labels.map(addLabelDefaults), + cells: addDashboardIDToCells(dashboard.cells, dashboard.id), } } export const createDashboard = async ( - dashboard: Partial + props: Partial ): Promise => { - const {data} = await dashboardsAPI.dashboardsPost(dashboard) + const dashboard = await client.dashboards.create(props) return { - ...data, - labels: data.labels.map(addLabelDefaults), - cells: addDashboardIDToCells(data.cells, data.id), + ...dashboard, + labels: dashboard.labels.map(addLabelDefaults), + cells: addDashboardIDToCells(dashboard.cells, dashboard.id), } } export const deleteDashboard = async (dashboard: Dashboard): Promise => { - await dashboardsAPI.dashboardsDashboardIDDelete(dashboard.id) + await client.dashboards.delete(dashboard.id) } export const updateDashboard = async ( dashboard: Dashboard ): Promise => { - const {data} = await dashboardsAPI.dashboardsDashboardIDPatch( - dashboard.id, - dashboard - ) + const updated = await client.dashboards.update(dashboard.id, dashboard) return { - ...data, - labels: data.labels.map(addLabelDefaults), - cells: addDashboardIDToCells(data.cells, data.id), + ...updated, + labels: updated.labels.map(addLabelDefaults), + cells: addDashboardIDToCells(updated.cells, updated.id), } } -export const loadDashboardLinks = async ( - activeDashboard: Dashboard -): Promise => { - const dashboards = await getDashboards() - - const links = linksFromDashboards(dashboards) - const dashboardLinks = updateDashboardLinks(links, activeDashboard) - - return dashboardLinks -} - export const addCell = async ( dashboardID: string, cell: NewCell @@ -131,11 +104,7 @@ export const addDashboardLabels = async ( ): Promise => { const addedLabels = await Promise.all( labels.map(async label => { - await dashboardsAPI.dashboardsDashboardIDLabelsPost(dashboardID, { - labelID: label.id, - }) - - return label + return client.dashboards.createLabel(dashboardID, label.id) }) ) @@ -147,14 +116,8 @@ export const removeDashboardLabels = async ( labels: Label[] ): Promise => { await Promise.all( - labels.map(async label => { - const { - data, - } = await dashboardsAPI.dashboardsDashboardIDLabelsLabelIDDelete( - dashboardID, - label.id - ) - return data + labels.map(label => { + return client.dashboards.deleteLabel(dashboardID, label.id) }) ) } @@ -163,10 +126,7 @@ export const readView = async ( dashboardID: string, cellID: string ): Promise => { - const {data} = await dashboardsAPI.dashboardsDashboardIDCellsCellIDViewGet( - dashboardID, - cellID - ) + const data = await client.dashboards.getView(dashboardID, cellID) const view: View = {...data, dashboardID, cellID} @@ -178,26 +138,13 @@ export const updateView = async ( cellID: string, view: Partial ): Promise => { - const {data} = await dashboardsAPI.dashboardsDashboardIDCellsCellIDViewPatch( - dashboardID, - cellID, - view - ) + const data = await client.dashboards.updateView(dashboardID, cellID, view) const viewWithIDs: View = {...data, dashboardID, cellID} return viewWithIDs } -export const addCellUpdateView = async ( - dashboard: Dashboard, - cell: Cell, - view: View -): Promise => { - const createdCell = await addCell(dashboard.id, cell) - return updateView(dashboard.id, createdCell.id, view) -} - export const cloneDashboard = async ( dashboardToClone: Dashboard, dashboards: Dashboard[] @@ -209,26 +156,7 @@ export const cloneDashboard = async ( dashboardToClone.name ) - const dashboardNoCells = _.omit(dashboardToClone, ['cells']) - - const createdDashboard = await createDashboard({ - ...dashboardNoCells, - name: clonedName, - }) - - const cells = dashboardToClone.cells - - const pendingViews = cells.map(c => readView(dashboardToClone.id, c.id)) - - const views = await Promise.all(pendingViews) - - const pendingUpdatedViews = views.map(view => { - const cell = cells.find(c => c.id === view.id) - - return addCellUpdateView(createdDashboard, cell, view) - }) - - await Promise.all(pendingUpdatedViews) - - return createdDashboard + if (dashboardToClone.id) { + return client.dashboards.clone(dashboardToClone.id, clonedName) + } } diff --git a/ui/src/dashboards/components/DashboardHeader.tsx b/ui/src/dashboards/components/DashboardHeader.tsx index b4772106a7..3405aeb301 100644 --- a/ui/src/dashboards/components/DashboardHeader.tsx +++ b/ui/src/dashboards/components/DashboardHeader.tsx @@ -23,7 +23,6 @@ import {addNote} from 'src/dashboards/actions/v2/notes' import * as AppActions from 'src/types/actions/app' import * as QueriesModels from 'src/types/queries' import {Dashboard} from 'src/api' -import {DashboardSwitcherLinks} from 'src/types/v2/dashboards' interface OwnProps { activeDashboard: string @@ -38,7 +37,6 @@ interface OwnProps { showTemplateControlBar: boolean zoomedTimeRange: QueriesModels.TimeRange onRenameDashboard: (name: string) => Promise - dashboardLinks: DashboardSwitcherLinks isHidden: boolean } diff --git a/ui/src/dashboards/components/DashboardPage.tsx b/ui/src/dashboards/components/DashboardPage.tsx index a287aea950..306bdd41d4 100644 --- a/ui/src/dashboards/components/DashboardPage.tsx +++ b/ui/src/dashboards/components/DashboardPage.tsx @@ -25,18 +25,13 @@ import {setActiveTimeMachine} from 'src/timeMachine/actions' // Utils import {getDeep} from 'src/utils/wrappers' -import {updateDashboardLinks} from 'src/dashboards/utils/dashboardSwitcherLinks' import {GlobalAutoRefresher} from 'src/utils/AutoRefresher' import {createView} from 'src/shared/utils/view' import {cellAddFailed} from 'src/shared/copy/notifications' -// APIs -import {loadDashboardLinks} from 'src/dashboards/apis/v2' - // Constants import {DASHBOARD_LAYOUT_ROW_HEIGHT} from 'src/shared/constants' import {DEFAULT_TIME_RANGE} from 'src/shared/constants/timeRanges' -import {EMPTY_LINKS} from 'src/dashboards/constants/dashboardHeader' import {VEO_TIME_MACHINE_ID} from 'src/timeMachine/constants' // Types @@ -48,7 +43,6 @@ import { View, ViewType, TimeRange, - DashboardSwitcherLinks, AppState, } from 'src/types/v2' import {NewView, XYView, QueryViewProperties} from 'src/types/v2/dashboards' @@ -115,7 +109,6 @@ type Props = PassedProps & interface State { scrollTop: number windowHeight: number - dashboardLinks: DashboardSwitcherLinks isShowingVEO: boolean } @@ -127,7 +120,6 @@ class DashboardPage extends Component { this.state = { scrollTop: 0, windowHeight: window.innerHeight, - dashboardLinks: EMPTY_LINKS, isShowingVEO: false, } } @@ -140,8 +132,6 @@ class DashboardPage extends Component { window.addEventListener('resize', this.handleWindowResize, true) await this.getDashboard() - - this.getDashboardLinks() } public componentDidUpdate(prevProps: Props) { @@ -179,7 +169,7 @@ class DashboardPage extends Component { handleChooseAutoRefresh, handleClickPresentationButton, } = this.props - const {dashboardLinks, isShowingVEO} = this.state + const {isShowingVEO} = this.state return ( @@ -193,7 +183,6 @@ class DashboardPage extends Component { onManualRefresh={onManualRefresh} zoomedTimeRange={zoomedTimeRange} onRenameDashboard={this.handleRenameDashboard} - dashboardLinks={dashboardLinks} activeDashboard={dashboard ? dashboard.name : ''} showTemplateControlBar={showTemplateControlBar} handleChooseAutoRefresh={handleChooseAutoRefresh} @@ -234,16 +223,6 @@ class DashboardPage extends Component { const {params, getDashboard} = this.props await getDashboard(params.dashboardID) - this.updateActiveDashboard() - } - - private updateActiveDashboard(): void { - this.setState((prevState, props) => ({ - dashboardLinks: updateDashboardLinks( - prevState.dashboardLinks, - props.dashboard - ), - })) } private inView = (cell: Cell): boolean => { @@ -334,7 +313,6 @@ class DashboardPage extends Component { const renamedDashboard = {...dashboard, name} await updateDashboard(renamedDashboard) - this.updateActiveDashboard() } private handleDeleteDashboardCell = async (cell: Cell): Promise => { @@ -342,14 +320,7 @@ class DashboardPage extends Component { await deleteCell(dashboard, cell) } - private handleZoomedTimeRange = (__: TimeRange): void => { - // const {setZoomedTimeRange, updateQueryParams} = this.props - // setZoomedTimeRange(zoomedTimeRange) - // updateQueryParams({ - // zoomedLower: zoomedTimeRange.lower, - // zoomedUpper: zoomedTimeRange.upper, - // }) - } + private handleZoomedTimeRange = (__: TimeRange): void => {} private setScrollTop = (e: MouseEvent): void => { const target = e.target as HTMLElement @@ -357,20 +328,6 @@ class DashboardPage extends Component { this.setState({scrollTop: target.scrollTop}) } - private getDashboardLinks = async (): Promise => { - const {dashboard: activeDashboard} = this.props - - try { - const dashboardLinks = await loadDashboardLinks(activeDashboard) - - this.setState({ - dashboardLinks, - }) - } catch (error) { - console.error(error) - } - } - private handleWindowResize = (): void => { this.setState({windowHeight: window.innerHeight}) } diff --git a/ui/src/organizations/apis/index.ts b/ui/src/organizations/apis/index.ts index cd9a01b213..45dec54399 100644 --- a/ui/src/organizations/apis/index.ts +++ b/ui/src/organizations/apis/index.ts @@ -1,7 +1,7 @@ // Libraries import _ from 'lodash' -import {dashboardsAPI} from 'src/utils/api' +import {client} from 'src/utils/api' // Types import {Organization} from 'src/api' @@ -16,11 +16,9 @@ export const getDashboards = async ( try { let result if (org) { - const {data} = await dashboardsAPI.dashboardsGet(org.name) - result = data.dashboards + result = await client.dashboards.getAllByOrg(org.name) } else { - const {data} = await dashboardsAPI.dashboardsGet(null) - result = data.dashboards + result = await client.dashboards.getAll() } return result diff --git a/ui/src/types/v2/dashboards.ts b/ui/src/types/v2/dashboards.ts index 2b0246ee62..99f0d47707 100644 --- a/ui/src/types/v2/dashboards.ts +++ b/ui/src/types/v2/dashboards.ts @@ -1,5 +1,5 @@ import {Color} from 'src/types/colors' -import {Label} from 'src/types/v2/labels' +import {Label} from '@influxdata/influx' import { Dashboard as DashboardAPI, View as ViewAPI, diff --git a/ui/src/utils/api.ts b/ui/src/utils/api.ts index 7dfbf1f595..3a0a491dcd 100644 --- a/ui/src/utils/api.ts +++ b/ui/src/utils/api.ts @@ -1,9 +1,5 @@ -import {DashboardsApi} from 'src/api' - import Client from '@influxdata/influx' const basePath = '/api/v2' export const client = new Client(basePath) - -export const dashboardsAPI = new DashboardsApi({basePath}) From 3992fa9d5483032dd6041ac83e73aaaf581a709d Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 5 Feb 2019 16:44:25 -0800 Subject: [PATCH 56/95] Remove typescript client generation - All api calls are now through the client or raw XMLHTTPRequest --- Makefile | 3 - http/Makefile | 12 +- ui/mocks/dummyData.ts | 4 +- ui/package-lock.json | 6 +- ui/package.json | 2 +- ui/src/api/api.ts | 20524 ---------------- ui/src/api/configuration.ts | 74 - ui/src/api/custom.d.ts | 1 - ui/src/api/index.ts | 16 - ui/src/authorizations/apis/__mocks__/data.ts | 2 +- ui/src/authorizations/apis/__mocks__/index.ts | 2 +- .../multipleInput/MultipleInput.test.tsx | 2 +- .../multipleInput/MultipleRows.test.tsx | 2 +- .../inputs/multipleInput/Row.test.tsx | 2 +- .../components/label/LabelSelector.tsx | 14 +- .../components/label/LabelSelectorMenu.tsx | 2 +- ui/src/dashboards/actions/v2/index.ts | 2 +- ui/src/dashboards/apis/v2/index.ts | 4 +- .../dashboards/components/DashboardHeader.tsx | 2 +- .../utils/dashboardSwitcherLinks.ts | 2 +- ui/src/dataLoaders/actions/dataLoaders.ts | 4 +- .../components/BucketsDropdown.tsx | 2 +- .../components/DataLoaderSwitcher.tsx | 2 +- .../components/DataLoadersWizard.tsx | 2 +- .../dataLoaders/components/StepSwitcher.tsx | 2 +- .../CollectorsStepSwitcher.tsx | 2 +- .../collectorsWizard/CollectorsWizard.tsx | 2 +- .../configure/ConfigFieldHandler.test.tsx | 5 +- .../configure/PluginConfigForm.test.tsx | 2 +- .../configure/PluginConfigSwitcher.test.tsx | 2 +- .../select/SelectCollectorsStep.tsx | 2 +- .../select/StreamingSelector.tsx | 2 +- .../configureStep/ConfigureDataSourceStep.tsx | 2 +- .../ConfigureDataSourceSwitcher.tsx | 2 +- .../configureStep/ScraperTarget.tsx | 2 +- .../components/configureStep/Scraping.tsx | 2 +- .../streaming/ArrayFormElement.test.tsx | 2 +- .../streaming/ConfigFieldSwitcher.test.tsx | 2 +- .../lineProtocolWizard/LineProtocolWizard.tsx | 2 +- .../configure/LineProtocol.test.tsx | 2 +- .../configure/LineProtocol.tsx | 2 +- .../configure/LineProtocolTabs.tsx | 2 +- .../configure/PrecisionDropdown.tsx | 2 +- .../lineProtocolWizard/configure/TabBody.tsx | 2 +- .../verify/LineProtocolStepSwitcher.tsx | 2 +- ui/src/dataLoaders/constants/pluginConfigs.ts | 3 +- .../dataLoaders/reducers/dataLoaders.test.ts | 2 +- ui/src/dataLoaders/reducers/dataLoaders.ts | 2 +- .../dataLoaders/utils/pluginConfigs.test.ts | 5 +- ui/src/logs/actions/index.ts | 2 +- ui/src/logs/components/LogsHeader.tsx | 2 +- ui/src/logs/containers/logs_page/LogsPage.tsx | 2 +- ui/src/logs/utils/logQuery.test.ts | 2 +- ui/src/logs/utils/logQuery.ts | 2 +- ui/src/me/components/Resources.tsx | 2 +- ui/src/me/components/account/TokenRow.tsx | 2 +- ui/src/me/components/account/Tokens.tsx | 2 +- ui/src/me/components/account/TokensList.tsx | 2 +- .../components/account/ViewTokenOverlay.tsx | 2 +- .../components/CompletionAdvancedButton.tsx | 2 +- .../components/CompletionQuickStartButton.tsx | 2 +- .../onboarding/components/CompletionStep.tsx | 2 +- ui/src/organizations/actions/index.ts | 2 +- ui/src/organizations/apis/index.ts | 2 +- .../components/BucketOverlayForm.tsx | 2 +- ui/src/organizations/components/BucketRow.tsx | 2 +- ui/src/organizations/components/Buckets.tsx | 2 +- .../components/CollectorList.tsx | 2 +- .../organizations/components/CollectorRow.tsx | 2 +- .../organizations/components/Collectors.tsx | 2 +- .../components/CreateBucketOverlay.tsx | 2 +- .../components/CreateOrgOverlay.tsx | 2 +- .../components/GetOrgResources.tsx | 2 +- .../organizations/components/MemberList.tsx | 2 +- ui/src/organizations/components/Members.tsx | 2 +- ui/src/organizations/components/Retention.tsx | 2 +- .../components/RetentionDuration.tsx | 2 +- .../organizations/components/ScraperList.tsx | 2 +- .../organizations/components/ScraperRow.tsx | 2 +- ui/src/organizations/components/Scrapers.tsx | 2 +- ui/src/organizations/components/TaskList.tsx | 2 +- ui/src/organizations/components/TaskRow.tsx | 2 +- ui/src/organizations/components/Tasks.tsx | 2 +- .../components/UpdateBucketOverlay.tsx | 2 +- .../containers/OrganizationView.tsx | 2 +- ui/src/organizations/dummyData.ts | 2 +- ui/src/organizations/reducers/orgs.ts | 2 +- ui/src/protos/actions/index.ts | 2 +- ui/src/protos/reducers/index.ts | 2 +- .../shared/components/EditLabelsOverlay.tsx | 2 +- ui/src/shared/components/FetchLabels.tsx | 2 +- ui/src/shared/utils/labels.ts | 4 +- ui/src/sources/actions/index.ts | 2 +- .../components/CreateSourceOverlay.tsx | 2 +- ui/src/sources/components/SourcesListRow.tsx | 2 +- ui/src/tasks/actions/v2/index.ts | 2 +- ui/src/tasks/components/TaskForm.tsx | 2 +- ui/src/tasks/components/TaskRow.tsx | 2 +- ui/src/tasks/components/TasksList.tsx | 2 +- .../components/TasksOptionsBucketDropdown.tsx | 2 +- .../components/TasksOptionsOrgDropdown.tsx | 2 +- .../components/TasksOptionsOrgIDDropdown.tsx | 2 +- ui/src/tasks/containers/TaskEditPage.tsx | 2 +- ui/src/tasks/containers/TasksPage.tsx | 2 +- ui/src/tasks/dummyData.ts | 2 +- ui/src/tasks/reducers/v2/index.ts | 2 +- ui/src/types/logs.ts | 2 +- ui/src/types/v2/dashboards.ts | 2 +- ui/src/types/v2/dataLoaders.ts | 4 +- ui/src/types/v2/index.ts | 4 +- ui/src/types/v2/labels.ts | 4 +- ui/src/types/v2/tasks.ts | 2 +- 112 files changed, 129 insertions(+), 20750 deletions(-) delete mode 100644 ui/src/api/api.ts delete mode 100644 ui/src/api/configuration.ts delete mode 100644 ui/src/api/custom.d.ts delete mode 100644 ui/src/api/index.ts diff --git a/Makefile b/Makefile index b4dc09908e..315a0ab752 100644 --- a/Makefile +++ b/Makefile @@ -135,9 +135,6 @@ clean: $(RM) -r bin $(RM) -r dist -generate-typescript-client: - make -C http - define CHRONOGIRAFFE ._ o o \_`-)|_ diff --git a/http/Makefile b/http/Makefile index 910531c251..50bbe4259d 100644 --- a/http/Makefile +++ b/http/Makefile @@ -1,12 +1,8 @@ -# List any generated files here -TARGETS = ../ui/src/api/api.ts -# List any source files used to generate the targets here -SOURCES = cur_swagger.yml # List any directories that have their own Makefile here SUBDIRS = # Default target -all: $(SUBDIRS) $(TARGETS) swagger_gen.go +all: $(SUBDIRS) swagger_gen.go # Recurse into subdirs for same make goal $(SUBDIRS): @@ -14,7 +10,6 @@ $(SUBDIRS): # Clean all targets recursively clean: $(SUBDIRS) - rm -f $(TARGETS) rm -f swagger_gen.go swagger_gen.go: swagger.go redoc.go swagger.yml @@ -23,9 +18,4 @@ swagger_gen.go: swagger.go redoc.go swagger.yml GO_RUN := env GO111MODULE=on go run -ifndef SKIP_CLIENT -../ui/src/api/api.ts: $(SOURCES) - openapi-generator generate -g typescript-axios -o ../ui/src/api -i cur_swagger.yml -endif - .PHONY: all clean $(SUBDIRS) diff --git a/ui/mocks/dummyData.ts b/ui/mocks/dummyData.ts index 6aa8f17162..7c181d4f9d 100644 --- a/ui/mocks/dummyData.ts +++ b/ui/mocks/dummyData.ts @@ -1,5 +1,5 @@ import {Template, SourceLinks, TemplateType, TemplateValueType} from 'src/types' -import {Source} from 'src/api' +import {Source} from '@influxdata/influx' import {Cell, Dashboard, Label} from 'src/types/v2' import {Links} from 'src/types/v2/links' import {Task} from 'src/types/v2/tasks' @@ -20,7 +20,7 @@ import { TelegrafPluginInputSwap, Task as TaskApi, Organization, -} from 'src/api' +} from '@influxdata/influx' export const links: Links = { authorizations: '/api/v2/authorizations', diff --git a/ui/package-lock.json b/ui/package-lock.json index ade579bfbd..8b2e3f44d1 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -829,9 +829,9 @@ "dev": true }, "@influxdata/influx": { - "version": "0.1.16", - "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.16.tgz", - "integrity": "sha512-L5gVs6Fe0JD5LxZuFlv0POBGoifi13syqhJmVLGoFmkWKpVVQ/k0ugY8hGwY/1Ub3nbBK/nUnBvr7+kdrxEhHQ==", + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.1.17.tgz", + "integrity": "sha512-8cbN7VGPlNcE3iqqobhY8JKLX33WRgUN9tBWIze4J5SPx2MMO2wlssrQpuEUJ+AwTcMlvGhPlrWaNajW4ZG9Dg==", "requires": { "axios": "^0.18.0" } diff --git a/ui/package.json b/ui/package.json index edd9981332..7386c2ab1b 100644 --- a/ui/package.json +++ b/ui/package.json @@ -117,7 +117,7 @@ }, "dependencies": { "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/influx": "^0.1.16", + "@influxdata/influx": "^0.1.17", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/api/api.ts b/ui/src/api/api.ts deleted file mode 100644 index 87c888e8ea..0000000000 --- a/ui/src/api/api.ts +++ /dev/null @@ -1,20524 +0,0 @@ -// tslint:disable -/// -/** - * Influx API Service - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * OpenAPI spec version: 0.1.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -import * as url from "url"; -import { Configuration } from "./configuration"; -import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; - -const BASE_PATH = "http://localhost:9999/api/v2".replace(/\/+$/, ""); - -/** - * - * @export - */ -export const COLLECTION_FORMATS = { - csv: ",", - ssv: " ", - tsv: "\t", - pipes: "|", -}; - -/** - * - * @export - * @interface RequestArgs - */ -export interface RequestArgs { - url: string; - options: any; -} - -/** - * - * @export - * @class BaseAPI - */ -export class BaseAPI { - protected configuration: Configuration | undefined; - - constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { - if (configuration) { - this.configuration = configuration; - this.basePath = configuration.basePath || this.basePath; - } - } -}; - -/** - * - * @export - * @class RequiredError - * @extends {Error} - */ -export class RequiredError extends Error { - name: "RequiredError" = "RequiredError"; - constructor(public field: string, msg?: string) { - super(msg); - } -} - -/** - * contains the AST for the supplied Flux query - * @export - * @interface ASTResponse - */ -export interface ASTResponse { - /** - * the AST of the supplied Flux query - * @type {any} - * @memberof ASTResponse - */ - ast?: any; -} - -/** - * - * @export - * @interface AnalyzeQueryResponse - */ -export interface AnalyzeQueryResponse { - /** - * - * @type {Array} - * @memberof AnalyzeQueryResponse - */ - errors?: Array; -} - -/** - * - * @export - * @interface AnalyzeQueryResponseErrors - */ -export interface AnalyzeQueryResponseErrors { - /** - * - * @type {number} - * @memberof AnalyzeQueryResponseErrors - */ - line?: number; - /** - * - * @type {number} - * @memberof AnalyzeQueryResponseErrors - */ - column?: number; - /** - * - * @type {number} - * @memberof AnalyzeQueryResponseErrors - */ - character?: number; - /** - * - * @type {string} - * @memberof AnalyzeQueryResponseErrors - */ - message?: string; -} - -/** - * - * @export - * @interface Authorization - */ -export interface Authorization { - /** - * ID of org that authorization is scoped to. - * @type {string} - * @memberof Authorization - */ - orgID: string; - /** - * if inactive the token is inactive and requests using the token will be rejected. - * @type {string} - * @memberof Authorization - */ - status?: Authorization.StatusEnum; - /** - * A description of the token. - * @type {string} - * @memberof Authorization - */ - description?: string; - /** - * List of permissions for an auth. An auth must have at least one Permission. - * @type {Array} - * @memberof Authorization - */ - permissions: Array; - /** - * - * @type {string} - * @memberof Authorization - */ - id?: string; - /** - * Passed via the Authorization Header and Token Authentication type. - * @type {string} - * @memberof Authorization - */ - token?: string; - /** - * ID of user that created and owns the token. - * @type {string} - * @memberof Authorization - */ - userID?: string; - /** - * Name of user that created and owns the token. - * @type {string} - * @memberof Authorization - */ - user?: string; - /** - * Name of the org token is scoped to. - * @type {string} - * @memberof Authorization - */ - org?: string; - /** - * - * @type {AuthorizationLinks} - * @memberof Authorization - */ - links?: AuthorizationLinks; -} - -/** - * @export - * @namespace Authorization - */ -export namespace Authorization { - /** - * @export - * @enum {string} - */ - export enum StatusEnum { - Active = 'active', - Inactive = 'inactive' - } -} - -/** - * - * @export - * @interface AuthorizationLinks - */ -export interface AuthorizationLinks { - /** - * - * @type {string} - * @memberof AuthorizationLinks - */ - self?: string; - /** - * - * @type {string} - * @memberof AuthorizationLinks - */ - user?: string; -} - -/** - * - * @export - * @interface Authorizations - */ -export interface Authorizations { - /** - * - * @type {Links} - * @memberof Authorizations - */ - links?: Links; - /** - * - * @type {Array} - * @memberof Authorizations - */ - authorizations?: Array; -} - -/** - * A description of a particular axis for a visualization - * @export - * @interface Axis - */ -export interface Axis { - /** - * The extents of an axis in the form [lower, upper]. Clients determine whether bounds are to be inclusive or exclusive of their limits - * @type {Array} - * @memberof Axis - */ - bounds?: Array; - /** - * label is a description of this Axis - * @type {string} - * @memberof Axis - */ - label?: string; - /** - * Prefix represents a label prefix for formatting axis values. - * @type {string} - * @memberof Axis - */ - prefix?: string; - /** - * Suffix represents a label suffix for formatting axis values. - * @type {string} - * @memberof Axis - */ - suffix?: string; - /** - * Base represents the radix for formatting axis values. - * @type {string} - * @memberof Axis - */ - base?: string; - /** - * Scale is the axis formatting scale. Supported: \"log\", \"linear\" - * @type {string} - * @memberof Axis - */ - scale?: string; -} - -/** - * - * @export - * @interface Bucket - */ -export interface Bucket { - /** - * - * @type {BucketLinks} - * @memberof Bucket - */ - links?: BucketLinks; - /** - * - * @type {string} - * @memberof Bucket - */ - id?: string; - /** - * - * @type {Owners} - * @memberof Bucket - */ - owners?: Owners; - /** - * - * @type {string} - * @memberof Bucket - */ - name: string; - /** - * - * @type {string} - * @memberof Bucket - */ - organization?: string; - /** - * - * @type {string} - * @memberof Bucket - */ - rp?: string; - /** - * - * @type {string} - * @memberof Bucket - */ - organizationID?: string; - /** - * rules to expire or retain data. No rules means data never expires. - * @type {Array} - * @memberof Bucket - */ - retentionRules: Array; -} - -/** - * - * @export - * @interface BucketLinks - */ -export interface BucketLinks { - /** - * - * @type {string} - * @memberof BucketLinks - */ - self?: string; - /** - * - * @type {string} - * @memberof BucketLinks - */ - org?: string; - /** - * - * @type {string} - * @memberof BucketLinks - */ - write?: string; -} - -/** - * - * @export - * @interface BucketRetentionRules - */ -export interface BucketRetentionRules { - /** - * - * @type {string} - * @memberof BucketRetentionRules - */ - type: BucketRetentionRules.TypeEnum; - /** - * duration in seconds for how long data will be kept in the database. - * @type {number} - * @memberof BucketRetentionRules - */ - everySeconds: number; -} - -/** - * @export - * @namespace BucketRetentionRules - */ -export namespace BucketRetentionRules { - /** - * @export - * @enum {string} - */ - export enum TypeEnum { - Expire = 'expire' - } -} - -/** - * - * @export - * @interface Buckets - */ -export interface Buckets { - /** - * - * @type {Links} - * @memberof Buckets - */ - links?: Links; - /** - * - * @type {Array} - * @memberof Buckets - */ - buckets?: Array; -} - -/** - * - * @export - * @interface Cell - */ -export interface Cell { - /** - * - * @type {string} - * @memberof Cell - */ - id?: string; - /** - * - * @type {CellLinks} - * @memberof Cell - */ - links?: CellLinks; - /** - * - * @type {string} - * @memberof Cell - */ - name?: string; - /** - * - * @type {number} - * @memberof Cell - */ - x?: number; - /** - * - * @type {number} - * @memberof Cell - */ - y?: number; - /** - * - * @type {number} - * @memberof Cell - */ - w?: number; - /** - * - * @type {number} - * @memberof Cell - */ - h?: number; -} - -/** - * - * @export - * @interface CellLinks - */ -export interface CellLinks { - /** - * - * @type {string} - * @memberof CellLinks - */ - self?: string; - /** - * - * @type {string} - * @memberof CellLinks - */ - view?: string; -} - -/** - * - * @export - * @interface CellUpdate - */ -export interface CellUpdate { - /** - * - * @type {string} - * @memberof CellUpdate - */ - name?: string; -} - -/** - * - * @export - * @interface ConstantMacroProperties - */ -export interface ConstantMacroProperties { - /** - * - * @type {string} - * @memberof ConstantMacroProperties - */ - type?: ConstantMacroProperties.TypeEnum; - /** - * - * @type {Array} - * @memberof ConstantMacroProperties - */ - values?: Array; -} - -/** - * @export - * @namespace ConstantMacroProperties - */ -export namespace ConstantMacroProperties { - /** - * @export - * @enum {string} - */ - export enum TypeEnum { - Constant = 'constant' - } -} - -/** - * - * @export - * @interface CreateCell - */ -export interface CreateCell { - /** - * - * @type {string} - * @memberof CreateCell - */ - name?: string; - /** - * - * @type {number} - * @memberof CreateCell - */ - x?: number; - /** - * - * @type {number} - * @memberof CreateCell - */ - y?: number; - /** - * - * @type {number} - * @memberof CreateCell - */ - w?: number; - /** - * - * @type {number} - * @memberof CreateCell - */ - h?: number; - /** - * makes a copy of the provided view - * @type {string} - * @memberof CreateCell - */ - usingView?: string; -} - -/** - * - * @export - * @interface CreateProtoResourcesRequest - */ -export interface CreateProtoResourcesRequest { - /** - * - * @type {string} - * @memberof CreateProtoResourcesRequest - */ - orgID?: string; -} - -/** - * - * @export - * @interface Dashboard - */ -export interface Dashboard { - /** - * - * @type {DashboardLinks} - * @memberof Dashboard - */ - links?: DashboardLinks; - /** - * - * @type {string} - * @memberof Dashboard - */ - id?: string; - /** - * id of organization that owns dashboard - * @type {string} - * @memberof Dashboard - */ - orgID?: string; - /** - * user-facing name of the dashboard - * @type {string} - * @memberof Dashboard - */ - name?: string; - /** - * user-facing description of the dashboard - * @type {string} - * @memberof Dashboard - */ - description?: string; - /** - * - * @type {DashboardMeta} - * @memberof Dashboard - */ - meta?: DashboardMeta; - /** - * - * @type {Array} - * @memberof Dashboard - */ - cells?: Array; - /** - * - * @type {Array