diff --git a/.dockerignore b/.dockerignore index f59dc719..d64bff9c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,25 +1,19 @@ # Misc -.github -.scripts -.static Makefile +Dockerfile # Test environment test # Documentation -README.md - -# Repository config files -.coveralls.yml -.travis.yml +*.md -# Docker config files -Dockerfile -.dockerignore +# All hidden folders +.* # Non-daemon source code client +*_test.go -# Node depedencies -node_modules +# Dependencies +bin diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..a4b33d2d --- /dev/null +++ b/.eslintrc @@ -0,0 +1,38 @@ +{ + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + } + }, + "rules": { + "semi": "error", + "no-mixed-spaces-and-tabs": "error", + "no-trailing-spaces": "error", + "no-const-assign": "error", + "no-lonely-if": "error", + "prefer-const": "error", + "no-var": "error", + "no-useless-computed-key": "error", + "quotes": [ + "error", + "single" + ], + "space-before-function-paren": [ + "error", + { + "anonymous": "always", + "named": "never", + "asyncArrow": "always" + } + ], + "prefer-arrow-callback": "error", + "space-before-blocks": "error", + "no-multiple-empty-lines": "warn", + "no-this-before-super": "warn", + "no-unreachable": "warn", + "constructor-super": "warn", + "valid-typeof": "warn" + } +} diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 74cec18e..b39db661 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -35,8 +35,7 @@ $> go get -u github.com/ubclaunchpad/inertia We use [dep](https://github.com/golang/dep) for managing Golang dependencies, and [npm](https://www.npmjs.com) to manage dependencies for Inertia's React web app. Make sure both are installed before running the following commands. ```bash -$> dep ensure # Inertia CLI and daemon dependencies -$> make web-deps # Inertia Web dependencies +$> make deps # Install all dependencies $> make RELEASE=test # installs Inertia build tagged as "test" $> inertia --version # check what version you have installed ``` diff --git a/.gitignore b/.gitignore index 1db8588f..537cc98d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ *.dll *.so *.dylib -inertia.* +/inertia.* +/inertia +/bin # Test binary, build with `go test -c` *.test diff --git a/.gometalinter.json b/.gometalinter.json new file mode 100644 index 00000000..9f93c809 --- /dev/null +++ b/.gometalinter.json @@ -0,0 +1,15 @@ +{ + "Enable": [ + "megacheck", + "interfacer", + "goconst", + "misspell", + "gofmt", + "goimports", + "gosimple", + "vet" + ], + "Exclude": [ + "client/bootstrap.go" + ] +} diff --git a/.travis.yml b/.travis.yml index 7666c038..ce68d759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,22 +31,18 @@ matrix: fast_finish: true before_install: - - go get honnef.co/go/tools/cmd/megacheck - - go get github.com/fzipp/gocyclo - - go get github.com/mattn/goveralls - - go get github.com/golang/dep/cmd/dep - - dep ensure + - go get -u github.com/mattn/goveralls + - go get -u github.com/golang/dep/cmd/dep + - make deps # Build daemon, run tests, and make various code quality checks script: - make testenv VPS_OS="$VPS_OS" VPS_VERSION="$VERSION" SSH_PORT=69 - - make testdaemon SSH_PORT=69 # Send test daemon to test VPS - - go test -v -race -coverprofile=coverage.out ./... + - make testdaemon SSH_PORT=69 # Send test daemon to testVPS + - go test -v -race -coverprofile=coverage.out ./... # Execute tests - goveralls -coverprofile=coverage.out -service=travis-ci -repotoken "$COVERALLS_TOKEN" - - GO_FILES=$(find . -iname '*.go' -type f | grep -v /vendor/) - - gocyclo -over 19 $GO_FILES # Forbid code with huge functions - - go vet ./... # Report suspicious constructs - - megacheck ./... # Static analysis + - make lint # Static code analysis + - docker kill $(docker ps -q) # Remove testvps, etc # Push version-tagged Docker image and build platform binaries before_deploy: diff --git a/Dockerfile b/Dockerfile index e718e41d..af99f746 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,9 @@ ENV BUILD_HOME=/go/src/github.com/ubclaunchpad/inertia/daemon/web ADD ./daemon/web ${BUILD_HOME} WORKDIR ${BUILD_HOME} # Build and minify client. -RUN npm install --production +RUN if [ ! -d "node_modules" ]; then \ + npm install --production; \ + fi RUN npm run build ### Part 2 - Building the Inertia daemon diff --git a/Gopkg.lock b/Gopkg.lock index ff6059b7..eee04f42 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -13,6 +13,12 @@ revision = "78439966b38d69bf38227fbf57ac8a6fee70f69a" version = "v0.4.5" +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + [[projects]] name = "github.com/davecgh/go-spew" packages = ["spew"] @@ -22,8 +28,8 @@ [[projects]] name = "github.com/dgrijalva/jwt-go" packages = ["."] - revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" - version = "v3.1.0" + revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" + version = "v3.2.0" [[projects]] name = "github.com/docker/distribution" @@ -54,8 +60,8 @@ "client", "pkg/tlsconfig" ] - revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363" - version = "v1.13.1" + revision = "eef6495eddab52828327aade186443681ed71a4e" + version = "v17.03.2-ce-rc1" [[projects]] name = "github.com/docker/go-connections" @@ -73,6 +79,19 @@ revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52" version = "v0.3.2" +[[projects]] + name = "github.com/emirpasic/gods" + packages = [ + "containers", + "lists", + "lists/arraylist", + "trees", + "trees/binaryheap", + "utils" + ] + revision = "f6c17b524822278a87e3b3bd809fec33b51f5b46" + version = "v1.9.0" + [[projects]] name = "github.com/google/go-github" packages = ["github"] @@ -136,8 +155,8 @@ [[projects]] name = "github.com/sirupsen/logrus" packages = ["."] - revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" - version = "v1.0.4" + revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" + version = "v1.0.5" [[projects]] branch = "master" @@ -177,6 +196,8 @@ [[projects]] name = "golang.org/x/crypto" packages = [ + "bcrypt", + "blowfish", "cast5", "curve25519", "ed25519", @@ -284,8 +305,8 @@ "utils/merkletrie/internal/frame", "utils/merkletrie/noder" ] - revision = "886dc83f3ed518a78772055497bcc7d7621b468e" - version = "v4.1.1" + revision = "1d28459504251497e0ce6132a0fadd5eb44ffd22" + version = "v4.2.0" [[projects]] name = "gopkg.in/warnings.v0" @@ -296,6 +317,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5b5d8e6e2a0597fd5a14c0bfc3d0e54dd03347f272439a71d8850f1b6c763a12" + inputs-digest = "00c2d3d5757dba4a76cbd3006884e20477d9c43da5a2e471316e97cd8fa4fd8a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 3441ac26..433bd5bf 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,10 +1,15 @@ +[prune] + non-go = true + unused-packages = true + go-tests = true + [[constraint]] name = "github.com/spf13/cobra" branch = "master" [[constraint]] name = "gopkg.in/src-d/go-git.v4" - version = "4.1.1" + version = "4.2.0" [[constraint]] name = "github.com/google/go-github" @@ -12,20 +17,20 @@ [[constraint]] name = "github.com/sirupsen/logrus" - version = "1.0.4" + version = "1.0.5" [[constraint]] name = "github.com/docker/docker" - version = "1.13.1" + version = "v17.03.2-ce" [[constraint]] name = "github.com/dgrijalva/jwt-go" - version = "3.1.0" + version = "3.2.0" [[constraint]] name = "github.com/BurntSushi/toml" version = "0.3.0" [[constraint]] - revision = "9de5f2eaf759b4c4550b3db39fed2e9e5f86f45c" - name = "golang.org/x/crypto" + name = "github.com/boltdb/bolt" + version = "1.3.1" diff --git a/Makefile b/Makefile index 15e89a47..3291be8a 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,12 @@ all: inertia ls: @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs +# Sets up all dependencies +deps: + curl -sfL https://install.goreleaser.com/github.com/alecthomas/gometalinter.sh | bash + dep ensure + make web-deps + # Install Inertia with release version inertia: go install -ldflags "-X main.Version=$(RELEASE)" @@ -20,11 +26,14 @@ inertia: inertia-tagged: go install -ldflags "-X main.Version=$(TAG)" -# Remove binaries +# Remove Inertia binaries clean: rm -f ./inertia find . -type f -name inertia.\* -exec rm {} \; +lint: + PATH=$(PATH):./bin bash -c './bin/gometalinter --vendor ./...' + # Run unit test suite test: go test ./... -short -ldflags "-X main.Version=test" --cover @@ -34,7 +43,9 @@ test-v: go test ./... -short -ldflags "-X main.Version=test" -v --cover # Run unit and integration tests - creates fresh test VPS and test daemon beforehand +# Also attempts to run linter test-all: + make lint make testenv VPS_OS=$(VPS_OS) VPS_VERSION=$(VPS_VERSION) make testdaemon go test ./... -ldflags "-X main.Version=test" --cover @@ -86,9 +97,9 @@ daemon: bootstrap: go-bindata -o client/bootstrap.go -pkg client client/bootstrap/... -# Install Inertia Web dependencies. +# Install Inertia Web dependencies. Use PACKAGE to install something. web-deps: - (cd ./daemon/web; npm install) + (cd ./daemon/web; npm install $(PACKAGE)) # Run local development instance of Inertia Web. web-run: diff --git a/client/bootstrap.go b/client/bootstrap.go index cfe14ab8..b688dd0b 100644 --- a/client/bootstrap.go +++ b/client/bootstrap.go @@ -72,7 +72,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _clientBootstrapDaemonDownSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\xce\xc1\x4a\xc3\x40\x10\xc6\xf1\xfb\x3c\xc5\x47\xdb\xeb\xe6\x0d\x72\x88\x36\x88\x60\x57\x28\x7a\xf0\xd4\xae\xd9\xd9\x74\x48\x33\x5b\x67\xb7\xa8\x6f\x2f\x22\x42\xe8\xfd\xe3\xff\xfb\xd6\xb8\x0b\x45\x06\x94\xc1\xe4\x52\x91\xb2\xe1\xdd\x44\x47\xd1\x11\x31\x7f\x2a\xea\x89\x11\x03\xcf\x59\x1b\xa2\xc2\x15\x8e\x89\xb6\x5d\xbf\x7b\xf6\x07\xdf\xed\xfa\x56\x94\xad\x4a\x70\x7f\x23\xa2\x35\xee\x4f\x3c\x4c\x90\x84\x70\x36\x0e\xf1\x1b\x76\x55\x15\x1d\x1b\xea\x9e\xf6\x7d\xb7\x7d\x3b\xec\x5f\xbd\x7f\xf4\x0f\xed\xb1\x5c\x63\x46\xcc\xc3\xc4\x86\x4b\x81\xfb\x80\x73\x49\xce\x95\x0d\x2b\x0d\x33\xb7\x9b\x05\xb5\x3a\xfe\xd6\x5f\xc2\xc4\xe0\x2f\x29\xf5\xff\x63\x43\xcb\x8c\xcd\x70\x09\x9b\x1b\x8a\x7e\x02\x00\x00\xff\xff\x8a\x49\xa7\x95\xe9\x00\x00\x00") +var _clientBootstrapDaemonDownSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x5c\xce\xb1\x6e\xc2\x30\x10\xc6\xf1\xfd\x9e\xe2\x2b\xb0\x1a\x9e\x20\x43\x2a\x22\x54\xa9\xb8\x12\x52\x87\x4e\x60\xe2\x73\x38\xd1\x9c\xa9\x7d\xa8\xaf\x5f\x45\x74\x88\xd8\x6e\xf8\xdf\x4f\xdf\xf2\x65\x73\x16\xdd\xd4\x0b\xd1\x12\xaf\xa1\x4a\x8f\xda\x17\xb9\x19\x52\x2e\x38\x17\xd1\x41\x74\x40\xcc\xbf\x0a\xbb\x30\x62\xe0\x31\xeb\x9a\xa8\xb2\xc1\x31\xd1\xb6\xed\xf6\x1f\xfe\xe8\xdb\x7d\xd7\x88\x72\x31\x09\xee\x11\x4d\xe2\x8e\xed\xff\x05\x7d\x56\x0b\x53\x81\xa0\x11\x16\xae\x0c\xb1\x07\x2c\x69\x3a\xa5\xa2\xdc\x55\x45\x87\x35\xb5\xef\x87\xae\xdd\x7e\x1d\x0f\x9f\xde\xbf\xf9\x5d\x73\xaa\xf7\x98\x11\x73\x7f\xe5\x82\x5b\x85\xfb\x81\x73\x49\xbe\x8d\x0b\x16\x1a\x46\x6e\x56\xb3\x21\x8b\x13\xcd\xfb\x32\xc2\x25\xac\x9e\x4c\xfa\x0b\x00\x00\xff\xff\x62\xed\x0f\x4a\xfb\x00\x00\x00") func clientBootstrapDaemonDownShBytes() ([]byte, error) { return bindataRead( @@ -87,12 +87,12 @@ func clientBootstrapDaemonDownSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/daemon-down.sh", size: 233, mode: os.FileMode(420), modTime: time.Unix(1522812136, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-down.sh", size: 251, mode: os.FileMode(420), modTime: time.Unix(1523130093, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _clientBootstrapDaemonUpSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x54\x51\x6f\xdb\x38\x0c\x7e\xd7\xaf\xe0\x9c\x14\x7d\x99\xec\x76\xc3\x01\xbb\x0e\x7e\xc8\xad\xc6\x1a\xac\x4d\x8a\xa4\x87\xc3\xa1\x57\x64\x8a\xcd\xd4\x5a\x6c\x49\x13\xe9\x64\xeb\xaf\x3f\xc8\x4e\xe2\xa4\xe8\x53\x62\x89\xfc\xf8\xf1\xe3\x27\x0e\xe0\x2f\x45\x3a\x07\xca\xbd\x76\x0c\x2b\xeb\x61\xe9\xb5\x79\xd6\xe6\x19\x1a\x07\x5c\x22\x14\x0a\x6b\x6b\x62\x21\x08\x19\x24\x0a\x71\x3d\xca\xee\xa6\x93\xc5\x2c\xbb\xcd\x46\xf3\x2c\x3d\x7b\xbc\x7c\xa2\xfd\xe1\xfd\x74\xf6\x90\x9e\x3d\x7e\x78\x22\x71\x33\x9d\x3f\x2c\x46\xd7\xd7\xb3\x6c\x3e\x4f\xcf\x1e\x3f\x3e\xd1\x21\x75\x32\xba\xcb\x52\x6d\xd0\xb3\x56\xb2\xc3\x17\xe3\xbb\xd1\xd7\x2c\x6d\x96\x79\xa5\x1a\x93\x97\x4e\x15\xc9\x2e\xe2\x6a\x78\x5a\x51\x7c\x99\x4e\x1e\x46\xe3\x49\x36\xeb\xca\x7d\xba\xf8\x74\x29\xc4\x00\xe6\xc8\x81\x73\xa1\x3d\xe6\x6c\xbd\x46\x12\xf5\xba\xd0\x1e\xa4\x83\xe1\xcd\xf4\x2e\x4b\x9c\xb7\x3f\x30\xe7\xd7\xc7\x44\x55\xc8\xff\x52\x62\xbe\x06\xbd\x02\x55\x79\x54\xc5\x6f\xf0\x8d\x31\x41\x08\x65\x0a\x60\xb5\x46\x28\xec\xd6\x00\xfe\xd2\xc4\xe1\x78\x2f\xcc\xe8\x76\x96\x8d\xae\xff\x5d\xcc\xfe\x9e\x4c\xc6\x93\xaf\xe9\x77\x6a\x0a\x0b\x85\xcd\xd7\xe8\xc1\x11\xc8\x9f\x20\xe5\x4a\x57\x8c\x1e\x22\xa3\x6a\x4c\x87\x47\x3a\x44\xdf\x85\x5e\xc1\x23\xbc\x03\xf9\x02\xd1\xf0\x15\x58\x04\x4f\x9f\xc3\x14\x8c\x00\x00\xc0\xbc\xb4\x10\x7d\xd3\x55\x15\xea\x1f\x88\xe4\xd6\xb0\x0a\x62\xc5\x71\x1c\xb5\x81\xc7\x0c\x7c\x0d\x72\x05\xaf\x81\xc5\x4a\x7f\x0e\x4d\xdf\x7b\x74\xca\x23\x28\xe7\xbc\x75\x5e\x2b\xde\x4f\x1c\x74\xad\x9e\x31\xee\xd8\x45\xaf\x66\x10\xc1\xbb\x14\x22\x46\xe2\x53\x86\x03\xb8\x6f\xaa\xaa\xf5\xcd\x6e\x7a\x07\x99\xfa\x06\x42\x48\xe0\x3d\x3e\x8d\x78\x8b\xbc\x0b\x68\xc3\xd6\x1b\x02\x2b\xc2\x23\x94\x5b\xab\x8a\x13\x19\x4e\xe1\x76\xf4\xdf\x02\xad\xac\x2a\x40\xca\x9f\x8d\x0e\x8e\xd6\x90\x74\x19\xb2\xcd\x10\x2b\x1d\x74\x99\x35\xa6\xd7\x15\xb6\x9a\x4b\x50\x79\x8e\x44\xc0\xb6\x6d\xaf\xb4\xc4\x7b\x40\x0a\x3f\xdc\xfa\xc4\x63\x85\x1b\x65\xf8\xd8\x86\x20\xc5\x00\xb8\xd4\x04\x9a\xc0\x60\x40\x51\xfe\x37\x2c\x31\x57\x0d\x21\x6c\x11\xb6\x21\xa3\x7f\x6c\xa1\xc6\x12\x41\x2d\x2b\x04\x62\xe5\x59\x0c\x5a\x70\x62\xeb\x7a\x56\x04\x21\x72\x47\x25\x86\x31\x9f\x13\xa8\x8a\x6c\x1b\xe1\xed\x06\x3d\x69\x55\xbd\x17\x03\x28\x99\x1d\x5d\x25\xc9\x76\xbb\x8d\xab\x4d\x19\x6b\x9b\x38\x4b\x4c\x49\x61\x0d\x4b\xfc\xe5\x2c\xa1\xe4\x12\x65\xd7\x8f\xec\xfa\x91\xc6\xb2\xc4\x0d\x1a\xc9\x56\x2a\xd9\xbb\xac\xe4\xba\x12\x83\xa3\x82\x1e\x73\x5b\xd7\x68\x0a\x2c\x8e\xcb\xfd\x70\xc8\xea\xe5\xc5\xc6\xcf\x9a\xcb\x66\x19\xca\x7e\xb8\xb8\xfc\x23\xb9\xf8\x33\xb9\xf8\x98\x14\xb6\x2d\xd0\xd0\xa1\xac\x36\xfb\x7f\x2b\xeb\x65\xae\x13\x31\x80\x11\x81\x02\x8f\xd4\x54\xfc\xbe\xd3\xb0\x9f\x4a\xa9\x08\xbc\xb5\xbc\x9f\xcc\x4e\x0e\x8f\xb5\x65\x84\x8d\xa3\x58\x9c\x3c\x84\xc6\x80\x0c\x83\xf7\x35\xfc\xd7\x9a\x42\xba\xde\xd8\x61\x95\x44\x57\xd1\xf0\x74\xb9\x44\xfb\xc8\x0d\x24\x1b\xe5\x13\xdf\x98\xa4\x83\x8b\x83\x48\x57\x6f\x1d\xf6\x29\x51\xbb\x5f\xa2\xab\x44\x39\x97\xb4\x86\xd9\x5d\x21\x84\x8b\x74\x77\xdf\x9f\xce\xe7\x37\x8b\x6f\x93\xe9\x3f\x93\x45\xd8\x9e\xf3\xf4\xfc\x90\x99\xc4\x44\x65\xb2\x36\x76\x6b\x16\xe1\x9b\xce\xf7\x59\x32\xac\x94\xbe\x8f\x76\xa7\xec\xee\xa2\xee\xe5\x44\x2d\x91\x7e\x1b\x47\xe2\xff\x00\x00\x00\xff\xff\xf6\xc7\xff\x7f\xf7\x05\x00\x00") +var _clientBootstrapDaemonUpSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x54\x5d\x6f\xe3\x36\x10\x7c\xd7\xaf\x98\xc8\x4e\xd3\x02\x95\xd4\x5c\x5f\x0e\x3e\xe8\x00\xf7\x22\x5c\x82\x26\x76\x60\xe7\x5a\x14\x69\xe0\xa3\xa5\x75\xc4\x5a\x22\x75\xe4\xca\x6e\xfb\xeb\x0b\x52\x72\xfc\x91\x00\x7d\x92\x4d\xee\x0e\x67\x67\x67\x77\x70\x96\x2c\xa5\x4a\x6c\x19\x04\x03\xfc\x22\xac\xcc\x61\x73\x23\x1b\xc6\x4a\x1b\x58\x62\x96\xea\x19\x6d\x83\x1b\x45\x86\xa5\x80\xa1\x6f\xad\x34\x54\x93\x62\x8b\xef\x0b\x69\x28\x67\x6d\x24\xd9\x1f\x41\x9c\xff\x10\x0c\x20\x54\x81\xa5\x91\xca\x25\x72\x49\x28\x04\xd5\x5a\x41\xab\x4a\x2a\x8a\x83\xc0\x12\x23\x22\xf7\xde\x17\x4b\x06\xc2\x3c\xb7\x1e\x2d\x0e\xae\xc6\xd9\xdd\x74\xb2\x98\x65\xb7\xd9\x78\x9e\xa5\xe7\x8f\x97\x4f\x76\x77\x78\x3f\x9d\x3d\xa4\xe7\x8f\xef\x9e\x6c\x70\x3d\x9d\x3f\x2c\xc6\x57\x57\xb3\x6c\x3e\x4f\xcf\x1f\x7f\x7e\xb2\x0e\x6c\x47\x50\xd6\xe2\x99\x50\x10\x0b\x59\xed\x31\x27\xe3\xbb\x2c\x95\x5d\x48\xd4\x31\x0a\x6e\xee\xc6\x9f\xb3\xb4\x5d\xe6\x95\x68\x55\x5e\x36\xa2\x48\xfa\x88\xd1\xf0\x98\x8a\xc7\x67\x14\x9a\xac\xba\x60\xd4\x82\x99\x0c\xb6\xa5\x60\x34\xda\xf0\x61\x99\xa6\x55\x16\x5a\x41\x2a\x7f\x9a\x6b\xc5\xc2\xa1\x3a\x61\x2c\x2a\xad\x9e\xdd\x57\x32\xa4\x45\x2d\x9a\x86\x0a\xb0\xee\x43\x8d\x13\x13\x07\x05\xc7\xc1\xa7\xe9\xe4\x61\x7c\x33\xc9\x66\x9d\x00\xef\x7f\x7a\x7f\xe9\xc8\xcc\x89\x5d\x53\x0e\xe4\x8f\x83\x7a\x5d\x48\x83\xa8\xc1\xf0\x7a\x7a\x97\x25\x8d\xd1\x7f\x51\xce\xa7\xc7\xd6\x56\xa7\x47\x71\x5f\xb5\x03\xfe\x54\x52\xbe\x86\x5c\x41\x54\x86\x44\xf1\x8f\xab\xc7\x77\xd2\x75\x95\xc5\x9a\x50\xe8\xad\x02\xfd\x2d\xad\x77\x46\x57\x75\x1c\x8c\x6f\x67\xd9\xf8\xea\x8f\xc5\xec\xcb\x64\x72\x33\xf9\x9c\x7e\xb5\x6d\xa1\x51\xe8\x7c\x4d\x06\x8d\x45\xf4\x0d\x51\xb4\x92\x95\xd3\x2d\x54\xa2\xa6\x74\x78\xd0\x99\xf0\x6b\x20\x57\x78\xc4\x19\xa2\x7f\x11\x0e\x4f\xc0\x42\x3c\x7d\x70\x0a\xa9\x00\x00\x28\x2f\x35\xc2\xfb\xb6\x73\xe6\x0b\x91\x5d\xfb\xfb\x36\xb0\x86\xad\x88\x9a\xd0\xe7\x1c\x92\x31\x35\xa2\x15\x4e\xdf\xc0\x47\x24\x05\x6d\x12\xd5\x56\x15\xde\x7d\xfc\xee\x32\x58\xc9\x0f\x41\xc7\x2a\x3c\x71\x43\x88\xb3\x14\x21\x93\xe5\x63\x66\x03\x5c\xe9\xad\xaa\xb4\x28\xfc\x94\x90\x65\x2a\x76\x7c\xbc\x2b\xe3\x83\x02\x76\xa1\x8e\xfb\xd0\x3b\xf1\x35\xd5\xc6\x91\xe9\x2e\x5f\xf3\xa3\xca\x52\xff\xec\xad\x7b\xd2\xf1\xc1\xb2\x95\x55\x01\x76\xc6\xb4\xa5\x6e\xab\x02\xa5\xd8\x10\x96\x44\x0a\x36\x6f\x2e\x0a\x48\xc5\xba\x4f\x73\xa6\xfb\xed\x7e\x0e\xc1\x48\x3a\x9a\xd1\x2b\x9a\xb7\xff\x43\xd1\x57\x1b\xc9\x63\x80\xb7\xc4\x74\xe6\x9a\xb5\x6a\x3f\x10\xd8\x4a\x2e\x21\xf2\x9c\xac\xdd\x8d\x40\xa9\x2d\xef\x90\xad\xfb\xb0\xf7\x5d\x30\x80\xa1\x8a\x36\x42\x71\x1f\xb2\xf7\xbd\x4b\x15\x55\xa5\xb7\x7e\x61\xed\xd1\xdd\x2f\xa3\xab\xd8\x0f\x0b\x79\x74\xd7\xf0\xbb\xcc\xc7\xd5\xda\xbc\xec\x08\x37\xad\xa5\xde\x82\x4b\x69\xb1\xd5\x66\x6d\x47\xc1\x00\x25\x73\x63\x47\x49\xf2\x2c\xb9\x6c\x97\x71\xae\xeb\xe4\xad\x4d\x31\x28\xf5\x36\x92\x1c\xf9\xbc\xa0\xd3\x6c\xd6\x8f\xcc\xcb\xe2\xeb\x96\xc4\xf0\x60\xb0\xc3\xe0\xc8\x92\xad\x42\x54\x20\x8a\x4c\x8d\x3f\xbd\xc4\x51\xb3\x77\x9d\x8f\x1f\x85\xc3\xe3\x55\x10\xee\x22\x37\x48\x36\xc2\x24\xa6\x55\x49\x07\x17\x3b\xe5\x46\x6f\x1d\xee\x53\x42\x3f\xf9\xe1\x28\x11\x4d\x93\x78\x49\xfb\x2b\x82\xbb\x48\xfb\xfb\xfd\xe9\x7c\x7e\xbd\xf8\x75\x32\xfd\x7d\xb2\x70\xdb\x77\x9e\x5e\xbc\x64\x26\xb1\xb5\x65\xb2\x56\x7a\xab\x16\xee\xbf\xbd\xd8\x65\x45\x6e\xce\xf7\x75\xf8\x41\xef\xef\xc2\xde\x4f\x9e\xc8\x7e\x9b\x87\xaf\x9d\xf3\x5f\x00\x00\x00\xff\xff\x12\x2d\x88\x33\xa1\x06\x00\x00") func clientBootstrapDaemonUpShBytes() ([]byte, error) { return bindataRead( @@ -107,12 +107,12 @@ func clientBootstrapDaemonUpSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1527, mode: os.FileMode(493), modTime: time.Unix(1522816187, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1697, mode: os.FileMode(493), modTime: time.Unix(1523130426, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _clientBootstrapDockerSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x52\xd1\x6e\xd4\x30\x10\x7c\xf7\x57\x0c\xbd\x53\x0b\x52\x93\xb4\x15\xe2\x81\xaa\x48\xe5\x7a\x0f\x88\x4a\x95\x7a\xed\x33\x72\x93\xcd\xc5\x6a\x62\xa7\xde\x75\x4b\x40\xfc\x3b\xb2\x2f\x09\x14\x10\x90\x27\xc7\x3b\x3b\x9e\x99\xdd\xc5\x8b\xe2\xce\xd8\x82\x1b\xa5\x16\x78\xef\x9c\xb0\x78\xdd\x33\x34\x3a\x5d\x36\xc6\x12\x6a\xe7\x51\xb9\xf2\x9e\x3c\xb4\xad\xc6\x63\x56\xba\xae\x77\x4c\xb9\x5a\xe0\xa6\x31\x0c\xc3\xe8\x3d\x89\x0c\xd0\x6d\xdf\xe8\x1c\x1f\x2c\x8b\x6e\x5b\x46\x19\x7c\x0b\x67\xdb\x01\xa6\x86\x11\x54\x8e\xd8\x1e\x08\xe8\xb3\x61\x49\xfd\xc4\x42\x15\x9c\xc5\xed\x5d\xb0\x12\x70\xfc\x26\x3f\x7a\x7d\x08\x4f\x0f\xc1\x78\x62\x70\xa8\x5c\x92\xa1\x51\xd3\x13\x58\xa8\xe7\x5c\x29\x26\x41\x46\x4a\x5d\x5c\xad\x3e\xae\xaf\x3f\x6d\xae\x6e\xaf\x57\xeb\xb3\x2d\x49\xbe\xd3\x98\x97\xae\x9b\x8a\x17\xeb\xcd\xcd\xd9\x41\x21\x5d\x5f\x6c\x49\xb2\x11\xc0\xcd\x41\xb4\xbd\x6a\xa8\xbc\x8f\xea\x26\x9b\x9e\x74\x35\xc0\xec\x1c\x50\x95\x2b\x53\xa3\xd1\xdc\x4c\x80\x93\x77\x45\x45\x8f\x85\x0d\x6d\x7b\x0a\x69\xc8\x2a\x00\xd1\x90\xe0\x48\xd5\xe6\x54\xa9\x9a\xa4\x6c\x6a\xd3\xd2\xcb\x57\xf8\x9a\xaa\x0b\x9c\xfb\x2d\xbf\x1d\xcf\xc0\xf2\x18\xec\x82\x2f\x09\xb7\xd7\x97\x3f\x6e\x4f\x50\x11\x8b\xb1\x5a\x8c\xb3\x88\x0c\x79\x2a\x4e\x0a\x52\x9a\x7f\x7e\x3f\x7e\x29\xaa\x84\xc9\x6a\xde\x5c\xc6\x57\x32\x87\xbd\xe5\xc9\xde\x4e\x62\x3b\xf1\x3c\x6d\x49\xfe\xc5\x93\x30\xd9\x55\x6a\xc7\xf2\x78\x64\x60\x9a\x51\x9e\x24\x78\x8b\x5d\x25\xfa\xfe\x16\xe3\x3c\xef\xf4\x17\x67\xb1\x5e\x6d\x76\x11\xda\x92\x78\x1a\x26\xca\xc0\xe2\xba\x29\xdb\x18\xec\xd6\x53\x8f\xec\x61\x6a\x2b\x48\xca\x82\x07\x16\xea\x32\x4f\x2d\x69\xa6\x9f\xb4\x25\x5d\x43\x98\x09\x90\x0d\xe3\x50\xd4\xac\x6c\x81\x1b\x3f\x40\x1c\x2a\xf7\x64\x5b\xa7\x2b\x04\x36\x76\x3b\x2e\xa2\x4f\xb6\x0e\x47\xe4\x1d\xd5\xce\x13\x3c\xb1\xf3\x12\x41\xe2\x26\xea\xa9\x65\xce\x7f\x9e\x29\x96\xcf\x56\x6e\xfe\x8d\x4b\xf6\x6b\x8e\xcd\xb3\xea\xef\x11\xea\x5e\xb2\x18\x73\xe8\x2b\x2d\x84\xfd\xfd\xf9\x26\x9b\x37\x30\xc9\x98\x3b\xfe\x4b\xc6\x5f\x05\xd4\x46\xd5\x46\xa9\x94\x25\x93\x7f\x34\x25\x4d\x9b\xcd\xa2\xbd\xa8\xef\x01\x00\x00\xff\xff\xc6\xe8\xe7\x56\x15\x04\x00\x00") +var _clientBootstrapDockerSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x52\x5d\x6f\xd4\x30\x10\x7c\xf7\xaf\x18\x7a\xa7\x16\x24\x7c\xa1\xf7\x48\x55\xa4\x72\x77\x4f\x54\x3a\xe9\xae\x7d\x46\xae\xb3\x49\xac\x26\x76\xea\xdd\xb4\x04\xc4\x7f\x47\xf9\x84\x82\x80\xe6\xc9\xf1\xcc\xce\x8e\x67\x77\xf1\x2a\xb9\x73\x3e\xe1\x42\xa9\x05\x3e\x86\x20\x2c\xd1\xd4\x0c\x83\xca\xd8\xc2\x79\x42\x16\x22\xd2\x60\xef\x29\xc2\xf8\x74\x3c\x6a\x1b\xaa\x3a\x30\xad\x94\x62\x12\x68\x52\x6a\xbb\xdf\x7c\xda\x1d\x3e\x1f\xf7\xb7\x87\xcd\xee\x32\x27\x59\x0d\xd4\x95\x0d\xd5\x04\x6e\x77\xc7\x9b\xcb\xb3\x44\xaa\x3a\xc9\x49\xf4\x48\xe0\xe2\xac\xeb\x7e\xbc\x77\x35\x9c\x67\x31\x65\x69\xc4\x05\x0f\x97\x61\x3b\x74\x76\x0c\x53\x46\x32\x69\x3b\x31\x28\x5d\x29\x97\xa1\x30\x5c\x4c\xf6\xd6\x1f\x92\x94\x1e\x13\xdf\x94\xe5\x05\xa4\x20\xaf\x00\x80\xbe\x38\xc1\x3b\x95\xb9\x0b\xa5\x32\x12\x5b\x64\xae\xa4\xd7\x6f\xf0\xad\x47\x17\xb8\x8a\x39\xbf\x1f\xcf\xc0\xf2\x1c\x1c\x9a\x68\x09\xb7\x87\xeb\x9f\xb7\x6b\xa4\xc4\xe2\xfc\xe0\xab\x53\x58\xf5\xe0\xe4\xc0\x36\xb1\xfc\x4b\xff\xee\xe3\x26\x0d\x03\x47\x67\x7c\xbc\xee\xba\xe8\x80\x93\xe5\xfa\x64\xb0\x58\x4e\x3a\x4f\x39\xc9\xff\x74\x7a\x8e\xde\xf7\xe5\x58\x9e\x8f\x0a\x4c\x33\x2b\x92\x34\xd1\x63\x40\xba\x77\x7f\xef\xe2\xbd\xaa\xcc\xd7\xe0\xb1\xdb\x1c\x87\x08\xbd\x25\x46\xa4\x87\xc6\x45\x82\x6d\x58\x42\x35\x65\xdb\x05\x9b\x47\xaa\xa1\x1f\xa6\xb2\x84\xc4\x26\xdc\xb2\x50\xa5\x23\x95\x64\x98\x7e\xf1\xd6\xfb\x6a\x9b\x59\x00\xba\x1d\x87\xa2\x66\x67\x0b\xdc\xc4\x16\x12\x90\x86\x27\x5f\x06\x93\xa2\x61\xe7\xf3\x21\x96\x10\xfb\x67\xbd\x1d\x99\x77\x94\x85\x48\x88\xc4\x21\x4a\x47\x92\x30\x49\x4f\x25\x73\xfe\xf3\x4c\xb1\x7c\xb6\x82\xf3\x6f\xb7\x74\xbf\xe7\x58\x3c\x43\xff\x8c\xd0\xd4\xa2\xbb\x98\x9b\x3a\x35\x42\x38\x3d\x9d\x6f\xf4\xbc\x81\xbd\x8d\xb9\xe2\x45\x36\xfe\x69\x20\x73\x2a\x73\x4a\xf5\x59\x32\xc5\x47\x67\x69\xda\x6c\x16\x13\x45\xfd\x08\x00\x00\xff\xff\x55\xed\x48\x14\xac\x03\x00\x00") func clientBootstrapDockerShBytes() ([]byte, error) { return bindataRead( @@ -127,7 +127,7 @@ func clientBootstrapDockerSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/docker.sh", size: 1045, mode: os.FileMode(493), modTime: time.Unix(1522901380, 0)} + info := bindataFileInfo{name: "client/bootstrap/docker.sh", size: 940, mode: os.FileMode(493), modTime: time.Unix(1523130093, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -152,7 +152,7 @@ func clientBootstrapKeygenSh() (*asset, error) { return a, nil } -var _clientBootstrapTokenSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x4c\x90\xc1\x4a\xc3\x40\x10\x86\xef\xfb\x14\xbf\xb4\xd2\x53\xb2\xf7\x42\x0e\x45\x82\x29\xd6\x46\x8c\xe0\x45\x08\xdb\x64\x74\x97\xd8\xd9\xb8\xb3\x6b\xf1\xed\x25\x9a\x6a\x8f\x33\xdf\x7c\x3f\x33\xb3\xb8\xd2\x07\xc7\x5a\xac\x52\x42\x11\x19\x29\xf5\x58\xee\xca\x4d\x53\x16\xd7\xa2\xd4\x02\xb7\xc4\x14\x4c\x24\x81\x61\x34\x4d\x85\xe8\x07\x62\xbc\xfa\x80\x24\x84\x93\x8b\x16\x9b\x87\x2d\x02\x7d\x24\x92\x28\xf9\x85\x03\x83\xde\xd0\xd1\xf3\x2c\x25\x71\xfc\x86\x9b\xdd\x36\x57\x92\x7a\x8f\xde\x77\x03\x05\x84\xc4\xc8\xb2\x70\xc4\x8b\x02\x80\xec\x13\xcb\xaa\xbe\x2f\xd7\xda\x8c\xa3\xb6\x5e\xe2\x19\xd0\xb4\x40\x7b\xb7\xaf\x9f\xf7\x6d\x55\x37\x4f\x4d\xb1\xfa\x9b\xd1\xb9\x88\xd5\x03\xfb\x13\xb7\x53\x2d\xab\x7f\x6b\x4a\x2b\x7e\x32\xcf\xbd\x8c\x38\x86\xaf\xd1\x3b\x8e\x85\x63\x0a\xd1\x99\x19\xa5\x43\xf7\x6e\x12\x77\x76\x34\xbd\x9e\xd1\x7a\x39\xff\xe4\xf7\x0e\xf5\x1d\x00\x00\xff\xff\xa4\x4f\x24\xd1\x35\x01\x00\x00") +var _clientBootstrapTokenSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\xcf\x41\x4b\xfb\x40\x10\x05\xf0\xfb\x7e\x8a\xf7\xa7\xfd\xd3\x53\xb2\xf7\x42\x0e\x45\x82\x29\xd6\x46\x8c\xe2\x45\x08\xdb\x64\x6c\x42\xcc\x6c\x9c\xd9\x55\xfc\xf6\x12\x4d\xf5\x38\xf3\x9b\x79\xf0\x56\xff\xec\xa9\x67\xab\x9d\x31\x4a\x01\x09\x19\xb3\xc2\xa3\x92\xc0\xc9\x39\x8e\xc4\x21\x35\xf7\xf9\x21\xdf\x55\x79\xf6\x5f\x67\xbc\x26\x26\x71\x81\xe0\xd0\x3a\x1a\x3d\x23\xf8\x81\x18\x51\x7b\x3e\xe3\xea\xb0\xc7\x8b\x17\xec\xee\xf6\x10\x7a\x8b\xa4\x41\x53\xa3\xb1\xf5\x68\x7d\x33\x90\x40\x22\x23\x49\x64\xc4\xb3\x01\x80\xe4\x1d\xeb\xa2\xbc\xcd\xb7\xd6\x4d\x93\xed\xbc\x86\x0b\x10\xaa\xaa\xa8\x6f\x8e\xe5\xd3\xb1\x2e\xca\xea\xa1\xca\x36\xbf\x37\x36\x55\xed\xec\xc0\xfe\x83\xeb\x79\xd6\xcd\xdf\xd7\x9c\x96\x7d\x67\x5e\x76\x09\x71\x90\xcf\xc9\xf7\x1c\xb2\x9e\x49\x42\xef\x16\x8a\xa7\xe6\xd5\x45\x6e\xba\xc9\xb5\x76\xa1\xed\x7a\x29\xfc\x53\xcc\x7c\x05\x00\x00\xff\xff\xfc\x14\x01\x6b\x23\x01\x00\x00") func clientBootstrapTokenShBytes() ([]byte, error) { return bindataRead( @@ -167,7 +167,7 @@ func clientBootstrapTokenSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 309, mode: os.FileMode(493), modTime: time.Unix(1522812136, 0)} + info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 291, mode: os.FileMode(493), modTime: time.Unix(1523130093, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -225,10 +225,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ "client/bootstrap/daemon-down.sh": clientBootstrapDaemonDownSh, - "client/bootstrap/daemon-up.sh": clientBootstrapDaemonUpSh, - "client/bootstrap/docker.sh": clientBootstrapDockerSh, - "client/bootstrap/keygen.sh": clientBootstrapKeygenSh, - "client/bootstrap/token.sh": clientBootstrapTokenSh, + "client/bootstrap/daemon-up.sh": clientBootstrapDaemonUpSh, + "client/bootstrap/docker.sh": clientBootstrapDockerSh, + "client/bootstrap/keygen.sh": clientBootstrapKeygenSh, + "client/bootstrap/token.sh": clientBootstrapTokenSh, } // AssetDir returns the file names below a certain @@ -270,14 +270,15 @@ type bintree struct { Func func() (*asset, error) Children map[string]*bintree } + var _bintree = &bintree{nil, map[string]*bintree{ "client": &bintree{nil, map[string]*bintree{ "bootstrap": &bintree{nil, map[string]*bintree{ "daemon-down.sh": &bintree{clientBootstrapDaemonDownSh, map[string]*bintree{}}, - "daemon-up.sh": &bintree{clientBootstrapDaemonUpSh, map[string]*bintree{}}, - "docker.sh": &bintree{clientBootstrapDockerSh, map[string]*bintree{}}, - "keygen.sh": &bintree{clientBootstrapKeygenSh, map[string]*bintree{}}, - "token.sh": &bintree{clientBootstrapTokenSh, map[string]*bintree{}}, + "daemon-up.sh": &bintree{clientBootstrapDaemonUpSh, map[string]*bintree{}}, + "docker.sh": &bintree{clientBootstrapDockerSh, map[string]*bintree{}}, + "keygen.sh": &bintree{clientBootstrapKeygenSh, map[string]*bintree{}}, + "token.sh": &bintree{clientBootstrapTokenSh, map[string]*bintree{}}, }}, }}, }} @@ -328,4 +329,3 @@ func _filePath(dir, name string) string { cannonicalName := strings.Replace(name, "\\", "/", -1) return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) } - diff --git a/client/bootstrap/daemon-down.sh b/client/bootstrap/daemon-down.sh index fbcd91f5..f323ae2b 100644 --- a/client/bootstrap/daemon-down.sh +++ b/client/bootstrap/daemon-down.sh @@ -1,11 +1,11 @@ +#!/bin/sh + # Basic script for bringing down the daemon. set -e DAEMON_NAME=inertia-daemon -# Check if already running. +# Get daemon container and take it down if it is running. ALREADY_RUNNING=`sudo docker ps -q --filter "name=$DAEMON_NAME"` - -# Take existing down. sudo docker rm -f $ALREADY_RUNNING diff --git a/client/bootstrap/daemon-up.sh b/client/bootstrap/daemon-up.sh index 89856462..5b9f5e5a 100755 --- a/client/bootstrap/daemon-up.sh +++ b/client/bootstrap/daemon-up.sh @@ -1,43 +1,51 @@ -# Basic script for bringing up the daemon. +#!/bin/sh + +# Basic script for setting up Inertia requirements (directories, etc) +# and brining the daemon online. set -e +# User arguments. DAEMON_RELEASE=%[1]s DAEMON_PORT=%[2]s HOST_ADDRESS=%[3]s +# Inertia image details. DAEMON_NAME=inertia-daemon IMAGE=ubclaunchpad/inertia:$DAEMON_RELEASE + +# It doesn't matter what port the daemon runs on in the container +# as long as it is mapped to the correct DAEMON_PORT. CONTAINER_PORT=8081 -# Set up directories +# Set up directories. mkdir -p $HOME/project mkdir -p $HOME/ssl +mkdir -p $HOME/.inertia # Check if already running and take down existing daemon. ALREADY_RUNNING=`sudo docker ps -q --filter "name=$DAEMON_NAME"` if [ ! -z "$ALREADY_RUNNING" ]; then - echo "Killing existing container..." - sudo docker rm -f $ALREADY_RUNNING + echo "Putting existing Inertia daemon to sleep" + sudo docker rm -f $ALREADY_RUNNING > /dev/null 2>&1 fi; -# Prepare appropriate daemon image. if [ "$DAEMON_RELEASE" != "test" ]; then - # Pull the inertia daemon. - echo "Pulling Inertia daemon..." - sudo docker pull $IMAGE + # Download requested daemon image. + echo "Downloading $IMAGE" + sudo docker pull $IMAGE > /dev/null 2>&1 else - echo "Loading existing Inertia daemon image..." - sudo docker load --quiet -i /daemon-image + # Load test build that should have been scp'd into + # the VPS at /daemon-image. + echo "Loading $IMAGE" + sudo docker load -i /daemon-image > /dev/null 2>&1 fi -# Run container with access to the host docker socket and relevant directories - -# this is necessary because we want the daemon to be able start -# and stop containers on the host. It's also controversial, -# https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container.html -# It's also recommended, -# https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/ -# As a result, this container has root access on the remote vps. +# Run container with access to the host docker socket and +# relevant host directories to allow for container control. +# See the README for more details on how this works: +# https://github.com/ubclaunchpad/inertia#how-it-works +echo "Running daemon on port $DAEMON_PORT" sudo docker run -d --rm \ -p "$DAEMON_PORT":"$CONTAINER_PORT" \ -v /var/run/docker.sock:/var/run/docker.sock \ @@ -45,4 +53,4 @@ sudo docker run -d --rm \ -e HOME="$HOME" \ -e SSH_KNOWN_HOSTS='/app/host/.ssh/known_hosts' \ --name "$DAEMON_NAME" \ - "$IMAGE" "$HOST_ADDRESS" + "$IMAGE" "$HOST_ADDRESS" > /dev/null 2>&1 diff --git a/client/bootstrap/docker.sh b/client/bootstrap/docker.sh index f50a79cf..43532641 100755 --- a/client/bootstrap/docker.sh +++ b/client/bootstrap/docker.sh @@ -1,15 +1,13 @@ #!/bin/sh # Bootstraps a machine for docker and docker-compose. -# This is pretty alpha. Installs curl only if it doesn't exist. -# Tested on Ubuntu 16.04, requires sudo for a few steps. set -e DOCKER_SOURCE=get.docker.com DOCKER_DEST='/tmp/get-docker.sh' -# Check if docker aready installed. +# Skip installation if Docker is already installed. if hash docker 2>/dev/null; then exit 0 fi; diff --git a/client/bootstrap/token.sh b/client/bootstrap/token.sh index dfc9e00b..78f4ab57 100755 --- a/client/bootstrap/token.sh +++ b/client/bootstrap/token.sh @@ -2,10 +2,10 @@ set -e +# User argument. RELEASE=%s -# Generates an SSH token for use with API requests. -# Generate a daemon token using CLI. +# Generate a daemon token using CLI for API requests. sudo docker run --rm \ -v $HOME:/app/host \ -e SSH_KNOWN_HOSTS='/app/host/.ssh/known_hosts' \ diff --git a/client/deployment.go b/client/deployment.go index 7f2dfdbc..5a902932 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -73,24 +73,24 @@ func (d *Deployment) Up(buildType string, stream bool) (*http.Response, error) { Branch: d.Branch, }, } - return d.post("/up", reqContent) + return d.request("POST", "/up", reqContent) } // Down brings the project down on the remote VPS instance specified // in the configuration object. func (d *Deployment) Down() (*http.Response, error) { - return d.post("/down", nil) + return d.request("POST", "/down", nil) } // Status lists the currently active containers on the remote VPS instance func (d *Deployment) Status() (*http.Response, error) { - return d.post("/status", nil) + return d.request("GET", "/status", nil) } // Reset shuts down deployment and deletes the contents of the deployment's // project directory func (d *Deployment) Reset() (*http.Response, error) { - return d.post("/reset", nil) + return d.request("POST", "/reset", nil) } // Logs get logs of given container @@ -99,10 +99,36 @@ func (d *Deployment) Logs(stream bool, container string) (*http.Response, error) Stream: stream, Container: container, } - return d.post("/logs", reqContent) + return d.request("GET", "/logs", reqContent) } -func (d *Deployment) post(endpoint string, requestBody *common.DaemonRequest) (*http.Response, error) { +// AddUser adds an authorized user for access to Inertia Web +func (d *Deployment) AddUser(username, password string, admin bool) (*http.Response, error) { + reqContent := &common.UserRequest{ + Username: username, + Password: password, + Admin: admin, + } + return d.request("POST", "/user/adduser", reqContent) +} + +// RemoveUser prevents a user from accessing Inertia Web +func (d *Deployment) RemoveUser(username string) (*http.Response, error) { + reqContent := &common.UserRequest{Username: username} + return d.request("POST", "/user/removeuser", reqContent) +} + +// ResetUsers resets all users on the remote. +func (d *Deployment) ResetUsers() (*http.Response, error) { + return d.request("POST", "/user/resetusers", nil) +} + +// ListUsers lists all users on the remote. +func (d *Deployment) ListUsers() (*http.Response, error) { + return d.request("GET", "/user/listusers", nil) +} + +func (d *Deployment) request(method, endpoint string, requestBody interface{}) (*http.Response, error) { // Assemble URL url, err := url.Parse("https://" + d.RemoteVPS.GetIPAndPort()) if err != nil { @@ -114,7 +140,7 @@ func (d *Deployment) post(endpoint string, requestBody *common.DaemonRequest) (* // Assemble request var payload io.Reader if requestBody != nil { - body, err := json.Marshal(*requestBody) + body, err := json.Marshal(requestBody) if err != nil { return nil, err } @@ -122,7 +148,7 @@ func (d *Deployment) post(endpoint string, requestBody *common.DaemonRequest) (* } else { payload = nil } - req, err := http.NewRequest("POST", urlString, payload) + req, err := http.NewRequest(method, urlString, payload) if err != nil { return nil, err } diff --git a/client/deployment_test.go b/client/deployment_test.go index 9c09b5ee..08574821 100644 --- a/client/deployment_test.go +++ b/client/deployment_test.go @@ -123,7 +123,7 @@ func TestStatus(t *testing.T) { rw.WriteHeader(http.StatusOK) // Check request method - assert.Equal(t, "POST", req.Method) + assert.Equal(t, "GET", req.Method) // Check correct endpoint called endpoint := req.URL.Path @@ -177,7 +177,7 @@ func TestLogs(t *testing.T) { rw.WriteHeader(http.StatusOK) // Check request method - assert.Equal(t, "POST", req.Method) + assert.Equal(t, "GET", req.Method) // Check correct endpoint called endpoint := req.URL.Path diff --git a/client/remote.go b/client/remote.go index 28a072e8..c18c8dd2 100644 --- a/client/remote.go +++ b/client/remote.go @@ -41,9 +41,8 @@ func (remote *RemoteVPS) GetIPAndPort() string { // public-private key-pair. It outputs configuration information // for the user. func (remote *RemoteVPS) Bootstrap(runner SSHSession, name string, config *Config) error { - println("Setting up remote " + name + " at " + remote.IP) + println("Setting up remote \"" + name + "\" at " + remote.IP) - // Generate a session for each command. println(">> Step 1/4: Installing docker...") err := remote.installDocker(runner) if err != nil { @@ -59,6 +58,8 @@ func (remote *RemoteVPS) Bootstrap(runner SSHSession, name string, config *Confi return err } + // This step needs to run before any other commands that rely on + // the daemon image, since the daemon is loaded here. println("\n>> Step 3/4: Starting daemon...") if err != nil { return err diff --git a/common/request.go b/common/request.go index c22a9b20..e08d4cb1 100644 --- a/common/request.go +++ b/common/request.go @@ -1,14 +1,8 @@ package common const ( - // DefaultSecret used for some verification - DefaultSecret = "inertia" - // MsgDaemonOK is the OK response upon successfully reaching daemon MsgDaemonOK = "I'm a little Webhook, short and stout!" - - // DefaultPort defines the standard daemon port - DefaultPort = "8081" ) // DaemonRequest is the configurable body of a request to the daemon. @@ -26,3 +20,11 @@ type GitOptions struct { RemoteURL string `json:"remote"` Branch string `json:"branch"` } + +// UserRequest is used for logging in or modifying users +type UserRequest struct { + Username string `json:"username"` + Password string `json:"password"` + Email string `json:"email"` + Admin bool `json:"admin"` +} diff --git a/daemon/inertia/auth/auth.go b/daemon/inertia/auth/auth.go index ef3d063f..f543ccd3 100644 --- a/daemon/inertia/auth/auth.go +++ b/daemon/inertia/auth/auth.go @@ -10,19 +10,22 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" ) -var ( +const ( // DaemonGithubKeyLocation is the default path of the deploy key DaemonGithubKeyLocation = "/app/host/.ssh/id_rsa_inertia_deploy" - malformedAuthStringErrorMsg = "Malformed authentication string" - tokenInvalidErrorMsg = "Token invalid" + tokenInvalidErrorMsg = "Token invalid" ) // GetAPIPrivateKey returns the private RSA key to authenticate HTTP // requests sent to the daemon. For now, we simply use the GitHub -// deploy key. -func GetAPIPrivateKey(*jwt.Token) (interface{}, error) { - pemFile, err := os.Open(DaemonGithubKeyLocation) +// deploy key. Retrieves from default DaemonGithubKeyLocation. +func GetAPIPrivateKey(t *jwt.Token) (interface{}, error) { + return getAPIPrivateKeyFromPath(t, DaemonGithubKeyLocation) +} + +func getAPIPrivateKeyFromPath(t *jwt.Token, path string) (interface{}, error) { + pemFile, err := os.Open(path) if err != nil { return nil, err } @@ -51,8 +54,12 @@ func GenerateToken(key []byte) (string, error) { } // GitAuthFailedErr attaches the daemon key in the error message -func GitAuthFailedErr() error { - bytes, err := ioutil.ReadFile(DaemonGithubKeyLocation + ".pub") +func GitAuthFailedErr(path ...string) error { + keyLoc := DaemonGithubKeyLocation + if len(path) > 0 { + keyLoc = path[0] + } + bytes, err := ioutil.ReadFile(keyLoc + ".pub") if err != nil { bytes = []byte(err.Error() + "\nError reading key - try running 'inertia [REMOTE] init' again: ") } diff --git a/daemon/inertia/auth/auth_test.go b/daemon/inertia/auth/auth_test.go index 17cb31f0..7211162b 100644 --- a/daemon/inertia/auth/auth_test.go +++ b/daemon/inertia/auth/auth_test.go @@ -1,94 +1,57 @@ package auth import ( - "fmt" - "net/http" - "net/http/httptest" "os" "path" "testing" jwt "github.com/dgrijalva/jwt-go" "github.com/stretchr/testify/assert" - "github.com/ubclaunchpad/inertia/common" ) var ( - testPrivateKey = []byte("very_sekrit_key") - testToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.AqFWnFeY9B8jj7-l3z0a9iaZdwIca7xhUF3fuaJjU90" + testPrivateKey = []byte("very_sekrit_key") + testToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.AqFWnFeY9B8jj7-l3z0a9iaZdwIca7xhUF3fuaJjU90" + testInertiaKeyPath = path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test/keys/id_rsa") ) +// Helper function that implements jwt.keyFunc func getFakeAPIKey(tok *jwt.Token) (interface{}, error) { return testPrivateKey, nil } -func TestGenerateToken(t *testing.T) { - token, err := GenerateToken(testPrivateKey) - assert.Nil(t, err, "generateToken must not fail") - assert.Equal(t, token, testToken) -} - -func TestAuthorizationOK(t *testing.T) { - req, _ := http.NewRequest("GET", "/health-check", nil) - - // Set the token for authorization. - bearerTokenString := fmt.Sprintf("Bearer %s", testToken) - req.Header.Set("Authorization", bearerTokenString) - rr := httptest.NewRecorder() - - // Our handlers satisfy http.Handler, so we can call their ServeHTTP method - // directly and pass in our Request and ResponseRecorder. - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - assert.Equal(t, rr.Code, http.StatusOK) - assert.Equal(t, rr.Body.String(), common.MsgDaemonOK) +func TestGetAPIPrivateKey(t *testing.T) { + key, err := getAPIPrivateKeyFromPath(nil, testInertiaKeyPath) + assert.Nil(t, err) + assert.Contains(t, string(key.([]byte)), "user: git, name: ssh-public-keys") } -func TestAuthorizationMalformedBearerString(t *testing.T) { - req, _ := http.NewRequest("GET", "/health-check", nil) - - // Set the token for authorization. - req.Header.Set("Authorization", "Beare") - rr := httptest.NewRecorder() - - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) - assert.Equal(t, rr.Body.String(), malformedAuthStringErrorMsg+"\n") +func TestGetGithubKey(t *testing.T) { + pemFile, err := os.Open(testInertiaKeyPath) + assert.Nil(t, err) + _, err = GetGithubKey(pemFile) + assert.Nil(t, err) } -func TestAuthorizationTooManySegments(t *testing.T) { - req, _ := http.NewRequest("GET", "/health-check", nil) - - // Set the token for authorization. - req.Header.Set("Authorization", "Bearer a.b.c.d") - rr := httptest.NewRecorder() - - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) +func TestGenerateToken(t *testing.T) { + token, err := GenerateToken(testPrivateKey) + assert.Nil(t, err, "generateToken must not fail") + assert.Equal(t, token, testToken) - assert.Equal(t, rr.Code, http.StatusForbidden) + otherToken, err := GenerateToken([]byte("another_sekrit_key")) + assert.Nil(t, err) + assert.NotEqual(t, token, otherToken) } -func TestAuthorizationSignatureInvalid(t *testing.T) { - req, _ := http.NewRequest("GET", "/health-check", nil) - - // Break the last component of the token (signature). - bearerTokenString := fmt.Sprintf("Bearer %s", testToken+"0") - req.Header.Set("Authorization", bearerTokenString) - rr := httptest.NewRecorder() - - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) +func TestGitAuthFailedErr(t *testing.T) { + err := GitAuthFailedErr(testInertiaKeyPath) + assert.NotNil(t, err) + // Check for a substring of public key + assert.Contains(t, err.Error(), "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD") } -func TestGetGithubKey(t *testing.T) { - inertiaKeyPath := path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test/keys/id_rsa") - pemFile, err := os.Open(inertiaKeyPath) - assert.Nil(t, err) - _, err = GetGithubKey(pemFile) - assert.Nil(t, err) +func TestGitAuthFailedErrFailed(t *testing.T) { + err := GitAuthFailedErr("wow") + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "Error reading key") } diff --git a/daemon/inertia/auth/handler.go b/daemon/inertia/auth/handler.go deleted file mode 100644 index ce3c5e1a..00000000 --- a/daemon/inertia/auth/handler.go +++ /dev/null @@ -1,50 +0,0 @@ -package auth - -import ( - "fmt" - "net/http" - "strings" - - jwt "github.com/dgrijalva/jwt-go" - "github.com/ubclaunchpad/inertia/common" -) - -// Authorized is a function decorator for authorizing RESTful -// daemon requests. It wraps handler functions and ensures the -// request is authorized. Returns a function -func Authorized(handler http.HandlerFunc, keyLookup func(*jwt.Token) (interface{}, error)) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // Collect the token from the header. - bearerString := r.Header.Get("Authorization") - - // Split out the actual token from the header. - splitToken := strings.Split(bearerString, "Bearer ") - if len(splitToken) < 2 { - http.Error(w, malformedAuthStringErrorMsg, http.StatusForbidden) - return - } - tokenString := splitToken[1] - - // Parse takes the token string and a function for looking up the key. - token, err := jwt.Parse(tokenString, keyLookup) - if err != nil { - http.Error(w, err.Error(), http.StatusForbidden) - return - } - - // Verify the claims (none for now) and token. - if _, ok := token.Claims.(jwt.MapClaims); !ok || !token.Valid { - http.Error(w, tokenInvalidErrorMsg, http.StatusForbidden) - return - } - - // We're authorized, run the handler. - handler(w, r) - } -} - -// HealthCheckHandler returns a 200 if the daemon is happy. -func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, common.MsgDaemonOK) -} diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go new file mode 100644 index 00000000..d0735570 --- /dev/null +++ b/daemon/inertia/auth/password.go @@ -0,0 +1,52 @@ +package auth + +import ( + "errors" + + "golang.org/x/crypto/bcrypt" +) + +var ( + errSameUsernamePassword = errors.New("Username and password must be different") + errInvalidUsername = errors.New("Only letters, numbers, underscores, and dashes are allowed in usernames, and username must be at least 3 characters") + errInvalidPassword = errors.New("Only letters, numbers, underscores, and dashes are allowed in passwords, and password must be at least 5 characters") +) + +// hashPassword generates a bcrypt-encrypted hash from given password +func hashPassword(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", errors.New("bcrypt password hashing unsuccessful: " + err.Error()) + } + return string(hash), nil +} + +// correctPassword checks if given password maps correctly to the given hash +func correctPassword(hash string, password string) bool { + return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil +} + +// validateCredentialValues takes a username and password and verifies +// if they are of sufficient length and if they only contain legal characters +func validateCredentialValues(username, password string) error { + if username == password { + return errSameUsernamePassword + } + if len(password) < 5 || len(password) >= 128 || !isLegalString(password) { + return errInvalidPassword + } + if len(username) < 3 || len(username) >= 128 || !isLegalString(username) { + return errInvalidUsername + } + return nil +} + +// isLegalString returns true if `str` only contains characters [A-Z], [a-z], or '_' or '-' +func isLegalString(str string) bool { + for _, c := range str { + if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_' && c != '-' { + return false + } + } + return true +} diff --git a/daemon/inertia/auth/password_test.go b/daemon/inertia/auth/password_test.go new file mode 100644 index 00000000..2b9342b3 --- /dev/null +++ b/daemon/inertia/auth/password_test.go @@ -0,0 +1,47 @@ +package auth + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHashPassword(t *testing.T) { + unhashed := "amazing" + hashed, err := hashPassword(unhashed) + assert.Nil(t, err) + assert.NotEqual(t, unhashed, hashed) +} + +func TestCorrectPassword(t *testing.T) { + unhashed := "amazing" + hashed, err := hashPassword(unhashed) + assert.Nil(t, err) + assert.NotEqual(t, unhashed, hashed) + + correct := correctPassword(hashed, unhashed) + assert.True(t, correct) + + correct = correctPassword(hashed, "ummmmm") + assert.False(t, correct) +} + +func TestValidateCredentialValues(t *testing.T) { + err := validateCredentialValues("finasdfsdfe", "okaasdfasdy") + assert.Nil(t, err) + + err = validateCredentialValues("ohnoitsme", "ohnoitsme") + assert.Equal(t, errSameUsernamePassword, err) + + err = validateCredentialValues("wowwow", "oh") + assert.Equal(t, errInvalidPassword, err) + + err = validateCredentialValues("um", "ohasdf") + assert.Equal(t, errInvalidUsername, err) + + err = validateCredentialValues("wow!!!!!!", "oasdfasdfh") + assert.Equal(t, errInvalidUsername, err) + + err = validateCredentialValues("wowwow", "oasdfasdfh!!!!") + assert.Equal(t, errInvalidPassword, err) +} diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go new file mode 100644 index 00000000..7465e730 --- /dev/null +++ b/daemon/inertia/auth/permissions.go @@ -0,0 +1,348 @@ +package auth + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strings" + + jwt "github.com/dgrijalva/jwt-go" + "github.com/ubclaunchpad/inertia/common" +) + +// UserDatabasePath is the default location for storing users. +const UserDatabasePath = "/app/host/.inertia/users.db" + +// PermissionsHandler handles users, permissions, and sessions on top +// of an http.ServeMux. It is used for Inertia Web. +type PermissionsHandler struct { + domain string + users *userManager + sessions *sessionManager + mux *http.ServeMux + keyLookup func(*jwt.Token) (interface{}, error) + userPaths []string + adminPaths []string +} + +// NewPermissionsHandler returns a new handler for authenticating +// users and handling user administration. Param userlandPath is +// used to set cookie domain. +func NewPermissionsHandler( + dbPath, hostDomain string, timeout int, + keyLookup ...func(*jwt.Token) (interface{}, error), +) (*PermissionsHandler, error) { + // Set up user manager + userManager, err := newUserManager(dbPath) + if err != nil { + return nil, err + } + + // Set up session manager + sessionManager := newSessionManager(hostDomain, timeout) + + // Set up permissions handler + mux := http.NewServeMux() + handler := &PermissionsHandler{ + domain: hostDomain, + users: userManager, + sessions: sessionManager, + mux: mux, + } + handler.keyLookup = GetAPIPrivateKey + if len(keyLookup) > 0 { + handler.keyLookup = keyLookup[0] + } + + // The following endpoints are for user administration and session + // administration + userHandler := http.NewServeMux() + userHandler.HandleFunc("/login", handler.loginHandler) + userHandler.HandleFunc("/logout", handler.logoutHandler) + handler.userPaths = []string{ + "/user/validate", + } + userHandler.HandleFunc("/validate", handler.validateHandler) + handler.adminPaths = []string{ + "/user/adduser", + "/user/removeuser", + "/user/resetusers", + "/user/listusers", + } + userHandler.HandleFunc("/adduser", handler.addUserHandler) + userHandler.HandleFunc("/removeuser", handler.removeUserHandler) + userHandler.HandleFunc("/resetusers", handler.resetUsersHandler) + userHandler.HandleFunc("/listusers", handler.listUsersHandler) + mux.Handle("/user/", http.StripPrefix("/user", userHandler)) + + return handler, nil +} + +// Close releases resources held by the PermissionsHandler +func (h *PermissionsHandler) Close() error { + h.sessions.Close() + return h.users.Close() +} + +// nolint: gocyclo +func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // CORS for development + origin, err := url.Parse(r.Header.Get("Origin")) + if err == nil && origin.Hostname() == "127.0.0.1" { + allowedOrigin := "http://" + origin.Host + w.Header().Set("Access-Control-Allow-Origin", allowedOrigin) + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + if r.Method == "OPTIONS" { + return + } + } + + // http.StripPrefix removes the leading slash, but in the interest + // of maintaining similar behaviour to stdlib handler functions, + // we manually add a leading "/" here instead of having users not add + // a leading "/" on the path if it dosn't already exist. + path := r.URL.Path + if !strings.HasPrefix(path, "/") { + path = "/" + path + r.URL.Path = path + } + + // Check if this is restricted + adminRestricted := false + for _, prefix := range h.adminPaths { + if strings.HasPrefix(path, prefix) { + adminRestricted = true + } + } + userRestricted := false + for _, prefix := range h.userPaths { + if strings.HasPrefix(path, prefix) { + userRestricted = true + } + } + + // Serve if path is public + if !userRestricted && !adminRestricted { + h.mux.ServeHTTP(w, r) + return + } + + // Check token in header - if no tokens, check cookie + bearerString := r.Header.Get("Authorization") + splitToken := strings.Split(bearerString, "Bearer ") + if len(splitToken) == 2 { + tokenString := splitToken[1] + + // Parse takes the token string and a function for looking up the key. + token, err := jwt.Parse(tokenString, h.keyLookup) + if err != nil { + http.Error(w, err.Error(), http.StatusForbidden) + return + } + + // Verify the claims (none for now) and token. + if _, ok := token.Claims.(jwt.MapClaims); !ok || !token.Valid { + http.Error(w, tokenInvalidErrorMsg, http.StatusForbidden) + return + } + + // @todo: manage admin-restricted endpoints + + // Serve the requested endpoint to token holders + h.mux.ServeHTTP(w, r) + return + } + + // Check if session is valid + s, err := h.sessions.GetSession(w, r) + if err != nil { + if err == errSessionNotFound || err == errCookieNotFound { + http.Error(w, err.Error(), http.StatusForbidden) + } else { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + return + } + + // Check if user has sufficient permissions for path + if adminRestricted { + admin, err := h.users.IsAdmin(s.Username) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + if !admin { + http.Error(w, "Admin privileges required", http.StatusForbidden) + } + return + } + + // Serve the requested page if permissions were granted + h.mux.ServeHTTP(w, r) +} + +// AttachPublicHandler attaches given path and handler and makes it publicly available +func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.Handler) { + h.mux.Handle(path, handler) +} + +// AttachPublicHandlerFunc attaches given path and handler and makes it publicly available +func (h *PermissionsHandler) AttachPublicHandlerFunc(path string, handler http.HandlerFunc) { + h.mux.HandleFunc(path, handler) +} + +// AttachUserRestrictedHandlerFunc attaches and restricts given path and handler to logged in users. +func (h *PermissionsHandler) AttachUserRestrictedHandlerFunc(path string, handler http.HandlerFunc) { + // Add path to user-restricted paths + h.userPaths = append(h.userPaths, path) + h.mux.HandleFunc(path, handler) +} + +// AttachAdminRestrictedHandlerFunc attaches and restricts given path and handler to logged in admins. +func (h *PermissionsHandler) AttachAdminRestrictedHandlerFunc(path string, handler http.HandlerFunc) { + // Add path as one that requires elevated permissions + h.adminPaths = append(h.adminPaths, path) + h.mux.HandleFunc(path, handler) +} + +func (h *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { + // Retrieve user details from request + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusLengthRequired) + return + } + defer r.Body.Close() + var userReq common.UserRequest + err = json.Unmarshal(body, &userReq) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Add user (as admin if specified) + err = h.users.AddUser(userReq.Username, userReq.Password, userReq.Admin) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, "[SUCCESS %d] User %s added!\n", http.StatusCreated, userReq.Username) +} + +func (h *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Request) { + // Retrieve user details from request + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusLengthRequired) + return + } + defer r.Body.Close() + var userReq common.UserRequest + err = json.Unmarshal(body, &userReq) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Remove user credentials + err = h.users.RemoveUser(userReq.Username) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // End user sessions + h.sessions.EndAllUserSessions(userReq.Username) + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] User %s removed\n", http.StatusOK, userReq.Username) +} + +func (h *PermissionsHandler) resetUsersHandler(w http.ResponseWriter, r *http.Request) { + // Delete all users + err := h.users.Reset() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Delete all sessions + h.sessions.EndAllSessions() + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] User and session databases reset\n", http.StatusOK) +} + +func (h *PermissionsHandler) listUsersHandler(w http.ResponseWriter, r *http.Request) { + users := h.users.UserList() + userList := "" + for _, user := range users { + userList += " - " + user + "\n" + } + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + if len(users) != 0 { + fmt.Fprintf(w, "[SUCCESS %d] Users: \n%s\n", http.StatusOK, userList) + } else { + fmt.Fprintf(w, "[SUCCESS %d] No users registered.", http.StatusOK) + } +} + +func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { + // Retrieve user details from request + body, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusLengthRequired) + return + } + defer r.Body.Close() + var userReq common.UserRequest + err = json.Unmarshal(body, &userReq) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Log in user if password is correct + correct, err := h.users.IsCorrectCredentials(userReq.Username, userReq.Password) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if !correct { + http.Error(w, "Login failed", http.StatusForbidden) + return + } + err = h.sessions.BeginSession(userReq.Username, w, r) + if err != nil { + http.Error(w, "Login failed: "+err.Error(), http.StatusForbidden) + return + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] User %s logged in\n", http.StatusOK, userReq.Username) +} + +func (h *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Request) { + err := h.sessions.EndSession(w, r) + if err != nil { + http.Error(w, "Logout failed: "+err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] Session ended\n", http.StatusOK) +} + +func (h *PermissionsHandler) validateHandler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go new file mode 100644 index 00000000..7736cc4e --- /dev/null +++ b/daemon/inertia/auth/permissions_test.go @@ -0,0 +1,340 @@ +package auth + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path" + "testing" + + "github.com/ubclaunchpad/inertia/common" + + "github.com/stretchr/testify/assert" +) + +func getTestPermissionsHandler(dir string) (*PermissionsHandler, error) { + err := os.Mkdir(dir, os.ModePerm) + if err != nil { + return nil, err + } + return NewPermissionsHandler( + path.Join(dir, "users.db"), + "127.0.0.1", 3000, + getFakeAPIKey, + ) +} + +func TestServeHTTPPublicPath(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachPublicHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + req, err := http.NewRequest("POST", ts.URL+"/test", nil) + assert.Nil(t, err) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestServeHTTPWithUserReject(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + req, err := http.NewRequest("POST", ts.URL+"/test", nil) + assert.Nil(t, err) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusForbidden, resp.StatusCode) +} + +func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + // Register user + err = ph.users.AddUser("bobheadxi", "wowgreat", false) + assert.Nil(t, err) + + // Login in as user, use cookiejar to catch cookie + user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} + body, err := json.Marshal(user) + assert.Nil(t, err) + req, err := http.NewRequest("POST", ts.URL+"/user/login", bytes.NewReader(body)) + assert.Nil(t, err) + loginResp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer loginResp.Body.Close() + assert.Equal(t, http.StatusOK, loginResp.StatusCode) + + // Check for cookies + assert.True(t, len(loginResp.Cookies()) > 0) + cookie := loginResp.Cookies()[0] + assert.Equal(t, "ubclaunchpad-inertia", cookie.Name) + + // Attempt to validate + req, err = http.NewRequest("POST", ts.URL+"/user/validate", nil) + assert.Nil(t, err) + req.AddCookie(cookie) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Log out + req, err = http.NewRequest("POST", ts.URL+"/user/logout", nil) + assert.Nil(t, err) + req.AddCookie(cookie) + logoutResp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer logoutResp.Body.Close() + assert.Equal(t, http.StatusOK, logoutResp.StatusCode) + + // Check for cookies + assert.True(t, len(logoutResp.Cookies()) > 0) + cookie = logoutResp.Cookies()[0] + assert.Equal(t, "ubclaunchpad-inertia", cookie.Name) + assert.Equal(t, -1, cookie.MaxAge) +} + +func TestServeHTTPWithUserLoginAndAccept(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + // Register user + err = ph.users.AddUser("bobheadxi", "wowgreat", false) + assert.Nil(t, err) + + // Login in as user, use cookiejar to catch cookie + user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} + body, err := json.Marshal(user) + assert.Nil(t, err) + req, err := http.NewRequest("POST", ts.URL+"/user/login", bytes.NewReader(body)) + assert.Nil(t, err) + loginResp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer loginResp.Body.Close() + assert.Equal(t, http.StatusOK, loginResp.StatusCode) + + // Check for cookies + assert.True(t, len(loginResp.Cookies()) > 0) + cookie := loginResp.Cookies()[0] + assert.Equal(t, "ubclaunchpad-inertia", cookie.Name) + + // Attempt to access restricted endpoint with cookie + req, err = http.NewRequest("POST", ts.URL+"/test", nil) + assert.Nil(t, err) + req.AddCookie(cookie) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestServeHTTPDenyNonAdmin(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachAdminRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + // Register user + err = ph.users.AddUser("bobheadxi", "wowgreat", false) + assert.Nil(t, err) + + // Login in as user, use cookiejar to catch cookie + user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} + body, err := json.Marshal(user) + assert.Nil(t, err) + req, err := http.NewRequest("POST", ts.URL+"/user/login", bytes.NewReader(body)) + assert.Nil(t, err) + loginResp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer loginResp.Body.Close() + assert.Equal(t, http.StatusOK, loginResp.StatusCode) + + // Check for cookies + assert.True(t, len(loginResp.Cookies()) > 0) + cookie := loginResp.Cookies()[0] + assert.Equal(t, "ubclaunchpad-inertia", cookie.Name) + + // Attempt to access restricted endpoint with cookie + req, err = http.NewRequest("POST", ts.URL+"/test", nil) + assert.Nil(t, err) + req.AddCookie(cookie) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusForbidden, resp.StatusCode) +} + +func TestServeHTTPAllowAdmin(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachAdminRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + // Register user + err = ph.users.AddUser("bobheadxi", "wowgreat", true) + assert.Nil(t, err) + + // Login in as user, use cookiejar to catch cookie + user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} + body, err := json.Marshal(user) + assert.Nil(t, err) + req, err := http.NewRequest("POST", ts.URL+"/user/login", bytes.NewReader(body)) + assert.Nil(t, err) + loginResp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer loginResp.Body.Close() + assert.Equal(t, http.StatusOK, loginResp.StatusCode) + + // Check for cookies + assert.True(t, len(loginResp.Cookies()) > 0) + cookie := loginResp.Cookies()[0] + assert.Equal(t, "ubclaunchpad-inertia", cookie.Name) + + // Attempt to access restricted endpoint with cookie + req, err = http.NewRequest("POST", ts.URL+"/test", nil) + assert.Nil(t, err) + req.AddCookie(cookie) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + + assert.Equal(t, http.StatusOK, resp.StatusCode) +} + +func TestUserControlHandlers(t *testing.T) { + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + ts.Config.Handler = ph + + // Test handler uses the getFakeAPIToken keylookup, which + // will match with the testToken + bearerTokenString := fmt.Sprintf("Bearer %s", testToken) + + // Add a new user + body, err := json.Marshal(&common.UserRequest{ + Username: "jimmyneutron", + Password: "asfasdlfjk", + Admin: false, + }) + assert.Nil(t, err) + payload := bytes.NewReader(body) + req, err := http.NewRequest("POST", ts.URL+"/user/adduser", payload) + assert.Nil(t, err) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", bearerTokenString) + resp, err := http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusCreated, resp.StatusCode) + + // Remove a user + body, err = json.Marshal(&common.UserRequest{ + Username: "jimmyneutron", + }) + assert.Nil(t, err) + payload = bytes.NewReader(body) + req, err = http.NewRequest("POST", ts.URL+"/user/removeuser", payload) + assert.Nil(t, err) + req.Header.Set("Authorization", bearerTokenString) + resp, err = http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // List users + req, err = http.NewRequest("POST", ts.URL+"/user/listusers", nil) + assert.Nil(t, err) + req.Header.Set("Authorization", bearerTokenString) + resp, err = http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusOK, resp.StatusCode) + + // Reset all users + req, err = http.NewRequest("POST", ts.URL+"/user/resetusers", nil) + assert.Nil(t, err) + req.Header.Set("Authorization", bearerTokenString) + resp, err = http.DefaultClient.Do(req) + assert.Nil(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusOK, resp.StatusCode) +} diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go new file mode 100644 index 00000000..9d49fa70 --- /dev/null +++ b/daemon/inertia/auth/sessions.go @@ -0,0 +1,178 @@ +package auth + +import ( + "errors" + "net/http" + "net/url" + "sync" + "time" +) + +// session are properties associated with session, +// used for database entries +type session struct { + Username string `json:"username"` + Expires time.Time `json:"created"` +} + +type sessionManager struct { + cookieName string + cookieDomain string + cookieTimeout time.Duration + internal map[string]*session + + sync.RWMutex + endSessionCleanup chan bool +} + +func newSessionManager(domain string, timeout int) *sessionManager { + manager := &sessionManager{ + cookieName: "ubclaunchpad-inertia", + cookieDomain: domain, + cookieTimeout: time.Duration(timeout) * time.Minute, + internal: make(map[string]*session), + + endSessionCleanup: make(chan bool), + } + + // Set up session cleanup goroutine + ticker := time.NewTicker(manager.cookieTimeout) + go func() { + for { + select { + case <-manager.endSessionCleanup: + ticker.Stop() + return + case <-ticker.C: + manager.Lock() + for id, session := range manager.internal { + if !manager.isValidSession(session) { + delete(manager.internal, id) + } + } + manager.Unlock() + } + } + }() + + return manager +} + +func (s *sessionManager) Close() { + s.endSessionCleanup <- true + + s.Lock() + s.internal = make(map[string]*session) + s.Unlock() +} + +// SessionBegin starts a new session with user by setting a cookie +// and adding session to memory +func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r *http.Request) error { + expiration := time.Now().Add(s.cookieTimeout) + id, err := generateSessionID() + if err != nil { + return errors.New("Failed to begin session for " + username + ": " + err.Error()) + } + + // Add session to map + s.Lock() + s.internal[id] = &session{ + Username: username, + Expires: expiration, + } + s.Unlock() + + // Add cookie with session ID + http.SetCookie(w, &http.Cookie{ + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + MaxAge: int(s.cookieTimeout / time.Second), + HttpOnly: true, + Expires: expiration, + }) + return nil +} + +// SessionEnd ends a session and sets cookie to expire +func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) error { + cookie, err := r.Cookie(s.cookieName) + if err != nil { + return errors.New("Invalid cookie: " + err.Error()) + } + if cookie.Value == "" { + return errors.New("Invalid cookie") + } + id, err := url.QueryUnescape(cookie.Value) + if err != nil { + return errors.New("Invalid cookie: " + err.Error()) + } + + // Delete session from map + s.Lock() + delete(s.internal, id) + s.Unlock() + + // Set cookie to expire immediately + http.SetCookie(w, &http.Cookie{ + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + MaxAge: -1, + HttpOnly: true, + Expires: time.Unix(0, 0), + }) + return nil +} + +// GetSession verifies if given request is from a valid session and returns it +func (s *sessionManager) GetSession(w http.ResponseWriter, r *http.Request) (*session, error) { + + cookie, err := r.Cookie(s.cookieName) + if err != nil || cookie.Value == "" { + return nil, errCookieNotFound + } + id, err := url.QueryUnescape(cookie.Value) + if err != nil { + return nil, err + } + + s.RLock() + session, found := s.internal[id] + if !found { + s.RUnlock() + return nil, errSessionNotFound + } + if !s.isValidSession(session) { + s.RUnlock() + s.EndSession(w, r) + return nil, errSessionNotFound + } + s.RUnlock() + + return session, nil +} + +// endAllUserSessions removes all active sessions with given user +func (s *sessionManager) EndAllUserSessions(username string) { + s.Lock() + for id, session := range s.internal { + if session.Username == username { + delete(s.internal, id) + } + } + s.Unlock() +} + +// EndAllSessions removes all active sessions +func (s *sessionManager) EndAllSessions() { + s.Lock() + s.internal = make(map[string]*session) + s.Unlock() +} + +// isValidSession checks if session is expired +func (s *sessionManager) isValidSession(session *session) bool { + return session.Expires.After(time.Now()) +} diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go new file mode 100644 index 00000000..82098392 --- /dev/null +++ b/daemon/inertia/auth/users.go @@ -0,0 +1,209 @@ +package auth + +import ( + "encoding/json" + "errors" + + "github.com/boltdb/bolt" +) + +var ( + errSessionNotFound = errors.New("Session not found") + errCookieNotFound = errors.New("Cookie not found") + errUserNotFound = errors.New("User not found") +) + +const ( + loginAttemptsLimit = 5 +) + +// userProps are properties associated with user, used +// for database entries +type userProps struct { + HashedPassword string + Admin bool + LoginAttempts int +} + +// userManager administers sessions and user accounts +type userManager struct { + // db is a boltdb database, which is an embedded + // key/value database where each "bucket" is a collection + db *bolt.DB + usersBucket []byte +} + +func newUserManager(dbPath string) (*userManager, error) { + manager := &userManager{ + usersBucket: []byte("users"), + } + + // Set up database + db, err := bolt.Open(dbPath, 0600, nil) + if err != nil { + return nil, err + } + err = db.Update(func(tx *bolt.Tx) error { + _, err = tx.CreateBucketIfNotExists(manager.usersBucket) + return err + }) + manager.db = db + + return manager, nil +} + +// Close ends the session cleanup job and releases the DB handler +func (m *userManager) Close() error { + return m.db.Close() +} + +// Reset deletes all users and drops all active sessions +func (m *userManager) Reset() error { + return m.db.Update(func(tx *bolt.Tx) error { + err := tx.DeleteBucket(m.usersBucket) + if err != nil { + return err + } + _, err = tx.CreateBucket(m.usersBucket) + return err + }) +} + +// AddUser inserts a new user +func (m *userManager) AddUser(username, password string, admin bool) error { + err := validateCredentialValues(username, password) + if err != nil { + return err + } + hashedPassword, err := hashPassword(password) + if err != nil { + return err + } + props := userProps{HashedPassword: string(hashedPassword), Admin: admin} + return m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + bytes, err := json.Marshal(props) + if err != nil { + return err + } + return users.Put([]byte(username), bytes) + }) +} + +// RemoveUser removes user with given username and ends related sessions +func (m *userManager) RemoveUser(username string) error { + return m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + return users.Delete([]byte(username)) + }) +} + +// UserList returns a list of all registered users +func (m *userManager) UserList() []string { + userList := make([]string, 0) + m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + return users.ForEach(func(username, v []byte) error { + userList = append(userList, string(username)) + return nil + }) + }) + return userList +} + +// HasUser returns nil if user exists in database +func (m *userManager) HasUser(username string) error { + found := false + err := m.db.View(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + user := users.Get([]byte(username)) + if user != nil { + found = true + } + return nil + }) + if err != nil { + return err + } + if !found { + return errUserNotFound + } + return nil +} + +// IsCorrectCredentials checks if username and password has a match +// in the database +func (m *userManager) IsCorrectCredentials(username, password string) (bool, error) { + correct := false + userbytes := []byte(username) + var userErr error + transactionErr := m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + propsBytes := users.Get(userbytes) + if propsBytes == nil { + return errUserNotFound + } + props := &userProps{} + err := json.Unmarshal(propsBytes, props) + if err != nil { + return errors.New("Corrupt user properties: " + err.Error()) + } + + // Delete user since LoginAttempts must be updated + err = users.Delete(userbytes) + if err != nil { + return err + } + + correct = correctPassword(props.HashedPassword, password) + if !correct { + // Track number of login attempts and don't add + // user back to the database if past limit + props.LoginAttempts++ + if props.LoginAttempts <= loginAttemptsLimit { + bytes, err := json.Marshal(props) + if err != nil { + return err + } + return users.Put(userbytes, bytes) + } + + // Rollback will occur if transaction returns and + // error, so store in variable + userErr = errors.New("Too many login attempts - user deleted") + return nil + } + + // Reset attempts to 0 if login successful + props.LoginAttempts = 0 + bytes, err := json.Marshal(props) + if err != nil { + return err + } + return users.Put(userbytes, bytes) + }) + + if userErr != nil { + return correct, userErr + } + return correct, transactionErr +} + +// IsAdmin checks if given user is has administrator priviledges +func (m *userManager) IsAdmin(username string) (bool, error) { + admin := false + err := m.db.View(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + propsBytes := users.Get([]byte(username)) + if propsBytes != nil { + props := &userProps{} + err := json.Unmarshal(propsBytes, props) + if err != nil { + return errors.New("Corrupt user properties: " + err.Error()) + } + admin = props.Admin + } + return nil + }) + return admin, err +} diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go new file mode 100644 index 00000000..fb844aed --- /dev/null +++ b/daemon/inertia/auth/users_test.go @@ -0,0 +1,128 @@ +package auth + +import ( + "os" + "path" + "testing" + + "github.com/stretchr/testify/assert" +) + +func getTestUserManager(dir string) (*userManager, error) { + err := os.Mkdir(dir, os.ModePerm) + if err != nil { + return nil, err + } + return newUserManager(path.Join(dir, "users.db")) +} + +func TestAddUserAndIsCorrectCredentials(t *testing.T) { + dir := "./test_users" + manager, err := getTestUserManager(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer manager.Close() + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + correct, err := manager.IsCorrectCredentials("bobheadxi", "not_quite_best") + assert.Nil(t, err) + assert.False(t, correct) + + correct, err = manager.IsCorrectCredentials("bobheadxi", "best_person_ever") + assert.Nil(t, err) + assert.True(t, correct) +} + +func TestAllUserManagementOperations(t *testing.T) { + dir := "./test_users" + manager, err := getTestUserManager(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer manager.Close() + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + err = manager.AddUser("whoisthat", "ummmmmmmmmm", false) + assert.Nil(t, err) + + users := manager.UserList() + assert.Equal(t, len(users), 2) + + err = manager.HasUser("bobheadxi") + assert.Nil(t, err) + + err = manager.RemoveUser("bobheadxi") + assert.Nil(t, err) + + err = manager.HasUser("bobheadxi") + assert.Equal(t, errUserNotFound, err) +} + +func TestIsAdmin(t *testing.T) { + dir := "./test_users" + manager, err := getTestUserManager(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer manager.Close() + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + admin, err := manager.IsAdmin("bobheadxi") + assert.Nil(t, err) + assert.True(t, admin) + + err = manager.AddUser("chadlagore", "chadlad", false) + assert.Nil(t, err) + + admin, err = manager.IsAdmin("chadlagore") + assert.Nil(t, err) + assert.False(t, admin) +} + +func TestRemoveUser(t *testing.T) { + dir := "./test_users" + manager, err := getTestUserManager(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer manager.Close() + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + err = manager.RemoveUser("bobheadxi") + assert.Nil(t, err) + + err = manager.HasUser("bobheadxi") + assert.NotNil(t, err) + assert.Equal(t, errUserNotFound, err) +} + +func TestTooManyLogins(t *testing.T) { + dir := "./test_users_login_limit" + manager, err := getTestUserManager(dir) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer manager.Close() + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + for i := 0; i < loginAttemptsLimit; i++ { + correct, err := manager.IsCorrectCredentials("bobheadxi", "not_quite_best") + assert.Nil(t, err) + assert.False(t, correct) + } + + correct, err := manager.IsCorrectCredentials("bobheadxi", "not_quite_best") + assert.False(t, correct) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "login attempts") + + err = manager.HasUser("bobheadxi") + assert.NotNil(t, err) + assert.Equal(t, errUserNotFound, err) +} diff --git a/daemon/inertia/auth/util.go b/daemon/inertia/auth/util.go new file mode 100644 index 00000000..ccb7dc06 --- /dev/null +++ b/daemon/inertia/auth/util.go @@ -0,0 +1,15 @@ +package auth + +import ( + "crypto/rand" + "encoding/base64" + "io" +) + +func generateSessionID() (string, error) { + b := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "", err + } + return base64.URLEncoding.EncodeToString(b), nil +} diff --git a/daemon/inertia/cmd.go b/daemon/inertia/cmd.go index 060b7f13..e4937e9e 100644 --- a/daemon/inertia/cmd.go +++ b/daemon/inertia/cmd.go @@ -4,7 +4,6 @@ import ( "fmt" "os" - "github.com/ubclaunchpad/inertia/common" "github.com/ubclaunchpad/inertia/daemon/inertia/auth" log "github.com/sirupsen/logrus" @@ -14,14 +13,16 @@ import ( // Version is the current build of Inertia var Version string -// runCmd represents the daemon run command +// runCmd starts the daemon var runCmd = &cobra.Command{ - Use: "run", - Short: "Run the daemon", - Long: `Run the daemon on a port. -Example: + Version: getVersion(), + Use: "run", + Short: "Run the daemon", + Long: `Run the daemon on a port, default 8081. Requires +host address as an argument. -inertia daemon run -p 8081`, +Example: + inertia daemon run 0.0.0.0 -p 8081`, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { port, err := cmd.Flags().GetString("port") @@ -32,12 +33,12 @@ inertia daemon run -p 8081`, }, } -// tokenCmd represents the daemon run command +// tokenCmd retrieves the daemon token var tokenCmd = &cobra.Command{ Use: "token", Short: "Produce an API token to use with the daemon", Long: `Produce an API token to use with the daemon, - Created using an RSA private key.`, +Created using an RSA private key.`, Run: func(cmd *cobra.Command, args []string) { keyBytes, err := auth.GetAPIPrivateKey(nil) if err != nil { @@ -69,7 +70,7 @@ func getVersion() string { func init() { rootCmd.AddCommand(runCmd) rootCmd.AddCommand(tokenCmd) - runCmd.Flags().StringP("port", "p", common.DefaultPort, "Set port for daemon to run on") + runCmd.Flags().StringP("port", "p", "8081", "Set port for daemon to run on") } func main() { diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 746c76b6..cec2cda7 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -61,20 +61,38 @@ func run(host, port, version string) { } } - // API endpoints - mux := http.NewServeMux() - mux.HandleFunc("/up", auth.Authorized(upHandler, auth.GetAPIPrivateKey)) - mux.HandleFunc("/down", auth.Authorized(downHandler, auth.GetAPIPrivateKey)) - mux.HandleFunc("/status", auth.Authorized(statusHandler, auth.GetAPIPrivateKey)) - mux.HandleFunc("/reset", auth.Authorized(resetHandler, auth.GetAPIPrivateKey)) - mux.HandleFunc("/logs", auth.Authorized(logHandler, auth.GetAPIPrivateKey)) - mux.HandleFunc("/health-check", auth.Authorized(auth.HealthCheckHandler, auth.GetAPIPrivateKey)) + webPrefix := "/web/" + handler, err := auth.NewPermissionsHandler( + auth.UserDatabasePath, host, 120, + ) + if err != nil { + println(err.Error()) + return + } + defer handler.Close() + + // Inertia web + handler.AttachPublicHandler( + webPrefix, + http.StripPrefix( + webPrefix, http.FileServer(http.Dir("/app/inertia-web")), + ), + ) // GitHub webhook endpoint - mux.HandleFunc("/", gitHubWebHookHandler) + handler.AttachPublicHandlerFunc("/webhook", gitHubWebHookHandler) - // Inertia web - // mux.Handle("/admin/", http.StripPrefix("/admin/", http.FileServer(http.Dir("/app/inertia-web")))) + // CLI API endpoints + handler.AttachUserRestrictedHandlerFunc("/status", statusHandler) + handler.AttachUserRestrictedHandlerFunc("/logs", logHandler) + handler.AttachAdminRestrictedHandlerFunc("/up", upHandler) + handler.AttachAdminRestrictedHandlerFunc("/down", downHandler) + handler.AttachAdminRestrictedHandlerFunc("/reset", resetHandler) + + // Root "ok" endpoint + handler.AttachPublicHandlerFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) // Serve daemon on port println("Serving daemon on port " + port) @@ -82,7 +100,7 @@ func run(host, port, version string) { ":"+port, daemonSSLCert, daemonSSLKey, - mux, + handler, )) } diff --git a/daemon/inertia/logs.go b/daemon/inertia/logs.go index d8270926..6ed39ecd 100644 --- a/daemon/inertia/logs.go +++ b/daemon/inertia/logs.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io/ioutil" "net/http" + "strings" docker "github.com/docker/docker/client" "github.com/ubclaunchpad/inertia/common" @@ -30,7 +31,7 @@ func logHandler(w http.ResponseWriter, r *http.Request) { logger := newLogger(upReq.Stream, w) defer logger.Close() - if container != "/inertia-daemon" && deployment == nil { + if !strings.Contains(container, "inertia-daemon") && deployment == nil { logger.Err(msgNoDeployment, http.StatusPreconditionFailed) return } @@ -42,7 +43,7 @@ func logHandler(w http.ResponseWriter, r *http.Request) { } defer cli.Close() - logs, err := deployment.Logs(project.LogOptions{ + logs, err := project.ContainerLogs(project.LogOptions{ Container: upReq.Container, Stream: upReq.Stream, }, cli) diff --git a/daemon/inertia/mock_test.go b/daemon/inertia/mock_test.go index 8d7c8f9e..86ab6b8a 100644 --- a/daemon/inertia/mock_test.go +++ b/daemon/inertia/mock_test.go @@ -20,7 +20,6 @@ type FakeDeployment struct { DownFunc func(in1 *docker.Client, in2 io.Writer) error GetBranchFunc func() string GetStatusFunc func(in1 *docker.Client) (*project.DeploymentStatus, error) - LogsFunc func(in1 project.LogOptions, in2 *docker.Client) (io.ReadCloser, error) } func (f *FakeDeployment) Deploy(o project.DeployOptions, c *docker.Client, w io.Writer) error { @@ -35,10 +34,6 @@ func (f *FakeDeployment) Destroy(c *docker.Client, w io.Writer) error { return f.DestroyFunc(c, w) } -func (f *FakeDeployment) Logs(o project.LogOptions, c *docker.Client) (io.ReadCloser, error) { - return f.LogsFunc(o, c) -} - func (f *FakeDeployment) GetStatus(c *docker.Client) (*project.DeploymentStatus, error) { return f.GetStatusFunc(c) } diff --git a/daemon/inertia/project/deployment.go b/daemon/inertia/project/deployment.go index a4a728da..e5e8e381 100644 --- a/daemon/inertia/project/deployment.go +++ b/daemon/inertia/project/deployment.go @@ -39,9 +39,7 @@ type Deployer interface { Down(*docker.Client, io.Writer) error Destroy(*docker.Client, io.Writer) error - Logs(LogOptions, *docker.Client) (io.ReadCloser, error) GetStatus(*docker.Client) (*DeploymentStatus, error) - SetConfig(DeploymentConfig) GetBranch() string CompareRemotes(string) error @@ -171,23 +169,6 @@ func (d *Deployment) Destroy(cli *docker.Client, out io.Writer) error { return common.RemoveContents(Directory) } -// LogOptions is used to configure retrieved container logs -type LogOptions struct { - Container string - Stream bool -} - -// Logs get logs ;) -func (d *Deployment) Logs(opts LogOptions, cli *docker.Client) (io.ReadCloser, error) { - ctx := context.Background() - return cli.ContainerLogs(ctx, opts.Container, types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: opts.Stream, - Timestamps: true, - }) -} - // DeploymentStatus lists details about the deployed project type DeploymentStatus struct { Branch string @@ -347,7 +328,7 @@ func (d *Deployment) herokuishBuild(cli *docker.Client, out io.Writer) error { } // Attach logs and report build progress until container exits - reader, err := d.Logs(LogOptions{Container: resp.ID, Stream: true}, cli) + reader, err := ContainerLogs(LogOptions{Container: resp.ID, Stream: true}, cli) if err != nil { return err } diff --git a/daemon/inertia/project/docker.go b/daemon/inertia/project/docker.go index 060a050d..91765612 100644 --- a/daemon/inertia/project/docker.go +++ b/daemon/inertia/project/docker.go @@ -17,6 +17,23 @@ var ( ErrNoContainers = errors.New("There are currently no active containers") ) +// LogOptions is used to configure retrieved container logs +type LogOptions struct { + Container string + Stream bool +} + +// ContainerLogs get logs ;) +func ContainerLogs(opts LogOptions, cli *docker.Client) (io.ReadCloser, error) { + ctx := context.Background() + return cli.ContainerLogs(ctx, opts.Container, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: opts.Stream, + Timestamps: true, + }) +} + // getActiveContainers returns all active containers and returns and error // if the Daemon is the only active container func getActiveContainers(cli *docker.Client) ([]types.Container, error) { diff --git a/daemon/inertia/project/git.go b/daemon/inertia/project/git.go index 6a612872..76bc12ac 100644 --- a/daemon/inertia/project/git.go +++ b/daemon/inertia/project/git.go @@ -12,7 +12,6 @@ import ( "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/transport" - "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh" ) var ( @@ -33,7 +32,7 @@ func SimplifyGitErr(err error) error { } // initializeRepository sets up a project repository for the first time -func initializeRepository(remoteURL, branch string, authMethod ssh.AuthMethod, w io.Writer) (*git.Repository, error) { +func initializeRepository(remoteURL, branch string, authMethod transport.AuthMethod, w io.Writer) (*git.Repository, error) { fmt.Fprintln(w, "Setting up project...") // Clone project repo, err := clone(Directory, remoteURL, branch, authMethod, w) @@ -48,7 +47,7 @@ func initializeRepository(remoteURL, branch string, authMethod ssh.AuthMethod, w // clone wraps git.PlainClone() and returns a more helpful error message // if the given error is an authentication-related error. -func clone(directory, remoteURL, branch string, auth ssh.AuthMethod, out io.Writer) (*git.Repository, error) { +func clone(directory, remoteURL, branch string, auth transport.AuthMethod, out io.Writer) (*git.Repository, error) { fmt.Fprintf(out, "Cloning branch %s from %s...\n", branch, remoteURL) ref := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", branch)) repo, err := git.PlainClone(directory, false, &git.CloneOptions{ @@ -72,7 +71,7 @@ func clone(directory, remoteURL, branch string, auth ssh.AuthMethod, out io.Writ // forcePull deletes the project directory and makes a fresh clone of given repo // git.Worktree.Pull() only supports merges that can be resolved as a fast-forward -func forcePull(directory string, repo *git.Repository, auth ssh.AuthMethod, out io.Writer) (*git.Repository, error) { +func forcePull(directory string, repo *git.Repository, auth transport.AuthMethod, out io.Writer) (*git.Repository, error) { fmt.Fprintln(out, "Making a force pull...") remotes, err := repo.Remotes() if err != nil { @@ -97,7 +96,7 @@ func forcePull(directory string, repo *git.Repository, auth ssh.AuthMethod, out } // updateRepository pulls and checkouts given branch from repository -func updateRepository(directory string, repo *git.Repository, branch string, auth ssh.AuthMethod, out io.Writer) error { +func updateRepository(directory string, repo *git.Repository, branch string, auth transport.AuthMethod, out io.Writer) error { tree, err := repo.Worktree() if err != nil { return err diff --git a/daemon/web/client.js b/daemon/web/client.js index c6b7be08..3c1bb322 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -1,25 +1,41 @@ import React from 'react'; export default class InertiaClient { - constructor(url) { - this.url = "https://" + url; - } + constructor(url) { + this.url = 'https://' + url; + } + + /** + * Makes a GET request to the given API endpoint with the given params. + * @param {String} endpoint + * @param {Object} params + */ + async _get(endpoint, params) { + params.method = 'GET'; + params.credentials = 'include'; + const request = new Request(this.url + endpoint, params); - /** - * Makes a GET request to the given API endpoint with the given params. - * @param {String} endpoint - * @param {Object} params - */ - async _get(endpoint, params) { - // @todo + try { + return await fetch(request); + } catch (e) { + return e; } + } + + /** + * Makes a POST request to the given API endpoint with the given params. + * @param {String} endpoint + * @param {Object} params + */ + async _post(endpoint, params) { + params.method = 'POST'; + params.credentials = 'include'; + const request = new Request(this.url + endpoint, params); - /** - * Makes a POST request to the given API endpoint with the given params. - * @param {String} endpoint - * @param {Object} params - */ - async _post(endpoint, params) { - // @todo + try { + return await fetch(request); + } catch (e) { + return e; } + } } diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index c62a815a..209a53f0 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -1,34 +1,105 @@ import React from 'react'; +import { Redirect, HashRouter, Route } from 'react-router-dom'; import PropTypes from 'prop-types'; +import createHistory from 'history/createBrowserHistory'; import InertiaClient from '../client'; +import Login from './Login'; +import Home from './Home'; + +// render a route component that requires authentication +const AuthRoute = ({ authenticated, component: Component, props, ...rest }) => ( + ( + authenticated + ? + : + )} /> +); + +// render a route component with props +const PropsRoute = ({ component: Component, props, ...rest }) => ( + ( + + )} /> +); export default class App extends React.Component { constructor(props) { super(props); + + this.state = { + loading: true, + authenticated: false, + }; + + this.isAuthenticated = this.isAuthenticated.bind(this); + + this.isAuthenticated().then((authenticated) => { + this.setState({ + loading: false, + authenticated: authenticated, + }); + }); + + const history = createHistory(); + history.listen(() => { + this.setState({ loading: true, authenticated: false }); + this.isAuthenticated().then((authenticated) => { + this.setState({ + loading: false, + authenticated: authenticated, + }); + }); + }); + } + + async isAuthenticated() { + const params = { + headers: { 'Accept': 'application/json' }, + }; + const response = await this.props.client._get( + '/user/validate', params + ); + return (response.status === 200); } render() { - return ( -
-

- + const { component: Component, ...rest } = this.props; + if (this.state.loading) { + return ( +

+ Loading...

-

- This is the Inertia web client! -

-
- ); + ); + } else { + return ( + +
+ } /> + + +
+
+ ); + } } } App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) -} + client: PropTypes.instanceOf(InertiaClient), + authenticated: PropTypes.instanceOf(Boolean), + loading: PropTypes.instanceOf(Boolean), +}; const styles = { container: { display: 'flex', - }, + height: '100%', + width: '100%' + } }; diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js new file mode 100644 index 00000000..735a7dfe --- /dev/null +++ b/daemon/web/components/Home.js @@ -0,0 +1,159 @@ +import React from 'react'; + +const SidebarHeader = ({ children }) => ( + +); +const sidebarHeaderStyles = { + container: { + display: 'flex', + alignItems: 'center', + height: '3rem', + width: '100%', + paddingLeft: '2rem' + }, + + text: { + textDecoration: 'none', + color: '#5f5f5f' + } +}; + +const SidebarButton = ({ children }) => ( + +); +const sidebarButtonStyles = { + container: { + display: 'flex', + alignItems: 'center', + height: '3rem', + width: '100%', + paddingLeft: '3rem' + }, + + text: { + textDecoration: 'none', + color: '#101010' + } +}; + + +export default class Home extends React.Component { + constructor(props) { + super(props); + this.handleGetLogs = this.handleGetLogs.bind(this); + this.handleLogout = this.handleLogout.bind(this); + } + + async handleGetLogs() { + const endpoint = '/logs'; + const params = { + headers: { + 'Accept': 'application/json' + } + }; + const response = await this.props.client._get(endpoint, params); + } + + async handleLogout() { + const endpoint = '/user/logout'; + const params = { + headers: { + 'Accept': 'application/json' + } + }; + + const response = await this.props.client._post(endpoint, params); + this.props.history.push('/login'); + } + + render() { + return ( +
+ +
+

Inertia Web

+ logout +
+ +
+ +
+ Deployments + project-app + project-db + project-server +
+ +
+
+

coming soon!

+
+
+ +
+ +
+ ); + } +} + +// hardcode all styles for now, until we flesh out UI +const styles = { + container: { + display: 'flex', + flexFlow: 'column', + height: '100%', + width: '100%' + }, + + innerContainer: { + display: 'flex', + flexFlow: 'row', + height: '100%', + width: '100%' + }, + + headerBar: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + height: '4rem', + padding: '0 2rem', + borderBottom: '1px solid #c1c1c1' + }, + + sidebar: { + display: 'flex', + flexFlow: 'column', + width: '20rem', + height: '100%', + paddingTop: '0.5rem', + borderRight: '1px solid #c1c1c1', + backgroundColor: '#f0f0f0' + }, + + main: { + height: '100%', + width: '100%', + overflowY: 'scroll' + }, + + button: { + flex: 'none' + }, + + underConstruction: { + textAlign: 'center', + fontSize: 24, + color: '#9f9f9f' + } +}; diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js new file mode 100644 index 00000000..cbe212e0 --- /dev/null +++ b/daemon/web/components/Login.js @@ -0,0 +1,89 @@ +import React from 'react'; + +export default class Login extends React.Component { + constructor(props) { + super(props); + this.state = { + username: '', + password: '', + loginAlert: '' + }; + this.handleLoginSubmit = this.handleLoginSubmit.bind(this); + this.handleUsernameBlur = this.handleUsernameBlur.bind(this); + this.handlePasswordBlur = this.handlePasswordBlur.bind(this); + } + + async handleLoginSubmit() { + const endpoint = '/user/login'; + const params = { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: JSON.stringify({ + username: this.state.username, + password: this.state.password, + email: '', + admin: true + }) + }; + const response = await this.props.client._post(endpoint, params); + if (response.status !== 200) { + this.setState({ loginAlert: 'Username and/or password is incorrect' }); + return; + } + + this.props.history.push('/home'); + } + + handleUsernameBlur(e) { + this.setState({ username: e.target.value }); + } + + handlePasswordBlur(e) { + this.setState({ password: e.target.value }); + } + + render() { + return ( +
+

+ +

+
+ + + +

{this.state.loginAlert}

+
+
+ ); + } +} + +const styles = { + container: { + display: 'flex', + flexFlow: 'column', + justifyContent: 'center', + height: '100%', + width: '100%' + }, + + login: { + position: 'relative', + display: 'flex', + flexFlow: 'column', + alignItems: 'center', + margin: '0.5rem 0', + marginBottom: '10rem' + }, + + loginAlert: { + position: 'absolute', + top: '105%' + } +}; + diff --git a/daemon/web/index.css b/daemon/web/index.css new file mode 100644 index 00000000..f7b2074e --- /dev/null +++ b/daemon/web/index.css @@ -0,0 +1,36 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +html { + height: 100vh; + width: 100vw; +} + +body { + height: 100%; + width: 100%; + font-family: 'Roboto', sans-serif; +} + +#app { + height: 100%; + width: 100%; +} \ No newline at end of file diff --git a/daemon/web/index.html b/daemon/web/index.html index be97268b..41a96e35 100644 --- a/daemon/web/index.html +++ b/daemon/web/index.html @@ -3,12 +3,12 @@ - Inertia + + Inertia Web
- diff --git a/daemon/web/index.js b/daemon/web/index.js index c217b3c2..ee1a4a2e 100644 --- a/daemon/web/index.js +++ b/daemon/web/index.js @@ -3,8 +3,12 @@ import ReactDOM from 'react-dom'; import App from './components/App'; import InertiaClient from './client'; +import './index.css'; // Define where the Inertia daemon is hosted. -const daemonAddress = window.location.host; +const daemonAddress = (process.env.NODE_ENV === 'development') ? '127.0.0.1:8081' : window.location.host; const client = new InertiaClient(daemonAddress); -ReactDOM.render(, document.getElementById('app')); +ReactDOM.render( + , + document.getElementById('app') +); diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index b721899c..5d9407c3 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -7,8 +7,7 @@ "@sindresorhus/is": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", - "dev": true + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, "accepts": { "version": "1.3.5", @@ -25,25 +24,17 @@ "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" }, "acorn-dynamic-import": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", "requires": { - "acorn": "4.0.13" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" - } + "acorn": "5.5.3" } }, "acorn-jsx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, "requires": { "acorn": "3.3.0" }, @@ -51,8 +42,7 @@ "acorn": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" } } }, @@ -71,21 +61,15 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=" }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" }, "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" }, "ansi-html": { "version": "0.0.7", @@ -105,23 +89,26 @@ "any-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.2.0.tgz", - "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=", - "dev": true + "integrity": "sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI=" }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "requires": { - "micromatch": "3.1.9", + "micromatch": "3.1.10", "normalize-path": "2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -144,8 +131,7 @@ "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" }, "array-find-index": { "version": "1.0.2", @@ -187,8 +173,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "asap": { "version": "2.0.6", @@ -221,16 +206,12 @@ "ast-types": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", - "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==", - "dev": true + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==" }, "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "requires": { - "lodash": "4.17.5" - } + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-each": { "version": "1.0.1", @@ -242,6 +223,19 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000830", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -297,7 +291,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -308,7 +301,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, "requires": { "babel-helper-explode-assignable-expression": "6.24.1", "babel-runtime": "6.26.0", @@ -356,7 +348,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -367,7 +358,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, "requires": { "babel-helper-bindify-decorators": "6.24.1", "babel-runtime": "6.26.0", @@ -448,7 +438,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -508,9 +497,9 @@ } }, "babel-minify-webpack-plugin": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/babel-minify-webpack-plugin/-/babel-minify-webpack-plugin-0.3.0.tgz", - "integrity": "sha512-avrx0Fa615QfivVV8PakEwOtthts/3qVFV+FYJffJn8WanaX4geKMGTYaPKITUXhqqEfuBJokdRQC5arNTZNIA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-minify-webpack-plugin/-/babel-minify-webpack-plugin-0.3.1.tgz", + "integrity": "sha512-Johg6Ju0Gxevk2R55eutMqnyXwlyUzCtwunBpiyNzoxGnKum+x5nfNuYZYHGd5Bmc1gmhjwzb7GkxHWOtYWmtQ==", "requires": { "babel-core": "6.26.0", "babel-preset-minify": "0.3.0", @@ -612,50 +601,42 @@ "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" }, "babel-plugin-syntax-decorators": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" }, "babel-plugin-syntax-flow": { "version": "6.18.0", @@ -670,20 +651,17 @@ "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, "babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-generators": "6.13.0", @@ -694,7 +672,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, "requires": { "babel-helper-remap-async-to-generator": "6.24.1", "babel-plugin-syntax-async-functions": "6.13.0", @@ -705,7 +682,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, "requires": { "babel-plugin-syntax-class-constructor-call": "6.18.0", "babel-runtime": "6.26.0", @@ -716,7 +692,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-plugin-syntax-class-properties": "6.13.0", @@ -728,7 +703,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, "requires": { "babel-helper-explode-class": "6.24.1", "babel-plugin-syntax-decorators": "6.13.0", @@ -953,7 +927,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, "requires": { "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", "babel-plugin-syntax-exponentiation-operator": "6.13.0", @@ -964,7 +937,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, "requires": { "babel-plugin-syntax-export-extensions": "6.13.0", "babel-runtime": "6.26.0" @@ -1003,7 +975,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, "requires": { "babel-plugin-syntax-object-rest-spread": "6.13.0", "babel-runtime": "6.26.0" @@ -1103,6 +1074,23 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.0.tgz", "integrity": "sha512-AVDVEmp0S9mbF1O8zekWbsOOmqnR08PZah5NRZJqSvJnFgiL0ep4Lwo4EymH8OieJR2QgQdR3q71TNW+wiVn4g==" }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.3", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + } + } + }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", @@ -1189,7 +1177,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, "requires": { "babel-plugin-transform-class-constructor-call": "6.24.1", "babel-plugin-transform-export-extensions": "6.22.0", @@ -1200,7 +1187,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, "requires": { "babel-plugin-syntax-dynamic-import": "6.18.0", "babel-plugin-transform-class-properties": "6.24.1", @@ -1212,7 +1198,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, "requires": { "babel-plugin-syntax-trailing-function-commas": "6.22.0", "babel-plugin-transform-async-generator-functions": "6.24.1", @@ -1340,8 +1325,12 @@ "binaryextensions": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", - "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==", - "dev": true + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, "bn.js": { "version": "4.11.8", @@ -1503,13 +1492,22 @@ "pako": "1.0.6" } }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "requires": { + "caniuse-db": "1.0.30000830", + "electron-to-chromium": "1.3.42" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { "base64-js": "1.2.3", - "ieee754": "1.1.10", + "ieee754": "1.1.11", "isarray": "1.0.0" } }, @@ -1538,6 +1536,33 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.2", + "mississippi": "2.0.0", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.3.0", + "unique-filename": "1.1.0", + "y18n": "4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1558,7 +1583,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", - "dev": true, "requires": { "clone-response": "1.0.2", "get-stream": "3.0.0", @@ -1567,13 +1591,19 @@ "lowercase-keys": "1.0.0", "normalize-url": "2.0.1", "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } } }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, "requires": { "callsites": "0.2.0" } @@ -1581,8 +1611,7 @@ "callsites": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" }, "camel-case": { "version": "3.0.0", @@ -1594,9 +1623,9 @@ } }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", @@ -1605,24 +1634,24 @@ "requires": { "camelcase": "2.1.1", "map-obj": "1.0.1" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - } } }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000830", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" } }, + "caniuse-db": { + "version": "1.0.30000830", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000830.tgz", + "integrity": "sha1-bkUlWzRWSf0V/1kHLaHhK7PeLxM=" + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1638,13 +1667,12 @@ "chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" }, "chokidar": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.2.tgz", - "integrity": "sha512-l32Hw3wqB0L2kGVmSbK/a+xXLDrUEsc84pSgMkmwygHvD7ubRsP/vxxHa5BtB6oix1XLLVCHyYMsckRXxThmZw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", "requires": { "anymatch": "2.0.0", "async-each": "1.0.1", @@ -1660,6 +1688,16 @@ "upath": "1.0.4" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "chrome-trace-event": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-0.1.2.tgz", + "integrity": "sha1-kPNohdU0WlBiEzLwcXtZWIPV2YI=" + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -1672,8 +1710,15 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "requires": { + "chalk": "1.1.3" + } }, "class-utils": { "version": "0.3.6", @@ -1759,7 +1804,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, "requires": { "restore-cursor": "2.0.0" } @@ -1767,14 +1811,12 @@ "cli-spinners": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" }, "cli-table": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "dev": true, "requires": { "colors": "1.0.3" }, @@ -1782,8 +1824,7 @@ "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" } } }, @@ -1791,7 +1832,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", - "dev": true, "requires": { "slice-ansi": "0.0.4", "string-width": "1.0.2" @@ -1800,14 +1840,12 @@ "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -1819,36 +1857,44 @@ "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, "clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "1.0.0" } @@ -1856,14 +1902,12 @@ "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" }, "cloneable-readable": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, "requires": { "inherits": "2.0.3", "process-nextick-args": "2.0.0", @@ -1873,8 +1917,15 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "requires": { + "q": "1.5.1" + } }, "code-point-at": { "version": "1.1.0", @@ -1890,11 +1941,20 @@ "object-visit": "1.0.1" } }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "requires": { + "clone": "1.0.4", + "color-convert": "1.9.1", + "color-string": "0.3.0" + } + }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -1902,19 +1962,35 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "requires": { + "color-name": "1.1.3" + } + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", + "requires": { + "color": "0.11.4", + "css-color-names": "0.0.4", + "has": "1.0.1" + } }, "colors": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", - "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==", - "dev": true + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" }, "commander": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.0.tgz", - "integrity": "sha512-7B1ilBwtYSbetCgTY1NJFg+gVpestg0fdA1MhC1Vs4ssyfSXnCAjFr+QcQM9/RedXC0EaUx1sG8Smgw2VfgKEg==" + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "commondir": { "version": "1.0.1", @@ -1957,7 +2033,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz", "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5", @@ -2007,6 +2082,19 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -2039,7 +2127,7 @@ "cipher-base": "1.0.4", "inherits": "2.0.3", "ripemd160": "2.0.1", - "sha.js": "2.4.10" + "sha.js": "2.4.11" } }, "create-hmac": { @@ -2052,7 +2140,7 @@ "inherits": "2.0.3", "ripemd160": "2.0.1", "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "sha.js": "2.4.11" } }, "cross-spawn": { @@ -2083,6 +2171,32 @@ "randomfill": "1.0.4" } }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" + }, + "css-loader": { + "version": "0.28.11", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", + "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", + "requires": { + "babel-code-frame": "6.26.0", + "css-selector-tokenizer": "0.7.0", + "cssnano": "3.10.0", + "icss-utils": "2.1.0", + "loader-utils": "1.1.0", + "lodash.camelcase": "4.3.0", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-modules-extract-imports": "1.2.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0", + "postcss-value-parser": "3.3.0", + "source-list-map": "2.0.0" + } + }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -2094,11 +2208,86 @@ "nth-check": "1.0.1" } }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "requires": { + "cssesc": "0.1.0", + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + } + } + }, "css-what": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=" }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "requires": { + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.1", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.2", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "requires": { + "clap": "1.2.3", + "source-map": "0.5.7" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -2107,25 +2296,20 @@ "array-find-index": "1.0.2" } }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "requires": { - "es5-ext": "0.10.41" - } + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" }, "dargs": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", - "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=", - "dev": true + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" }, "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", - "dev": true + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" }, "date-now": { "version": "0.1.4", @@ -2135,8 +2319,7 @@ "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, "debug": { "version": "2.6.9", @@ -2160,7 +2343,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, "requires": { "mimic-response": "1.0.0" } @@ -2173,14 +2355,12 @@ "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", - "dev": true + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "define-properties": { "version": "1.1.2", @@ -2200,6 +2380,11 @@ "isobject": "3.0.1" } }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, "del": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", @@ -2235,8 +2420,7 @@ "detect-conflict": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", - "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=", - "dev": true + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" }, "detect-indent": { "version": "4.0.0", @@ -2254,8 +2438,7 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "diffie-hellman": { "version": "5.0.2", @@ -2293,7 +2476,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, "requires": { "esutils": "2.0.2" } @@ -2359,14 +2541,23 @@ "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "stream-shift": "1.0.0" + } }, "editions": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", - "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", - "dev": true + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" }, "ee-first": { "version": "1.1.1", @@ -2376,14 +2567,17 @@ "ejs": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", - "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", - "dev": true + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=" + }, + "electron-to-chromium": { + "version": "1.3.42", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", + "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=" }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", - "dev": true + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" }, "elliptic": { "version": "6.4.0", @@ -2417,15 +2611,22 @@ "iconv-lite": "0.4.19" } }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", "requires": { "graceful-fs": "4.1.11", "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.8" + "tapable": "1.0.0" } }, "entities": { @@ -2445,7 +2646,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", - "dev": true, "requires": { "string-template": "0.2.1", "xtend": "4.0.1" @@ -2481,71 +2681,6 @@ "is-symbol": "1.0.1" } }, - "es5-ext": { - "version": "0.10.41", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.41.tgz", - "integrity": "sha512-MYK02wXfwTMie5TEJWPolgOsXEmz7wKCQaGzgmRjZOoV6VLG8I5dSv2bn6AOClXhK64gnSQTQ9W9MKvx87J4gw==", - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "next-tick": "1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2556,22 +2691,10 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.1", - "estraverse": "4.2.0" - } - }, "eslint": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.0.tgz", - "integrity": "sha512-r83L5CuqaocDvfwdojbz68b6tCUk8KJkqfppO+gmSAQqYCzTr0bCSMu6A6yFCLKG65j5eKcKUw4Cw4Yl4gfWkg==", - "dev": true, + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "requires": { "ajv": "5.5.2", "babel-code-frame": "6.26.0", @@ -2588,7 +2711,7 @@ "file-entry-cache": "2.0.0", "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "11.3.0", + "globals": "11.4.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", "inquirer": "3.3.0", @@ -2617,7 +2740,6 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.1.0", @@ -2628,14 +2750,12 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -2644,7 +2764,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -2655,28 +2774,19 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } }, "globals": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", - "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", + "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -2685,7 +2795,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -2696,7 +2805,6 @@ "version": "7.7.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==", - "dev": true, "requires": { "doctrine": "2.1.0", "has": "1.0.1", @@ -2708,7 +2816,6 @@ "version": "3.7.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, "requires": { "esrecurse": "4.2.1", "estraverse": "4.2.0" @@ -2717,14 +2824,12 @@ "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" }, "espree": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, "requires": { "acorn": "5.5.3", "acorn-jsx": "3.0.1" @@ -2733,14 +2838,12 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, "esquery": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true, "requires": { "estraverse": "4.2.0" } @@ -2768,15 +2871,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.41" - } - }, "eventemitter3": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", @@ -2821,8 +2915,7 @@ "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" }, "expand-brackets": { "version": "2.1.4", @@ -2949,7 +3042,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, "requires": { "homedir-polyfill": "1.0.1" } @@ -3021,7 +3113,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", - "dev": true, "requires": { "chardet": "0.4.2", "iconv-lite": "0.4.19", @@ -3074,8 +3165,12 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" }, "faye-websocket": { "version": "0.10.0", @@ -3110,7 +3205,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5" } @@ -3119,7 +3213,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, "requires": { "flat-cache": "1.3.0", "object-assign": "4.1.1" @@ -3187,7 +3280,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, "requires": { "readable-stream": "2.3.5" } @@ -3196,7 +3288,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, "requires": { "circular-json": "0.3.3", "del": "2.2.2", @@ -3208,7 +3299,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", @@ -3223,7 +3313,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, "requires": { "array-union": "1.0.2", "arrify": "1.0.1", @@ -3236,16 +3325,28 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" + }, "flow-parser": { "version": "0.68.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", - "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=", - "dev": true + "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=" + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5" + } }, "for-in": { "version": "1.0.2", @@ -3287,12 +3388,22 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.5" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4095,8 +4206,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "get-caller-file": { "version": "1.0.2", @@ -4122,7 +4232,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", - "dev": true, "requires": { "got": "7.1.0", "is-plain-obj": "1.1.0" @@ -4132,7 +4241,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, "requires": { "decompress-response": "3.3.0", "duplexer3": "0.1.4", @@ -4141,7 +4249,7 @@ "is-retry-allowed": "1.1.0", "is-stream": "1.1.0", "isurl": "1.0.0", - "lowercase-keys": "1.0.0", + "lowercase-keys": "1.0.1", "p-cancelable": "0.3.0", "p-timeout": "1.2.1", "safe-buffer": "5.1.1", @@ -4153,14 +4261,12 @@ "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" }, "p-timeout": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -4168,14 +4274,12 @@ "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, "requires": { "prepend-http": "1.0.4" } @@ -4186,7 +4290,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", - "dev": true, "requires": { "gh-got": "6.0.0" } @@ -4208,7 +4311,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", - "dev": true, "requires": { "glob": "7.1.2", "yargs": "1.2.6" @@ -4217,14 +4319,12 @@ "minimist": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", - "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", - "dev": true + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" }, "yargs": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", - "dev": true, "requires": { "minimist": "0.1.0" } @@ -4286,7 +4386,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, "requires": { "global-prefix": "1.0.2", "is-windows": "1.0.2", @@ -4297,7 +4396,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "homedir-polyfill": "1.0.1", @@ -4334,7 +4432,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", - "dev": true, "requires": { "@sindresorhus/is": "0.7.0", "cacheable-request": "2.1.4", @@ -4344,7 +4441,7 @@ "into-stream": "3.1.0", "is-retry-allowed": "1.1.0", "isurl": "1.0.0", - "lowercase-keys": "1.0.0", + "lowercase-keys": "1.0.1", "mimic-response": "1.0.0", "p-cancelable": "0.4.0", "p-timeout": "2.0.1", @@ -4364,7 +4461,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -4393,25 +4489,22 @@ "has-color": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbol-support-x": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, "requires": { "has-symbol-support-x": "1.4.2" } @@ -4467,6 +4560,18 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, + "history": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", + "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", + "requires": { + "invariant": "2.2.4", + "loose-envify": "1.3.1", + "resolve-pathname": "2.2.0", + "value-equal": "0.4.0", + "warning": "3.0.0" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -4477,6 +4582,11 @@ "minimalistic-crypto-utils": "1.0.1" } }, + "hoist-non-react-statics": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz", + "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==" + }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -4490,7 +4600,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, "requires": { "parse-passwd": "1.0.0" } @@ -4511,24 +4620,29 @@ "wbuf": "1.7.3" } }, + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=" + }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" }, "html-minifier": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.11.tgz", - "integrity": "sha512-kIi9C090qWW5cGxEf+EwNUczduyVR6krk29WB3zDSWBQN6xuh/1jCXgmY4SvqzaJMOZFCnf8wcNzA8iPsfLiUQ==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.12.tgz", + "integrity": "sha512-+N778qLf0RWBscD0TPGoYdeGNDZ0s76/0pQhY1/409EOudcENkm9IbSkk37RDyPdg/09GVHTKotU4ya93RF1Gg==", "requires": { "camel-case": "3.0.0", "clean-css": "4.1.11", - "commander": "2.15.0", + "commander": "2.15.1", "he": "1.1.1", "ncname": "1.0.0", "param-case": "2.1.1", "relateurl": "0.2.7", - "uglify-js": "3.3.15" + "uglify-js": "3.3.16" }, "dependencies": { "source-map": { @@ -4537,22 +4651,22 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "uglify-js": { - "version": "3.3.15", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.15.tgz", - "integrity": "sha512-bqtBCAINYXX/OkdnqMGpbXr+OPWc00hsozRpk+dAtfnbdk2jjKiLmyOkQ7zamg648lVMnzATL8JrSN6LmaVpYA==", + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.16.tgz", + "integrity": "sha512-FMh5SRqJRGhv9BbaTffENIpDDQIoPDR8DBraunGORGhySArsXlw9++CN+BWzPBLpoI4RcSnpfGPnilTxWL3Vvg==", "requires": { - "commander": "2.15.0", + "commander": "2.15.1", "source-map": "0.6.1" } } } }, "html-webpack-plugin": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.0.6.tgz", - "integrity": "sha1-01sEUqrhKaip8/rEShaaYl2M8/o=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.1.0.tgz", + "integrity": "sha1-bgK6rtsekGMQkX8DI5x5OnWvKIU=", "requires": { - "html-minifier": "3.5.11", + "html-minifier": "3.5.12", "loader-utils": "0.2.17", "lodash": "4.17.5", "pretty-error": "2.1.1", @@ -4571,11 +4685,6 @@ "json5": "0.5.1", "object-assign": "4.1.1" } - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" } } }, @@ -4624,8 +4733,7 @@ "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" }, "http-deceiver": { "version": "1.2.7", @@ -4781,42 +4889,106 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, - "ieee754": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.10.tgz", - "integrity": "sha512-byWFX8OyW/qeVxcY21r6Ncxl0ZYHgnf0cPup2h34eHXrCJbOp7IuqnJ4Q0omfyWl6Z++BTI6bByf31pZt7iRLg==" - }, - "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", - "dev": true - }, - "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" }, - "indent-string": { + "icss-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "requires": { - "repeating": "2.0.1" - } - }, - "indexof": { - "version": "0.0.1", + "postcss": "6.0.21" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "requires": { + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "ieee754": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "indexof": { + "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" }, @@ -4837,14 +5009,12 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -4865,14 +5035,12 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -4881,7 +5049,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -4891,14 +5058,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -4907,7 +5072,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -4931,7 +5095,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", - "dev": true, "requires": { "from2": "2.3.0", "p-is-promise": "1.1.0" @@ -4960,6 +5123,11 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=" + }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -5101,14 +5269,12 @@ "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", - "dev": true + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, "is-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-0.2.0.tgz", "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", - "dev": true, "requires": { "symbol-observable": "0.2.4" }, @@ -5116,8 +5282,7 @@ "symbol-observable": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", - "dev": true + "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=" } } }, @@ -5160,8 +5325,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-plain-object": { "version": "2.0.4", @@ -5184,8 +5348,7 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-regex": { "version": "1.0.4", @@ -5198,20 +5361,17 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" }, "is-scoped": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", - "dev": true, "requires": { "scoped-regex": "1.0.0" } @@ -5221,6 +5381,14 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "requires": { + "html-comment-regex": "1.1.1" + } + }, "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", @@ -5269,7 +5437,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", - "dev": true, "requires": { "binaryextensions": "2.1.1", "editions": "1.3.4", @@ -5280,12 +5447,16 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, "requires": { "has-to-string-tag-x": "1.4.1", "is-object": "1.0.1" } }, + "js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -5295,7 +5466,6 @@ "version": "3.11.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true, "requires": { "argparse": "1.0.10", "esprima": "4.0.0" @@ -5305,7 +5475,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.0.tgz", "integrity": "sha512-JAcQINNMFpdzzpKJN8k5xXjF3XDuckB1/48uScSzcnNyK199iWEc9AxKL9OoX5144M2w5zEx9Qs4/E/eBZZUlw==", - "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0", "babel-preset-es2015": "6.24.1", @@ -5319,7 +5488,7 @@ "neo-async": "2.5.0", "node-dir": "0.1.8", "nomnom": "1.8.1", - "recast": "0.14.5", + "recast": "0.14.7", "temp": "0.8.3", "write-file-atomic": "1.3.4" }, @@ -5328,7 +5497,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -5336,20 +5504,17 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "babylon": { "version": "7.0.0-beta.42", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", - "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", - "dev": true + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==" }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -5360,7 +5525,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -5369,7 +5533,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -5377,14 +5540,12 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -5393,7 +5554,6 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -5420,19 +5580,12 @@ "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-loader": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, "json-parse-better-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", - "dev": true + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==" }, "json-schema-traverse": { "version": "0.3.1", @@ -5442,8 +5595,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json3": { "version": "3.3.2", @@ -5459,7 +5611,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", - "dev": true, "requires": { "array-includes": "3.0.3" } @@ -5468,7 +5619,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "dev": true, "requires": { "json-buffer": "3.0.0" } @@ -5486,11 +5636,6 @@ "is-buffer": "1.1.6" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -5503,7 +5648,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -5513,7 +5657,6 @@ "version": "0.13.0", "resolved": "https://registry.npmjs.org/listr/-/listr-0.13.0.tgz", "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -5538,7 +5681,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -5548,7 +5690,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -5558,14 +5699,12 @@ "listr-silent-renderer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" }, "listr-update-renderer": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-truncate": "0.2.1", @@ -5581,7 +5720,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -5590,14 +5728,12 @@ "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -5608,7 +5744,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -5620,7 +5755,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -5629,7 +5763,6 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5", "object-assign": "4.1.1" @@ -5638,14 +5771,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -5654,20 +5785,29 @@ } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", "pify": "2.3.0", - "strip-bom": "3.0.0" + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } } } }, @@ -5700,21 +5840,35 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, "lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, "requires": { "chalk": "2.3.2" }, @@ -5723,7 +5877,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -5732,7 +5885,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -5742,14 +5894,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -5760,7 +5910,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", - "dev": true, "requires": { "ansi-escapes": "1.4.0", "cli-cursor": "1.0.2" @@ -5769,14 +5918,12 @@ "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "cli-cursor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -5784,14 +5931,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -5804,10 +5949,10 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=" }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + "loglevelnext": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.3.tgz", + "integrity": "sha512-OCxd/b78TijTB4b6zVqLbMrxhebyvdZKwqpL0VHUZ0pYhavXaPD4l6Xrr4n5xqTYWiqtb0i7ikSoJY/myQ/Org==" }, "loose-envify": { "version": "1.3.1", @@ -5832,10 +5977,9 @@ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" }, "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, "lru-cache": { "version": "4.1.2", @@ -5846,6 +5990,11 @@ "yallist": "2.1.2" } }, + "macaddress": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=" + }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", @@ -5872,6 +6021,11 @@ "object-visit": "1.0.1" } }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" + }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", @@ -5909,7 +6063,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", - "dev": true, "requires": { "through2": "2.0.3", "vinyl": "1.2.0", @@ -5920,7 +6073,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-3.0.2.tgz", "integrity": "sha1-3Qpuryu4prN3QAZ6pUnrUwEFr58=", - "dev": true, "requires": { "commondir": "1.0.1", "deep-extend": "0.4.2", @@ -5935,30 +6087,26 @@ }, "dependencies": { "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "clone-stats": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" }, "vinyl": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, "requires": { - "clone": "2.1.1", + "clone": "2.1.2", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", "cloneable-readable": "1.1.2", @@ -5994,81 +6142,10 @@ "trim-newlines": "1.0.0" }, "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } } } }, @@ -6083,9 +6160,9 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", - "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -6144,8 +6221,7 @@ "mimic-response": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", - "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=", - "dev": true + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" }, "minimalistic-assert": { "version": "1.0.0", @@ -6170,6 +6246,23 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "requires": { + "concat-stream": "1.6.1", + "duplexify": "3.5.4", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.4.0", + "stream-each": "1.2.2", + "through2": "2.0.3" + } + }, "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", @@ -6197,6 +6290,19 @@ "minimist": "0.0.8" } }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -6220,7 +6326,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, "requires": { "array-differ": "1.0.0", "array-union": "1.0.2", @@ -6231,8 +6336,7 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nan": { "version": "2.10.0", @@ -6269,8 +6373,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "ncname": { "version": "1.0.0", @@ -6290,16 +6393,10 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==" }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, "nice-try": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", - "dev": true + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" }, "no-case": { "version": "2.3.2", @@ -6312,8 +6409,7 @@ "node-dir": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", - "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=", - "dev": true + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" }, "node-fetch": { "version": "1.7.3", @@ -6363,7 +6459,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, "requires": { "chalk": "0.4.0", "underscore": "1.6.0" @@ -6372,14 +6467,12 @@ "ansi-styles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" }, "chalk": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, "requires": { "ansi-styles": "1.0.0", "has-color": "0.1.7", @@ -6389,8 +6482,7 @@ "strip-ansi": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" } } }, @@ -6413,11 +6505,15 @@ "remove-trailing-separator": "1.1.0" } }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" + }, "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "dev": true, "requires": { "prepend-http": "2.0.0", "query-string": "5.1.1", @@ -6440,6 +6536,11 @@ "boolbase": "1.0.0" } }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -6572,7 +6673,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -6589,7 +6689,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -6597,21 +6696,12 @@ "prelude-ls": "1.1.2", "type-check": "0.3.2", "wordwrap": "1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } } }, "ora": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, "requires": { "chalk": "1.1.3", "cli-cursor": "1.0.2", @@ -6623,7 +6713,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, "requires": { "restore-cursor": "1.0.1" } @@ -6631,14 +6720,12 @@ "onetime": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, "requires": { "exit-hook": "1.1.1", "onetime": "1.1.0" @@ -6693,14 +6780,12 @@ "p-cancelable": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.0.tgz", - "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==", - "dev": true + "integrity": "sha512-/AodqPe1y/GYbhSlnMjxukLGQfQIgsmjSy2CXCNB96kg4ozKvmlovuHEKICToOO/yS3LLWgrWI1dFtFfrePS1g==" }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, "requires": { "p-reduce": "1.0.0" } @@ -6713,14 +6798,12 @@ "p-is-promise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", - "dev": true + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, "p-lazy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", - "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=", - "dev": true + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" }, "p-limit": { "version": "1.2.0", @@ -6746,14 +6829,12 @@ "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", - "dev": true, "requires": { "p-finally": "1.0.0" } @@ -6768,6 +6849,16 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.5" + } + }, "param-case": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", @@ -6825,8 +6916,7 @@ "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, "parseurl": { "version": "1.3.2", @@ -6871,8 +6961,7 @@ "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, "path-to-regexp": { "version": "0.1.7", @@ -6880,11 +6969,13 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "requires": { - "pify": "2.3.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" }, "dependencies": { "pify": { @@ -6903,7 +6994,7 @@ "create-hmac": "1.1.6", "ripemd160": "2.0.1", "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "sha.js": "2.4.11" } }, "pify": { @@ -6935,8 +7026,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" }, "portfinder": { "version": "1.0.13", @@ -6960,48 +7050,568 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "requires": { + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" + } }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "requires": { + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } }, - "prettier": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", - "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", - "dev": true + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "requires": { + "postcss": "5.2.18" + } }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "requires": { - "renderkid": "2.0.1", - "utila": "0.4.0" + "postcss": "5.2.18" } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "requires": { + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "postcss-filter-plugins": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", + "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "requires": { + "postcss": "5.2.18", + "uniqid": "4.1.1" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "requires": { + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.1" + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=" + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "requires": { + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "requires": { + "alphanum-sort": "1.0.2", + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", + "requires": { + "postcss": "6.0.21" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "requires": { + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.21" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "requires": { + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.21" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "requires": { + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.21" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "postcss": { + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", + "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "requires": { + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "requires": { + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "requires": { + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "1.1.0" + } + } + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "requires": { + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "uniqs": "2.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", + "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "requires": { + "renderkid": "2.0.1", + "utila": "0.4.0" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.11.10", @@ -7016,8 +7626,7 @@ "progress": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" }, "promise": { "version": "7.3.1", @@ -7027,6 +7636,11 @@ "asap": "2.0.6" } }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, "prop-types": { "version": "15.6.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", @@ -7068,11 +7682,35 @@ "randombytes": "2.0.6" } }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "requires": { + "duplexify": "3.5.4", + "inherits": "2.0.3", + "pump": "2.0.1" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", @@ -7082,7 +7720,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "dev": true, "requires": { "decode-uri-component": "0.2.0", "object-assign": "4.1.1", @@ -7178,33 +7815,93 @@ "prop-types": "15.6.1" } }, + "react-router": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", + "integrity": "sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg==", + "requires": { + "history": "4.7.2", + "hoist-non-react-statics": "2.5.0", + "invariant": "2.2.4", + "loose-envify": "1.3.1", + "path-to-regexp": "1.7.0", + "prop-types": "15.6.1", + "warning": "3.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz", + "integrity": "sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA==", + "requires": { + "history": "4.7.2", + "invariant": "2.2.4", + "loose-envify": "1.3.1", + "prop-types": "15.6.1", + "react-router": "4.2.0", + "warning": "3.0.0" + } + }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", - "dev": true, "requires": { "pify": "3.0.0", "safe-buffer": "5.1.1" } }, "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "requires": { - "load-json-file": "2.0.0", + "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "path-type": "1.1.0" } }, "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + } } }, "readable-stream": { @@ -7233,10 +7930,9 @@ } }, "recast": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.5.tgz", - "integrity": "sha512-GNFQGQrqW1R8w9XhhgYIN8H7ePPp088D+svHlb7DdP5DCqNDqTwH7lt378EouM+L18kCwkmqpAz1unLqpPhHmw==", - "dev": true, + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", + "integrity": "sha512-/nwm9pkrcWagN40JeJhkPaRxiHXBRkXyRh/hgU088Z/v+qCy+zIHHY6bC6o7NaKAxPqtE6nD8zBH1LfU0/Wx6A==", "requires": { "ast-types": "0.11.3", "esprima": "4.0.0", @@ -7247,8 +7943,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -7256,9 +7951,8 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "1.6.0" } }, "redent": { @@ -7270,6 +7964,38 @@ "strip-indent": "1.0.1" } }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "requires": { + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "requires": { + "balanced-match": "0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + } + } + }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", @@ -7310,8 +8036,7 @@ "regexpp": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.0.1.tgz", - "integrity": "sha512-8Ph721maXiOYSLtaDGKVmDn5wdsNaF6Px85qFNeMPQq0r8K5Y10tgP6YuR65Ws35n4DvzFcCxEnRNBIXQunzLw==", - "dev": true + "integrity": "sha512-8Ph721maXiOYSLtaDGKVmDn5wdsNaF6Px85qFNeMPQq0r8K5Y10tgP6YuR65Ws35n4DvzFcCxEnRNBIXQunzLw==" }, "regexpu-core": { "version": "2.0.0", @@ -7393,8 +8118,7 @@ "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" }, "require-directory": { "version": "2.1.1", @@ -7410,7 +8134,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, "requires": { "caller-path": "0.1.0", "resolve-from": "1.0.1" @@ -7419,8 +8142,7 @@ "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" } } }, @@ -7430,10 +8152,9 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", + "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", "requires": { "path-parse": "1.0.5" } @@ -7450,7 +8171,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, "requires": { "expand-tilde": "2.0.2", "global-modules": "1.0.0" @@ -7461,6 +8181,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -7470,16 +8195,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, "requires": { - "lowercase-keys": "1.0.0" + "lowercase-keys": "1.0.1" } }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, "requires": { "onetime": "2.0.1", "signal-exit": "3.0.2" @@ -7490,14 +8213,6 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "requires": { - "align-text": "0.1.4" - } - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -7519,22 +8234,27 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, "requires": { "is-promise": "2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "1.2.0" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" }, "rx-lite-aggregates": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, "requires": { "rx-lite": "4.0.8" } @@ -7543,7 +8263,6 @@ "version": "5.5.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", - "dev": true, "requires": { "symbol-observable": "1.0.1" } @@ -7561,11 +8280,24 @@ "ret": "0.1.15" } }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "schema-utils": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "requires": { + "ajv": "6.3.0", + "ajv-keywords": "3.1.0" + } + }, "scoped-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", - "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", - "dev": true + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" }, "select-hose": { "version": "2.0.0", @@ -7605,6 +8337,11 @@ "statuses": "1.4.0" } }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=" + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -7672,9 +8409,9 @@ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sha.js": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", - "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -7697,7 +8434,6 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", - "dev": true, "requires": { "glob": "7.1.2", "interpret": "1.1.0", @@ -7718,7 +8454,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0" }, @@ -7726,16 +8461,14 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" } } }, "slide": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" }, "snapdragon": { "version": "0.8.2", @@ -7885,7 +8618,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, "requires": { "is-plain-obj": "1.1.0" } @@ -7963,13 +8695,13 @@ "http-deceiver": "1.2.7", "safe-buffer": "5.1.1", "select-hose": "2.0.0", - "spdy-transport": "2.0.20" + "spdy-transport": "2.1.0" } }, "spdy-transport": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz", - "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", + "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", "requires": { "debug": "2.6.9", "detect-node": "2.0.3", @@ -7991,8 +8723,15 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "requires": { + "safe-buffer": "5.1.1" + } }, "static-extend": { "version": "0.1.2", @@ -8078,6 +8817,15 @@ "readable-stream": "2.3.5" } }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } + }, "stream-http": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", @@ -8090,11 +8838,15 @@ "xtend": "4.0.1" } }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, "stream-to-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", - "dev": true, "requires": { "any-observable": "0.2.0" } @@ -8102,14 +8854,12 @@ "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" }, "string-width": { "version": "2.1.1", @@ -8165,7 +8915,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "dev": true, "requires": { "first-chunk-stream": "2.0.0", "strip-bom": "2.0.0" @@ -8175,7 +8924,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "0.2.1" } @@ -8198,25 +8946,66 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "style-loader": { + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz", + "integrity": "sha512-2I7AVP73MvK33U7B9TKlYZAqdROyMXDYSMvHLX43qy3GCOaJNiV6i0v/sv9idWIaQ42Yn2dNv79Q5mKXbKhAZg==", + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.4.5" + } }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "requires": { + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + } + } + } + }, "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" }, "table": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, "requires": { "ajv": "5.5.2", "ajv-keywords": "2.1.1", @@ -8230,7 +9019,6 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.1.0", @@ -8241,14 +9029,12 @@ "ajv-keywords": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -8257,24 +9043,16 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", "supports-color": "5.3.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -8282,15 +9060,14 @@ } }, "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" }, "temp": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, "requires": { "os-tmpdir": "1.0.2", "rimraf": "2.2.8" @@ -8299,34 +9076,29 @@ "rimraf": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" } } }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "textextensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", - "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==", - "dev": true + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, "requires": { "readable-stream": "2.3.5", "xtend": "4.0.1" @@ -8337,16 +9109,10 @@ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=" }, - "time-stamp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", - "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=" - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, "timers-browserify": { "version": "2.0.6", @@ -8360,7 +9126,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "1.0.2" } @@ -8427,7 +9192,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -8444,58 +9208,60 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "ua-parser-js": { "version": "0.7.17", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "commander": "2.13.0", + "source-map": "0.6.1" }, "dependencies": { - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "optional": true - }, "uglifyjs-webpack-plugin": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", - "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.4.tgz", + "integrity": "sha512-z0IbjpW8b3O/OVn+TTZN4pI29RN1zktFBXLIzzfZ+++cUtZ1ERSlLWgpE/5OERuEUs1ijVQnpYAkSlpoVmQmSQ==", "requires": { - "source-map": "0.5.7", - "uglify-js": "2.8.29", - "webpack-sources": "1.1.0" + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "schema-utils": "0.4.5", + "serialize-javascript": "1.4.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "union-value": { "version": "1.0.0", @@ -8529,6 +9295,40 @@ } } }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "uniqid": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", + "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "requires": { + "macaddress": "0.2.8" + } + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" + }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "requires": { + "imurmurhash": "0.1.4" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -8573,8 +9373,7 @@ "untildify": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.2.tgz", - "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=", - "dev": true + "integrity": "sha1-fx8wIFWz/qDz6B3HjrNnZstl4/E=" }, "upath": { "version": "1.0.4", @@ -8607,6 +9406,11 @@ } } }, + "url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" + }, "url-parse": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", @@ -8627,7 +9431,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, "requires": { "prepend-http": "2.0.0" } @@ -8635,8 +9438,7 @@ "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", - "dev": true + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, "use": { "version": "3.1.0", @@ -8700,8 +9502,7 @@ "v8-compile-cache": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz", - "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==", - "dev": true + "integrity": "sha512-ejdrifsIydN1XDH7EuR2hn8ZrkRKUYF7tUcBjBy/lhrCvs2K+zRlbW9UHc0IQ9RsYFZJFqJrieoIHfkCa0DBRA==" }, "validate-npm-package-license": { "version": "3.0.3", @@ -8712,18 +9513,27 @@ "spdx-expression-parse": "3.0.0" } }, + "value-equal": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz", + "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "vendors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", + "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=" + }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -8732,7 +9542,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -8745,14 +9554,12 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, "requires": { "is-utf8": "0.2.1" } @@ -8767,12 +9574,20 @@ "indexof": "0.0.1" } }, + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "1.3.1" + } + }, "watchpack": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", "requires": { - "chokidar": "2.0.2", + "chokidar": "2.0.3", "graceful-fs": "4.1.11", "neo-async": "2.5.0" } @@ -8786,49 +9601,35 @@ } }, "webpack": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.2.0.tgz", + "integrity": "sha512-O/KmJ2MYoSfsZzq3//RyyYICYTb1gPAuYSIoD4XbxWFqkDrZCkF8BIAwPuFjA8SFqTcsIL3gTS7hiTZaUN2Tjw==", "requires": { "acorn": "5.5.3", - "acorn-dynamic-import": "2.0.2", + "acorn-dynamic-import": "3.0.0", "ajv": "6.3.0", "ajv-keywords": "3.1.0", - "async": "2.6.0", - "enhanced-resolve": "3.4.1", - "escope": "3.6.0", - "interpret": "1.1.0", - "json-loader": "0.5.7", - "json5": "0.5.1", + "chrome-trace-event": "0.1.2", + "enhanced-resolve": "4.0.0", + "eslint-scope": "3.7.1", "loader-runner": "2.3.0", "loader-utils": "1.1.0", "memory-fs": "0.4.1", + "micromatch": "3.1.10", "mkdirp": "0.5.1", + "neo-async": "2.5.0", "node-libs-browser": "2.1.0", - "source-map": "0.5.7", - "supports-color": "4.5.0", - "tapable": "0.2.8", - "uglifyjs-webpack-plugin": "0.4.6", + "schema-utils": "0.4.5", + "tapable": "1.0.0", + "uglifyjs-webpack-plugin": "1.2.4", "watchpack": "1.5.0", - "webpack-sources": "1.1.0", - "yargs": "8.0.2" - }, - "dependencies": { - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "requires": { - "has-flag": "2.0.0" - } - } + "webpack-sources": "1.1.0" } }, "webpack-addons": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", - "dev": true, "requires": { "jscodeshift": "0.4.1" }, @@ -8837,7 +9638,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -8845,26 +9645,17 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, "ast-types": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", - "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -8875,7 +9666,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -8884,7 +9674,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -8892,14 +9681,12 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -8908,7 +9695,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", - "dev": true, "requires": { "async": "1.5.2", "babel-plugin-transform-flow-strip-types": "6.22.0", @@ -8931,7 +9717,6 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -8952,7 +9737,6 @@ "version": "0.12.9", "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", - "dev": true, "requires": { "ast-types": "0.10.1", "core-js": "2.5.3", @@ -8964,16 +9748,14 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, "webpack-cli": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", - "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", - "dev": true, + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.13.tgz", + "integrity": "sha512-0lnOi3yla8FsZVuMsbfnNRB/8DlfuDugKdekC+4ykydZG0+UOidMi5J5LLWN4c0VJ8PqC19yMXXkYyCq78OuqA==", "requires": { "chalk": "2.3.2", "cross-spawn": "6.0.5", @@ -9005,14 +9787,12 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -9020,14 +9800,12 @@ "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "chalk": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -9038,7 +9816,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", - "dev": true, "requires": { "string-width": "2.1.1", "strip-ansi": "4.0.0", @@ -9049,7 +9826,6 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "1.0.4", "path-key": "2.0.1", @@ -9058,28 +9834,10 @@ "which": "1.3.0" } }, - "enhanced-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", - "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "tapable": "1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "inquirer": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.1.0.tgz", "integrity": "sha512-kn7N70US1MSZHZHSGJLiZ7iCwwncc7b0gc68YtlX29OjI3Mp0tSVV+snVXpZ1G+ONS3Ac9zd1m6hve2ibLDYfA==", - "dev": true, "requires": { "ansi-escapes": "3.0.0", "chalk": "2.3.2", @@ -9100,7 +9858,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -9109,22 +9866,14 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true - }, "yargs": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "dev": true, "requires": { "cliui": "4.0.0", "decamelize": "1.2.0", @@ -9144,7 +9893,6 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, "requires": { "camelcase": "4.1.0" } @@ -9152,33 +9900,35 @@ } }, "webpack-dev-middleware": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", - "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.0.1.tgz", + "integrity": "sha512-JCturcEZNGA0KHEpOJVRTC/VVazTcPfpR9c1Au6NO9a+jxCRchMi87Qe7y3JeOzc0v5eMMKpuGBnPdN52NA+CQ==", "requires": { + "loud-rejection": "1.6.0", "memory-fs": "0.4.1", - "mime": "1.6.0", + "mime": "2.2.0", "path-is-absolute": "1.0.1", "range-parser": "1.2.0", - "time-stamp": "2.0.0" + "url-join": "4.0.0", + "webpack-log": "1.1.2" }, "dependencies": { "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", + "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==" } } }, "webpack-dev-server": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.2.tgz", - "integrity": "sha512-zrPoX97bx47vZiAXfDrkw8pe9QjJ+lunQl3dypojyWwWr1M5I2h0VSrMPfTjopHQPRNn+NqfjcMmhoLcUJe2gA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.1.tgz", + "integrity": "sha512-u5lz6REb3+KklgSIytUIOrmWgnpgFmfj/+I+GBXurhEoCsHXpG9twk4NO3bsu72GC9YtxIsiavjfRdhmNt0A/A==", "requires": { "ansi-html": "0.0.7", "array-includes": "3.0.3", "bonjour": "3.5.0", - "chokidar": "2.0.2", + "chokidar": "2.0.3", "compression": "1.7.2", "connect-history-api-fallback": "1.5.0", "debug": "3.1.0", @@ -9200,25 +9950,11 @@ "spdy": "3.4.7", "strip-ansi": "3.0.1", "supports-color": "5.3.0", - "webpack-dev-middleware": "1.12.2", - "yargs": "6.6.0" + "webpack-dev-middleware": "3.0.1", + "webpack-log": "1.1.2", + "yargs": "9.0.1" }, "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -9227,98 +9963,43 @@ "ms": "2.0.0" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "has-flag": "3.0.0" } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + } + } + }, + "webpack-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.1.2.tgz", + "integrity": "sha512-B53SD4N4BHpZdUwZcj4st2QT7gVfqZtqHDruC1N+K2sciq0Rt/3F1Dx6RlylVkcrToMLTaiaeT48k9Lq4iDVDA==", + "requires": { + "chalk": "2.3.2", + "log-symbols": "2.2.0", + "loglevelnext": "1.0.3", + "uuid": "3.2.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "color-convert": "1.9.1" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "requires": { - "is-utf8": "0.2.1" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" } }, "supports-color": { @@ -9328,39 +10009,6 @@ "requires": { "has-flag": "3.0.0" } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "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": "4.2.1" - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "requires": { - "camelcase": "3.0.0" - } } } }, @@ -9399,6 +10047,11 @@ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" + }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", @@ -9412,15 +10065,18 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" - }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "requires": { + "errno": "0.1.7" + } }, "wrap-ansi": { "version": "2.1.0", @@ -9452,7 +10108,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, "requires": { "mkdirp": "0.5.1" } @@ -9461,7 +10116,6 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "imurmurhash": "0.1.4", @@ -9489,9 +10143,9 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "requires": { "camelcase": "4.1.0", "cliui": "3.2.0", @@ -9513,26 +10167,47 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" } } } @@ -9556,7 +10231,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.0.5.tgz", "integrity": "sha512-6/W7/B54OPHJXob0n0+pmkwFsirC8cokuQkPSmT/D0lCcSxkKtg/BA6ZnjUBIwjuGqmw3DTrT4en++htaUju5g==", - "dev": true, "requires": { "chalk": "2.3.2", "debug": "3.1.0", @@ -9577,7 +10251,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } @@ -9586,7 +10259,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -9597,22 +10269,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -9623,7 +10287,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.3.tgz", "integrity": "sha512-mODmrZ26a94djmGZZuIiomSGlN4wULdou29ZwcySupb2e9FdvoCl7Ps2FqHFjEHio3kOl/iBeaNqrnx3C3NwWg==", - "dev": true, "requires": { "async": "2.6.0", "chalk": "2.3.2", @@ -9656,16 +10319,22 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "1.9.1" } }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.5" + } + }, "chalk": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -9676,22 +10345,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "4.0.0", @@ -9702,14 +10363,12 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, "requires": { "error-ex": "1.3.1", "json-parse-better-errors": "1.0.1" @@ -9719,7 +10378,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, "requires": { "pify": "3.0.0" } @@ -9728,7 +10386,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, "requires": { "load-json-file": "4.0.0", "normalize-package-data": "2.4.0", @@ -9739,7 +10396,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, "requires": { "find-up": "2.1.0", "read-pkg": "3.0.0" @@ -9749,7 +10405,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", - "dev": true, "requires": { "has-flag": "3.0.0" } diff --git a/daemon/web/package.json b/daemon/web/package.json index 3752770d..5714f018 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -2,30 +2,34 @@ "name": "inertia-web", "version": "1.0.0", "description": "Simple, self-hosted continuous deployment", - "repositiory": "github:ubclaunchpad/inertia", + "repository": "github:ubclaunchpad/inertia", "author": "UBC Launch Pad", "license": "MIT", "main": "index.js", "scripts": { - "start": "NODE_ENV=development webpack-dev-server --hot --host 0.0.0.0", + "start": "NODE_ENV=development webpack-dev-server --host=127.0.0.1", "build": "NODE_ENV=production webpack --config webpack.prod.js", "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "babel-core": "^6.26.0", - "babel-loader": "^7.1.2", + "babel-loader": "^7.1.4", + "babel-minify-webpack-plugin": "^0.3.1", + "babel-polyfill": "^6.26.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", - "html-webpack-plugin": "^3.0.6", + "babel-preset-stage-3": "^6.24.1", + "css-loader": "^0.28.11", + "eslint": "^4.19.1", + "eslint-plugin-react": "^7.7.0", + "html-webpack-plugin": "^3.1.0", + "prop-types": "^15.6.1", "react": "^16.2.0", "react-dom": "^16.2.0", - "webpack": "^3.10.0", - "webpack-dev-server": "^2.11.1", - "babel-minify-webpack-plugin": "^0.3.0" - }, - "devDependencies": { - "eslint": "^4.16.0", - "eslint-plugin-react": "^7.6.0", - "webpack-cli": "^2.0.10" + "react-router-dom": "^4.2.2", + "style-loader": "^0.21.0", + "webpack": "^4.2.0", + "webpack-cli": "^2.0.13", + "webpack-dev-server": "^3.1.1" } } diff --git a/daemon/web/webpack.config.js b/daemon/web/webpack.config.js index 22d2823f..766ba164 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -1,15 +1,10 @@ /* eslint-disable */ const webpack = require('webpack'); -const MinifyPlugin = require('babel-minify-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); -const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({ - template: './index.html', - filename: 'index.html', - inject: 'body', -}) const config = { - entry: './index.js', + mode: 'development', + entry: ['babel-polyfill', './index.js'], output: { path: `${__dirname}/public/`, filename: 'bundle.js', @@ -18,25 +13,47 @@ const config = { port: 7900, inline: true, contentBase: './public', - publicPath: '/', + publicPath: '/web/', }, devtool: 'inline-source-map', module: { - loaders: [ + rules: [ { test: /\.jsx?$/, - exclude: '/node_modules/', - loader: 'babel-loader', - query: { - presets: ['es2015', 'react'], - }, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'stage-3', 'react'], + }, + } + ], }, + { + test: /\.css/, + exclude: /node_modules/, + use: ['style-loader', 'css-loader'], + } ], }, plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - HtmlWebpackPluginConfig, + new webpack.DefinePlugin({ + 'process.env': { + // define environment variables here + NODE_ENV: JSON.stringify(process.env.NODE_ENV), + } + }), + new webpack.DefinePlugin({ + // suppress react devtools console warning + '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' + }), + new HtmlWebpackPlugin({ + template: './index.html', + filename: 'index.html', + inject: 'body' + }) ] }; -module.exports = env => config; +module.exports = config; diff --git a/daemon/web/webpack.prod.js b/daemon/web/webpack.prod.js index 961d194b..6da67222 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -6,24 +6,34 @@ const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({ template: './index.html', filename: 'index.html', inject: 'body', -}) +}); const config = { - entry: './index.js', + mode: 'production', + entry: ['babel-polyfill', './index.js'], output: { path: `${__dirname}/public/`, filename: 'bundle.js', }, module: { - loaders: [ + rules: [ { test: /\.jsx?$/, - exclude: '/node_modules/', - loader: 'babel-loader', - query: { - presets: ['es2015', 'react'], - }, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react', 'stage-3'], + }, + } + ], }, + { + test: /\.css/, + exclude: /node_modules/, + use: ['style-loader', 'css-loader'], + } ], }, plugins: [ @@ -33,4 +43,4 @@ const config = { ] }; -module.exports = env => config; +module.exports = config; diff --git a/deploy_cmd.go b/deploy.go similarity index 77% rename from deploy_cmd.go rename to deploy.go index b80fdc98..10cf8df9 100644 --- a/deploy_cmd.go +++ b/deploy.go @@ -20,12 +20,13 @@ var deploymentUpCmd = &cobra.Command{ This will run 'docker-compose up --build'. Requires the Inertia daemon to be active on your remote - do this by running 'inertia [REMOTE] init'`, Run: func(cmd *cobra.Command, args []string) { - // Start the deployment - deployment, err := client.GetDeployment(strings.Split(cmd.Parent().Use, " ")[0]) + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) if err != nil { log.Fatal(err) } stream, err := cmd.Flags().GetBool("stream") + if err != nil { log.Fatal(err) } @@ -42,7 +43,7 @@ var deploymentUpCmd = &cobra.Command{ if !stream { body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.WithError(err) + log.Fatal(err) } switch resp.StatusCode { case http.StatusCreated: @@ -75,20 +76,20 @@ var deploymentDownCmd = &cobra.Command{ This will kill all active project containers on your remote. Requires project to be online - do this by running 'inertia [REMOTE] up`, Run: func(cmd *cobra.Command, args []string) { - // Shut down the deployment - deployment, err := client.GetDeployment(strings.Split(cmd.Parent().Use, " ")[0]) + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) if err != nil { log.Fatal(err) } resp, err := deployment.Down() if err != nil { - log.WithError(err) + log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.WithError(err) + log.Fatal(err) } switch resp.StatusCode { @@ -112,22 +113,21 @@ var deploymentStatusCmd = &cobra.Command{ Requires the Inertia daemon to be active on your remote - do this by running 'inertia [REMOTE] up'`, Run: func(cmd *cobra.Command, args []string) { - - // Get status of the deployment - deployment, err := client.GetDeployment(strings.Split(cmd.Parent().Use, " ")[0]) + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) if err != nil { log.Fatal(err) } host := "http://" + deployment.RemoteVPS.GetIPAndPort() resp, err := deployment.Status() if err != nil { - log.WithError(err) + log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.WithError(err) + log.Fatal(err) } switch resp.StatusCode { @@ -147,43 +147,6 @@ var deploymentStatusCmd = &cobra.Command{ }, } -var deploymentResetCmd = &cobra.Command{ - Use: "reset", - Short: "Reset the project on your remote", - Long: `Reset the project on your remote. - On this remote, this kills all active containers and clears the project - directory, allowing you to assign a different Inertia project to this - remote. Requires Inertia daemon to be active on your remote - do this by - running 'inertia [REMOTE] init'`, - Run: func(cmd *cobra.Command, args []string) { - // Remove project from deployment - deployment, err := client.GetDeployment(strings.Split(cmd.Parent().Use, " ")[0]) - if err != nil { - log.Fatal(err) - } - resp, err := deployment.Reset() - if err != nil { - log.WithError(err) - } - - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - log.WithError(err) - } - - switch resp.StatusCode { - case http.StatusOK: - fmt.Printf("(Status code %d) %s\n", resp.StatusCode, body) - case http.StatusForbidden: - fmt.Printf("(Status code %d) Bad auth: %s\n", resp.StatusCode, body) - default: - fmt.Printf("(Status code %d) Unknown response from daemon: %s\n", - resp.StatusCode, body) - } - }, -} - var deploymentLogsCmd = &cobra.Command{ Use: "logs", Short: "Access logs of your VPS", @@ -192,8 +155,8 @@ var deploymentLogsCmd = &cobra.Command{ also be used to access logs of specific containers - use 'inertia [REMOTE] status' to see what containers are accessible.`, Run: func(cmd *cobra.Command, args []string) { - // Start the deployment - deployment, err := client.GetDeployment(strings.Split(cmd.Parent().Use, " ")[0]) + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) if err != nil { log.Fatal(err) } @@ -216,7 +179,7 @@ var deploymentLogsCmd = &cobra.Command{ if !stream { body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.WithError(err) + log.Fatal(err) } switch resp.StatusCode { case http.StatusOK: @@ -242,31 +205,24 @@ var deploymentLogsCmd = &cobra.Command{ }, } -// deploymentSSHCmd represents the inertia [REMOTE] ssh command var deploymentSSHCmd = &cobra.Command{ Use: "ssh", Short: "Start an interactive SSH session", Long: `Starts up an interact SSH session with your remote.`, Run: func(cmd *cobra.Command, args []string) { - config, err := client.GetProjectConfigFromDisk() + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) if err != nil { log.Fatal(err) } - remoteName := strings.Split(cmd.Parent().Use, " ")[0] - remote, found := config.GetRemote(remoteName) - if found { - session := client.NewSSHRunner(remote) - if err = session.RunSession(); err != nil { - log.Fatal(err.Error()) - } - } else { - log.Fatal(errors.New("There does not appear to be a remote with this name. Have you modified the Inertia configuration file?")) + session := client.NewSSHRunner(deployment.RemoteVPS) + if err = session.RunSession(); err != nil { + log.Fatal(err.Error()) } }, } -// deploymentInitCmd represents the inertia [REMOTE] init command var deploymentInitCmd = &cobra.Command{ Use: "init", Short: "Initialize the VPS for continuous deployment", @@ -277,13 +233,13 @@ A URL will be provided to direct GitHub webhooks to, the daemon will request access to the repository via a public key, and will listen for updates to this repository's remote master branch.`, Run: func(cmd *cobra.Command, args []string) { - // Ensure project initialized. + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + + // Bootstrap needs to write to configuration. config, err := client.GetProjectConfigFromDisk() if err != nil { log.Fatal(err) } - - remoteName := strings.Split(cmd.Parent().Use, " ")[0] remote, found := config.GetRemote(remoteName) if found { session := client.NewSSHRunner(remote) @@ -297,12 +253,50 @@ for updates to this repository's remote master branch.`, }, } +var deploymentResetCmd = &cobra.Command{ + Use: "reset", + Short: "Reset the project on your remote", + Long: `Reset the project on your remote. +On this remote, this kills all active containers and clears the project +directory, allowing you to assign a different Inertia project to this +remote. Requires Inertia daemon to be active on your remote - do this by +running 'inertia [REMOTE] init'`, + Run: func(cmd *cobra.Command, args []string) { + remoteName := strings.Split(cmd.Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) + if err != nil { + log.Fatal(err) + } + resp, err := deployment.Reset() + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + + switch resp.StatusCode { + case http.StatusOK: + fmt.Printf("(Status code %d) %s\n", resp.StatusCode, body) + case http.StatusForbidden: + fmt.Printf("(Status code %d) Bad auth: %s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon: %s\n", + resp.StatusCode, body) + } + }, +} + func init() { config, err := client.GetProjectConfigFromDisk() if err != nil { return } + // Make a new command for each remote with all associated + // deployment commands. for _, remote := range config.Remotes { cmd := &cobra.Command{ Use: remote.Name + " [COMMAND]", @@ -321,36 +315,54 @@ with your GitHub repository. Run 'inertia [REMOTE] init' to gather this information.`, } - up := &cobra.Command{} - *up = *deploymentUpCmd + // Deep copy and attach each deployment command. + up := deepCopy(deploymentUpCmd) up.Flags().String("type", "", "Specify a build method for your project") cmd.AddCommand(up) - down := &cobra.Command{} - *down = *deploymentDownCmd + down := deepCopy(deploymentDownCmd) cmd.AddCommand(down) - status := &cobra.Command{} - *status = *deploymentStatusCmd + status := deepCopy(deploymentStatusCmd) cmd.AddCommand(status) - reset := &cobra.Command{} - *reset = *deploymentResetCmd - cmd.AddCommand(reset) - - logs := &cobra.Command{} - *logs = *deploymentLogsCmd + logs := deepCopy(deploymentLogsCmd) cmd.AddCommand(logs) - ssh := &cobra.Command{} - *ssh = *deploymentSSHCmd + user := deepCopy(deploymentUserCmd) + adduser := deepCopy(deploymentUserAddCmd) + adduser.Flags().Bool("admin", false, "Create an admin user") + removeuser := deepCopy(deploymentUserRemoveCmd) + resetusers := deepCopy(deploymentUsersResetCmd) + listusers := deepCopy(deploymentUsersListCmd) + user.AddCommand(adduser) + user.AddCommand(removeuser) + user.AddCommand(resetusers) + user.AddCommand(listusers) + cmd.AddCommand(user) + + ssh := deepCopy(deploymentSSHCmd) cmd.AddCommand(ssh) - init := &cobra.Command{} - *init = *deploymentInitCmd + init := deepCopy(deploymentInitCmd) cmd.AddCommand(init) - cmd.PersistentFlags().Bool("stream", false, "Stream output from daemon") + reset := deepCopy(deploymentResetCmd) + cmd.AddCommand(reset) + + // Attach a "stream" option on all commands, even if it doesn't + // do anything for some commands yet. + cmd.PersistentFlags().BoolP( + "stream", "s", false, + "Stream output from daemon - doesn't do anything on some commands.", + ) rootCmd.AddCommand(cmd) } } + +// deepCopy is a helper function for deeply copying a command. +func deepCopy(cmd *cobra.Command) *cobra.Command { + newCmd := &cobra.Command{} + *newCmd = *cmd + return newCmd +} diff --git a/deploy_users.go b/deploy_users.go new file mode 100644 index 00000000..934ad2de --- /dev/null +++ b/deploy_users.go @@ -0,0 +1,180 @@ +package main + +import ( + "fmt" + "io/ioutil" + "net/http" + "strings" + "syscall" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/ubclaunchpad/inertia/client" + "golang.org/x/crypto/ssh/terminal" +) + +var deploymentUserCmd = &cobra.Command{ + Use: "user", + Short: "Configure user access to Inertia Web", + Long: `Configure user access to the Inertia Web application.`, +} + +var deploymentUserAddCmd = &cobra.Command{ + Use: "add", + Short: "Create a user with access to Inertia Web", + Long: `Create a user with access to the Inertia Web application. + +This user will be able to log in and view or configure the +deployment from the web app. + +Use the --admin flag to create an admin user.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + remoteName := strings.Split(cmd.Parent().Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) + if err != nil { + log.Fatal(err) + } + admin, err := cmd.Flags().GetBool("admin") + if err != nil { + log.Fatal(err) + } + + fmt.Print("Enter a password for user: ") + bytePassword, err := terminal.ReadPassword(int(syscall.Stdin)) + if err != nil { + log.Fatal("Invalid password") + } + password := strings.TrimSpace(string(bytePassword)) + fmt.Print("\n") + + resp, err := deployment.AddUser(args[0], password, admin) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal(err) + } + + switch resp.StatusCode { + case http.StatusCreated: + fmt.Printf("(Status code %d) User added!\n", resp.StatusCode) + case http.StatusForbidden: + fmt.Printf("(Status code %d) Bad auth:\n%s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", + resp.StatusCode, body) + } + }, +} + +var deploymentUserRemoveCmd = &cobra.Command{ + Use: "rm", + Short: "Remove a user with access to Inertia Web", + Long: `Remove a user with access to the Inertia Web application. + +This user will no longer be able to log in and view or configure the +deployment from the web app.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + remoteName := strings.Split(cmd.Parent().Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) + if err != nil { + log.Fatal(err) + } + + resp, err := deployment.RemoveUser(args[0]) + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.WithError(err) + } + + switch resp.StatusCode { + case http.StatusOK: + fmt.Printf("(Status code %d) User removed.\n", resp.StatusCode) + case http.StatusForbidden: + fmt.Printf("(Status code %d) Bad auth:\n%s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", + resp.StatusCode, body) + } + }, +} + +var deploymentUsersResetCmd = &cobra.Command{ + Use: "reset", + Short: "Reset user database on your remote.", + Long: `Removes all users credentials on your remote. All users will +no longer be able to log in and view or configure the deployment +from the web app.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + remoteName := strings.Split(cmd.Parent().Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) + if err != nil { + log.Fatal(err) + } + + resp, err := deployment.ResetUsers() + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.WithError(err) + } + + switch resp.StatusCode { + case http.StatusOK: + fmt.Printf("(Status code %d) All users removed.\n", resp.StatusCode) + case http.StatusForbidden: + fmt.Printf("(Status code %d) Bad auth:\n%s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", + resp.StatusCode, body) + } + }, +} + +var deploymentUsersListCmd = &cobra.Command{ + Use: "ls", + Short: "List all users registered on your remote.", + Long: `List all users with access to Inertia Web on your remote.`, + Run: func(cmd *cobra.Command, args []string) { + remoteName := strings.Split(cmd.Parent().Parent().Use, " ")[0] + deployment, err := client.GetDeployment(remoteName) + if err != nil { + log.Fatal(err) + } + + resp, err := deployment.ListUsers() + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.WithError(err) + } + + switch resp.StatusCode { + case http.StatusOK: + fmt.Printf("(Status code %d) %s\n", resp.StatusCode, body) + case http.StatusForbidden: + fmt.Printf("(Status code %d) Bad auth:\n%s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", + resp.StatusCode, body) + } + }, +} diff --git a/init_cmd.go b/init.go similarity index 100% rename from init_cmd.go rename to init.go diff --git a/remote_cmd.go b/remote.go similarity index 90% rename from remote_cmd.go rename to remote.go index f9972460..0d36b49a 100644 --- a/remote_cmd.go +++ b/remote.go @@ -19,7 +19,6 @@ var ( errInvalidSecret = errors.New("invalid secret") ) -// remoteCmd represents the remote command var remoteCmd = &cobra.Command{ Use: "remote", Short: "Configure the local settings for a remote VPS instance", @@ -36,7 +35,6 @@ inerta remote status gcloud`, Args: cobra.MinimumNArgs(1), } -// addCmd represents the remote add command var addCmd = &cobra.Command{ Use: "add [REMOTE]", Short: "Add a reference to a remote VPS instance", @@ -80,7 +78,8 @@ file. Specify a VPS name.`, }, } -// addRemoteWalkthough is the walkthrough that asks users for RemoteVPS details +// addRemoteWalkthough is the command line walkthrough that asks +// users for RemoteVPS details func addRemoteWalkthrough(in io.Reader, name, port, sshPort, currBranch string, config *client.Config) error { homeEnvVar := os.Getenv("HOME") sshDir := filepath.Join(homeEnvVar, ".ssh") @@ -142,7 +141,6 @@ func addRemoteWalkthrough(in io.Reader, name, port, sshPort, currBranch string, return config.Write() } -// listCmd represents the inertia list command var listCmd = &cobra.Command{ Use: "ls", Short: "List currently configured remotes", @@ -164,7 +162,6 @@ var listCmd = &cobra.Command{ }, } -// removeCmd represents the inertia list command var removeCmd = &cobra.Command{ Use: "rm [REMOTE]", Short: "Remove a remote.", @@ -227,15 +224,7 @@ func init() { remoteCmd.AddCommand(removeCmd) remoteCmd.AddCommand(showCmd) - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // remoteCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: listCmd.Flags().BoolP("verbose", "v", false, "Verbose output") - addCmd.Flags().StringP("port", "p", common.DefaultPort, "Daemon port") + addCmd.Flags().StringP("port", "p", "8081", "Daemon port") addCmd.Flags().StringP("sshPort", "s", "22", "SSH port") } diff --git a/remote_cmd_test.go b/remote_test.go similarity index 100% rename from remote_cmd_test.go rename to remote_test.go