From 9b8389bea1db53d31d6702317245a5309e0d5d1e Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Tue, 20 Mar 2018 21:20:36 -0700 Subject: [PATCH 01/73] Add inertia binary to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1db8588f..20143cf7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,8 @@ *.dll *.so *.dylib -inertia.* +/inertia.* +/inertia # Test binary, build with `go test -c` *.test From 5812c2f8dfe9fd7009ce61e01ea34a98c5fc1459 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 02:04:35 -0700 Subject: [PATCH 02/73] Scaffold daemon permissions handling * User administration implementation using xyproto/permissionbold and boltDB * Route Inertia web through permissions handler * Set up basic user administration endpoints * Set up basic login/logout endpoints --- Gopkg.lock | 34 ++++- Gopkg.toml | 4 + common/request.go | 8 ++ daemon/inertia/auth/permissions.go | 170 ++++++++++++++++++++++++ daemon/inertia/auth/permissions_test.go | 18 +++ daemon/inertia/daemon.go | 21 ++- 6 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 daemon/inertia/auth/permissions.go create mode 100644 daemon/inertia/auth/permissions_test.go diff --git a/Gopkg.lock b/Gopkg.lock index ff6059b7..590acf1a 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"] @@ -174,9 +180,35 @@ packages = ["."] revision = "ba9c9e33906f58169366275e3450db66139a31a9" +[[projects]] + name = "github.com/xyproto/cookie" + packages = ["."] + revision = "8ce3defb0907741a2a8c9b56cce0f716c933ce34" + version = "2.0" + +[[projects]] + name = "github.com/xyproto/permissionbolt" + packages = ["."] + revision = "657ad1a411098f614a30382e53d4267067b0fa43" + version = "2.3" + +[[projects]] + name = "github.com/xyproto/pinterface" + packages = ["."] + revision = "05fa0e3080664c781c213d0a890a9d22718f7afb" + version = "4.1" + +[[projects]] + name = "github.com/xyproto/simplebolt" + packages = ["."] + revision = "3ad76f169f0ede30c60f6b098efd305ad995e417" + version = "3.0" + [[projects]] name = "golang.org/x/crypto" packages = [ + "bcrypt", + "blowfish", "cast5", "curve25519", "ed25519", @@ -296,6 +328,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5b5d8e6e2a0597fd5a14c0bfc3d0e54dd03347f272439a71d8850f1b6c763a12" + inputs-digest = "294a0ae7024c96836ece6ea3bef954904613ea63c41d34dfe0bbb463315dae47" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 3441ac26..4ebb1c4c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -29,3 +29,7 @@ [[constraint]] revision = "9de5f2eaf759b4c4550b3db39fed2e9e5f86f45c" name = "golang.org/x/crypto" + +[[constraint]] + name = "github.com/xyproto/permissionbolt" + version = "2.3.0" diff --git a/common/request.go b/common/request.go index c817adac..03667c3d 100644 --- a/common/request.go +++ b/common/request.go @@ -23,3 +23,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/permissions.go b/daemon/inertia/auth/permissions.go new file mode 100644 index 00000000..09080acd --- /dev/null +++ b/daemon/inertia/auth/permissions.go @@ -0,0 +1,170 @@ +package auth + +import ( + "encoding/json" + "io/ioutil" + "net/http" + + "github.com/ubclaunchpad/inertia/common" + "github.com/xyproto/permissionbolt" + "github.com/xyproto/pinterface" +) + +// 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 { + // perm is a Permissions structure that can be used to deny requests + // and acquire the UserState. By using `pinterface.IPermissions` instead + // of `*permissionbolt.Permissions`, the code is compatible with not only + // `permissionbolt`, but also other modules that uses other database + // backends, like `permissions2` which uses Redis. + perm pinterface.IPermissions + + // Mux is the HTTP multiplexer + Mux *http.ServeMux +} + +// Implement the ServeHTTP method to make a permissionHandler a http.Handler +func (ph *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Check if the user has the right admin/user rights + if ph.perm.Rejected(w, r) { + ph.perm.DenyFunction()(w, r) + return + } + // Serve the requested page if permissions were granted + ph.Mux.ServeHTTP(w, r) +} + +// addUserHandler handles requests to add users +func (ph *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) + userstate := ph.perm.UserState() + userstate.AddUser(userReq.Username, userReq.Password, userReq.Email) + userstate.MarkConfirmed(userReq.Username) + if userReq.Admin { + userstate.SetAdminStatus(userReq.Username) + } +} + +// removeUserHandler handles requests to add users +func (ph *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 + userstate := ph.perm.UserState() + userstate.RemoveUser(userReq.Username) +} + +// loginHandler handles requests to add users +func (ph *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 + userstate := ph.perm.UserState() + correct := userstate.CorrectPassword(userReq.Username, userReq.Password) + if correct { + userstate.Login(w, userReq.Username) + } else { + http.Error(w, "Login failed", http.StatusForbidden) + } +} + +// logoutHandler handles requests to add users +func (ph *PermissionsHandler) logoutHandler(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 out user + userstate := ph.perm.UserState() + userstate.Logout(userReq.Username) +} + +func redirectToLogin(w http.ResponseWriter, r *http.Request) { + // @todo: direct to login page + http.Error(w, "Permission denied!", http.StatusForbidden) +} + +// NewPermissionsHandler returns a new handler for authenticating +// users and handling user administration +func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { + mux := http.NewServeMux() + perm, err := permissionbolt.NewWithConf(dbPath) + if err != nil { + println("Could not open Bolt database") + return nil, err + } + + // Set permissions + perm.Clear() + perm.SetUserPath([]string{"/"}) + perm.SetPublicPath([]string{"/login"}) + + // Set default handler for unauthenticated users + perm.SetDenyFunction(redirectToLogin) + + // Set up webhandler + ph := &PermissionsHandler{perm: perm, Mux: mux} + + // The following endpoints are for user administration and must + // be used from the CLI and delivered with the daemon token. + mux.HandleFunc("/adduser", Authorized(ph.addUserHandler, GetAPIPrivateKey)) + mux.HandleFunc("/removeuser", Authorized(ph.removeUserHandler, GetAPIPrivateKey)) + + // The following endpoints are for the web app. + mux.HandleFunc("/login", ph.loginHandler) + mux.HandleFunc("/logout", ph.logoutHandler) + + return ph, nil +} diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go new file mode 100644 index 00000000..8c38a22e --- /dev/null +++ b/daemon/inertia/auth/permissions_test.go @@ -0,0 +1,18 @@ +package auth + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPermissionsHandlerConstructor(t *testing.T) { + dir := "./test" + err := os.Mkdir(dir, os.ModePerm) + assert.Nil(t, err) + defer os.RemoveAll(dir) + ph, err := NewPermissionsHandler("./test/users.db") + assert.Nil(t, err) + assert.NotNil(t, ph) +} diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 1279b21f..c6a868f1 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -62,8 +62,21 @@ func run(host, port, version string) { } } - // API endpoints + // GitHub webhook endpoint mux := http.NewServeMux() + mux.HandleFunc("/", gitHubWebHookHandler) + + // Inertia web - PermissionsHandler is used to authenticate web + // app access and manage users + permHandler, err := auth.NewPermissionsHandler(auth.UserDatabasePath) + if err != nil { + println(err.Error()) + return + } + permHandler.Mux.Handle("/", http.FileServer(http.Dir("/app/inertia-web"))) + mux.Handle("/web/", http.StripPrefix("/web", permHandler)) + + // API endpoints mux.HandleFunc("/up", auth.Authorized(upHandler, auth.GetAPIPrivateKey)) mux.HandleFunc("/down", auth.Authorized(downHandler, auth.GetAPIPrivateKey)) mux.HandleFunc("/status", auth.Authorized(statusHandler, auth.GetAPIPrivateKey)) @@ -71,12 +84,6 @@ func run(host, port, version string) { mux.HandleFunc("/logs", auth.Authorized(logHandler, auth.GetAPIPrivateKey)) mux.HandleFunc("/health-check", auth.Authorized(auth.HealthCheckHandler, auth.GetAPIPrivateKey)) - // GitHub webhook endpoint - mux.HandleFunc("/", gitHubWebHookHandler) - - // Inertia web - mux.Handle("/admin/", http.StripPrefix("/admin/", http.FileServer(http.Dir("/app/inertia-web")))) - // Serve daemon on port println("Serving daemon on port " + port) println(http.ListenAndServeTLS( From 336f38546be707c39f6e734136e9d050da37c46e Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 18:42:04 -0700 Subject: [PATCH 03/73] Initialize .inertia directory on host --- Gopkg.lock | 2 +- client/bootstrap.go | 6 +++--- client/bootstrap/daemon-up.sh | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 590acf1a..63b6bc1d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -328,6 +328,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "294a0ae7024c96836ece6ea3bef954904613ea63c41d34dfe0bbb463315dae47" + inputs-digest = "468c11fee7752d824dd1afaf7eaf0cd0bba548f3d29017006099aac6e2ec5bdf" solver-name = "gps-cdcl" solver-version = 1 diff --git a/client/bootstrap.go b/client/bootstrap.go index e17e112e..4da458be 100644 --- a/client/bootstrap.go +++ b/client/bootstrap.go @@ -92,7 +92,7 @@ func clientBootstrapDaemonDownSh() (*asset, error) { 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\x27\xd2\xc9\xd6\x5f\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\x2f\xf0\x8d\x31\x41\x08\x65\x0a\x60\xb5\x46\x28\xec\xd6\x00\xfe\xd4\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\xff\x41\xca\x95\xae\x18\x3d\x44\x46\xd5\x98\x0e\x8f\x74\x88\xbe\x0b\xbd\x82\x47\x78\x07\xf2\x05\xa2\xe1\x2b\xb0\x08\x9e\x3e\x87\x29\x18\x01\x00\x80\x79\x69\x21\xfa\xa6\xab\x2a\xd4\x3f\x10\xc9\xad\x61\x15\xc4\x8a\xe3\x38\x6a\x03\x8f\x19\xf8\x1a\xe4\x0a\x5e\x03\x8b\x95\xfe\x1c\x9a\xbe\xf7\xe8\x94\x47\x50\xce\x79\xeb\xbc\x56\xbc\x9f\x38\xe8\x5a\x3d\x63\xdc\xb1\x8b\x5e\xcd\x20\x82\x77\x29\x44\x8c\xc4\xa7\x0c\x07\x70\xdf\x54\x55\xeb\x9b\xdd\xf4\x0e\x32\xf5\x0d\x84\x90\xc0\x7b\x7c\x1a\xf1\x16\x79\x17\xd0\x86\xad\x37\x04\x56\x84\x47\x28\xb7\xad\x4f\x4e\x84\x38\x05\xdc\x35\xf0\x16\x6c\x65\x55\x01\x52\x43\xd2\x45\xca\x36\x52\xac\x74\x50\x64\xd6\x98\x5e\x51\xd8\x6a\x2e\x41\xe5\x39\x12\x01\xdb\xb6\xb1\xd2\x12\xef\x81\x28\xfc\x70\xeb\x10\x8f\x15\x6e\x94\xe1\x63\x03\x82\x14\x03\xe0\x52\x13\x68\x02\x83\x01\x45\xf9\x5f\xb0\xc4\x5c\x35\x84\xb0\x45\xd8\x86\x8c\xfe\x99\x85\x1a\x4b\x04\xb5\xac\x10\x88\x95\x67\x31\x68\xc1\x89\xad\xeb\x59\x11\x84\xc8\x1d\x95\x18\xc6\x7c\x4e\xa0\x2a\xb2\x6d\x84\xb7\x1b\xf4\xa4\x55\xf5\x5e\x0c\xa0\x64\x76\x74\x95\x24\xdb\xed\x36\xae\x36\x65\xac\x6d\xe2\x2c\x31\x25\x85\x35\x2c\xf1\xa7\xb3\x84\x92\x4b\x94\x5d\x3f\xb2\xeb\x47\x1a\xcb\x12\x37\x68\x24\x5b\xa9\x64\xef\xaf\x92\xeb\x4a\x0c\x8e\x0a\x7a\xcc\x6d\x5d\xa3\x29\xb0\x38\x2e\xf7\xc3\x21\xab\x97\x17\x1b\x3f\x6b\x2e\x9b\x65\x28\xfb\xe1\xe2\xf2\x8f\xe4\xe2\xcf\xe4\xe2\x63\x52\xd8\xb6\x40\x43\x87\xb2\xda\xec\xff\xad\xac\x97\xb9\x4e\xc4\x00\x46\x04\x0a\x3c\x52\x53\xf1\xfb\x4e\xc3\x7e\x2a\xa5\x22\xf0\xd6\xf2\x7e\x32\x3b\x39\x3c\xd6\x96\x11\x36\x8e\x62\x71\xf2\x04\x1a\x03\xb2\x00\x29\x7d\x0d\xff\xb5\x66\x90\xae\xb7\x74\x58\x22\xd1\x55\x34\x3c\x5d\x2b\xd1\x3e\x72\x03\xc9\x46\xf9\xc4\x37\x26\xe9\xe0\xe2\x20\xd2\xd5\x5b\x87\x7d\x4a\xd4\x6e\x96\xe8\x2a\x51\xce\x25\xad\x61\x76\x57\x08\xe1\x22\xdd\xdd\xf7\xa7\xf3\xf9\xcd\xe2\xdb\x64\xfa\xcf\x64\x11\xf6\xe6\x3c\x3d\x3f\x64\x26\x31\x51\x99\xac\x8d\xdd\x9a\x45\xf8\xa6\xf3\x7d\x96\x0c\xcb\xa4\xef\xa3\xdd\x26\xbb\xbb\xa8\x7b\x33\x51\x4b\xa4\xdf\xc3\x91\xf8\x1d\x00\x00\xff\xff\x74\x47\xad\x86\xf1\x05\x00\x00") +var _clientBootstrapDaemonUpSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x54\x4d\x6f\xdb\x38\x10\xbd\xf3\x57\x4c\x65\x07\xb9\x94\x52\xd2\x62\x81\xae\x0b\x1d\xbc\x8d\xd0\x18\x4d\xec\xc0\xce\x62\xb1\xc8\x06\x2e\x2d\x8d\x23\xd6\x12\xc9\xe5\x8c\xec\x36\xbf\xbe\xa0\xfc\x21\xdb\xc8\xc9\xd6\x70\xe6\xcd\x9b\xc7\xc7\xe9\xc1\x5f\x8a\x74\x0e\x94\x7b\xed\x18\x96\xd6\xc3\xc2\x6b\xf3\xa2\xcd\x0b\x34\x0e\xb8\x44\x28\x14\xd6\xd6\xc4\x42\x10\x32\x48\x14\xe2\x66\x98\xdd\x4f\xc6\xf3\x69\x76\x97\x0d\x67\x59\x7a\xf1\x74\xfd\x4c\xfb\xe0\xc3\x64\xfa\x98\x5e\x3c\x7d\x78\x26\x71\x3b\x99\x3d\xce\x87\x37\x37\xd3\x6c\x36\x4b\x2f\x9e\x3e\x3e\xd3\xa1\x74\x3c\xbc\xcf\x52\x6d\xd0\xb3\x56\x72\x8b\x2f\x46\xf7\xc3\xaf\x59\xda\x2c\xf2\x4a\x35\x26\x2f\x9d\x2a\x92\x5d\xc6\xa0\x7f\xda\x51\x7c\x99\x8c\x1f\x87\xa3\x71\x36\xdd\xb6\xfb\x74\xf5\xe9\x5a\x88\x1e\xcc\x90\x03\xe7\x42\x7b\xcc\xd9\x7a\x8d\x24\xea\x55\xa1\x3d\x48\x07\xfd\xdb\xc9\x7d\x96\x38\x6f\x7f\x60\xce\xe7\x61\xa2\xea\x3c\x14\xef\x7a\x07\xdc\x2f\x25\xe6\x2b\xd0\x4b\x50\x95\x47\x55\xfc\x02\xdf\x18\x13\x04\x52\xa6\x00\x56\x2b\x84\xc2\x6e\x0c\xe0\x4f\x4d\x1c\xc2\x7b\xc1\x86\x77\xd3\x6c\x78\xf3\xef\x7c\xfa\xf7\x78\x3c\x1a\x7f\x4d\xbf\x53\x53\x58\x28\x6c\xbe\x42\x0f\x8e\x40\xfe\x0f\x52\x2e\x75\xc5\xe8\x21\x32\xaa\xc6\xb4\x7f\xa4\x4f\xf4\x5d\xe8\x25\x3c\xc1\x3b\x90\xaf\x10\xf5\xcf\xc0\x22\x78\xfe\x1c\x6e\xc7\x08\x00\x00\xcc\x4b\x0b\xd1\x37\x5d\x55\xa1\xff\x81\x48\x6e\x0d\xab\x30\x48\x1c\xc7\x51\x9b\x78\xcc\xc0\xd7\x20\x97\x70\x0e\x2c\x96\xfa\x73\x18\xfa\xc1\xa3\x53\x1e\x41\x39\xe7\xad\xf3\x5a\xf1\xde\x09\xa0\x6b\xf5\x82\xf1\x96\x5d\x74\x76\x37\x11\xbc\x4b\x21\x62\x24\x3e\x65\xd8\x83\x87\xa6\xaa\x5a\x3f\xed\x94\x3d\xc8\xd4\x0d\x10\x52\x02\xef\xd1\x69\xc6\x5b\xe4\x5d\x40\xeb\xb7\x9e\x11\x58\x11\x1e\xa1\xdc\xb5\xfe\x39\x11\xe2\x14\x70\x37\xc0\x5b\xb0\x95\x55\x05\x48\x0d\xc9\x36\x53\xb6\x99\x62\xa9\x83\x22\xd3\xc6\x74\x8a\xc2\x46\x73\x09\x2a\xcf\x91\x08\xd8\xb6\x83\x95\x96\x78\x0f\x44\xe1\x87\x5b\x87\x78\xac\x70\xad\x0c\x1f\x1b\x13\xa4\xe8\x01\x97\x9a\x40\x13\x18\x0c\x28\xca\xff\x82\x05\xe6\xaa\x21\x84\x0d\xc2\x26\x54\x74\xcf\x2f\xf4\x58\x20\xa8\x45\x85\x40\xac\x3c\x8b\x5e\x0b\x4e\x6c\x5d\xc7\x8a\x20\x64\xee\xa8\xc4\x30\xe2\x4b\x02\x55\x91\x6d\x33\xbc\x5d\xa3\x27\xad\xaa\xf7\xa2\x07\x25\xb3\xa3\x41\x92\x6c\x36\x9b\xb8\x5a\x97\xb1\xb6\x89\xb3\xc4\x94\x14\xd6\xb0\xc4\x9f\xce\x12\x4a\x2e\x51\x6e\xe7\x91\xdb\x79\xa4\xb1\x2c\x71\x8d\x46\xb2\x95\x4a\x76\xfe\x2a\xb9\xae\x44\xef\xa8\xa1\xc7\xdc\xd6\x35\x9a\x02\x8b\xe3\x76\x3f\x1c\xb2\x7a\x7d\xb5\xf1\x8b\xe6\xb2\x59\x84\xb6\x1f\xae\xae\xff\x48\xae\xfe\x4c\xae\x3e\x26\x85\x6d\x1b\x34\x74\x68\xab\xcd\xfe\xdf\xd2\x7a\x99\xeb\x44\xf4\x60\x48\xa0\xc0\x23\x35\x15\xbf\xdf\x6a\xd8\xdd\x4a\xa9\x08\xbc\xb5\xbc\xbf\x99\x9d\x1c\x1e\x6b\xcb\x08\x6b\x47\xb1\x38\x79\x02\x8d\x01\x59\x80\x94\xbe\x86\xff\x5a\x33\x48\xd7\x59\x3a\x2c\x97\x68\x10\xf5\x4f\xd7\x4d\xb4\xcf\x5c\x43\xb2\x56\x3e\xf1\x8d\x49\xb6\x70\x71\x10\x69\xf0\x56\xb0\x2b\x89\xda\xf5\x12\x0d\x12\xe5\x5c\xd2\x1a\x66\x77\x84\x10\x0e\xd2\xdd\x79\x17\x9d\xcd\x6e\xe7\xdf\xc6\x93\x7f\xc6\xf3\xb0\x4f\x67\xe9\xe5\xa1\x32\x89\x89\xca\x64\x65\xec\xc6\xcc\xc3\x37\x5d\xee\xab\x64\x58\x26\xdd\x1c\xed\x36\xd9\x9d\x45\xdb\x37\x13\xb5\x44\xba\xfd\x1c\x89\xdf\x01\x00\x00\xff\xff\x4a\x93\x14\x8d\x09\x06\x00\x00") func clientBootstrapDaemonUpShBytes() ([]byte, error) { return bindataRead( @@ -107,7 +107,7 @@ func clientBootstrapDaemonUpSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1521, mode: os.FileMode(493), modTime: time.Unix(1521411052, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1545, mode: os.FileMode(493), modTime: time.Unix(1521682890, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -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(1521409807, 0)} + info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 309, mode: os.FileMode(493), modTime: time.Unix(1521411375, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/client/bootstrap/daemon-up.sh b/client/bootstrap/daemon-up.sh index 3a44db9b..079b7b48 100755 --- a/client/bootstrap/daemon-up.sh +++ b/client/bootstrap/daemon-up.sh @@ -13,6 +13,7 @@ CONTAINER_PORT=8081 # 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"` From 1da39390fda173b92ae0a97d481b7ea94b167c4f Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 18:42:15 -0700 Subject: [PATCH 04/73] Fix typo in package.json repository field --- daemon/web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/web/package.json b/daemon/web/package.json index 3752770d..1afcaaf0 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -2,7 +2,7 @@ "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", From 084c593bf35f15ed4dc2a0b18772217a1f539195 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 19:23:13 -0700 Subject: [PATCH 05/73] Clean up bootstrapping process and scripts --- client/bootstrap.go | 16 ++++++------ client/bootstrap/daemon-down.sh | 6 ++--- client/bootstrap/daemon-up.sh | 43 +++++++++++++++++++-------------- client/bootstrap/docker.sh | 4 +-- client/bootstrap/token.sh | 4 +-- client/remote.go | 21 ++++++++-------- client/remote_test.go | 4 +-- common/request.go | 3 --- daemon/inertia/main.go | 9 +++---- remote.go | 2 +- 10 files changed, 56 insertions(+), 56 deletions(-) diff --git a/client/bootstrap.go b/client/bootstrap.go index 4da458be..b2a5a3de 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(1514021421, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-down.sh", size: 251, mode: os.FileMode(420), modTime: time.Unix(1521684556, 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\x4d\x6f\xdb\x38\x10\xbd\xf3\x57\x4c\x65\x07\xb9\x94\x52\xd2\x62\x81\xae\x0b\x1d\xbc\x8d\xd0\x18\x4d\xec\xc0\xce\x62\xb1\xc8\x06\x2e\x2d\x8d\x23\xd6\x12\xc9\xe5\x8c\xec\x36\xbf\xbe\xa0\xfc\x21\xdb\xc8\xc9\xd6\x70\xe6\xcd\x9b\xc7\xc7\xe9\xc1\x5f\x8a\x74\x0e\x94\x7b\xed\x18\x96\xd6\xc3\xc2\x6b\xf3\xa2\xcd\x0b\x34\x0e\xb8\x44\x28\x14\xd6\xd6\xc4\x42\x10\x32\x48\x14\xe2\x66\x98\xdd\x4f\xc6\xf3\x69\x76\x97\x0d\x67\x59\x7a\xf1\x74\xfd\x4c\xfb\xe0\xc3\x64\xfa\x98\x5e\x3c\x7d\x78\x26\x71\x3b\x99\x3d\xce\x87\x37\x37\xd3\x6c\x36\x4b\x2f\x9e\x3e\x3e\xd3\xa1\x74\x3c\xbc\xcf\x52\x6d\xd0\xb3\x56\x72\x8b\x2f\x46\xf7\xc3\xaf\x59\xda\x2c\xf2\x4a\x35\x26\x2f\x9d\x2a\x92\x5d\xc6\xa0\x7f\xda\x51\x7c\x99\x8c\x1f\x87\xa3\x71\x36\xdd\xb6\xfb\x74\xf5\xe9\x5a\x88\x1e\xcc\x90\x03\xe7\x42\x7b\xcc\xd9\x7a\x8d\x24\xea\x55\xa1\x3d\x48\x07\xfd\xdb\xc9\x7d\x96\x38\x6f\x7f\x60\xce\xe7\x61\xa2\xea\x3c\x14\xef\x7a\x07\xdc\x2f\x25\xe6\x2b\xd0\x4b\x50\x95\x47\x55\xfc\x02\xdf\x18\x13\x04\x52\xa6\x00\x56\x2b\x84\xc2\x6e\x0c\xe0\x4f\x4d\x1c\xc2\x7b\xc1\x86\x77\xd3\x6c\x78\xf3\xef\x7c\xfa\xf7\x78\x3c\x1a\x7f\x4d\xbf\x53\x53\x58\x28\x6c\xbe\x42\x0f\x8e\x40\xfe\x0f\x52\x2e\x75\xc5\xe8\x21\x32\xaa\xc6\xb4\x7f\xa4\x4f\xf4\x5d\xe8\x25\x3c\xc1\x3b\x90\xaf\x10\xf5\xcf\xc0\x22\x78\xfe\x1c\x6e\xc7\x08\x00\x00\xcc\x4b\x0b\xd1\x37\x5d\x55\xa1\xff\x81\x48\x6e\x0d\xab\x30\x48\x1c\xc7\x51\x9b\x78\xcc\xc0\xd7\x20\x97\x70\x0e\x2c\x96\xfa\x73\x18\xfa\xc1\xa3\x53\x1e\x41\x39\xe7\xad\xf3\x5a\xf1\xde\x09\xa0\x6b\xf5\x82\xf1\x96\x5d\x74\x76\x37\x11\xbc\x4b\x21\x62\x24\x3e\x65\xd8\x83\x87\xa6\xaa\x5a\x3f\xed\x94\x3d\xc8\xd4\x0d\x10\x52\x02\xef\xd1\x69\xc6\x5b\xe4\x5d\x40\xeb\xb7\x9e\x11\x58\x11\x1e\xa1\xdc\xb5\xfe\x39\x11\xe2\x14\x70\x37\xc0\x5b\xb0\x95\x55\x05\x48\x0d\xc9\x36\x53\xb6\x99\x62\xa9\x83\x22\xd3\xc6\x74\x8a\xc2\x46\x73\x09\x2a\xcf\x91\x08\xd8\xb6\x83\x95\x96\x78\x0f\x44\xe1\x87\x5b\x87\x78\xac\x70\xad\x0c\x1f\x1b\x13\xa4\xe8\x01\x97\x9a\x40\x13\x18\x0c\x28\xca\xff\x82\x05\xe6\xaa\x21\x84\x0d\xc2\x26\x54\x74\xcf\x2f\xf4\x58\x20\xa8\x45\x85\x40\xac\x3c\x8b\x5e\x0b\x4e\x6c\x5d\xc7\x8a\x20\x64\xee\xa8\xc4\x30\xe2\x4b\x02\x55\x91\x6d\x33\xbc\x5d\xa3\x27\xad\xaa\xf7\xa2\x07\x25\xb3\xa3\x41\x92\x6c\x36\x9b\xb8\x5a\x97\xb1\xb6\x89\xb3\xc4\x94\x14\xd6\xb0\xc4\x9f\xce\x12\x4a\x2e\x51\x6e\xe7\x91\xdb\x79\xa4\xb1\x2c\x71\x8d\x46\xb2\x95\x4a\x76\xfe\x2a\xb9\xae\x44\xef\xa8\xa1\xc7\xdc\xd6\x35\x9a\x02\x8b\xe3\x76\x3f\x1c\xb2\x7a\x7d\xb5\xf1\x8b\xe6\xb2\x59\x84\xb6\x1f\xae\xae\xff\x48\xae\xfe\x4c\xae\x3e\x26\x85\x6d\x1b\x34\x74\x68\xab\xcd\xfe\xdf\xd2\x7a\x99\xeb\x44\xf4\x60\x48\xa0\xc0\x23\x35\x15\xbf\xdf\x6a\xd8\xdd\x4a\xa9\x08\xbc\xb5\xbc\xbf\x99\x9d\x1c\x1e\x6b\xcb\x08\x6b\x47\xb1\x38\x79\x02\x8d\x01\x59\x80\x94\xbe\x86\xff\x5a\x33\x48\xd7\x59\x3a\x2c\x97\x68\x10\xf5\x4f\xd7\x4d\xb4\xcf\x5c\x43\xb2\x56\x3e\xf1\x8d\x49\xb6\x70\x71\x10\x69\xf0\x56\xb0\x2b\x89\xda\xf5\x12\x0d\x12\xe5\x5c\xd2\x1a\x66\x77\x84\x10\x0e\xd2\xdd\x79\x17\x9d\xcd\x6e\xe7\xdf\xc6\x93\x7f\xc6\xf3\xb0\x4f\x67\xe9\xe5\xa1\x32\x89\x89\xca\x64\x65\xec\xc6\xcc\xc3\x37\x5d\xee\xab\x64\x58\x26\xdd\x1c\xed\x36\xd9\x9d\x45\xdb\x37\x13\xb5\x44\xba\xfd\x1c\x89\xdf\x01\x00\x00\xff\xff\x4a\x93\x14\x8d\x09\x06\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: 1545, mode: os.FileMode(493), modTime: time.Unix(1521682890, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1697, mode: os.FileMode(493), modTime: time.Unix(1521685343, 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\x5f\x4f\xdc\x3e\x10\x7c\xf7\xa7\x18\xb8\x13\x7f\x24\x92\x00\xfa\xe9\xf7\x50\x44\x25\x7a\x9c\xaa\xaa\x48\x48\x1c\x3c\x57\x26\xd9\x5c\x2c\x12\x3b\x78\x37\xd0\xb4\xea\x77\xaf\xe2\x8b\x53\xae\xa5\x2a\x79\x72\xbc\xb3\xeb\x99\xd9\x99\xed\x64\xf7\xc6\x66\x5c\x29\x35\xc3\x07\xe7\x84\xc5\xeb\x96\xa1\xd1\xe8\xbc\x32\x96\x50\x3a\x8f\xc2\xe5\x0f\xe4\xa1\x6d\x31\x1e\x93\xdc\x35\xad\x63\x4a\xd5\x0c\xb7\x95\x61\x18\x46\xeb\x49\xa4\x87\xae\xdb\x4a\xa7\xf8\x64\x59\x74\x5d\x33\xf2\xce\xd7\x70\xb6\xee\x61\x4a\x18\x41\xe1\x88\xed\xbe\x80\xbe\x1a\x96\xd0\x4f\x2c\x54\xc0\x59\xdc\xdd\x77\x56\x3a\x9c\xfc\x9f\x1e\xff\x77\x04\x4f\x8f\x9d\xf1\xc4\xe0\xae\x70\x81\x86\x46\x49\xcf\x60\xa1\x96\x53\xa5\x98\x04\x09\x29\x75\x79\xbd\xf8\xbc\xbc\xf9\xb2\xba\xbe\xbb\x59\x2c\xcf\xd7\x24\xe9\x86\x63\x9a\xbb\x26\x16\x2f\x97\xab\xdb\xf3\xfd\x4c\x9a\x36\x5b\x93\x24\x23\x80\xab\xfd\x41\xf6\xa2\xa2\xfc\x61\x60\x17\x65\x7a\xd2\x45\x0f\xb3\x51\x40\x45\xaa\x4c\x89\x4a\x73\x15\x01\xa7\xef\xb3\x82\x9e\x32\xdb\xd5\xf5\x19\xa4\x22\xab\x00\x0c\x82\x04\xc7\xaa\x34\x67\x4a\x95\x24\x79\x55\x9a\x9a\x0e\x0e\xf1\x3d\x54\x67\xb8\xf0\x6b\x7e\x37\x9e\x81\xf9\x09\xd8\x75\x3e\x27\xdc\xdd\x5c\xfd\xba\x3d\x45\x41\x2c\xc6\x6a\x31\xce\x62\x98\x90\x86\x62\x64\x10\xdc\x7c\xfd\xfd\xe1\x0b\x56\x05\x4c\x52\xf2\xea\x6a\x78\x25\x71\xd8\x9d\x9f\xee\x6e\x28\xd6\x71\xce\xf3\x9a\xe4\x5f\x73\x02\x26\xb9\x0e\xed\x98\x9f\x8c\x13\x98\x26\x94\x27\xe9\xbc\xc5\xa6\x32\xe8\xfe\x31\xd8\xf9\x91\x24\x1a\xf5\xea\xc6\x4d\x89\x9d\x83\xbf\xd8\x79\xf8\x82\xc7\x0c\x17\x8d\xfe\xe6\x2c\x96\x8b\xd5\x66\x19\x36\x27\x8e\xb1\x40\xde\xb1\xb8\x26\x6e\x29\x9a\xb4\xf6\xd4\x22\x79\x8c\xad\x19\x49\x9e\x71\xcf\x42\x4d\xe2\xa9\x26\xcd\xf4\x9a\xd2\xbe\x9b\x06\x21\xe9\x47\x5e\x7f\xea\x9d\xe1\xd6\xf7\x10\x87\xc2\x3d\xdb\xda\xe9\x02\x1d\x1b\xbb\x1e\x23\xee\x83\x61\x47\x2f\xd0\xf7\x54\x3a\x4f\xf0\xc4\xce\xcb\x00\x14\x17\x9f\x89\x6d\xe9\x04\x37\x25\xa6\xd4\x60\xbe\x15\xea\xe9\x77\x88\xf1\x6f\xfc\x83\x86\x6a\x0b\x31\xd5\xb6\xc8\x0f\x9f\x6e\x25\x19\x96\xda\xb5\x85\x16\xc2\xde\xde\x74\x93\x4c\x79\x0f\xb4\xb6\xba\xde\x44\xeb\x4d\x84\x4a\x33\x46\x45\x95\x46\xa9\x60\x3d\x93\x7f\x32\x39\xc5\x2c\xb0\x68\x2f\xea\x67\x00\x00\x00\xff\xff\x99\xac\x13\xfb\x96\x04\x00\x00") +var _clientBootstrapDockerSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x52\x4d\x6f\xdb\x30\x0c\xbd\xeb\x57\xb0\x4d\xd0\x0f\x60\xb2\xd7\x1c\x57\x74\x40\x97\x04\x3b\xac\x40\x80\xa4\x3d\x0f\xaa\x4c\xd9\x42\x6d\xc9\x15\xe9\x76\xd9\xb0\xff\x3e\xc8\xb6\xbc\x66\x5b\xb1\xea\x24\x89\x8f\xe4\xe3\xe3\x9b\x1d\xe5\xf7\xd6\xe5\x54\x09\x31\x83\x4f\xde\x33\x71\x50\x2d\x81\x82\x46\xe9\xca\x3a\x04\xe3\x03\x14\x5e\x3f\x60\x00\xe5\x8a\xf1\x2a\xb5\x6f\x5a\x4f\x98\x09\x41\xc8\x20\x51\x88\xd5\x66\xf9\x65\xbd\xfd\xba\xdb\xdc\x6d\x97\xeb\xab\x12\x39\x1b\xa0\x99\xf6\x4d\x0a\xae\xd6\xbb\xdb\xab\xd3\x9c\x9b\x36\x2f\x91\xe5\x08\xa0\xea\x34\x76\xdf\x3d\xd8\x16\xac\x23\x56\x75\xad\xd8\x7a\x07\xd6\xc0\x6a\xe8\x6c\x09\x54\x1d\x50\x15\xfb\x84\xc0\x22\x13\xd6\x40\xa5\xa8\x4a\xf4\x16\x1f\xf3\x02\x9f\x72\xd7\xd5\xf5\x25\x70\x85\x4e\x00\x00\xe0\x37\xcb\xf0\x5e\x18\x7b\x29\x84\x41\xd6\x95\xb1\x35\x9e\x9d\xc3\x8f\x3e\x3a\x83\xeb\x50\xd2\x87\xf1\x0e\x30\xbf\x00\xf2\x5d\xd0\x08\x77\xdb\x9b\xdf\xbf\x0b\x28\x90\xd8\xba\x81\x57\xac\x90\xf5\xc1\xc4\x40\x77\xa1\x7e\xa5\x7f\x3c\xd4\x15\x7e\xc0\x48\x43\xbb\x9b\xd8\x45\x7a\x38\x9e\x2f\x8e\x07\x8a\x75\xaa\xf3\x5c\x22\xff\xaf\x4e\x8f\x91\x9b\x3e\x1d\xe6\x17\x63\x05\xc2\x09\x15\x90\xbb\xe0\x60\x88\xc4\xb9\x7f\x46\x79\x3f\x23\x27\xa1\xac\x01\x1b\x1f\x48\xee\x94\xa3\x40\xc4\xbd\x98\x47\x67\xaf\xc8\x79\xfe\x82\xc7\x0c\xae\x1b\xf5\xdd\x3b\x58\x2f\x77\xc3\x32\x9c\x46\x82\x80\x8f\x9d\x0d\x08\xba\x23\xf6\x4d\xda\x52\x12\xa9\x0c\xd8\x82\x7c\x4c\xa9\x39\xb2\xce\x69\x4f\x8c\x8d\x0c\x58\xa3\x22\xfc\xd7\xa4\xfb\x6e\x2a\x04\x72\x3f\xf2\xfa\x7b\xde\x19\xdc\x86\x3d\xb0\x87\xc2\x3f\xbb\xda\xab\x02\x3a\xb2\xae\x1c\x04\xf7\xa1\x17\xec\xdd\x0b\xf4\x3d\x1a\x1f\x10\x02\x92\x0f\x1c\x81\xec\x53\x9b\x94\x96\x4d\x70\x6b\x60\x72\x0d\xcc\x0f\x4c\x3e\x3d\xa3\xad\xff\xe0\xdf\xcf\x50\x1d\x20\xa6\xd8\x01\xf9\x78\x54\xcb\x32\x2e\xb5\x6b\x0b\xc5\x08\x27\x27\xd3\x8f\x9c\xfc\xde\xd3\x3a\xc8\x7a\x13\xad\x37\x11\x32\x76\xb4\x8a\x30\x56\x88\x5e\x7a\xc2\xf0\x64\x35\x26\x2f\x10\xab\xc0\xe2\x57\x00\x00\x00\xff\xff\x7c\x0e\x86\xaa\x2d\x04\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: 1174, mode: os.FileMode(493), modTime: time.Unix(1521099304, 0)} + info := bindataFileInfo{name: "client/bootstrap/docker.sh", size: 1069, mode: os.FileMode(493), modTime: time.Unix(1521684579, 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(1521411375, 0)} + info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 291, mode: os.FileMode(493), modTime: time.Unix(1521684609, 0)} a := &asset{bytes: bytes, info: info} return a, nil } 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 079b7b48..5b9f5e5a 100755 --- a/client/bootstrap/daemon-up.sh +++ b/client/bootstrap/daemon-up.sh @@ -1,16 +1,24 @@ -# 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 @@ -18,27 +26,26 @@ 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 "Launching existing Inertia daemon image..." - sudo docker load -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 \ @@ -46,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 b50e9503..f1299481 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/remote.go b/client/remote.go index b74d598b..e3ea9083 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,27 +58,27 @@ func (remote *RemoteVPS) Bootstrap(runner SSHSession, name string, config *Confi return err } - println("\n>> Step 3/4: Starting daemon...") + println("\n>> Step 3/4: Fetching daemon API token...") + token, err := remote.getDaemonAPIToken(runner, config.Version) if err != nil { return err } - err = remote.DaemonUp(runner, config.Version, remote.IP, remote.Daemon.Port) + remote.Daemon.Token = token + err = config.Write() if err != nil { return err } - println("\n>> Step 4/4: Fetching daemon API token...") - token, err := remote.getDaemonAPIToken(runner, config.Version) + println("\n>> Step 4/4: Starting daemon...") if err != nil { return err } - remote.Daemon.Token = token - err = config.Write() + err = remote.DaemonUp(runner, config.Version, remote.IP, remote.Daemon.Port) if err != nil { return err } - println("Inertia has been set up and daemon is running on remote!\n") + println("\nInertia is now set up and the daemon is running on your remote!\n") println("=============================\n") @@ -87,13 +86,13 @@ func (remote *RemoteVPS) Bootstrap(runner SSHSession, name string, config *Confi println("GitHub Deploy Key (add to https://www.github.com//settings/keys/new): ") println(pub.String()) - // Output Webhook url to user. + // Output webhook url to user. println("GitHub WebHook URL (add to https://www.github.com//settings/hooks/new): ") println("http://" + remote.IP + ":" + remote.Daemon.Port) println("Github WebHook Secret: " + common.DefaultSecret + "\n") println("Inertia daemon successfully deployed! Add your webhook url and deploy\nkey to enable continuous deployment.") - fmt.Printf("Then run 'inertia %s up' to deploy your application.\n", name) + fmt.Printf("Then run 'inertia %s up' to deploy your application!\n", name) return nil } diff --git a/client/remote_test.go b/client/remote_test.go index ea6656d1..09907969 100644 --- a/client/remote_test.go +++ b/client/remote_test.go @@ -106,8 +106,8 @@ func TestBootstrap(t *testing.T) { // Make sure all commands are formatted correctly assert.Equal(t, string(dockerScript), session.Calls[0]) assert.Equal(t, string(keyScript), session.Calls[1]) - assert.Equal(t, daemonScript, session.Calls[2]) - assert.Equal(t, tokenScript, session.Calls[3]) + assert.Equal(t, tokenScript, session.Calls[2]) + assert.Equal(t, daemonScript, session.Calls[3]) } func TestInstrumentedBootstrap(t *testing.T) { diff --git a/common/request.go b/common/request.go index 03667c3d..caf831ed 100644 --- a/common/request.go +++ b/common/request.go @@ -6,9 +6,6 @@ const ( // DaemonOkResp is the OK response upon successfully reaching daemon DaemonOkResp = "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. diff --git a/daemon/inertia/main.go b/daemon/inertia/main.go index 060b7f13..65b14e47 100644 --- a/daemon/inertia/main.go +++ b/daemon/inertia/main.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,11 +13,11 @@ 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. + Long: `Run the daemon on a port, default 8081. Example: inertia daemon run -p 8081`, @@ -32,7 +31,7 @@ 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", @@ -69,7 +68,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/remote.go b/remote.go index b05c57e5..c6ab5e9d 100644 --- a/remote.go +++ b/remote.go @@ -277,6 +277,6 @@ func init() { // 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") } From 687e9f3c197ba4ed39d81697a0c02985615a16a2 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 20:35:32 -0700 Subject: [PATCH 06/73] Add ability to list makefile targets, improve make web-* commands * make commands to list all Makefile commands * Rename test-verbose to testv * Rename web-dev to web-run * Add web-deps to install Inertia Web dependencies --- Makefile | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c99e9a91..6f6e47d7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: inertia test test-verbose testenv clean daemon testdaemon bootstrap +.PHONY: commands inertia inertia-tagged clean test testv testenv testdaemon daemon bootstrap web-deps web-run web-build TAG = `git describe --tags` PACKAGES = `go list ./... | grep -v vendor/` @@ -9,6 +9,9 @@ RELEASE = canary all: inertia +commands: + @$(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 + # Install Inertia with release version inertia: go install -ldflags "-X main.Version=$(RELEASE)" @@ -29,7 +32,7 @@ test: go test $(PACKAGES) -ldflags "-X main.Version=test" --cover # Run test suite - creates test VPS and test daemon beforehand -test-verbose: +testv: make testenv VPS_OS=$(VPS_OS) VPS_VERSION=$(VPS_VERSION) make testdaemon go test $(PACKAGES) -ldflags "-X main.Version=test" -v --cover @@ -74,10 +77,14 @@ daemon: bootstrap: go-bindata -o client/bootstrap.go -pkg client client/bootstrap/... -# Run local development instance of Inertia web. -web-dev: - (cd ./daemon/web; npm install; npm start) +# Install Inertia Web dependencies. +web-deps: + (cd ./daemon/web; npm install) + +# Run local development instance of Inertia Web. +web-run: + (cd ./daemon/web; npm start) -# Build and minify Inertia web. +# Build and minify Inertia Web. web-build: (cd ./daemon/web; npm install --production; npm run build) From 2ef31eb2cd85ce2c51739e5d543378820ac65881 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 21:08:46 -0700 Subject: [PATCH 07/73] Update README * Updated development instructions * Updated usage section * Updated wording in various places --- README.md | 93 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 88987b60..dd1be55d 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,8 @@ ---------------- -Inertia is a cross-platform command line tool that aims to simplify setup and management of automated deployment of docker-compose projects on any virtual private server. It aims to provide the ease and flexibility of services like Heroku without the complexity of Kubernetes while still giving users full control over their projects. +Inertia is a cross-platform command line tool that simplifies setup and management of automated project deployment on any virtual private server. It aims to provide the ease and flexibility of services like Heroku without the complexity of Kubernetes while still giving users full control over their projects. -- [Installation](#package-installation) - [Usage](#rocket-usage) - [Setup](#setup) - [Continuous Deployment](#continuous-deployment) @@ -34,9 +33,11 @@ Inertia is a cross-platform command line tool that aims to simplify setup and ma - [Motivation and Design](#bulb-motivation-and-design) - [Development](#construction-development) -## :package: Installation +# :rocket: Usage -To get started, just download an Inertia CLI binary for your platform from the [Releases](https://github.com/ubclaunchpad/inertia/releases) page. You can add this binary to your PATH or execute it directly to use the CLI: +All you need to get started is a docker-compose project, an Inertia CLI binary, and access to a virtual private server. + +Inertia CLI binaries can be downloaded for various platforms in the [Releases](https://github.com/ubclaunchpad/inertia/releases) page. You can add this binary to your PATH or execute it directly to use the Inertia CLI: ```bash $> mv $INERTIA_IMAGE ./inertia @@ -45,9 +46,7 @@ $> ./inertia You can also [install Inertia from source](#installing-from-source). -## :rocket: Usage - -### Setup +## Setup Initializing a project for use with Inertia only takes a few simple steps: @@ -68,7 +67,7 @@ An Inertia daemon is now running on your remote instance. This daemon will be us See our [wiki](https://github.com/ubclaunchpad/inertia/wiki/VPS-Compatibility) for more details on platform compatibility. -### Continuous Deployment +## Continuous Deployment You can now set up continuous deployment using the output of `inertia $VPS_NAME init`: @@ -87,7 +86,7 @@ Github WebHook Secret: inertia The daemon will accept POST requests from GitHub at the URL provided. Add this webhook URL in your GitHub settings area (at the URL provided) so that the daemon will receive updates from GitHub when your repository is updated. -### Deployment Management +## Deployment Management To manually deploy your project: @@ -101,7 +100,7 @@ There are a variety of other commands available for managing your project deploy $> inertia $VPS_NAME --help ``` -### Release Streams +## Release Streams The version of Inertia you are using can be seen in Inertia's `.inertia.toml` configuration file, or by running `inertia --version`. @@ -113,7 +112,7 @@ You can manually change the daemon version pulled by editing the Inertia configu The daemon component of an Inertia release can be patched separately from the CLI component - see our [wiki](https://github.com/ubclaunchpad/inertia/wiki/Daemon-Releases) for more details. -### Swag +## Swag [![Deployed with Inertia](https://img.shields.io/badge/Deploying%20with-Inertia-blue.svg)](https://github.com/ubclaunchpad/inertia) @@ -122,7 +121,7 @@ The daemon component of an Inertia release can be patched separately from the CL [![Deployed with Inertia](https://img.shields.io/badge/Deploying%20with-Inertia-blue.svg)](https://github.com/ubclaunchpad/inertia) ``` -## :bulb: Motivation and Design +# :bulb: Motivation and Design At [UBC Launch Pad](http://www.ubclaunchpad.com), we are frequently changing hosting providers based on available funding and sponsorship. Inertia is a project to develop an in-house continuous deployment system to make deploying applications simple and painless, regardless of the hosting provider. @@ -132,7 +131,7 @@ The primary design goals of Inertia are to: * maximimise compatibility across different client and VPS platforms * offer a convenient interface for managing the deployed application -### How It Works +## How It Works Inertia consists of two major components: a deployment daemon and a command line interface. @@ -144,71 +143,85 @@ The deployment daemon runs persistently in the background on the server, receivi Inertia is set up serverside by executing a script over SSH that installs Docker and starts an Inertia daemon image with [access to the host Docker socket](https://bobheadxi.github.io/dockerception/#docker-in-docker). This Docker-in-Docker configuration gives the daemon the ability to start up other containers *alongside* it, rather than *within* it, as required. Once the daemon is set up, we avoid using further SSH commands and execute Docker commands through Docker's Golang API. Instead of installing the docker-compose toolset, we [use a docker-compose image](https://bobheadxi.github.io/dockerception/#docker-compose-in-docker) to build and deploy user projects. -## :construction: Development +# :construction: Development + +This section outlines the various tools available to help you get started developing Inertia. Run `make commands` to list all the Makefile shortcuts available. + +If you would like to contribute, feel free to comment on an issue or make one and open up a pull request! + +## Installing from Source -### Installing from Source +First, [install Go](https://golang.org/doc/install#install) and grab Inertia's source code: ```bash $> go get -u github.com/ubclaunchpad/inertia ``` -It is highly recommended that you use a [tagged build](https://github.com/ubclaunchpad/inertia/releases) to ensure compatibility between the CLI and your Inertia daemon. +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 -$> git checkout v0.1.0 -$> make inertia-tagged -$> inertia --version +$> dep ensure # Golang dependencies +$> make web-deps # Web app dependencies ``` -Alternatively, you can manually edit `.inertia.toml` to use your desired daemon version - see the [Release Streams](#release-streams) documentation for more details. +For usage, it is highly recommended that you use a [tagged build](https://github.com/ubclaunchpad/inertia/releases) to ensure compatibility between the CLI and your Inertia daemon. -### Dependencies +```bash +$> git checkout $VERSION +$> make inertia-tagged # installs a tagged version of Inertia +$> inertia --version # check what version you have installed +``` + +Alternatively, you can manually edit `.inertia.toml` to use your desired daemon version - see the [Release Streams](#release-streams) documentation for more details. -We use [dep](https://github.com/golang/dep) for managing dependencies. +For development, it is recommended that you make install a build tagged as `test` so that you can make use `make testdaemon` for local development. See the next section for more details. ```bash -$> go get -u github.com/golang/dep/cmd/dep -$> dep ensure +$> make RELEASE=test ``` -### Testing +## Testing -To run the Inertia test suite: +You will need Docker installed and running to run the Inertia test suite, which includes a number of integration tests. ```bash $> make test # test against ubuntu:latest $> make test VPS_OS=ubuntu VERSION=14.04 # test against ubuntu:14.04 ``` -You can also start a container that sets up a mock VPS for testing. +You can also manually start a container that sets up a mock VPS for testing: ```bash -$> make +$> make RELEASE=test # installs current Inertia build and mark as "test" $> make testenv VPS_OS=ubuntu VERSION=16.04 # defaults to ubuntu:lastest without args # note the location of the key that is printed ``` -You can [SSH into this container](https://bobheadxi.github.io/dockerception/#ssh-services-in-docker) and treat it just as you would treat a real VPS: +You can [SSH into this testvps container](https://bobheadxi.github.io/dockerception/#ssh-services-in-docker) and otherwise treat it just as you would treat a real VPS: ```bash $> cd /path/to/my/dockercompose/project $> inertia init $> inertia remote add local -# PEM file: /test_env/test_key, User: 'root', Address: 0.0.0.0 +# PEM file: inertia/test_env/test_key, User: 'root', Address: 0.0.0.0 $> inertia local init -$> inertia remote status local -Remote instance 'local' accepting requests at http://0.0.0.0:8081 +$> inertia local status ``` -The above steps will pull a daemon image from Docker Hub based on the version in your `.inertia.toml`. To use a daemon compiled from source, set your version to `test` and run: +The above steps will pull a daemon image from Docker Hub based on the version in your `.inertia.toml`. + +### Inertia Daemon + +To use a daemon compiled from source, set your Inertia version in `.inertia.toml` to `test` and run: ```bash $> make testdaemon +$> inertia local init ``` -Setting up a `testvps` using `inertia local init` will now use the custom daemon. +This will build a daemon image and `scp` it over to the test VPS. Setting up a `testvps` using `inertia local init` will now use this custom daemon. If you run into this error when deploying onto the `testvps`: @@ -227,7 +240,17 @@ You probably need to go into your Docker settings and add this line to the Docke This sneaky configuration file can be found under `Docker -> Preferences -> Daemon -> Advanced -> Edit File`. -### Compiling Bash Scripts +### Inertia Web + +To run a local instance of Inertia Web: + +```bash +$> make web-run +``` + +Make sure you have a local daemon set up for this web app to work - see the previous section for more details. + +## Compiling Bash Scripts To bootstrap servers, some bash scripting is often involved, but we'd like to avoid shipping bash scripts with our go binary. So we use [go-bindata](https://github.com/jteeuwen/go-bindata) to compile shell scripts into our go executables. From 8a9d80a7a228c89690b4d57c8f24d8532c8f9870 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 21:20:25 -0700 Subject: [PATCH 08/73] Scaffold clientside user management --- client/deployment.go | 33 +++++--- client/deployment_test.go | 4 +- deployment.go | 164 ++++++++++++++++++++------------------ deployment_users.go | 110 +++++++++++++++++++++++++ 4 files changed, 223 insertions(+), 88 deletions(-) create mode 100644 deployment_users.go diff --git a/client/deployment.go b/client/deployment.go index 9671d051..71bad084 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -59,7 +59,6 @@ func GetDeployment(name string) (*Deployment, error) { // Up brings the project up on the remote VPS instance specified // in the deployment object. func (d *Deployment) Up(stream bool) (*http.Response, error) { - // TODO: Support other Git remotes. origin, err := d.Repository.Remote("origin") if err != nil { return nil, err @@ -72,24 +71,24 @@ func (d *Deployment) Up(stream bool) (*http.Response, error) { Branch: d.Branch, }, } - return d.post("/up", reqContent) + return d.request("/up", "POST", 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("/down", "POST", 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("/status", "GET", 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("/reset", "POST", nil) } // Logs get logs of given container @@ -98,10 +97,26 @@ func (d *Deployment) Logs(stream bool, container string) (*http.Response, error) Stream: stream, Container: container, } - return d.post("/logs", reqContent) + return d.request("/logs", "GET", 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("/web/adduser", "POST", 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("/web/removeuser", "POST", reqContent) +} + +func (d *Deployment) request(endpoint, method string, requestBody interface{}) (*http.Response, error) { // Assemble URL url, err := url.Parse("https://" + d.RemoteVPS.GetIPAndPort()) if err != nil { @@ -113,7 +128,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 } @@ -121,7 +136,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 5eea36c7..aa676057 100644 --- a/client/deployment_test.go +++ b/client/deployment_test.go @@ -118,7 +118,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 @@ -172,7 +172,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/deployment.go b/deployment.go index c18ee994..5326c8c9 100644 --- a/deployment.go +++ b/deployment.go @@ -21,12 +21,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) } @@ -72,8 +73,8 @@ 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) } @@ -109,8 +110,8 @@ 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) } @@ -141,43 +142,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", @@ -186,8 +150,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) } @@ -236,31 +200,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", @@ -271,13 +228,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) @@ -291,12 +248,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]", @@ -315,35 +310,50 @@ 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) 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) + user.AddCommand(adduser) + user.AddCommand(removeuser) + 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/deployment_users.go b/deployment_users.go new file mode 100644 index 00000000..84751b3e --- /dev/null +++ b/deployment_users.go @@ -0,0 +1,110 @@ +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") + + 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.WithError(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) + case http.StatusPreconditionFailed: + fmt.Printf("(Status code %d) Problem with deployment setup:\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) + case http.StatusPreconditionFailed: + fmt.Printf("(Status code %d) Problem with deployment setup:\n%s\n", resp.StatusCode, body) + default: + fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", + resp.StatusCode, body) + } + }, +} From b694eacd2b0aa5ba91bff4866ec2dbda29b6678d Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 21:20:44 -0700 Subject: [PATCH 09/73] Improve Inertia Web build stage --- .dockerignore | 3 --- Dockerfile | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.dockerignore b/.dockerignore index 60f7a0a4..ab4a71b4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -20,6 +20,3 @@ Dockerfile # Non-daemon source code client - -# Node depedencies -node_modules 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 From 0ce7f6327d589957404ce8949fd25f86f59e8327 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 21:21:21 -0700 Subject: [PATCH 10/73] Standardize remote documentation No docs is the new standard (command tooltip itself is already documentation) --- remote.go | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/remote.go b/remote.go index c6ab5e9d..0d6935fd 100644 --- a/remote.go +++ b/remote.go @@ -20,7 +20,6 @@ var ( errInvalidAddress = errors.New("invalid IP address") ) -// remoteCmd represents the remote command var remoteCmd = &cobra.Command{ Use: "remote", Short: "Configure the local settings for a remote VPS instance", @@ -37,7 +36,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", @@ -81,7 +79,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") @@ -135,7 +134,6 @@ func addRemoteWalkthrough(in io.Reader, name, port, sshPort, currBranch string, return config.Write() } -// statusCmd represents the remote status command var statusCmd = &cobra.Command{ Use: "status [REMOTE]", Short: "Query the status of a remote instance", @@ -182,7 +180,6 @@ behaviour, and other information.`, }, } -// listCmd represents the inertia list command var listCmd = &cobra.Command{ Use: "ls", Short: "List currently configured remotes", @@ -204,7 +201,6 @@ var listCmd = &cobra.Command{ }, } -// removeCmd represents the inertia list command var removeCmd = &cobra.Command{ Use: "rm [REMOTE]", Short: "Remove a remote.", @@ -268,14 +264,6 @@ 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", "8081", "Daemon port") addCmd.Flags().StringP("sshPort", "s", "22", "SSH port") From e3a50f1f10360dca457e34cae67ad37d3a2160ad Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 21 Mar 2018 21:26:56 -0700 Subject: [PATCH 11/73] log.Fatal instead of log.WithError This should prevent those pesky nil-pointers --- deployment.go | 12 ++++++------ deployment_users.go | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/deployment.go b/deployment.go index 5326c8c9..9e6d263f 100644 --- a/deployment.go +++ b/deployment.go @@ -40,7 +40,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: @@ -80,13 +80,13 @@ var deploymentDownCmd = &cobra.Command{ } 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 { @@ -117,13 +117,13 @@ var deploymentStatusCmd = &cobra.Command{ } 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 { @@ -174,7 +174,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: diff --git a/deployment_users.go b/deployment_users.go index 84751b3e..d6ad0367 100644 --- a/deployment_users.go +++ b/deployment_users.go @@ -52,7 +52,7 @@ Use the --admin flag to create an admin user.`, defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - log.WithError(err) + log.Fatal(err) } switch resp.StatusCode { From bd7bda1d0e21d3a327bba208a83a12d634c10a8f Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 22 Mar 2018 01:16:40 -0700 Subject: [PATCH 12/73] WIP custom authentication module * Remove dependency on third-party authentication middleware --- Gopkg.lock | 28 +-- Gopkg.toml | 4 +- daemon/inertia/auth/auth_test.go | 13 +- .../inertia/auth/{handler.go => decorator.go} | 8 - daemon/inertia/auth/password.go | 59 ++++++ daemon/inertia/auth/password_test.go | 44 +++++ daemon/inertia/auth/permissions.go | 170 +++++++++--------- daemon/inertia/auth/permissions_test.go | 2 +- daemon/inertia/auth/users.go | 139 ++++++++++++++ daemon/inertia/auth/users_test.go | 29 +++ daemon/inertia/daemon.go | 13 +- 11 files changed, 373 insertions(+), 136 deletions(-) rename daemon/inertia/auth/{handler.go => decorator.go} (83%) create mode 100644 daemon/inertia/auth/password.go create mode 100644 daemon/inertia/auth/password_test.go create mode 100644 daemon/inertia/auth/users.go create mode 100644 daemon/inertia/auth/users_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 63b6bc1d..d6b104a5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -180,35 +180,9 @@ packages = ["."] revision = "ba9c9e33906f58169366275e3450db66139a31a9" -[[projects]] - name = "github.com/xyproto/cookie" - packages = ["."] - revision = "8ce3defb0907741a2a8c9b56cce0f716c933ce34" - version = "2.0" - -[[projects]] - name = "github.com/xyproto/permissionbolt" - packages = ["."] - revision = "657ad1a411098f614a30382e53d4267067b0fa43" - version = "2.3" - -[[projects]] - name = "github.com/xyproto/pinterface" - packages = ["."] - revision = "05fa0e3080664c781c213d0a890a9d22718f7afb" - version = "4.1" - -[[projects]] - name = "github.com/xyproto/simplebolt" - packages = ["."] - revision = "3ad76f169f0ede30c60f6b098efd305ad995e417" - version = "3.0" - [[projects]] name = "golang.org/x/crypto" packages = [ - "bcrypt", - "blowfish", "cast5", "curve25519", "ed25519", @@ -328,6 +302,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "468c11fee7752d824dd1afaf7eaf0cd0bba548f3d29017006099aac6e2ec5bdf" + inputs-digest = "327be67df8f02606e468ee931ddc33a045bf1422ccc9f3903acb143f3df39d39" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 4ebb1c4c..ed94db8b 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -31,5 +31,5 @@ name = "golang.org/x/crypto" [[constraint]] - name = "github.com/xyproto/permissionbolt" - version = "2.3.0" + name = "github.com/boltdb/bolt" + version = "1.3.1" diff --git a/daemon/inertia/auth/auth_test.go b/daemon/inertia/auth/auth_test.go index 83a8397d..5f141081 100644 --- a/daemon/inertia/auth/auth_test.go +++ b/daemon/inertia/auth/auth_test.go @@ -18,6 +18,11 @@ var ( testToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.AqFWnFeY9B8jj7-l3z0a9iaZdwIca7xhUF3fuaJjU90" ) +func testHealthCheckHandler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, common.DaemonOkResp) +} + func getFakeAPIKey(tok *jwt.Token) (interface{}, error) { return testPrivateKey, nil } @@ -37,7 +42,7 @@ func TestAuthorizationOK(t *testing.T) { // 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 := http.HandlerFunc(Authorized(testHealthCheckHandler, getFakeAPIKey)) handler.ServeHTTP(rr, req) assert.Equal(t, rr.Code, http.StatusOK) @@ -51,7 +56,7 @@ func TestAuthorizationMalformedBearerString(t *testing.T) { req.Header.Set("Authorization", "Beare") rr := httptest.NewRecorder() - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) + handler := http.HandlerFunc(Authorized(testHealthCheckHandler, getFakeAPIKey)) handler.ServeHTTP(rr, req) assert.Equal(t, rr.Code, http.StatusForbidden) @@ -65,7 +70,7 @@ func TestAuthorizationTooManySegments(t *testing.T) { req.Header.Set("Authorization", "Bearer a.b.c.d") rr := httptest.NewRecorder() - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) + handler := http.HandlerFunc(Authorized(testHealthCheckHandler, getFakeAPIKey)) handler.ServeHTTP(rr, req) assert.Equal(t, rr.Code, http.StatusForbidden) @@ -79,7 +84,7 @@ func TestAuthorizationSignatureInvalid(t *testing.T) { req.Header.Set("Authorization", bearerTokenString) rr := httptest.NewRecorder() - handler := http.HandlerFunc(Authorized(HealthCheckHandler, getFakeAPIKey)) + handler := http.HandlerFunc(Authorized(testHealthCheckHandler, getFakeAPIKey)) handler.ServeHTTP(rr, req) assert.Equal(t, rr.Code, http.StatusForbidden) diff --git a/daemon/inertia/auth/handler.go b/daemon/inertia/auth/decorator.go similarity index 83% rename from daemon/inertia/auth/handler.go rename to daemon/inertia/auth/decorator.go index 0215184d..dcc11497 100644 --- a/daemon/inertia/auth/handler.go +++ b/daemon/inertia/auth/decorator.go @@ -1,12 +1,10 @@ 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 @@ -42,9 +40,3 @@ func Authorized(handler http.HandlerFunc, keyLookup func(*jwt.Token) (interface{ 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.DaemonOkResp) -} diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go new file mode 100644 index 00000000..114cce56 --- /dev/null +++ b/daemon/inertia/auth/password.go @@ -0,0 +1,59 @@ +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 and underscore are allowed in usernames") + errInvalidPassword = errors.New("Only letters, numbers and underscore are allowed in passwords, and password must be at least 5 characters") +) + +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 +} + +func correctPassword(hash []byte, password string) bool { + return bcrypt.CompareHashAndPassword(hash, []byte(password)) == nil +} + +func validateCredentialValues(username, password string) error { + if username == password { + return errSameUsernamePassword + } + if len(password) < 5 { + return errInvalidPassword + } + validChars := "abcdefghijklmnopqrstuvwxyzæøåABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ_0123456789" + +NEXT_USERNAME_CHAR: + for _, char := range username { + for _, validChar := range validChars { + // if valid, skip to next character + if char == validChar { + continue NEXT_USERNAME_CHAR + } + } + return errInvalidUsername + } + +NEXT_PASSWORD_CHAR: + for _, char := range password { + for _, validChar := range validChars { + // if valid, skip to next character + if char == validChar { + continue NEXT_PASSWORD_CHAR + } + } + return errInvalidPassword + } + + return nil +} diff --git a/daemon/inertia/auth/password_test.go b/daemon/inertia/auth/password_test.go new file mode 100644 index 00000000..6380435e --- /dev/null +++ b/daemon/inertia/auth/password_test.go @@ -0,0 +1,44 @@ +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 TestCorrectPassowrd(t *testing.T) { + unhashed := "amazing" + hashed, err := hashPassword(unhashed) + assert.Nil(t, err) + assert.NotEqual(t, unhashed, hashed) + + correct := correctPassword([]byte(hashed), unhashed) + assert.True(t, correct) + + correct = correctPassword([]byte(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("wow", "oh") + assert.Equal(t, errInvalidPassword, err) + + err = validateCredentialValues("wow!!!!!!", "oasdfasdfh") + assert.Equal(t, errInvalidUsername, err) + + err = validateCredentialValues("wow", "oasdfasdfh!!!!") + assert.Equal(t, errInvalidPassword, err) +} diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 09080acd..e36346e1 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -2,12 +2,11 @@ package auth import ( "encoding/json" + "fmt" "io/ioutil" "net/http" "github.com/ubclaunchpad/inertia/common" - "github.com/xyproto/permissionbolt" - "github.com/xyproto/pinterface" ) // UserDatabasePath is the default location for storing users. @@ -16,30 +15,67 @@ 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 { - // perm is a Permissions structure that can be used to deny requests - // and acquire the UserState. By using `pinterface.IPermissions` instead - // of `*permissionbolt.Permissions`, the code is compatible with not only - // `permissionbolt`, but also other modules that uses other database - // backends, like `permissions2` which uses Redis. - perm pinterface.IPermissions - - // Mux is the HTTP multiplexer - Mux *http.ServeMux + users *userManager + mux *http.ServeMux + denyHandler http.Handler +} + +// NewPermissionsHandler returns a new handler for authenticating +// users and handling user administration +func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*PermissionsHandler, error) { + // Set up user manager + userManager, err := newUserManager(dbPath) + if err != nil { + return nil, err + } + + // Set up permissions handler + mux := http.NewServeMux() + handler := &PermissionsHandler{ + users: userManager, + mux: mux, + denyHandler: denyHandler, + } + + // The following endpoints are for user administration and must + // be used from the CLI and delivered with the daemon token. + mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) + mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) + + // The following endpoints require no prior authentication. + mux.HandleFunc("/login", handler.loginHandler) + + return handler, nil +} + +// Close releases resources held by the PermissionsHandler +func (handler *PermissionsHandler) Close() error { + return handler.users.Close() } // Implement the ServeHTTP method to make a permissionHandler a http.Handler -func (ph *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (handler *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check if the user has the right admin/user rights - if ph.perm.Rejected(w, r) { - ph.perm.DenyFunction()(w, r) - return - } + // Serve the requested page if permissions were granted - ph.Mux.ServeHTTP(w, r) + handler.mux.ServeHTTP(w, r) +} + +// AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. +func (handler *PermissionsHandler) AttachUserRestrictedHandler(path string, h http.Handler) { + // @todo + handler.mux.Handle(path, h) +} + +// AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. +func (handler *PermissionsHandler) AttachAdminRestrictedHandler(path string, h http.Handler) { + // @todo + handler.mux.Handle(path, h) } -// addUserHandler handles requests to add users -func (ph *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { +// User Administration Endpoint Handlers + +func (handler *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -55,16 +91,21 @@ func (ph *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Requ } // Add user (as admin if specified) - userstate := ph.perm.UserState() - userstate.AddUser(userReq.Username, userReq.Password, userReq.Email) - userstate.MarkConfirmed(userReq.Username) + err = handler.users.AddUser(userReq.Username, userReq.Password) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } if userReq.Admin { - userstate.SetAdminStatus(userReq.Username) + handler.users.AssignAdmin(userReq.Username) } + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusCreated) + fmt.Fprintf(w, "[SUCCESS %d] User %s added!\n", http.StatusCreated, userReq.Username) } -// removeUserHandler handles requests to add users -func (ph *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Request) { +func (handler *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -80,38 +121,18 @@ func (ph *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.R } // Remove user - userstate := ph.perm.UserState() - userstate.RemoveUser(userReq.Username) -} - -// loginHandler handles requests to add users -func (ph *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) + err = handler.users.RemoveUser(userReq.Username) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - // Log in user if password is correct - userstate := ph.perm.UserState() - correct := userstate.CorrectPassword(userReq.Username, userReq.Password) - if correct { - userstate.Login(w, userReq.Username) - } else { - http.Error(w, "Login failed", http.StatusForbidden) - } + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] User %s removed\n", http.StatusOK, userReq.Username) } -// logoutHandler handles requests to add users -func (ph *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Request) { +func (handler *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -126,45 +147,14 @@ func (ph *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Reque return } - // Log out user - userstate := ph.perm.UserState() - userstate.Logout(userReq.Username) -} - -func redirectToLogin(w http.ResponseWriter, r *http.Request) { - // @todo: direct to login page - http.Error(w, "Permission denied!", http.StatusForbidden) -} - -// NewPermissionsHandler returns a new handler for authenticating -// users and handling user administration -func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { - mux := http.NewServeMux() - perm, err := permissionbolt.NewWithConf(dbPath) + // Log in user if password is correct + correct, err := handler.users.IsCorrectCredentials(userReq.Username, userReq.Password) if err != nil { - println("Could not open Bolt database") - return nil, err + http.Error(w, err.Error(), http.StatusInternalServerError) + return } - - // Set permissions - perm.Clear() - perm.SetUserPath([]string{"/"}) - perm.SetPublicPath([]string{"/login"}) - - // Set default handler for unauthenticated users - perm.SetDenyFunction(redirectToLogin) - - // Set up webhandler - ph := &PermissionsHandler{perm: perm, Mux: mux} - - // The following endpoints are for user administration and must - // be used from the CLI and delivered with the daemon token. - mux.HandleFunc("/adduser", Authorized(ph.addUserHandler, GetAPIPrivateKey)) - mux.HandleFunc("/removeuser", Authorized(ph.removeUserHandler, GetAPIPrivateKey)) - - // The following endpoints are for the web app. - mux.HandleFunc("/login", ph.loginHandler) - mux.HandleFunc("/logout", ph.logoutHandler) - - return ph, nil + if !correct { + http.Error(w, "Login failed", http.StatusForbidden) + } + handler.users.LogIn(userReq.Username) } diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 8c38a22e..51e875c4 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -12,7 +12,7 @@ func TestPermissionsHandlerConstructor(t *testing.T) { err := os.Mkdir(dir, os.ModePerm) assert.Nil(t, err) defer os.RemoveAll(dir) - ph, err := NewPermissionsHandler("./test/users.db") + ph, err := NewPermissionsHandler("./test/users.db", nil) assert.Nil(t, err) assert.NotNil(t, ph) } diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go new file mode 100644 index 00000000..45dc5a60 --- /dev/null +++ b/daemon/inertia/auth/users.go @@ -0,0 +1,139 @@ +package auth + +import ( + "errors" + + "github.com/boltdb/bolt" +) + +// userManager administers sessions and user accounts +type userManager struct { + db *bolt.DB + userBucket []byte + adminBucket []byte + sessionBucket []byte +} + +func newUserManager(dbPath string) (*userManager, error) { + manager := &userManager{ + userBucket: []byte("users"), + adminBucket: []byte("admins"), + sessionBucket: []byte("sessions"), + } + + // Set up database + err := manager.initializeDatabase(dbPath) + if err != nil { + return nil, err + } + + return manager, nil +} + +func (m *userManager) initializeDatabase(path string) error { + db, err := bolt.Open(path, 0600, nil) + if err != nil { + return err + } + err = db.Update(func(tx *bolt.Tx) error { + _, err = tx.CreateBucketIfNotExists(m.userBucket) + if err != nil { + return err + } + + _, err = tx.CreateBucketIfNotExists(m.adminBucket) + if err != nil { + return err + } + + _, err = tx.CreateBucketIfNotExists(m.sessionBucket) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return err + } + m.db = db + return nil +} + +func (m *userManager) Close() error { + return m.db.Close() +} + +// User Administration Functions + +func (m *userManager) AddUser(username, password string) error { + err := validateCredentialValues(username, password) + if err != nil { + return err + } + hashedPassword, err := hashPassword(password) + if err != nil { + return err + } + return m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.userBucket) + return users.Put([]byte(username), []byte(hashedPassword)) + }) +} + +func (m *userManager) RemoveUser(username string) error { + return nil +} + +func (m *userManager) AssignAdmin(username string) error { + return nil +} + +// Check Functions + +func (m *userManager) HasUser(username string) (bool, error) { + found := false + err := m.db.View(func(tx *bolt.Tx) error { + users := tx.Bucket(m.userBucket) + user := users.Get([]byte(username)) + if user != nil { + found = true + } + return nil + }) + if err != nil { + return true, err + } + return found, nil +} + +func (m *userManager) IsCorrectCredentials(username, password string) (bool, error) { + correct := false + err := m.db.View(func(tx *bolt.Tx) error { + users := tx.Bucket(m.userBucket) + hashedPassword := users.Get([]byte(username)) + if hashedPassword == nil { + return errors.New("User not found") + } + correct = correctPassword(hashedPassword, password) + return nil + }) + if err != nil { + return false, err + } + return correct, nil +} + +func (m *userManager) IsAdmin(username string) (bool, error) { + return false, nil +} + +// Session Management + +func (m *userManager) LogIn(username string) { + return +} + +func (m *userManager) LogOut(username string) { + return +} diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go new file mode 100644 index 00000000..bcb6139b --- /dev/null +++ b/daemon/inertia/auth/users_test.go @@ -0,0 +1,29 @@ +package auth + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddUserAndIsCorrectCredentials(t *testing.T) { + dir := "./test" + err := os.Mkdir(dir, os.ModePerm) + assert.Nil(t, err) + defer os.RemoveAll(dir) + manager, err := newUserManager("./test/test.db") + assert.Nil(t, err) + assert.NotNil(t, manager) + + err = manager.AddUser("bobheadxi", "best_person_ever") + 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) +} diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index c6a868f1..762a518a 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -68,21 +68,21 @@ func run(host, port, version string) { // Inertia web - PermissionsHandler is used to authenticate web // app access and manage users - permHandler, err := auth.NewPermissionsHandler(auth.UserDatabasePath) + permHandler, err := auth.NewPermissionsHandler(auth.UserDatabasePath, redirectToLogin) if err != nil { println(err.Error()) return } - permHandler.Mux.Handle("/", http.FileServer(http.Dir("/app/inertia-web"))) + defer permHandler.Close() + permHandler.AttachUserRestrictedHandler("/", http.FileServer(http.Dir("/app/inertia-web"))) mux.Handle("/web/", http.StripPrefix("/web", permHandler)) - // API endpoints + // CLI API endpoints 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)) // Serve daemon on port println("Serving daemon on port " + port) @@ -93,3 +93,8 @@ func run(host, port, version string) { mux, )) } + +func redirectToLogin(w http.ResponseWriter, r *http.Request) { + // @todo: direct to login page + http.Error(w, "Permission denied!", http.StatusForbidden) +} From 6b58dfb321c06990e075f4abb02799dc1bfa1bd3 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 22 Mar 2018 19:20:19 -0700 Subject: [PATCH 13/73] Update README and Makefile docs Improved wording all around --- Makefile | 5 ++-- README.md | 72 ++++++++++++++++++++++++++----------------------------- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 6f6e47d7..263db1af 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: commands inertia inertia-tagged clean test testv testenv testdaemon daemon bootstrap web-deps web-run web-build +.PHONY: commands inertia inertia-tagged clean test test-v testenv testdaemon daemon bootstrap web-deps web-run web-build TAG = `git describe --tags` PACKAGES = `go list ./... | grep -v vendor/` @@ -9,6 +9,7 @@ RELEASE = canary all: inertia +# List all commands commands: @$(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 @@ -32,7 +33,7 @@ test: go test $(PACKAGES) -ldflags "-X main.Version=test" --cover # Run test suite - creates test VPS and test daemon beforehand -testv: +test-v: make testenv VPS_OS=$(VPS_OS) VPS_VERSION=$(VPS_VERSION) make testdaemon go test $(PACKAGES) -ldflags "-X main.Version=test" -v --cover diff --git a/README.md b/README.md index dd1be55d..72692844 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Inertia is a cross-platform command line tool that simplifies setup and management of automated project deployment on any virtual private server. It aims to provide the ease and flexibility of services like Heroku without the complexity of Kubernetes while still giving users full control over their projects. -- [Usage](#rocket-usage) +- [Usage](#package-usage) - [Setup](#setup) - [Continuous Deployment](#continuous-deployment) - [Deployment Management](#deployment-management) @@ -33,7 +33,7 @@ Inertia is a cross-platform command line tool that simplifies setup and manageme - [Motivation and Design](#bulb-motivation-and-design) - [Development](#construction-development) -# :rocket: Usage +# :package: Usage All you need to get started is a docker-compose project, an Inertia CLI binary, and access to a virtual private server. @@ -63,48 +63,44 @@ $> inertia $VPS_NAME status # Confirms that the daemon is online and accepting requests ``` -An Inertia daemon is now running on your remote instance. This daemon will be used to manage your deployment. +This daemon will be used to manage your deployment. See our [wiki](https://github.com/ubclaunchpad/inertia/wiki/VPS-Compatibility) for more details on platform compatibility. -## Continuous Deployment +## Deployment Management -You can now set up continuous deployment using the output of `inertia $VPS_NAME init`: +To manually deploy your project, you must first grant Inertia permission to clone your repository. This can be done by adding the GitHub Deploy Key that is displayed in the output of `inertia $VPS_NAME init` to your repository settings: ```bash GitHub Deploy Key (add here https://www.github.com//settings/keys/new): ssh-rsa <...> ``` -The Inertia daemon requires readonly access to your GitHub repository. Add the deploy key to your GitHub repository settings at the URL provided in the output - this will grant the daemon access to clone your repository. +Once this is done, you can use Inertia to bring your project online on your remote VPS: ```bash -GitHub WebHook URL (add here https://www.github.com//settings/hooks/new): -http://myhost.com:8081 -Github WebHook Secret: inertia -``` +$> inertia $VPS_NAME up --stream +``` -The daemon will accept POST requests from GitHub at the URL provided. Add this webhook URL in your GitHub settings area (at the URL provided) so that the daemon will receive updates from GitHub when your repository is updated. +Run `inertia $VPS_NAME --help` to see the other commands Inertia offers for managing your deployment. -## Deployment Management +## Continuous Deployment -To manually deploy your project: +To enable continuous deployment, you need the webhook URL that is printed during `inertia $VPS_NAME init`: ```bash -$> inertia $VPS_NAME up --stream -``` +GitHub WebHook URL (add here https://www.github.com//settings/hooks/new): +http://myhost.com:8081 +Github WebHook Secret: inertia +``` -There are a variety of other commands available for managing your project deployment. See the CLI documentation for more details: - -```bash -$> inertia $VPS_NAME --help -``` +The daemon will accept POST requests from GitHub at the URL provided. Add this webhook URL in your GitHub settings area (at the URL provided) so that the daemon will receive updates from GitHub when your repository is updated. Once this is done, the daemon will automatically build and deploy any changes that are made to the deployed branch. ## Release Streams -The version of Inertia you are using can be seen in Inertia's `.inertia.toml` configuration file, or by running `inertia --version`. +The version of Inertia you are using can be seen in Inertia's `.inertia.toml` configuration file, or by running `inertia --version`. The version in `.inertia.toml` is used to determine what version of the Inertia daemon to use when you run `inertia $VPS_NAME init`. -You can manually change the daemon version pulled by editing the Inertia configuration file. If you are building from source, you can also check out the desired version and run `make inertia-tagged`. +You can manually change the daemon version used by editing the Inertia configuration file. If you are building from source, you can also check out the desired version and run `make inertia-tagged` or `make RELEASE=$STREAM`. Inertia daemon releases are tagged as follows: - `v0.x.x` denotes [official, tagged releases](https://github.com/ubclaunchpad/inertia/releases) - these are recommended. - `latest` denotes the newest builds on `master`. @@ -114,13 +110,14 @@ The daemon component of an Inertia release can be patched separately from the CL ## Swag -[![Deployed with Inertia](https://img.shields.io/badge/Deploying%20with-Inertia-blue.svg)](https://github.com/ubclaunchpad/inertia) - +Add some bling to your Inertia-deployed project :sunglasses: ``` [![Deployed with Inertia](https://img.shields.io/badge/Deploying%20with-Inertia-blue.svg)](https://github.com/ubclaunchpad/inertia) ``` +[![Deployed with Inertia](https://img.shields.io/badge/Deploying%20with-Inertia-blue.svg)](https://github.com/ubclaunchpad/inertia) + # :bulb: Motivation and Design At [UBC Launch Pad](http://www.ubclaunchpad.com), we are frequently changing hosting providers based on available funding and sponsorship. Inertia is a project to develop an in-house continuous deployment system to make deploying applications simple and painless, regardless of the hosting provider. @@ -160,8 +157,8 @@ $> 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 # Golang dependencies -$> make web-deps # Web app dependencies +$> dep ensure # Inertia CLI and daemon dependencies +$> make web-deps # Inertia Web dependencies ``` For usage, it is highly recommended that you use a [tagged build](https://github.com/ubclaunchpad/inertia/releases) to ensure compatibility between the CLI and your Inertia daemon. @@ -174,13 +171,13 @@ $> inertia --version # check what version you have installed Alternatively, you can manually edit `.inertia.toml` to use your desired daemon version - see the [Release Streams](#release-streams) documentation for more details. -For development, it is recommended that you make install a build tagged as `test` so that you can make use `make testdaemon` for local development. See the next section for more details. +For development, you should install a build tagged as `test` so that you can make use `make testdaemon` for local development. See the next section for more details. ```bash -$> make RELEASE=test +$> make RELEASE=test # installs current Inertia build and mark as "test" ``` -## Testing +## Testing and Locally Deploying You will need Docker installed and running to run the Inertia test suite, which includes a number of integration tests. @@ -192,11 +189,10 @@ $> make test VPS_OS=ubuntu VERSION=14.04 # test against ubuntu:14.04 You can also manually start a container that sets up a mock VPS for testing: ```bash -$> make RELEASE=test -# installs current Inertia build and mark as "test" $> make testenv VPS_OS=ubuntu VERSION=16.04 -# defaults to ubuntu:lastest without args -# note the location of the key that is printed +# This defaults to ubuntu:lastest without args. +# Note the location of the key that is printed and use that when +# adding your local remote. ``` You can [SSH into this testvps container](https://bobheadxi.github.io/dockerception/#ssh-services-in-docker) and otherwise treat it just as you would treat a real VPS: @@ -210,9 +206,9 @@ $> inertia local init $> inertia local status ``` -The above steps will pull a daemon image from Docker Hub based on the version in your `.inertia.toml`. +The above steps will pull and use a daemon image from Docker Hub based on the version in your `.inertia.toml`. -### Inertia Daemon +### Daemon To use a daemon compiled from source, set your Inertia version in `.inertia.toml` to `test` and run: @@ -221,7 +217,7 @@ $> make testdaemon $> inertia local init ``` -This will build a daemon image and `scp` it over to the test VPS. Setting up a `testvps` using `inertia local init` will now use this custom daemon. +This will build a daemon image and `scp` it over to the test VPS, and use that image for the daemon when setting up `testvps` using `inertia local init` If you run into this error when deploying onto the `testvps`: @@ -240,9 +236,9 @@ You probably need to go into your Docker settings and add this line to the Docke This sneaky configuration file can be found under `Docker -> Preferences -> Daemon -> Advanced -> Edit File`. -### Inertia Web +### Web App -To run a local instance of Inertia Web: +Inertia Web is a React application. To run a local instance of Inertia Web: ```bash $> make web-run From 91f7f26b8061cab4864353d00a405af855efb6ac Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 22 Mar 2018 19:52:08 -0700 Subject: [PATCH 14/73] Revert boostrap order change Added comment explaining why. --- client/remote.go | 14 ++++++++------ client/remote_test.go | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/client/remote.go b/client/remote.go index e3ea9083..13b38690 100644 --- a/client/remote.go +++ b/client/remote.go @@ -58,22 +58,24 @@ func (remote *RemoteVPS) Bootstrap(runner SSHSession, name string, config *Confi return err } - println("\n>> Step 3/4: Fetching daemon API token...") - token, err := remote.getDaemonAPIToken(runner, config.Version) + // 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 } - remote.Daemon.Token = token - err = config.Write() + err = remote.DaemonUp(runner, config.Version, remote.IP, remote.Daemon.Port) if err != nil { return err } - println("\n>> Step 4/4: Starting daemon...") + println("\n>> Step 4/4: Fetching daemon API token...") + token, err := remote.getDaemonAPIToken(runner, config.Version) if err != nil { return err } - err = remote.DaemonUp(runner, config.Version, remote.IP, remote.Daemon.Port) + remote.Daemon.Token = token + err = config.Write() if err != nil { return err } diff --git a/client/remote_test.go b/client/remote_test.go index 09907969..ea6656d1 100644 --- a/client/remote_test.go +++ b/client/remote_test.go @@ -106,8 +106,8 @@ func TestBootstrap(t *testing.T) { // Make sure all commands are formatted correctly assert.Equal(t, string(dockerScript), session.Calls[0]) assert.Equal(t, string(keyScript), session.Calls[1]) - assert.Equal(t, tokenScript, session.Calls[2]) - assert.Equal(t, daemonScript, session.Calls[3]) + assert.Equal(t, daemonScript, session.Calls[2]) + assert.Equal(t, tokenScript, session.Calls[3]) } func TestInstrumentedBootstrap(t *testing.T) { From abaecb421413a2875d955577dab8480210952baa Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 22 Mar 2018 20:49:18 -0700 Subject: [PATCH 15/73] Complete user management implementations, setup for session control --- client/bootstrap.go | 10 +-- daemon/inertia/auth/password.go | 4 +- daemon/inertia/auth/password_test.go | 4 +- daemon/inertia/auth/permissions.go | 9 +-- daemon/inertia/auth/users.go | 106 +++++++++++++++++---------- daemon/inertia/auth/users_test.go | 52 ++++++++++++- daemon/inertia/auth/util.go | 15 ++++ 7 files changed, 145 insertions(+), 55 deletions(-) create mode 100644 daemon/inertia/auth/util.go diff --git a/client/bootstrap.go b/client/bootstrap.go index 00c3eef8..956816e0 100644 --- a/client/bootstrap.go +++ b/client/bootstrap.go @@ -87,7 +87,7 @@ func clientBootstrapDaemonDownSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/daemon-down.sh", size: 251, mode: os.FileMode(420), modTime: time.Unix(1521684556, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-down.sh", size: 251, mode: os.FileMode(420), modTime: time.Unix(1521773439, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -107,7 +107,7 @@ func clientBootstrapDaemonUpSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1697, mode: os.FileMode(493), modTime: time.Unix(1521685343, 0)} + info := bindataFileInfo{name: "client/bootstrap/daemon-up.sh", size: 1697, mode: os.FileMode(493), modTime: time.Unix(1521773439, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -127,7 +127,7 @@ func clientBootstrapDockerSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/docker.sh", size: 1069, mode: os.FileMode(493), modTime: time.Unix(1521684579, 0)} + info := bindataFileInfo{name: "client/bootstrap/docker.sh", size: 1069, mode: os.FileMode(493), modTime: time.Unix(1521773439, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -147,7 +147,7 @@ func clientBootstrapKeygenSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/keygen.sh", size: 589, mode: os.FileMode(493), modTime: time.Unix(1517083020, 0)} + info := bindataFileInfo{name: "client/bootstrap/keygen.sh", size: 589, mode: os.FileMode(493), modTime: time.Unix(1515346036, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -167,7 +167,7 @@ func clientBootstrapTokenSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 291, mode: os.FileMode(493), modTime: time.Unix(1521684609, 0)} + info := bindataFileInfo{name: "client/bootstrap/token.sh", size: 291, mode: os.FileMode(493), modTime: time.Unix(1521773439, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go index 114cce56..c7bc76b5 100644 --- a/daemon/inertia/auth/password.go +++ b/daemon/inertia/auth/password.go @@ -20,8 +20,8 @@ func hashPassword(password string) (string, error) { return string(hash), nil } -func correctPassword(hash []byte, password string) bool { - return bcrypt.CompareHashAndPassword(hash, []byte(password)) == nil +func correctPassword(hash string, password string) bool { + return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) == nil } func validateCredentialValues(username, password string) error { diff --git a/daemon/inertia/auth/password_test.go b/daemon/inertia/auth/password_test.go index 6380435e..c5444e3f 100644 --- a/daemon/inertia/auth/password_test.go +++ b/daemon/inertia/auth/password_test.go @@ -19,10 +19,10 @@ func TestCorrectPassowrd(t *testing.T) { assert.Nil(t, err) assert.NotEqual(t, unhashed, hashed) - correct := correctPassword([]byte(hashed), unhashed) + correct := correctPassword(hashed, unhashed) assert.True(t, correct) - correct = correctPassword([]byte(hashed), "ummmmm") + correct = correctPassword(hashed, "ummmmm") assert.False(t, correct) } diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index e36346e1..11f23088 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -24,7 +24,7 @@ type PermissionsHandler struct { // users and handling user administration func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*PermissionsHandler, error) { // Set up user manager - userManager, err := newUserManager(dbPath) + userManager, err := newUserManager(dbPath, 120) if err != nil { return nil, err } @@ -91,14 +91,11 @@ func (handler *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http } // Add user (as admin if specified) - err = handler.users.AddUser(userReq.Username, userReq.Password) + err = handler.users.AddUser(userReq.Username, userReq.Password, userReq.Admin) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - if userReq.Admin { - handler.users.AssignAdmin(userReq.Username) - } w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusCreated) @@ -156,5 +153,5 @@ func (handler *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.R if !correct { http.Error(w, "Login failed", http.StatusForbidden) } - handler.users.LogIn(userReq.Username) + handler.users.SessionBegin(userReq.Username) } diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 45dc5a60..aed562f5 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -1,24 +1,37 @@ package auth import ( + "encoding/json" "errors" "github.com/boltdb/bolt" ) +// userProps are properties associated with user, used +// for database entries +type userProps struct { + HashedPassword string `json:"hashedPassword"` + Admin bool `json:"admin"` +} + // userManager administers sessions and user accounts type userManager struct { - db *bolt.DB - userBucket []byte - adminBucket []byte - sessionBucket []byte + cookieName string + cookieTimeout int64 + + // bolt.DB is an embedded key/value database, + // where each "bucket" is a collection + db *bolt.DB + usersBucket []byte + sessionsBucket []byte } -func newUserManager(dbPath string) (*userManager, error) { +func newUserManager(dbPath string, timeout int64) (*userManager, error) { manager := &userManager{ - userBucket: []byte("users"), - adminBucket: []byte("admins"), - sessionBucket: []byte("sessions"), + cookieName: "ubclaunchpad/inertia", + cookieTimeout: timeout, + usersBucket: []byte("users"), + sessionsBucket: []byte("sessions"), } // Set up database @@ -36,17 +49,12 @@ func (m *userManager) initializeDatabase(path string) error { return err } err = db.Update(func(tx *bolt.Tx) error { - _, err = tx.CreateBucketIfNotExists(m.userBucket) + _, err = tx.CreateBucketIfNotExists(m.usersBucket) if err != nil { return err } - _, err = tx.CreateBucketIfNotExists(m.adminBucket) - if err != nil { - return err - } - - _, err = tx.CreateBucketIfNotExists(m.sessionBucket) + _, err = tx.CreateBucketIfNotExists(m.sessionsBucket) if err != nil { return err } @@ -66,7 +74,7 @@ func (m *userManager) Close() error { // User Administration Functions -func (m *userManager) AddUser(username, password string) error { +func (m *userManager) AddUser(username, password string, admin bool) error { err := validateCredentialValues(username, password) if err != nil { return err @@ -75,26 +83,30 @@ func (m *userManager) AddUser(username, password string) error { 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.userBucket) - return users.Put([]byte(username), []byte(hashedPassword)) + users := tx.Bucket(m.usersBucket) + bytes, err := json.Marshal(props) + if err != nil { + return err + } + return users.Put([]byte(username), bytes) }) } func (m *userManager) RemoveUser(username string) error { - return nil -} - -func (m *userManager) AssignAdmin(username string) error { - return nil + return m.db.Update(func(tx *bolt.Tx) error { + users := tx.Bucket(m.usersBucket) + return users.Delete([]byte(username)) + }) } -// Check Functions +// User Checks func (m *userManager) HasUser(username string) (bool, error) { found := false err := m.db.View(func(tx *bolt.Tx) error { - users := tx.Bucket(m.userBucket) + users := tx.Bucket(m.usersBucket) user := users.Get([]byte(username)) if user != nil { found = true @@ -110,30 +122,48 @@ func (m *userManager) HasUser(username string) (bool, error) { func (m *userManager) IsCorrectCredentials(username, password string) (bool, error) { correct := false err := m.db.View(func(tx *bolt.Tx) error { - users := tx.Bucket(m.userBucket) - hashedPassword := users.Get([]byte(username)) - if hashedPassword == nil { + users := tx.Bucket(m.usersBucket) + propsBytes := users.Get([]byte(username)) + if propsBytes == nil { return errors.New("User not found") } - correct = correctPassword(hashedPassword, password) + + props := &userProps{} + err := json.Unmarshal(propsBytes, props) + if err != nil { + return errors.New("Corrupt user properties: " + err.Error()) + } + correct = correctPassword(props.HashedPassword, password) return nil }) - if err != nil { - return false, err - } - return correct, nil + return correct, err } func (m *userManager) IsAdmin(username string) (bool, error) { - return false, nil + 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 } // Session Management -func (m *userManager) LogIn(username string) { - return +func (m *userManager) SessionBegin(username string) { +} + +func (m *userManager) SessionEnd(username string) { } -func (m *userManager) LogOut(username string) { - return +func (m *userManager) SessionDestroy(username string) { } diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index bcb6139b..fd8113a5 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -12,11 +12,11 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { err := os.Mkdir(dir, os.ModePerm) assert.Nil(t, err) defer os.RemoveAll(dir) - manager, err := newUserManager("./test/test.db") + manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) assert.NotNil(t, manager) - err = manager.AddUser("bobheadxi", "best_person_ever") + err = manager.AddUser("bobheadxi", "best_person_ever", true) assert.Nil(t, err) correct, err := manager.IsCorrectCredentials("bobheadxi", "not_quite_best") @@ -27,3 +27,51 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { assert.Nil(t, err) assert.True(t, correct) } + +func TestAddDeleteAndHasUser(t *testing.T) { + dir := "./test" + err := os.Mkdir(dir, os.ModePerm) + assert.Nil(t, err) + defer os.RemoveAll(dir) + manager, err := newUserManager("./test/test.db", 120) + assert.Nil(t, err) + assert.NotNil(t, manager) + + err = manager.AddUser("bobheadxi", "best_person_ever", true) + assert.Nil(t, err) + + found, err := manager.HasUser("bobheadxi") + assert.Nil(t, err) + assert.True(t, found) + + err = manager.RemoveUser("bobheadxi") + assert.Nil(t, err) + + found, err = manager.HasUser("bobheadxi") + assert.Nil(t, err) + assert.False(t, found) +} + +func TestIsAdmin(t *testing.T) { + dir := "./test" + err := os.Mkdir(dir, os.ModePerm) + assert.Nil(t, err) + defer os.RemoveAll(dir) + manager, err := newUserManager("./test/test.db", 120) + assert.Nil(t, err) + assert.NotNil(t, manager) + + 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) +} diff --git a/daemon/inertia/auth/util.go b/daemon/inertia/auth/util.go new file mode 100644 index 00000000..db35f8e2 --- /dev/null +++ b/daemon/inertia/auth/util.go @@ -0,0 +1,15 @@ +package auth + +import ( + "crypto/rand" + "encoding/base64" + "io" +) + +func generateSessionID() string { + b := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "" + } + return base64.URLEncoding.EncodeToString(b) +} From 74f72701acf4cc591f5c61d9acc1ec607320f55d Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 22 Mar 2018 20:57:50 -0700 Subject: [PATCH 16/73] Add err check --- deployment_users.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deployment_users.go b/deployment_users.go index d6ad0367..873ab3fa 100644 --- a/deployment_users.go +++ b/deployment_users.go @@ -36,6 +36,9 @@ Use the --admin flag to create an admin user.`, 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)) From df563cb721368380c4d3eaa10222120090b33c14 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 23 Mar 2018 19:01:05 -0700 Subject: [PATCH 17/73] Session management + cleaning --- daemon/inertia/auth/permissions.go | 13 ++- daemon/inertia/auth/users.go | 168 +++++++++++++++++++++++++---- daemon/inertia/auth/users_test.go | 3 + 3 files changed, 163 insertions(+), 21 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 11f23088..708c1530 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -18,6 +18,7 @@ type PermissionsHandler struct { users *userManager mux *http.ServeMux denyHandler http.Handler + publicPaths []string } // NewPermissionsHandler returns a new handler for authenticating @@ -39,6 +40,7 @@ func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*Permis // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. + handler.publicPaths = []string{"/adduser", "/removeuser"} mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) @@ -63,6 +65,7 @@ func (handler *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ // AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. func (handler *PermissionsHandler) AttachUserRestrictedHandler(path string, h http.Handler) { + handler.publicPaths = append(handler.publicPaths, path) // @todo handler.mux.Handle(path, h) } @@ -153,5 +156,13 @@ func (handler *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.R if !correct { http.Error(w, "Login failed", http.StatusForbidden) } - handler.users.SessionBegin(userReq.Username) + err = handler.users.SessionBegin(userReq.Username, w, r) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] User %s logged in\n", http.StatusOK, userReq.Username) } diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index aed562f5..40459153 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -3,10 +3,18 @@ package auth import ( "encoding/json" "errors" + "net/http" + "net/url" + "time" "github.com/boltdb/bolt" ) +var ( + errSessionNotFound = errors.New("Session not found") + errUserNotFound = errors.New("User not found") +) + // userProps are properties associated with user, used // for database entries type userProps struct { @@ -14,6 +22,13 @@ type userProps struct { Admin bool `json:"admin"` } +// sessionProps are properties associated with session, +// used for database entries +type sessionProps struct { + Username string `json:"username"` + Expires time.Time `json:"created"` +} + // userManager administers sessions and user accounts type userManager struct { cookieName string @@ -24,6 +39,8 @@ type userManager struct { db *bolt.DB usersBucket []byte sessionsBucket []byte + + endSessionCleanup chan bool } func newUserManager(dbPath string, timeout int64) (*userManager, error) { @@ -35,40 +52,33 @@ func newUserManager(dbPath string, timeout int64) (*userManager, error) { } // Set up database - err := manager.initializeDatabase(dbPath) + db, err := bolt.Open(dbPath, 0600, nil) if err != nil { return nil, err } - - return manager, nil -} - -func (m *userManager) initializeDatabase(path string) error { - db, err := bolt.Open(path, 0600, nil) - if err != nil { - return err - } err = db.Update(func(tx *bolt.Tx) error { - _, err = tx.CreateBucketIfNotExists(m.usersBucket) + _, err = tx.CreateBucketIfNotExists(manager.usersBucket) if err != nil { return err } - _, err = tx.CreateBucketIfNotExists(m.sessionsBucket) + _, err = tx.CreateBucketIfNotExists(manager.sessionsBucket) if err != nil { return err } return nil }) - if err != nil { - return err - } - m.db = db - return nil + manager.db = db + + manager.endSessionCleanup = make(chan bool) + go manager.cleanSessions() + + return manager, nil } func (m *userManager) Close() error { + m.endSessionCleanup <- true return m.db.Close() } @@ -159,11 +169,129 @@ func (m *userManager) IsAdmin(username string) (bool, error) { // Session Management -func (m *userManager) SessionBegin(username string) { +func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *http.Request) error { + cookie, err := r.Cookie(m.cookieName) + if err != nil || cookie.Value == "" { + id := generateSessionID() + expiration := time.Now().Add(time.Duration(m.cookieTimeout) * time.Minute) + err := m.addSession(id, username, expiration) + if err != nil { + return err + } + cookie := http.Cookie{ + Name: m.cookieName, + Value: url.QueryEscape(id), + Path: "/web", + Expires: expiration, + HttpOnly: true, + } + http.SetCookie(w, &cookie) + } + return nil } -func (m *userManager) SessionEnd(username string) { +func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie(m.cookieName) + if err != nil || cookie.Value == "" { + return + } + m.removeSession(cookie.Value) + expiration := time.Now() + newCookie := http.Cookie{ + Name: m.cookieName, + Path: "/web", + HttpOnly: true, + Expires: expiration, + MaxAge: -1, + } + http.SetCookie(w, &newCookie) } -func (m *userManager) SessionDestroy(username string) { +func (m *userManager) SessionCheck(w http.ResponseWriter, r *http.Request) (bool, error) { + cookie, err := r.Cookie(m.cookieName) + if err != nil || cookie.Value == "" { + return false, err + } + s, err := m.getSession(cookie.Value) + if err != nil { + return false, err + } + return m.isValidSession(s), nil +} + +// Session Helpers + +func (m *userManager) removeSession(id string) error { + return m.db.Update(func(tx *bolt.Tx) error { + sessions := tx.Bucket(m.sessionsBucket) + return sessions.Delete([]byte(id)) + }) +} + +func (m *userManager) addSession(id, username string, expires time.Time) error { + props := sessionProps{Username: username, Expires: expires} + return m.db.Update(func(tx *bolt.Tx) error { + sessions := tx.Bucket(m.sessionsBucket) + bytes, err := json.Marshal(props) + if err != nil { + return err + } + return sessions.Put([]byte(id), bytes) + }) +} + +func (m *userManager) getSession(id string) (*sessionProps, error) { + props := &sessionProps{} + err := m.db.View(func(tx *bolt.Tx) error { + users := tx.Bucket(m.sessionsBucket) + propsBytes := users.Get([]byte(id)) + if propsBytes != nil { + err := json.Unmarshal(propsBytes, props) + if err != nil { + return errors.New("Corrupt session properties: " + err.Error()) + } + } else { + return errSessionNotFound + } + return nil + }) + return props, err +} + +func (m *userManager) isValidSession(s *sessionProps) bool { + return s.Expires.Before(time.Now()) +} + +// cleanSessions is a goroutine that continously cleans sessions +func (m *userManager) cleanSessions() { + for { + select { + case <-m.endSessionCleanup: + return + default: + m.db.Update(func(tx *bolt.Tx) error { + sessions := tx.Bucket(m.sessionsBucket) + c := sessions.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + s := &sessionProps{} + err := json.Unmarshal(v, s) + if err != nil { + println(err) + continue + } + if !m.isValidSession(s) { + err = sessions.Delete(k) + if err != nil { + println(err) + } + } + } + return nil + }) + time.AfterFunc( + time.Duration(m.cookieTimeout)*time.Minute, + func() { m.cleanSessions() }, + ) + } + } } diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index fd8113a5..62ab805f 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -14,6 +14,7 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { defer os.RemoveAll(dir) manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) + defer manager.Close() assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) @@ -35,6 +36,7 @@ func TestAddDeleteAndHasUser(t *testing.T) { defer os.RemoveAll(dir) manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) + defer manager.Close() assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) @@ -59,6 +61,7 @@ func TestIsAdmin(t *testing.T) { defer os.RemoveAll(dir) manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) + defer manager.Close() assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) From 138e1b5769c3d58e552cd4703c607980b99b5ddd Mon Sep 17 00:00:00 2001 From: John Lee Date: Sat, 24 Mar 2018 14:51:13 -0700 Subject: [PATCH 18/73] trimmed and updated dependencies, updated webpack config --- daemon/web/package-lock.json | 2681 ++++++++++++++++++++++------------ daemon/web/package.json | 25 +- daemon/web/webpack.config.js | 34 +- daemon/web/webpack.prod.js | 19 +- 4 files changed, 1762 insertions(+), 997 deletions(-) diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index b721899c..10d3f8cb 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -14,6 +14,7 @@ "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, "requires": { "mime-types": "2.1.18", "negotiator": "0.6.1" @@ -22,21 +23,16 @@ "acorn": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true }, "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==", + "dev": true, "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": { @@ -60,6 +56,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.3.0.tgz", "integrity": "sha1-FlCkERTvAFdMrBC4Ay2PTBSBLac=", + "dev": true, "requires": { "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", @@ -69,17 +66,8 @@ "ajv-keywords": { "version": "3.1.0", "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" - } + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", + "dev": true }, "ansi-escapes": { "version": "3.0.0", @@ -90,17 +78,20 @@ "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true }, "any-observable": { "version": "0.2.0", @@ -112,11 +103,18 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, "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==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -129,17 +127,20 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, "array-differ": { "version": "1.0.0", @@ -150,17 +151,20 @@ "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true }, "array-flatten": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=" + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "dev": true }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, "requires": { "define-properties": "1.1.2", "es-abstract": "1.10.0" @@ -170,6 +174,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -177,12 +182,14 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, "arrify": { "version": "1.0.1", @@ -199,6 +206,7 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, "requires": { "bn.js": "4.11.8", "inherits": "2.0.3", @@ -209,6 +217,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, "requires": { "util": "0.10.3" } @@ -216,7 +225,8 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true }, "ast-types": { "version": "0.11.3", @@ -225,27 +235,28 @@ "dev": true }, "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=", + "dev": true }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true }, "atob": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, "requires": { "chalk": "1.1.3", "esutils": "2.0.2", @@ -256,6 +267,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-generator": "6.26.1", @@ -282,6 +294,7 @@ "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -319,6 +332,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -329,6 +343,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -340,6 +355,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -350,7 +366,8 @@ "babel-helper-evaluate-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.3.0.tgz", - "integrity": "sha512-dRFlMTqUJRGzx5a2smKxmptDdNCXKSkPcXWzKLwAV72hvIZumrd/0z9RcewHkr7PmAEq+ETtpD1GK6wZ6ZUXzw==" + "integrity": "sha512-dRFlMTqUJRGzx5a2smKxmptDdNCXKSkPcXWzKLwAV72hvIZumrd/0z9RcewHkr7PmAEq+ETtpD1GK6wZ6ZUXzw==", + "dev": true }, "babel-helper-explode-assignable-expression": { "version": "6.24.1", @@ -378,12 +395,14 @@ "babel-helper-flip-expressions": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.3.0.tgz", - "integrity": "sha512-kNGohWmtAG3b7tN1xocRQ5rsKkH/hpvZsMiGOJ1VwGJKhnwzR5KlB3rvKBaBPl5/IGHcopB2JN+r1SUEX1iMAw==" + "integrity": "sha512-kNGohWmtAG3b7tN1xocRQ5rsKkH/hpvZsMiGOJ1VwGJKhnwzR5KlB3rvKBaBPl5/IGHcopB2JN+r1SUEX1iMAw==", + "dev": true }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, "requires": { "babel-helper-get-function-arity": "6.24.1", "babel-runtime": "6.26.0", @@ -396,6 +415,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -405,6 +425,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -413,22 +434,26 @@ "babel-helper-is-nodes-equiv": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=" + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true }, "babel-helper-is-void-0": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.3.0.tgz", - "integrity": "sha512-JVqdX8y7Rf/x4NwbqtUI7mdQjL9HWoDnoAEQ8Gv8oxzjvbJv+n75f7l36m9Y8C7sCUltX3V5edndrp7Hp1oSXQ==" + "integrity": "sha512-JVqdX8y7Rf/x4NwbqtUI7mdQjL9HWoDnoAEQ8Gv8oxzjvbJv+n75f7l36m9Y8C7sCUltX3V5edndrp7Hp1oSXQ==", + "dev": true }, "babel-helper-mark-eval-scopes": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.3.0.tgz", - "integrity": "sha512-nrho5Dg4vl0VUgURVpGpEGiwbst5JX7efIyDHFxmkCx/ocQFnrPt8ze9Kxl6TKjR29bJ7D/XKY1NMlSxOQJRbQ==" + "integrity": "sha512-nrho5Dg4vl0VUgURVpGpEGiwbst5JX7efIyDHFxmkCx/ocQFnrPt8ze9Kxl6TKjR29bJ7D/XKY1NMlSxOQJRbQ==", + "dev": true }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -438,6 +463,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -460,12 +486,14 @@ "babel-helper-remove-or-void": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.3.0.tgz", - "integrity": "sha512-D68W1M3ibCcbg0ysh3ww4/O0g10X1CXK720oOuR8kpfY7w0yP4tVcpK7zDmI1JecynycTQYAZ1rhLJo9aVtIKQ==" + "integrity": "sha512-D68W1M3ibCcbg0ysh3ww4/O0g10X1CXK720oOuR8kpfY7w0yP4tVcpK7zDmI1JecynycTQYAZ1rhLJo9aVtIKQ==", + "dev": true }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", @@ -478,12 +506,14 @@ "babel-helper-to-multiple-sequence-expressions": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.3.0.tgz", - "integrity": "sha512-1uCrBD+EAaMnAYh7hc944n8Ga19y3daEnoXWPYDvFVsxMCc1l8aDjksApaCEaNSSuewq8BEcff47Cy1PbLg2Gw==" + "integrity": "sha512-1uCrBD+EAaMnAYh7hc944n8Ga19y3daEnoXWPYDvFVsxMCc1l8aDjksApaCEaNSSuewq8BEcff47Cy1PbLg2Gw==", + "dev": true }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -493,6 +523,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", + "dev": true, "requires": { "find-cache-dir": "1.0.0", "loader-utils": "1.1.0", @@ -503,14 +534,16 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } }, "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==", + "dev": true, "requires": { "babel-core": "6.26.0", "babel-preset-minify": "0.3.0", @@ -521,6 +554,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -529,6 +563,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.3.0.tgz", "integrity": "sha512-MqhSHlxkmgURqj3144qPksbZ/qof1JWdumcbucc4tysFcf3P3V3z3munTevQgKEFNMd8F5/ECGnwb63xogLjAg==", + "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -537,6 +572,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.3.0.tgz", "integrity": "sha512-1XeRpx+aY1BuNY6QU/cm6P+FtEi3ar3XceYbmC+4q4W+2Ewq5pL7V68oHg1hKXkBIE0Z4/FjSoHz6vosZLOe/A==", + "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -545,6 +581,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.3.0.tgz", "integrity": "sha512-SjM2Fzg85YZz+q/PNJ/HU4O3W98FKFOiP9K5z3sfonlamGOzvZw3Eup2OTiEBsbbqTeY8yzNCAv3qpJRYCgGmw==", + "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0", "babel-helper-mark-eval-scopes": "0.3.0", @@ -556,6 +593,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.3.0.tgz", "integrity": "sha512-B8lK+ekcpSNVH7PZpWDe5nC5zxjRiiT4nTsa6h3QkF3Kk6y9qooIFLemdGlqBq6j0zALEnebvCpw8v7gAdpgnw==", + "dev": true, "requires": { "babel-helper-is-void-0": "0.3.0" } @@ -564,6 +602,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.3.0.tgz", "integrity": "sha512-O+6CvF5/Ttsth3LMg4/BhyvVZ82GImeKMXGdVRQGK/8jFiP15EjRpdgFlxv3cnqRjqdYxLCS6r28VfLpb9C/kA==", + "dev": true, "requires": { "babel-helper-flip-expressions": "0.3.0" } @@ -571,12 +610,14 @@ "babel-plugin-minify-infinity": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.3.0.tgz", - "integrity": "sha512-Sj8ia3/w9158DWieUxU6/VvnYVy59geeFEkVgLZYBE8EBP+sN48tHtBM/jSgz0ejEdBlcfqJ6TnvPmVXTzR2BQ==" + "integrity": "sha512-Sj8ia3/w9158DWieUxU6/VvnYVy59geeFEkVgLZYBE8EBP+sN48tHtBM/jSgz0ejEdBlcfqJ6TnvPmVXTzR2BQ==", + "dev": true }, "babel-plugin-minify-mangle-names": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.3.0.tgz", "integrity": "sha512-PYTonhFWURsfAN8achDwvR5Xgy6EeTClLz+fSgGRqjAIXb0OyFm3/xfccbQviVi1qDXmlSnt6oJhBg8KE4Fn7Q==", + "dev": true, "requires": { "babel-helper-mark-eval-scopes": "0.3.0" } @@ -584,17 +625,20 @@ "babel-plugin-minify-numeric-literals": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.3.0.tgz", - "integrity": "sha512-TgZj6ay8zDw74AS3yiIfoQ8vRSNJisYO/Du60S8nPV7EW7JM6fDMx5Sar6yVHlVuuwNgvDUBh191K33bVrAhpg==" + "integrity": "sha512-TgZj6ay8zDw74AS3yiIfoQ8vRSNJisYO/Du60S8nPV7EW7JM6fDMx5Sar6yVHlVuuwNgvDUBh191K33bVrAhpg==", + "dev": true }, "babel-plugin-minify-replace": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.3.0.tgz", - "integrity": "sha512-VR6tTg2Lt0TicHIOw04fsUtpPw7RaRP8PC8YzSFwEixnzvguZjZJoL7TgG7ZyEWQD1cJ96UezswECmFNa815bg==" + "integrity": "sha512-VR6tTg2Lt0TicHIOw04fsUtpPw7RaRP8PC8YzSFwEixnzvguZjZJoL7TgG7ZyEWQD1cJ96UezswECmFNa815bg==", + "dev": true }, "babel-plugin-minify-simplify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.3.0.tgz", "integrity": "sha512-2M16ytQOCqBi7bYMu4DCWn8e6KyFCA108F6+tVrBJxOmm5u2sOmTFEa8s94tR9RHRRNYmcUf+rgidfnzL3ik9Q==", + "dev": true, "requires": { "babel-helper-flip-expressions": "0.3.0", "babel-helper-is-nodes-equiv": "0.0.1", @@ -605,6 +649,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.3.0.tgz", "integrity": "sha512-XRXpvsUCPeVw9YEUw+9vSiugcSZfow81oIJT0yR9s8H4W7yJ6FHbImi5DJHoL8KcDUjYnL9wYASXk/fOkbyR6Q==", + "dev": true, "requires": { "babel-helper-is-void-0": "0.3.0" } @@ -660,12 +705,14 @@ "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true }, "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", @@ -741,6 +788,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -749,6 +797,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -757,6 +806,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0", @@ -769,6 +819,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -785,6 +836,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -794,6 +846,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -802,6 +855,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -811,6 +865,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -819,6 +874,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -829,6 +885,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -837,6 +894,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", "babel-runtime": "6.26.0", @@ -847,6 +905,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, "requires": { "babel-plugin-transform-strict-mode": "6.24.1", "babel-runtime": "6.26.0", @@ -858,6 +917,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -868,6 +928,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", "babel-runtime": "6.26.0", @@ -878,6 +939,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, "requires": { "babel-helper-replace-supers": "6.24.1", "babel-runtime": "6.26.0" @@ -887,6 +949,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", @@ -900,6 +963,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -909,6 +973,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -917,6 +982,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -927,6 +993,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -935,6 +1002,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -943,6 +1011,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -974,6 +1043,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, "requires": { "babel-plugin-syntax-flow": "6.18.0", "babel-runtime": "6.26.0" @@ -982,22 +1052,26 @@ "babel-plugin-transform-inline-consecutive-adds": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.3.0.tgz", - "integrity": "sha512-iZsYAIjYLLfLK0yN5WVT7Xf7Y3wQ9Z75j9A8q/0IglQSpUt2ppTdHlwl/GeaXnxdaSmsxBu861klbTBbv2n+RA==" + "integrity": "sha512-iZsYAIjYLLfLK0yN5WVT7Xf7Y3wQ9Z75j9A8q/0IglQSpUt2ppTdHlwl/GeaXnxdaSmsxBu861klbTBbv2n+RA==", + "dev": true }, "babel-plugin-transform-member-expression-literals": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.0.tgz", - "integrity": "sha512-bxtac+8w755ctVeDs4vU98RhWY49eW1wO02HAN+eirZYSKk/dVrKONIznXbHmxWKxT4UX1rpTKOCyezuzLpbTw==" + "integrity": "sha512-bxtac+8w755ctVeDs4vU98RhWY49eW1wO02HAN+eirZYSKk/dVrKONIznXbHmxWKxT4UX1rpTKOCyezuzLpbTw==", + "dev": true }, "babel-plugin-transform-merge-sibling-variables": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.0.tgz", - "integrity": "sha512-9G1URVEEKoQLDqe0GwqYudECN7kE/q0OCNo5TiD1iwWnnaKi97xY915l5r2KKUvNflXEm9c3faNWknSXYQ7h6Q==" + "integrity": "sha512-9G1URVEEKoQLDqe0GwqYudECN7kE/q0OCNo5TiD1iwWnnaKi97xY915l5r2KKUvNflXEm9c3faNWknSXYQ7h6Q==", + "dev": true }, "babel-plugin-transform-minify-booleans": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.0.tgz", - "integrity": "sha512-JtpyTRyF+wF/r7GSxpRbNCrVve5M/aCC8xoGcnFItaPUDqjxKmFYvBzMc9u+g0lgo8NWjuZLc16MYaIwkHKD/A==" + "integrity": "sha512-JtpyTRyF+wF/r7GSxpRbNCrVve5M/aCC8xoGcnFItaPUDqjxKmFYvBzMc9u+g0lgo8NWjuZLc16MYaIwkHKD/A==", + "dev": true }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", @@ -1013,6 +1087,7 @@ "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.0.tgz", "integrity": "sha512-B8s+71+4DPye9+pmZiPGgLPy3YqcmIuvE/9UcZLczPlwL5ALwF6qRUdLC3Fk17NhL6jxp4u33ZVZ8R4kvASPzw==", + "dev": true, "requires": { "esutils": "2.0.2" } @@ -1021,6 +1096,7 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1029,6 +1105,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, "requires": { "babel-helper-builder-react-jsx": "6.26.0", "babel-plugin-syntax-jsx": "6.18.0", @@ -1039,6 +1116,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -1048,6 +1126,7 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -1057,6 +1136,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, "requires": { "regenerator-transform": "0.10.1" } @@ -1064,22 +1144,26 @@ "babel-plugin-transform-regexp-constructors": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.3.0.tgz", - "integrity": "sha512-h92YHzyl042rb0naKO8frTHntpRFwRgKkfWD8602kFHoQingjJNtbvZzvxqHncJ6XmKVyYvfrBpDOSkCTDIIxw==" + "integrity": "sha512-h92YHzyl042rb0naKO8frTHntpRFwRgKkfWD8602kFHoQingjJNtbvZzvxqHncJ6XmKVyYvfrBpDOSkCTDIIxw==", + "dev": true }, "babel-plugin-transform-remove-console": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.0.tgz", - "integrity": "sha512-mck9//yGTwObqqqDzY/sISO88/5/XfIB3ILb4uJLXk2xq124NT4yQVjFSRgVSbLcNq8OyBAn2acxKUqg4W/okQ==" + "integrity": "sha512-mck9//yGTwObqqqDzY/sISO88/5/XfIB3ILb4uJLXk2xq124NT4yQVjFSRgVSbLcNq8OyBAn2acxKUqg4W/okQ==", + "dev": true }, "babel-plugin-transform-remove-debugger": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.0.tgz", - "integrity": "sha512-i/HWGjsmL2d1N2dl+eIzf44XpSP5v7hi1/GXB0xzom9kjrU8js3T8Kadizn95ZxfHK592Vg8P4JJWP/fvimEWw==" + "integrity": "sha512-i/HWGjsmL2d1N2dl+eIzf44XpSP5v7hi1/GXB0xzom9kjrU8js3T8Kadizn95ZxfHK592Vg8P4JJWP/fvimEWw==", + "dev": true }, "babel-plugin-transform-remove-undefined": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.3.0.tgz", "integrity": "sha512-TYGQucc8iP3LJwN3kDZLEz5aa/2KuFrqpT+s8f8NnHsBU1sAgR3y8Opns0xhC+smyDYWscqFCKM1gbkWQOhhnw==", + "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -1087,12 +1171,14 @@ "babel-plugin-transform-simplify-comparison-operators": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.0.tgz", - "integrity": "sha512-EJyfYeph0CSekwQuwWVwJqy2go/bETkR95iaWQ/HTUis7tkCGNYmXngaFzuIXdmoPXfvmXYCvAXR4/93hqHVjw==" + "integrity": "sha512-EJyfYeph0CSekwQuwWVwJqy2go/bETkR95iaWQ/HTUis7tkCGNYmXngaFzuIXdmoPXfvmXYCvAXR4/93hqHVjw==", + "dev": true }, "babel-plugin-transform-strict-mode": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1101,12 +1187,14 @@ "babel-plugin-transform-undefined-to-void": { "version": "6.9.0", "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==" + "integrity": "sha512-AVDVEmp0S9mbF1O8zekWbsOOmqnR08PZah5NRZJqSvJnFgiL0ep4Lwo4EymH8OieJR2QgQdR3q71TNW+wiVn4g==", + "dev": true }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -1138,6 +1226,7 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0" } @@ -1146,6 +1235,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.3.0.tgz", "integrity": "sha512-+VV2GWEyak3eDOmzT1DDMuqHrw3VbE9nBNkx2LLVs4pH/Me32ND8DRpVDd8IRvk1xX5p75nygyRPtkMh6GIAbQ==", + "dev": true, "requires": { "babel-plugin-minify-builtins": "0.3.0", "babel-plugin-minify-constant-folding": "0.3.0", @@ -1176,6 +1266,7 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-react-display-name": "6.25.0", @@ -1225,6 +1316,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", @@ -1239,6 +1331,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, "requires": { "core-js": "2.5.3", "regenerator-runtime": "0.11.1" @@ -1248,6 +1341,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -1260,6 +1354,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-messages": "6.23.0", @@ -1276,6 +1371,7 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", @@ -1286,17 +1382,20 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, "requires": { "cache-base": "1.0.1", "class-utils": "0.3.6", @@ -1311,6 +1410,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -1320,22 +1420,26 @@ "base64-js": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", - "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", + "dev": true }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true }, "binaryextensions": { "version": "2.1.1", @@ -1343,15 +1447,23 @@ "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==", "dev": true }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true }, "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, "requires": { "bytes": "3.0.0", "content-type": "1.0.4", @@ -1369,6 +1481,7 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, "requires": { "array-flatten": "2.1.1", "deep-equal": "1.0.1", @@ -1381,12 +1494,14 @@ "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -1396,6 +1511,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, "requires": { "arr-flatten": "1.1.0", "array-unique": "0.3.2", @@ -1415,6 +1531,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -1423,6 +1540,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -1430,19 +1548,22 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true }, "browserify-aes": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, "requires": { "buffer-xor": "1.0.3", "cipher-base": "1.0.4", @@ -1456,6 +1577,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, "requires": { "browserify-aes": "1.1.1", "browserify-des": "1.0.0", @@ -1466,6 +1588,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, "requires": { "cipher-base": "1.0.4", "des.js": "1.0.0", @@ -1476,6 +1599,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, "requires": { "bn.js": "4.11.8", "randombytes": "2.0.6" @@ -1485,6 +1609,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, "requires": { "bn.js": "4.11.8", "browserify-rsa": "4.0.1", @@ -1499,6 +1624,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, "requires": { "pako": "1.0.6" } @@ -1507,41 +1633,77 @@ "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, "requires": { "base64-js": "1.2.3", - "ieee754": "1.1.10", + "ieee754": "1.1.11", "isarray": "1.0.0" } }, "buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "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==", + "dev": true + } + } }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, "requires": { "collection-visit": "1.0.0", "component-emitter": "1.2.1", @@ -1567,6 +1729,14 @@ "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=", + "dev": true + } } }, "caller-path": { @@ -1588,45 +1758,33 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, "requires": { "no-case": "2.3.2", "upper-case": "1.1.3" } }, "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=", + "dev": true }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, "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=", - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" } }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -1642,9 +1800,10 @@ "dev": true }, "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==", + "dev": true, "requires": { "anymatch": "2.0.0", "async-each": "1.0.1", @@ -1660,10 +1819,23 @@ "upath": "1.0.4" } }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "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=", + "dev": true + }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -1679,6 +1851,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, "requires": { "arr-union": "3.1.0", "define-property": "0.2.5", @@ -1690,6 +1863,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -1698,6 +1872,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -1706,6 +1881,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -1716,6 +1892,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -1724,6 +1901,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -1734,6 +1912,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -1743,7 +1922,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -1751,6 +1931,7 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", + "dev": true, "requires": { "source-map": "0.5.7" } @@ -1823,19 +2004,33 @@ "dev": true }, "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=", + "dev": true, "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=", + "dev": true, + "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=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-buffer": { @@ -1879,12 +2074,14 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, "requires": { "map-visit": "1.0.0", "object-visit": "1.0.1" @@ -1912,24 +2109,28 @@ "dev": true }, "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==", + "dev": true }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true }, "compressible": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", + "dev": true, "requires": { "mime-db": "1.33.0" } @@ -1938,6 +2139,7 @@ "version": "1.7.2", "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz", "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", + "dev": true, "requires": { "accepts": "1.3.5", "bytes": "3.0.0", @@ -1951,7 +2153,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.1", @@ -1967,12 +2170,14 @@ "connect-history-api-fallback": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=" + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "dev": true }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, "requires": { "date-now": "0.1.4" } @@ -1980,52 +2185,76 @@ "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true }, "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true }, - "core-js": { - "version": "2.5.3", + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "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", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.3", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "dev": true }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "create-ecdh": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, "requires": { "bn.js": "4.11.8", "elliptic": "6.4.0" @@ -2035,30 +2264,33 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, "requires": { "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": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, "requires": { "cipher-base": "1.0.4", "create-hash": "1.1.3", "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": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -2069,6 +2301,7 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, "requires": { "browserify-cipher": "1.0.0", "browserify-sign": "4.0.4", @@ -2087,6 +2320,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, "requires": { "boolbase": "1.0.0", "css-what": "2.1.0", @@ -2097,23 +2331,23 @@ "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=" + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, "requires": { "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=", + "dev": true }, "dargs": { "version": "5.1.0", @@ -2130,7 +2364,8 @@ "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true }, "dateformat": { "version": "3.0.3", @@ -2142,6 +2377,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -2149,12 +2385,14 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true }, "decompress-response": { "version": "3.3.0", @@ -2168,7 +2406,8 @@ "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true }, "deep-extend": { "version": "0.4.2", @@ -2186,6 +2425,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, "requires": { "foreach": "2.0.5", "object-keys": "1.0.11" @@ -2195,6 +2435,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, "requires": { "is-descriptor": "1.0.2", "isobject": "3.0.1" @@ -2204,6 +2445,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, "requires": { "globby": "6.1.0", "is-path-cwd": "1.0.0", @@ -2216,12 +2458,14 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -2230,7 +2474,8 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true }, "detect-conflict": { "version": "1.0.1", @@ -2242,6 +2487,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, "requires": { "repeating": "2.0.1" } @@ -2249,7 +2495,8 @@ "detect-node": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", - "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=" + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", + "dev": true }, "diff": { "version": "3.5.0", @@ -2261,6 +2508,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, "requires": { "bn.js": "4.11.8", "miller-rabin": "4.0.1", @@ -2270,12 +2518,14 @@ "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true }, "dns-packet": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, "requires": { "ip": "1.1.5", "safe-buffer": "5.1.1" @@ -2285,6 +2535,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, "requires": { "buffer-indexof": "1.1.1" } @@ -2302,6 +2553,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", + "dev": true, "requires": { "utila": "0.3.3" }, @@ -2309,7 +2561,8 @@ "utila": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true } } }, @@ -2317,6 +2570,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, "requires": { "domelementtype": "1.1.3", "entities": "1.1.1" @@ -2325,24 +2579,28 @@ "domelementtype": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true } } }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true }, "domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true }, "domhandler": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "dev": true, "requires": { "domelementtype": "1.3.0" } @@ -2351,6 +2609,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, "requires": { "dom-serializer": "0.1.0", "domelementtype": "1.3.0" @@ -2362,6 +2621,18 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", + "dev": true, + "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", @@ -2371,7 +2642,8 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true }, "ejs": { "version": "2.5.7", @@ -2389,6 +2661,7 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, "requires": { "bn.js": "4.11.8", "brorand": "1.1.0", @@ -2402,12 +2675,14 @@ "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true }, "encoding": { "version": "0.1.12", @@ -2417,26 +2692,37 @@ "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==", + "dev": true, + "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==", + "dev": true, "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": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, "requires": { "prr": "1.0.1" } @@ -2455,6 +2741,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, "requires": { "is-arrayish": "0.2.1" } @@ -2463,6 +2750,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, "requires": { "es-to-primitive": "1.1.1", "function-bind": "1.1.1", @@ -2475,102 +2763,29 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, "requires": { "is-callable": "1.1.3", "is-date-object": "1.0.1", "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", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", "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" - } + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.0.tgz", - "integrity": "sha512-r83L5CuqaocDvfwdojbz68b6tCUk8KJkqfppO+gmSAQqYCzTr0bCSMu6A6yFCLKG65j5eKcKUw4Cw4Yl4gfWkg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", "dev": true, "requires": { "ajv": "5.5.2", @@ -2588,7 +2803,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", @@ -2661,15 +2876,9 @@ } }, "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=", + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", + "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", "dev": true }, "strip-ansi": { @@ -2749,6 +2958,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, "requires": { "estraverse": "4.2.0" } @@ -2756,41 +2966,38 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "etag": { "version": "1.8.1", "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" - } + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true }, "eventemitter3": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true }, "eventsource": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, "requires": { "original": "1.0.0" } @@ -2799,6 +3006,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, "requires": { "md5.js": "1.3.4", "safe-buffer": "5.1.1" @@ -2808,6 +3016,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, "requires": { "cross-spawn": "5.1.0", "get-stream": "3.0.0", @@ -2828,6 +3037,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, "requires": { "debug": "2.6.9", "define-property": "0.2.5", @@ -2842,6 +3052,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -2850,6 +3061,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -2858,6 +3070,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -2866,6 +3079,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -2876,6 +3090,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -2884,6 +3099,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -2894,6 +3110,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -2903,7 +3120,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -2911,6 +3129,7 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, "requires": { "fill-range": "2.2.3" }, @@ -2919,6 +3138,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -2931,6 +3151,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -2939,6 +3160,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -2958,6 +3180,7 @@ "version": "4.16.3", "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "dev": true, "requires": { "accepts": "1.3.5", "array-flatten": "1.1.1", @@ -2994,7 +3217,8 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true } } }, @@ -3002,6 +3226,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, "requires": { "assign-symbols": "1.0.0", "is-extendable": "1.0.1" @@ -3011,6 +3236,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "2.0.4" } @@ -3032,6 +3258,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, "requires": { "array-unique": "0.3.2", "define-property": "1.0.0", @@ -3047,6 +3274,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -3055,6 +3283,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -3064,12 +3293,14 @@ "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -3081,6 +3312,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, "requires": { "websocket-driver": "0.7.0" } @@ -3128,12 +3360,14 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, "requires": { "extend-shallow": "2.0.1", "is-number": "3.0.0", @@ -3145,6 +3379,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -3155,6 +3390,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "1.0.2", @@ -3169,6 +3405,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, "requires": { "commondir": "1.0.1", "make-dir": "1.2.0", @@ -3179,6 +3416,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "2.0.0" } @@ -3247,15 +3485,27 @@ "integrity": "sha1-nMlmIKEC4xajFLa81WIFzqzoYtg=", "dev": true }, + "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==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, "requires": { "for-in": "1.0.2" } @@ -3263,17 +3513,20 @@ "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, "requires": { "map-cache": "0.2.2" } @@ -3281,7 +3534,8 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true }, "from2": { "version": "2.3.0", @@ -3293,15 +3547,29 @@ "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=", + "dev": true, + "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", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, "optional": true, "requires": { "nan": "2.10.0", @@ -3311,11 +3579,13 @@ "abbrev": { "version": "1.1.0", "bundled": true, + "dev": true, "optional": true }, "ajv": { "version": "4.11.8", "bundled": true, + "dev": true, "optional": true, "requires": { "co": "4.6.0", @@ -3324,16 +3594,19 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "dev": true }, "aproba": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", "bundled": true, + "dev": true, "optional": true, "requires": { "delegates": "1.0.0", @@ -3343,35 +3616,42 @@ "asn1": { "version": "0.2.3", "bundled": true, + "dev": true, "optional": true }, "assert-plus": { "version": "0.2.0", "bundled": true, + "dev": true, "optional": true }, "asynckit": { "version": "0.4.0", "bundled": true, + "dev": true, "optional": true }, "aws-sign2": { "version": "0.6.0", "bundled": true, + "dev": true, "optional": true }, "aws4": { "version": "1.6.0", "bundled": true, + "dev": true, "optional": true }, "balanced-match": { "version": "0.4.2", - "bundled": true + "bundled": true, + "dev": true }, "bcrypt-pbkdf": { "version": "1.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "tweetnacl": "0.14.5" @@ -3380,6 +3660,7 @@ "block-stream": { "version": "0.0.9", "bundled": true, + "dev": true, "requires": { "inherits": "2.0.3" } @@ -3387,6 +3668,7 @@ "boom": { "version": "2.10.1", "bundled": true, + "dev": true, "requires": { "hoek": "2.16.3" } @@ -3394,6 +3676,7 @@ "brace-expansion": { "version": "1.1.7", "bundled": true, + "dev": true, "requires": { "balanced-match": "0.4.2", "concat-map": "0.0.1" @@ -3401,44 +3684,53 @@ }, "buffer-shims": { "version": "1.0.0", - "bundled": true + "bundled": true, + "dev": true }, "caseless": { "version": "0.12.0", "bundled": true, + "dev": true, "optional": true }, "co": { "version": "4.6.0", "bundled": true, + "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "dev": true }, "combined-stream": { "version": "1.0.5", "bundled": true, + "dev": true, "requires": { "delayed-stream": "1.0.0" } }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "dev": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "dev": true }, "core-util-is": { "version": "1.0.2", - "bundled": true + "bundled": true, + "dev": true }, "cryptiles": { "version": "2.0.5", "bundled": true, + "dev": true, "requires": { "boom": "2.10.1" } @@ -3446,6 +3738,7 @@ "dashdash": { "version": "1.14.1", "bundled": true, + "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0" @@ -3454,6 +3747,7 @@ "assert-plus": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true } } @@ -3461,6 +3755,7 @@ "debug": { "version": "2.6.8", "bundled": true, + "dev": true, "optional": true, "requires": { "ms": "2.0.0" @@ -3469,25 +3764,30 @@ "deep-extend": { "version": "0.4.2", "bundled": true, + "dev": true, "optional": true }, "delayed-stream": { "version": "1.0.0", - "bundled": true + "bundled": true, + "dev": true }, "delegates": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "detect-libc": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "ecc-jsbn": { "version": "0.1.1", "bundled": true, + "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -3496,20 +3796,24 @@ "extend": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true }, "extsprintf": { "version": "1.0.2", - "bundled": true + "bundled": true, + "dev": true }, "forever-agent": { "version": "0.6.1", "bundled": true, + "dev": true, "optional": true }, "form-data": { "version": "2.1.4", "bundled": true, + "dev": true, "optional": true, "requires": { "asynckit": "0.4.0", @@ -3519,11 +3823,13 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true + "bundled": true, + "dev": true }, "fstream": { "version": "1.0.11", "bundled": true, + "dev": true, "requires": { "graceful-fs": "4.1.11", "inherits": "2.0.3", @@ -3534,6 +3840,7 @@ "fstream-ignore": { "version": "1.0.5", "bundled": true, + "dev": true, "optional": true, "requires": { "fstream": "1.0.11", @@ -3544,6 +3851,7 @@ "gauge": { "version": "2.7.4", "bundled": true, + "dev": true, "optional": true, "requires": { "aproba": "1.1.1", @@ -3559,6 +3867,7 @@ "getpass": { "version": "0.1.7", "bundled": true, + "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0" @@ -3567,6 +3876,7 @@ "assert-plus": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true } } @@ -3574,6 +3884,7 @@ "glob": { "version": "7.1.2", "bundled": true, + "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3585,16 +3896,19 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true + "bundled": true, + "dev": true }, "har-schema": { "version": "1.0.5", "bundled": true, + "dev": true, "optional": true }, "har-validator": { "version": "4.2.1", "bundled": true, + "dev": true, "optional": true, "requires": { "ajv": "4.11.8", @@ -3604,11 +3918,13 @@ "has-unicode": { "version": "2.0.1", "bundled": true, + "dev": true, "optional": true }, "hawk": { "version": "3.1.3", "bundled": true, + "dev": true, "requires": { "boom": "2.10.1", "cryptiles": "2.0.5", @@ -3618,11 +3934,13 @@ }, "hoek": { "version": "2.16.3", - "bundled": true + "bundled": true, + "dev": true }, "http-signature": { "version": "1.1.1", "bundled": true, + "dev": true, "optional": true, "requires": { "assert-plus": "0.2.0", @@ -3633,6 +3951,7 @@ "inflight": { "version": "1.0.6", "bundled": true, + "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -3640,16 +3959,19 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "dev": true }, "ini": { "version": "1.3.4", "bundled": true, + "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -3657,20 +3979,24 @@ "is-typedarray": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true }, "isarray": { "version": "1.0.0", - "bundled": true + "bundled": true, + "dev": true }, "isstream": { "version": "0.1.2", "bundled": true, + "dev": true, "optional": true }, "jodid25519": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -3679,16 +4005,19 @@ "jsbn": { "version": "0.1.1", "bundled": true, + "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", "bundled": true, + "dev": true, "optional": true }, "json-stable-stringify": { "version": "1.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "jsonify": "0.0.0" @@ -3697,16 +4026,19 @@ "json-stringify-safe": { "version": "5.0.1", "bundled": true, + "dev": true, "optional": true }, "jsonify": { "version": "0.0.0", "bundled": true, + "dev": true, "optional": true }, "jsprim": { "version": "1.4.0", "bundled": true, + "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0", @@ -3718,17 +4050,20 @@ "assert-plus": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true } } }, "mime-db": { "version": "1.27.0", - "bundled": true + "bundled": true, + "dev": true }, "mime-types": { "version": "2.1.15", "bundled": true, + "dev": true, "requires": { "mime-db": "1.27.0" } @@ -3736,17 +4071,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "dev": true, "requires": { "brace-expansion": "1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "dev": true }, "mkdirp": { "version": "0.5.1", "bundled": true, + "dev": true, "requires": { "minimist": "0.0.8" } @@ -3754,11 +4092,13 @@ "ms": { "version": "2.0.0", "bundled": true, + "dev": true, "optional": true }, "node-pre-gyp": { "version": "0.6.39", "bundled": true, + "dev": true, "optional": true, "requires": { "detect-libc": "1.0.2", @@ -3777,6 +4117,7 @@ "nopt": { "version": "4.0.1", "bundled": true, + "dev": true, "optional": true, "requires": { "abbrev": "1.1.0", @@ -3786,6 +4127,7 @@ "npmlog": { "version": "4.1.0", "bundled": true, + "dev": true, "optional": true, "requires": { "are-we-there-yet": "1.1.4", @@ -3796,21 +4138,25 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "dev": true }, "oauth-sign": { "version": "0.8.2", "bundled": true, + "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", "bundled": true, + "dev": true, "optional": true }, "once": { "version": "1.4.0", "bundled": true, + "dev": true, "requires": { "wrappy": "1.0.2" } @@ -3818,16 +4164,19 @@ "os-homedir": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", "bundled": true, + "dev": true, "optional": true }, "osenv": { "version": "0.1.4", "bundled": true, + "dev": true, "optional": true, "requires": { "os-homedir": "1.0.2", @@ -3836,30 +4185,36 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true + "bundled": true, + "dev": true }, "performance-now": { "version": "0.2.0", "bundled": true, + "dev": true, "optional": true }, "process-nextick-args": { "version": "1.0.7", - "bundled": true + "bundled": true, + "dev": true }, "punycode": { "version": "1.4.1", "bundled": true, + "dev": true, "optional": true }, "qs": { "version": "6.4.0", "bundled": true, + "dev": true, "optional": true }, "rc": { "version": "1.2.1", "bundled": true, + "dev": true, "optional": true, "requires": { "deep-extend": "0.4.2", @@ -3871,6 +4226,7 @@ "minimist": { "version": "1.2.0", "bundled": true, + "dev": true, "optional": true } } @@ -3878,6 +4234,7 @@ "readable-stream": { "version": "2.2.9", "bundled": true, + "dev": true, "requires": { "buffer-shims": "1.0.0", "core-util-is": "1.0.2", @@ -3891,6 +4248,7 @@ "request": { "version": "2.81.0", "bundled": true, + "dev": true, "optional": true, "requires": { "aws-sign2": "0.6.0", @@ -3920,32 +4278,38 @@ "rimraf": { "version": "2.6.1", "bundled": true, + "dev": true, "requires": { "glob": "7.1.2" } }, "safe-buffer": { "version": "5.0.1", - "bundled": true + "bundled": true, + "dev": true }, "semver": { "version": "5.3.0", "bundled": true, + "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", "bundled": true, + "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", "bundled": true, + "dev": true, "optional": true }, "sntp": { "version": "1.0.9", "bundled": true, + "dev": true, "requires": { "hoek": "2.16.3" } @@ -3953,6 +4317,7 @@ "sshpk": { "version": "1.13.0", "bundled": true, + "dev": true, "optional": true, "requires": { "asn1": "0.2.3", @@ -3969,6 +4334,7 @@ "assert-plus": { "version": "1.0.0", "bundled": true, + "dev": true, "optional": true } } @@ -3976,6 +4342,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -3985,6 +4352,7 @@ "string_decoder": { "version": "1.0.1", "bundled": true, + "dev": true, "requires": { "safe-buffer": "5.0.1" } @@ -3992,11 +4360,13 @@ "stringstream": { "version": "0.0.5", "bundled": true, + "dev": true, "optional": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, + "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4004,11 +4374,13 @@ "strip-json-comments": { "version": "2.0.1", "bundled": true, + "dev": true, "optional": true }, "tar": { "version": "2.2.1", "bundled": true, + "dev": true, "requires": { "block-stream": "0.0.9", "fstream": "1.0.11", @@ -4018,6 +4390,7 @@ "tar-pack": { "version": "3.4.0", "bundled": true, + "dev": true, "optional": true, "requires": { "debug": "2.6.8", @@ -4033,6 +4406,7 @@ "tough-cookie": { "version": "2.3.2", "bundled": true, + "dev": true, "optional": true, "requires": { "punycode": "1.4.1" @@ -4041,6 +4415,7 @@ "tunnel-agent": { "version": "0.6.0", "bundled": true, + "dev": true, "optional": true, "requires": { "safe-buffer": "5.0.1" @@ -4049,25 +4424,30 @@ "tweetnacl": { "version": "0.14.5", "bundled": true, + "dev": true, "optional": true }, "uid-number": { "version": "0.0.6", "bundled": true, + "dev": true, "optional": true }, "util-deprecate": { "version": "1.0.2", - "bundled": true + "bundled": true, + "dev": true }, "uuid": { "version": "3.0.1", "bundled": true, + "dev": true, "optional": true }, "verror": { "version": "1.3.6", "bundled": true, + "dev": true, "optional": true, "requires": { "extsprintf": "1.0.2" @@ -4076,6 +4456,7 @@ "wide-align": { "version": "1.1.2", "bundled": true, + "dev": true, "optional": true, "requires": { "string-width": "1.0.2" @@ -4083,14 +4464,16 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "dev": true } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -4101,22 +4484,26 @@ "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true }, "gh-got": { "version": "6.0.0", @@ -4141,7 +4528,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", @@ -4195,6 +4582,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4235,6 +4623,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -4244,6 +4633,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, "requires": { "is-glob": "2.0.1" } @@ -4251,12 +4641,14 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true }, "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" } @@ -4267,6 +4659,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, "requires": { "is-glob": "3.1.0", "path-dirname": "1.0.2" @@ -4276,6 +4669,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -4309,12 +4703,14 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, "requires": { "array-union": "1.0.2", "glob": "7.1.2", @@ -4326,7 +4722,8 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -4344,7 +4741,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", @@ -4358,7 +4755,8 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true }, "grouped-queue": { "version": "0.3.3", @@ -4372,12 +4770,14 @@ "handle-thing": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=" + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true }, "has": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, "requires": { "function-bind": "1.1.1" } @@ -4386,6 +4786,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4397,9 +4798,10 @@ "dev": true }, "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=", + "dev": true }, "has-symbol-support-x": { "version": "1.4.2", @@ -4420,6 +4822,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, "requires": { "get-value": "2.0.6", "has-values": "1.0.0", @@ -4430,6 +4833,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -4439,6 +4843,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -4449,6 +4854,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, "requires": { "inherits": "2.0.3" } @@ -4457,6 +4863,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -4465,12 +4872,14 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, "requires": { "hash.js": "1.1.3", "minimalistic-assert": "1.0.0", @@ -4481,6 +4890,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -4498,12 +4908,14 @@ "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, "requires": { "inherits": "2.0.3", "obuf": "1.1.2", @@ -4514,45 +4926,50 @@ "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true }, "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==", + "dev": true, "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": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "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==", + "dev": true, "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=", + "dev": true, "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", @@ -4565,17 +4982,13 @@ "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", "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==" } } }, @@ -4583,6 +4996,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "dev": true, "requires": { "domelementtype": "1.3.0", "domhandler": "2.1.0", @@ -4594,6 +5008,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, "requires": { "domelementtype": "1.3.0" } @@ -4601,12 +5016,14 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -4617,7 +5034,8 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true } } }, @@ -4630,12 +5048,14 @@ "http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, "requires": { "depd": "1.1.1", "inherits": "2.0.3", @@ -4646,24 +5066,28 @@ "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true } } }, "http-parser-js": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", - "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==" + "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", + "dev": true }, "http-proxy": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, "requires": { "eventemitter3": "1.2.0", "requires-port": "1.0.0" @@ -4673,6 +5097,7 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "dev": true, "requires": { "http-proxy": "1.16.2", "is-glob": "3.1.0", @@ -4684,6 +5109,7 @@ "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" } @@ -4691,12 +5117,14 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true }, "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", @@ -4707,6 +5135,7 @@ "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" } @@ -4715,6 +5144,7 @@ "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" }, @@ -4722,7 +5152,8 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true } } }, @@ -4730,6 +5161,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -4738,6 +5170,7 @@ "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", @@ -4757,12 +5190,14 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true }, "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" } @@ -4774,7 +5209,8 @@ "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true }, "iconv-lite": { "version": "0.4.19", @@ -4782,9 +5218,16 @@ "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==" + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true }, "ignore": { "version": "3.3.7", @@ -4796,6 +5239,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, "requires": { "pkg-dir": "2.0.0", "resolve-cwd": "2.0.0" @@ -4811,6 +5255,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, "requires": { "repeating": "2.0.1" } @@ -4818,12 +5263,14 @@ "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -4832,7 +5279,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ini": { "version": "1.3.5", @@ -4918,6 +5366,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "dev": true, "requires": { "meow": "3.7.0" } @@ -4925,7 +5374,8 @@ "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true }, "into-stream": { "version": "3.1.0", @@ -4941,6 +5391,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, "requires": { "loose-envify": "1.3.1" } @@ -4948,22 +5399,26 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true }, "ipaddr.js": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", + "dev": true }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -4971,19 +5426,22 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, "requires": { "binary-extensions": "1.11.0" } @@ -4991,12 +5449,14 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, "requires": { "builtin-modules": "1.1.1" } @@ -5004,12 +5464,14 @@ "is-callable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -5017,19 +5479,22 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "1.0.0", "is-data-descriptor": "1.0.0", @@ -5039,19 +5504,22 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -5059,17 +5527,20 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -5078,6 +5549,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -5086,6 +5558,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -5094,6 +5567,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -5125,6 +5599,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, "requires": { "is-number": "4.0.0" }, @@ -5132,19 +5607,22 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true } } }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true }, "is-path-in-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, "requires": { "is-path-inside": "1.0.1" } @@ -5153,6 +5631,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, "requires": { "path-is-inside": "1.0.2" } @@ -5167,6 +5646,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "requires": { "isobject": "3.0.1" } @@ -5174,12 +5654,14 @@ "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true }, "is-promise": { "version": "2.1.0", @@ -5191,6 +5673,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, "requires": { "has": "1.0.1" } @@ -5224,37 +5707,44 @@ "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isomorphic-fetch": { "version": "2.2.1", @@ -5319,7 +5809,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" }, @@ -5415,7 +5905,8 @@ "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true }, "json-buffer": { "version": "3.0.0", @@ -5423,11 +5914,6 @@ "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==" - }, "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", @@ -5437,7 +5923,8 @@ "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -5448,12 +5935,14 @@ "json3": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true }, "jsx-ast-utils": { "version": "2.0.1", @@ -5476,25 +5965,23 @@ "killable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", - "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=" + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "dev": true }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "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", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, "requires": { "invert-kv": "1.0.0" } @@ -5654,32 +6141,46 @@ } }, "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=", + "dev": true, "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=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "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" + } } } }, "loader-runner": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=" + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true }, "loader-utils": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -5690,6 +6191,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" @@ -5698,17 +6200,20 @@ "lodash": { "version": "4.17.5", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true }, "lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true }, "log-symbols": { "version": "2.2.0", @@ -5802,12 +6307,14 @@ "loglevel": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", - "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=" + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true }, - "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==", + "dev": true }, "loose-envify": { "version": "1.3.1", @@ -5821,6 +6328,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, "requires": { "currently-unhandled": "0.4.1", "signal-exit": "3.0.2" @@ -5829,18 +6337,20 @@ "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true }, "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, "lru-cache": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -5850,6 +6360,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", + "dev": true, "requires": { "pify": "3.0.0" } @@ -5857,17 +6368,20 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, "requires": { "object-visit": "1.0.1" } @@ -5876,6 +6390,7 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, "requires": { "hash-base": "3.0.4", "inherits": "2.0.3" @@ -5885,6 +6400,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -5895,12 +6411,14 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -5935,9 +6453,9 @@ }, "dependencies": { "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-stats": { @@ -5958,7 +6476,7 @@ "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", @@ -5972,6 +6490,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, "requires": { "errno": "0.1.7", "readable-stream": "2.3.5" @@ -5981,6 +6500,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, "requires": { "camelcase-keys": "2.1.0", "decamelize": "1.2.0", @@ -5994,98 +6514,31 @@ "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" - } + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true } } }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true }, "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==", + "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -6105,7 +6558,8 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -6113,6 +6567,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, "requires": { "bn.js": "4.11.8", "brorand": "1.1.0" @@ -6121,17 +6576,20 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true }, "mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true }, "mime-types": { "version": "2.1.18", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, "requires": { "mime-db": "1.33.0" } @@ -6139,7 +6597,8 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true }, "mimic-response": { "version": "1.0.0", @@ -6150,17 +6609,20 @@ "minimalistic-assert": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "1.1.11" } @@ -6168,12 +6630,32 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "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", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, "requires": { "for-in": "1.0.2", "is-extendable": "1.0.1" @@ -6183,6 +6665,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "2.0.4" } @@ -6193,19 +6676,36 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "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=", + "dev": true, + "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", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "multicast-dns": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, "requires": { "dns-packet": "1.3.1", "thunky": "1.0.2" @@ -6214,7 +6714,8 @@ "multicast-dns-service-types": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true }, "multimatch": { "version": "2.1.0", @@ -6238,12 +6739,14 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, "optional": true }, "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -6262,7 +6765,8 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -6276,6 +6780,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", + "dev": true, "requires": { "xml-char-classes": "1.0.0" } @@ -6283,17 +6788,14 @@ "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true }, "neo-async": { "version": "2.5.0", "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=" + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", + "dev": true }, "nice-try": { "version": "1.0.4", @@ -6305,6 +6807,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, "requires": { "lower-case": "1.1.4" } @@ -6327,12 +6830,14 @@ "node-forge": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", - "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", + "dev": true }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, "requires": { "assert": "1.4.1", "browserify-zlib": "0.2.0", @@ -6398,6 +6903,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, "requires": { "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", @@ -6409,6 +6915,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, "requires": { "remove-trailing-separator": "1.1.0" } @@ -6428,6 +6935,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, "requires": { "path-key": "2.0.1" } @@ -6436,6 +6944,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, "requires": { "boolbase": "1.0.0" } @@ -6443,7 +6952,8 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -6454,6 +6964,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, "requires": { "copy-descriptor": "0.1.1", "define-property": "0.2.5", @@ -6464,6 +6975,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -6472,6 +6984,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -6480,6 +6993,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -6488,6 +7002,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -6497,7 +7012,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } } @@ -6506,12 +7022,14 @@ "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, "requires": { "isobject": "3.0.1" } @@ -6520,6 +7038,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, "requires": { "define-properties": "1.1.2", "es-abstract": "1.10.0" @@ -6529,6 +7048,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" @@ -6538,6 +7058,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, "requires": { "isobject": "3.0.1" } @@ -6545,12 +7066,14 @@ "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, "requires": { "ee-first": "1.1.1" } @@ -6558,12 +7081,14 @@ "on-headers": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1.0.2" } @@ -6581,6 +7106,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "dev": true, "requires": { "is-wsl": "1.1.0" } @@ -6597,14 +7123,6 @@ "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": { @@ -6650,6 +7168,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "dev": true, "requires": { "url-parse": "1.0.5" }, @@ -6658,6 +7177,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, "requires": { "querystringify": "0.0.4", "requires-port": "1.0.0" @@ -6668,17 +7188,20 @@ "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -6688,7 +7211,8 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-cancelable": { "version": "0.4.0", @@ -6708,7 +7232,8 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true }, "p-is-promise": { "version": "1.1.0", @@ -6726,6 +7251,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, "requires": { "p-try": "1.0.0" } @@ -6734,6 +7260,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { "p-limit": "1.2.0" } @@ -6741,7 +7268,8 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true }, "p-reduce": { "version": "1.0.0", @@ -6761,17 +7289,31 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "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", "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, "requires": { "no-case": "2.3.2" } @@ -6780,6 +7322,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, "requires": { "asn1.js": "4.10.1", "browserify-aes": "1.1.1", @@ -6792,6 +7335,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -6802,12 +7346,14 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true }, "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" } @@ -6818,6 +7364,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, "requires": { "error-ex": "1.3.1" } @@ -6831,42 +7378,50 @@ "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, "path-parse": { "version": "1.0.5", @@ -6877,20 +7432,25 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true }, "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=", + "dev": true, "requires": { - "pify": "2.3.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" }, "dependencies": { "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -6898,28 +7458,32 @@ "version": "3.0.14", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, "requires": { "create-hash": "1.1.3", "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": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, "requires": { "pinkie": "2.0.4" } @@ -6928,6 +7492,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, "requires": { "find-up": "2.1.0" } @@ -6942,6 +7507,7 @@ "version": "1.0.13", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, "requires": { "async": "1.5.2", "debug": "2.6.9", @@ -6951,14 +7517,16 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true } } }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true }, "prelude-ls": { "version": "1.1.2", @@ -6975,7 +7543,8 @@ "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true }, "prettier": { "version": "1.11.1", @@ -6993,6 +7562,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, "requires": { "renderkid": "2.0.1", "utila": "0.4.0" @@ -7001,17 +7571,20 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true }, "progress": { "version": "2.0.0", @@ -7027,6 +7600,12 @@ "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=", + "dev": true + }, "prop-types": { "version": "15.6.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", @@ -7041,6 +7620,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", + "dev": true, "requires": { "forwarded": "0.1.2", "ipaddr.js": "1.6.0" @@ -7049,17 +7629,20 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "public-encrypt": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, "requires": { "bn.js": "4.11.8", "browserify-rsa": "4.0.1", @@ -7068,15 +7651,38 @@ "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==", + "dev": true, + "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==", + "dev": true, + "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=" + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true }, "query-string": { "version": "5.1.1", @@ -7092,22 +7698,26 @@ "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true }, "querystringify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", - "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=" + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "dev": true }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -7117,6 +7727,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -7127,6 +7738,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -7135,6 +7747,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, "requires": { "randombytes": "2.0.6", "safe-buffer": "5.1.1" @@ -7143,12 +7756,14 @@ "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", @@ -7189,28 +7804,52 @@ } }, "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=", + "dev": true, "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=", + "dev": true, "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=", + "dev": true, + "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=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } } }, "readable-stream": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -7225,6 +7864,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, "requires": { "graceful-fs": "4.1.11", "minimatch": "3.0.4", @@ -7233,9 +7873,9 @@ } }, "recast": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.5.tgz", - "integrity": "sha512-GNFQGQrqW1R8w9XhhgYIN8H7ePPp088D+svHlb7DdP5DCqNDqTwH7lt378EouM+L18kCwkmqpAz1unLqpPhHmw==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", + "integrity": "sha512-/nwm9pkrcWagN40JeJhkPaRxiHXBRkXyRh/hgU088Z/v+qCy+zIHHY6bC6o7NaKAxPqtE6nD8zBH1LfU0/Wx6A==", "dev": true, "requires": { "ast-types": "0.11.3", @@ -7258,13 +7898,14 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "1.6.0" } }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, "requires": { "indent-string": "2.1.0", "strip-indent": "1.0.1" @@ -7273,17 +7914,20 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true }, "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -7294,6 +7938,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, "requires": { "is-equal-shallow": "0.1.3" } @@ -7302,6 +7947,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, "requires": { "extend-shallow": "3.0.2", "safe-regex": "1.1.0" @@ -7317,6 +7963,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, "requires": { "regenerate": "1.3.3", "regjsgen": "0.2.0", @@ -7326,12 +7973,14 @@ "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true }, "regjsparser": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, "requires": { "jsesc": "0.5.0" }, @@ -7339,24 +7988,28 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true } } }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true }, "renderkid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "dev": true, "requires": { "css-select": "1.2.0", "dom-converter": "0.1.4", @@ -7368,24 +8021,28 @@ "utila": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true } } }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, "requires": { "is-finite": "1.0.2" } @@ -7399,12 +8056,14 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true }, "require-uncached": { "version": "1.0.3", @@ -7427,12 +8086,13 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", + "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -7442,6 +8102,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, "requires": { "resolve-from": "3.0.0" } @@ -7459,12 +8120,14 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "responselike": { "version": "1.0.2", @@ -7472,7 +8135,7 @@ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "dev": true, "requires": { - "lowercase-keys": "1.0.0" + "lowercase-keys": "1.0.1" } }, "restore-cursor": { @@ -7488,20 +8151,14 @@ "ret": { "version": "0.1.15", "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" - } + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, "requires": { "glob": "7.1.2" } @@ -7510,6 +8167,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, "requires": { "hash-base": "2.0.2", "inherits": "2.0.3" @@ -7524,6 +8182,15 @@ "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=", + "dev": true, + "requires": { + "aproba": "1.2.0" + } + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -7551,16 +8218,28 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, "requires": { "ret": "0.1.15" } }, + "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==", + "dev": true, + "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", @@ -7570,12 +8249,14 @@ "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true }, "selfsigned": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", + "dev": true, "requires": { "node-forge": "0.7.1" } @@ -7583,12 +8264,14 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -7605,10 +8288,17 @@ "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=", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, "requires": { "accepts": "1.3.5", "batch": "0.6.1", @@ -7623,6 +8313,7 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, "requires": { "encodeurl": "1.0.2", "escape-html": "1.0.3", @@ -7633,17 +8324,20 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, "requires": { "extend-shallow": "2.0.1", "is-extendable": "0.1.1", @@ -7655,6 +8349,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -7669,12 +8364,14 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true }, "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==", + "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -7684,6 +8381,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, "requires": { "shebang-regex": "1.0.0" } @@ -7691,7 +8389,8 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true }, "shelljs": { "version": "0.8.1", @@ -7707,12 +8406,14 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true }, "slice-ansi": { "version": "1.0.0", @@ -7741,6 +8442,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, "requires": { "base": "0.11.2", "debug": "2.6.9", @@ -7756,6 +8458,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -7764,6 +8467,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -7772,6 +8476,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -7780,6 +8485,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -7790,6 +8496,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -7798,6 +8505,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -7808,6 +8516,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -7817,7 +8526,8 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, @@ -7825,6 +8535,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, "requires": { "define-property": "1.0.0", "isobject": "3.0.1", @@ -7835,6 +8546,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -7845,6 +8557,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -7853,6 +8566,7 @@ "version": "0.3.19", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, "requires": { "faye-websocket": "0.10.0", "uuid": "3.2.1" @@ -7862,6 +8576,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "dev": true, "requires": { "debug": "2.6.9", "eventsource": "0.1.6", @@ -7875,6 +8590,7 @@ "version": "0.11.1", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, "requires": { "websocket-driver": "0.7.0" } @@ -7893,17 +8609,20 @@ "source-list-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==" + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "source-map-resolve": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, "requires": { "atob": "2.0.3", "decode-uri-component": "0.2.0", @@ -7916,6 +8635,7 @@ "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, "requires": { "source-map": "0.5.7" } @@ -7923,12 +8643,14 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.0" @@ -7937,12 +8659,14 @@ "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, "requires": { "spdx-exceptions": "2.1.0", "spdx-license-ids": "3.0.0" @@ -7951,25 +8675,28 @@ "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true }, "spdy": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, "requires": { "debug": "2.6.9", "handle-thing": "1.2.5", "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==", + "dev": true, "requires": { "debug": "2.6.9", "detect-node": "2.0.3", @@ -7984,6 +8711,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, "requires": { "extend-shallow": "3.0.2" } @@ -7994,10 +8722,20 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, "requires": { "define-property": "0.2.5", "object-copy": "0.1.0" @@ -8007,6 +8745,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -8015,6 +8754,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -8023,6 +8763,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8033,6 +8774,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -8041,6 +8783,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8051,6 +8794,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -8060,28 +8804,42 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, "requires": { "inherits": "2.0.3", "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==", + "dev": true, + "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", "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", + "dev": true, "requires": { "builtin-status-codes": "3.0.0", "inherits": "2.0.3", @@ -8090,6 +8848,12 @@ "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=", + "dev": true + }, "stream-to-observable": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.2.0.tgz", @@ -8115,6 +8879,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -8123,17 +8888,20 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, "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=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "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" } @@ -8144,6 +8912,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -8152,6 +8921,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -8159,7 +8929,8 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-bom-stream": { "version": "2.0.0", @@ -8185,12 +8956,14 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, "requires": { "get-stdin": "4.0.1" } @@ -8204,7 +8977,8 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true }, "symbol-observable": { "version": "1.0.1", @@ -8264,12 +9038,6 @@ "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", @@ -8282,9 +9050,10 @@ } }, "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==", + "dev": true }, "temp": { "version": "0.8.3", @@ -8335,12 +9104,8 @@ "thunky": { "version": "1.0.2", "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=" + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", + "dev": true }, "timed-out": { "version": "4.0.1", @@ -8352,6 +9117,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "dev": true, "requires": { "setimmediate": "1.0.5" } @@ -8368,17 +9134,20 @@ "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -8387,6 +9156,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, "requires": { "define-property": "2.0.2", "extend-shallow": "3.0.2", @@ -8398,6 +9168,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, "requires": { "is-number": "3.0.0", "repeat-string": "1.6.1" @@ -8406,22 +9177,26 @@ "toposort": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz", - "integrity": "sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw=" + "integrity": "sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw=", + "dev": true }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true }, "type-check": { "version": "0.3.2", @@ -8436,6 +9211,7 @@ "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "2.1.18" @@ -8452,43 +9228,52 @@ "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==", + "dev": true, "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==", + "dev": true + }, + "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 } } }, - "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==", + "dev": true, "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==", + "dev": true + } } }, "underscore": { @@ -8501,6 +9286,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, "requires": { "arr-union": "3.1.0", "get-value": "2.0.6", @@ -8512,6 +9298,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -8520,6 +9307,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, "requires": { "extend-shallow": "2.0.1", "is-extendable": "0.1.1", @@ -8529,15 +9317,35 @@ } } }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "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=", + "dev": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, "requires": { "has-value": "0.3.1", "isobject": "3.0.1" @@ -8547,6 +9355,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, "requires": { "get-value": "2.0.6", "has-values": "0.1.4", @@ -8557,6 +9366,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -8566,7 +9376,8 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true } } }, @@ -8579,22 +9390,26 @@ "upath": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", - "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==" + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", + "dev": true }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, "requires": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -8603,14 +9418,22 @@ "punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true } } }, + "url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", + "dev": true + }, "url-parse": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "dev": true, "requires": { "querystringify": "1.0.0", "requires-port": "1.0.0" @@ -8619,7 +9442,8 @@ "querystringify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true } } }, @@ -8642,6 +9466,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -8649,7 +9474,8 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -8657,6 +9483,7 @@ "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, "requires": { "inherits": "2.0.1" }, @@ -8664,19 +9491,22 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true } } }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, "requires": { "define-properties": "1.1.2", "object.getownpropertydescriptors": "2.0.3" @@ -8685,17 +9515,20 @@ "utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true }, "v8-compile-cache": { "version": "1.1.2", @@ -8707,6 +9540,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" @@ -8715,7 +9549,8 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true }, "vinyl": { "version": "1.2.0", @@ -8723,7 +9558,7 @@ "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" } @@ -8763,6 +9598,7 @@ "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, "requires": { "indexof": "0.0.1" } @@ -8771,8 +9607,9 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", + "dev": true, "requires": { - "chokidar": "2.0.2", + "chokidar": "2.0.3", "graceful-fs": "4.1.11", "neo-async": "2.5.0" } @@ -8781,47 +9618,36 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, "requires": { "minimalistic-assert": "1.0.0" } }, "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==", + "dev": true, "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": { @@ -8854,12 +9680,6 @@ "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 - }, "braces": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", @@ -8970,9 +9790,9 @@ } }, "webpack-cli": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.12.tgz", - "integrity": "sha512-kMi6NquWwUhmQok2IFrtAEIbaVvujzYvtDGb5WElkwylbLboDsCgizv8IjSi/Q6SQRJ8Crayl1JCBnIJ3rU4Rg==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.13.tgz", + "integrity": "sha512-0lnOi3yla8FsZVuMsbfnNRB/8DlfuDugKdekC+4ykydZG0+UOidMi5J5LLWN4c0VJ8PqC19yMXXkYyCq78OuqA==", "dev": true, "requires": { "chalk": "2.3.2", @@ -9058,23 +9878,6 @@ "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", @@ -9114,12 +9917,6 @@ "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", @@ -9152,33 +9949,38 @@ } }, "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==", + "dev": true, "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==", + "dev": true } } }, "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==", + "dev": true, "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,167 +10002,71 @@ "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", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "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==", + "dev": true, "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==", + "dev": true, + "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==", + "dev": true, "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==", + "dev": true, "requires": { - "is-utf8": "0.2.1" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" } }, "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" } - }, - "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" - } } } }, @@ -9368,6 +10074,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, "requires": { "source-list-map": "2.0.0", "source-map": "0.6.1" @@ -9376,7 +10083,8 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -9384,6 +10092,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, "requires": { "http-parser-js": "0.4.11", "websocket-extensions": "0.1.3" @@ -9392,7 +10101,8 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true }, "whatwg-fetch": { "version": "2.0.3", @@ -9403,6 +10113,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, "requires": { "isexe": "2.0.0" } @@ -9410,22 +10121,29 @@ "which-module": { "version": "2.0.0", "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=" + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "errno": "0.1.7" + } }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" @@ -9435,6 +10153,7 @@ "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", @@ -9446,7 +10165,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write": { "version": "0.2.1", @@ -9471,27 +10191,32 @@ "xml-char-classes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", - "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=" + "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", + "dev": true }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, "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=", + "dev": true, "requires": { "camelcase": "4.1.0", "cliui": "3.2.0", @@ -9511,28 +10236,55 @@ "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true }, - "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=", + "dev": true, "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=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "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=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" } } } @@ -9541,6 +10293,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, "requires": { "camelcase": "4.1.0" }, @@ -9548,7 +10301,8 @@ "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true } } }, @@ -9602,12 +10356,6 @@ "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", @@ -9661,6 +10409,15 @@ "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==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, "chalk": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", @@ -9681,12 +10438,6 @@ "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", diff --git a/daemon/web/package.json b/daemon/web/package.json index 1afcaaf0..3126bd30 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -7,25 +7,26 @@ "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", "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-preset-es2015": "^6.24.1", - "babel-preset-react": "^6.24.1", - "html-webpack-plugin": "^3.0.6", "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" + "react-dom": "^16.2.0" }, "devDependencies": { - "eslint": "^4.16.0", + "babel-core": "^6.26.0", + "babel-loader": "^7.1.4", + "babel-minify-webpack-plugin": "^0.3.1", + "babel-preset-es2015": "^6.24.1", + "babel-preset-react": "^6.24.1", + "babel-preset-stage-3": "^6.24.1", + "eslint": "^4.19.1", "eslint-plugin-react": "^7.6.0", - "webpack-cli": "^2.0.10" + "html-webpack-plugin": "^3.1.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..7db8e0ec 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -1,14 +1,9 @@ /* 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 = { + mode: 'development', entry: './index.js', output: { path: `${__dirname}/public/`, @@ -22,21 +17,34 @@ const config = { }, devtool: 'inline-source-map', module: { - loaders: [ + rules: [ { test: /\.jsx?$/, exclude: '/node_modules/', - loader: 'babel-loader', - query: { - presets: ['es2015', 'react'], - }, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react'], + }, + } + ], }, ], }, plugins: [ new webpack.EnvironmentPlugin(['NODE_ENV']), - HtmlWebpackPluginConfig, + new webpack.HotModuleReplacementPlugin(), + 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..8ff28367 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -6,23 +6,28 @@ const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({ template: './index.html', filename: 'index.html', inject: 'body', -}) +}); const config = { + mode: 'production', entry: './index.js', output: { path: `${__dirname}/public/`, filename: 'bundle.js', }, module: { - loaders: [ + rules: [ { test: /\.jsx?$/, exclude: '/node_modules/', - loader: 'babel-loader', - query: { - presets: ['es2015', 'react'], - }, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react'], + }, + } + ], }, ], }, @@ -33,4 +38,4 @@ const config = { ] }; -module.exports = env => config; +module.exports = config; From 990920c9f7ef23c67b31711a3a2e373942687496 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 15:50:30 -0700 Subject: [PATCH 19/73] In-memory session tracking, improved permissions API --- daemon/inertia/auth/permissions.go | 71 +++++++++---- daemon/inertia/auth/users.go | 163 +++++++++++------------------ daemon/inertia/auth/users_test.go | 8 +- 3 files changed, 112 insertions(+), 130 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 708c1530..81d150f0 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -19,6 +19,7 @@ type PermissionsHandler struct { mux *http.ServeMux denyHandler http.Handler publicPaths []string + adminPaths []string } // NewPermissionsHandler returns a new handler for authenticating @@ -51,34 +52,63 @@ func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*Permis } // Close releases resources held by the PermissionsHandler -func (handler *PermissionsHandler) Close() error { - return handler.users.Close() +func (h *PermissionsHandler) Close() error { + return h.users.Close() } // Implement the ServeHTTP method to make a permissionHandler a http.Handler -func (handler *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // Check if the user has the right admin/user rights +func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Check if path is public + // @todo + + // Check if session and user is valid + s, err := h.users.GetSession(w, r) + if err != nil { + if err == errSessionNotFound { + http.Error(w, err.Error(), http.StatusForbidden) + } else { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + return + } + err = h.users.HasUser(s.Username) + if err != nil { + if err == errUserNotFound { + http.Error(w, err.Error(), http.StatusForbidden) + } else { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + return + } + + // Check if user has sufficient permissions for path + // @todo // Serve the requested page if permissions were granted - handler.mux.ServeHTTP(w, r) + 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.publicPaths = append(h.publicPaths, path) + // @todo + h.mux.Handle(path, handler) } // AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. -func (handler *PermissionsHandler) AttachUserRestrictedHandler(path string, h http.Handler) { - handler.publicPaths = append(handler.publicPaths, path) +func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.Handler) { // @todo - handler.mux.Handle(path, h) + h.mux.Handle(path, handler) } // AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. -func (handler *PermissionsHandler) AttachAdminRestrictedHandler(path string, h http.Handler) { +func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.Handler) { + h.adminPaths = append(h.publicPaths, path) // @todo - handler.mux.Handle(path, h) + h.mux.Handle(path, handler) } -// User Administration Endpoint Handlers - -func (handler *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { +func (h *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -94,7 +124,7 @@ func (handler *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http } // Add user (as admin if specified) - err = handler.users.AddUser(userReq.Username, userReq.Password, userReq.Admin) + err = h.users.AddUser(userReq.Username, userReq.Password, userReq.Admin) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -105,7 +135,7 @@ func (handler *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http fmt.Fprintf(w, "[SUCCESS %d] User %s added!\n", http.StatusCreated, userReq.Username) } -func (handler *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Request) { +func (h *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -121,7 +151,7 @@ func (handler *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *h } // Remove user - err = handler.users.RemoveUser(userReq.Username) + err = h.users.RemoveUser(userReq.Username) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -132,7 +162,7 @@ func (handler *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *h fmt.Fprintf(w, "[SUCCESS %d] User %s removed\n", http.StatusOK, userReq.Username) } -func (handler *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { +func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -148,19 +178,16 @@ func (handler *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.R } // Log in user if password is correct - correct, err := handler.users.IsCorrectCredentials(userReq.Username, userReq.Password) + 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) - } - err = handler.users.SessionBegin(userReq.Username, w, r) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) return } + h.users.SessionBegin(userReq.Username, w, r) w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 40459153..6820c5d7 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -22,9 +22,9 @@ type userProps struct { Admin bool `json:"admin"` } -// sessionProps are properties associated with session, +// session are properties associated with session, // used for database entries -type sessionProps struct { +type session struct { Username string `json:"username"` Expires time.Time `json:"created"` } @@ -34,21 +34,23 @@ type userManager struct { cookieName string cookieTimeout int64 - // bolt.DB is an embedded key/value database, - // where each "bucket" is a collection - db *bolt.DB - usersBucket []byte - sessionsBucket []byte + // db is a boltdb database, which is an embedded + // key/value database where each "bucket" is a collection + db *bolt.DB + usersBucket []byte + // sessions is a map of active user sessions + sessions map[string]*session endSessionCleanup chan bool } func newUserManager(dbPath string, timeout int64) (*userManager, error) { manager := &userManager{ - cookieName: "ubclaunchpad/inertia", - cookieTimeout: timeout, - usersBucket: []byte("users"), - sessionsBucket: []byte("sessions"), + cookieName: "ubclaunchpad/inertia", + cookieTimeout: timeout, + usersBucket: []byte("users"), + sessions: make(map[string]*session), + endSessionCleanup: make(chan bool), } // Set up database @@ -58,20 +60,9 @@ func newUserManager(dbPath string, timeout int64) (*userManager, error) { } err = db.Update(func(tx *bolt.Tx) error { _, err = tx.CreateBucketIfNotExists(manager.usersBucket) - if err != nil { - return err - } - - _, err = tx.CreateBucketIfNotExists(manager.sessionsBucket) - if err != nil { - return err - } - - return nil + return err }) manager.db = db - - manager.endSessionCleanup = make(chan bool) go manager.cleanSessions() return manager, nil @@ -82,8 +73,6 @@ func (m *userManager) Close() error { return m.db.Close() } -// User Administration Functions - func (m *userManager) AddUser(username, password string, admin bool) error { err := validateCredentialValues(username, password) if err != nil { @@ -111,9 +100,7 @@ func (m *userManager) RemoveUser(username string) error { }) } -// User Checks - -func (m *userManager) HasUser(username string) (bool, error) { +func (m *userManager) HasUser(username string) error { found := false err := m.db.View(func(tx *bolt.Tx) error { users := tx.Bucket(m.usersBucket) @@ -124,9 +111,12 @@ func (m *userManager) HasUser(username string) (bool, error) { return nil }) if err != nil { - return true, err + return err } - return found, nil + if !found { + return errUserNotFound + } + return nil } func (m *userManager) IsCorrectCredentials(username, password string) (bool, error) { @@ -135,7 +125,7 @@ func (m *userManager) IsCorrectCredentials(username, password string) (bool, err users := tx.Bucket(m.usersBucket) propsBytes := users.Get([]byte(username)) if propsBytes == nil { - return errors.New("User not found") + return errUserNotFound } props := &userProps{} @@ -167,17 +157,19 @@ func (m *userManager) IsAdmin(username string) (bool, error) { return admin, err } -// Session Management - -func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *http.Request) error { +// SessionBegin starts and returns a new session or returns an existing session +func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(m.cookieName) + if err != nil || cookie.Value == "" { - id := generateSessionID() + // Create new session and cookie if no cookie yet expiration := time.Now().Add(time.Duration(m.cookieTimeout) * time.Minute) - err := m.addSession(id, username, expiration) - if err != nil { - return err + s := &session{ + Username: username, + Expires: expiration, } + id := generateSessionID() + m.sessions[id] = s cookie := http.Cookie{ Name: m.cookieName, Value: url.QueryEscape(id), @@ -186,16 +178,24 @@ func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *ht HttpOnly: true, } http.SetCookie(w, &cookie) + } else { + // Otherwise, end existing session and begin a new one + m.SessionEnd(w, r) + m.SessionBegin(username, w, r) } - return nil } +// SessionEnd ends a session and sets cookie to expire func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { return } - m.removeSession(cookie.Value) + id, err := url.QueryUnescape(cookie.Value) + if err != nil { + return + } + delete(m.sessions, id) expiration := time.Now() newCookie := http.Cookie{ Name: m.cookieName, @@ -207,58 +207,29 @@ func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, &newCookie) } -func (m *userManager) SessionCheck(w http.ResponseWriter, r *http.Request) (bool, error) { +// GetSession verifies if given request is from a valid session and returns it +func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*session, error) { cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { - return false, err + return nil, err } - s, err := m.getSession(cookie.Value) + id, err := url.QueryUnescape(cookie.Value) if err != nil { - return false, err + return nil, err } - return m.isValidSession(s), nil -} - -// Session Helpers - -func (m *userManager) removeSession(id string) error { - return m.db.Update(func(tx *bolt.Tx) error { - sessions := tx.Bucket(m.sessionsBucket) - return sessions.Delete([]byte(id)) - }) -} - -func (m *userManager) addSession(id, username string, expires time.Time) error { - props := sessionProps{Username: username, Expires: expires} - return m.db.Update(func(tx *bolt.Tx) error { - sessions := tx.Bucket(m.sessionsBucket) - bytes, err := json.Marshal(props) - if err != nil { - return err - } - return sessions.Put([]byte(id), bytes) - }) -} - -func (m *userManager) getSession(id string) (*sessionProps, error) { - props := &sessionProps{} - err := m.db.View(func(tx *bolt.Tx) error { - users := tx.Bucket(m.sessionsBucket) - propsBytes := users.Get([]byte(id)) - if propsBytes != nil { - err := json.Unmarshal(propsBytes, props) - if err != nil { - return errors.New("Corrupt session properties: " + err.Error()) - } - } else { - return errSessionNotFound - } - return nil - }) - return props, err + s, found := m.sessions[id] + if !found { + return nil, errSessionNotFound + } + if !m.isValidSession(s) { + m.SessionEnd(w, r) + return nil, errSessionNotFound + } + return s, nil } -func (m *userManager) isValidSession(s *sessionProps) bool { +// isValidSession checks if session is expired +func (m *userManager) isValidSession(s *session) bool { return s.Expires.Before(time.Now()) } @@ -269,25 +240,11 @@ func (m *userManager) cleanSessions() { case <-m.endSessionCleanup: return default: - m.db.Update(func(tx *bolt.Tx) error { - sessions := tx.Bucket(m.sessionsBucket) - c := sessions.Cursor() - for k, v := c.First(); k != nil; k, v = c.Next() { - s := &sessionProps{} - err := json.Unmarshal(v, s) - if err != nil { - println(err) - continue - } - if !m.isValidSession(s) { - err = sessions.Delete(k) - if err != nil { - println(err) - } - } + for id, s := range m.sessions { + if !m.isValidSession(s) { + delete(m.sessions, id) } - return nil - }) + } time.AfterFunc( time.Duration(m.cookieTimeout)*time.Minute, func() { m.cleanSessions() }, diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index 62ab805f..f8d3f36d 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -42,16 +42,14 @@ func TestAddDeleteAndHasUser(t *testing.T) { err = manager.AddUser("bobheadxi", "best_person_ever", true) assert.Nil(t, err) - found, err := manager.HasUser("bobheadxi") + err = manager.HasUser("bobheadxi") assert.Nil(t, err) - assert.True(t, found) err = manager.RemoveUser("bobheadxi") assert.Nil(t, err) - found, err = manager.HasUser("bobheadxi") - assert.Nil(t, err) - assert.False(t, found) + err = manager.HasUser("bobheadxi") + assert.Equal(t, errUserNotFound, err) } func TestIsAdmin(t *testing.T) { From ac3d349fe1f53efa8d9276fd2f78cabe03255308 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 17:00:58 -0700 Subject: [PATCH 20/73] Tidy up path restriction, remove explicit denyHandler --- daemon/inertia/auth/permissions.go | 51 ++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 81d150f0..0cbf41f3 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "net/http" + "strings" "github.com/ubclaunchpad/inertia/common" ) @@ -17,14 +18,13 @@ const UserDatabasePath = "/app/host/.inertia/users.db" type PermissionsHandler struct { users *userManager mux *http.ServeMux - denyHandler http.Handler publicPaths []string adminPaths []string } // NewPermissionsHandler returns a new handler for authenticating // users and handling user administration -func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*PermissionsHandler, error) { +func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { // Set up user manager userManager, err := newUserManager(dbPath, 120) if err != nil { @@ -34,20 +34,20 @@ func NewPermissionsHandler(dbPath string, denyHandler http.HandlerFunc) (*Permis // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ - users: userManager, - mux: mux, - denyHandler: denyHandler, + users: userManager, + mux: mux, + adminPaths: make([]string, 0), } + // Set paths that don't require authentication. + handler.publicPaths = []string{"/login", "/adduser", "/removeuser"} + mux.HandleFunc("/login", handler.loginHandler) + // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. - handler.publicPaths = []string{"/adduser", "/removeuser"} mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) - // The following endpoints require no prior authentication. - mux.HandleFunc("/login", handler.loginHandler) - return handler, nil } @@ -58,10 +58,16 @@ func (h *PermissionsHandler) Close() error { // Implement the ServeHTTP method to make a permissionHandler a http.Handler func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // Check if path is public - // @todo + path := r.URL.Path + + // Serve if path is public + for _, prefix := range h.publicPaths { + if strings.HasPrefix(path, prefix) { + h.mux.ServeHTTP(w, r) + } + } - // Check if session and user is valid + // Check if session is valid s, err := h.users.GetSession(w, r) if err != nil { if err == errSessionNotFound { @@ -71,6 +77,8 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } return } + + // Check if user is valid err = h.users.HasUser(s.Username) if err != nil { if err == errUserNotFound { @@ -82,7 +90,18 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // Check if user has sufficient permissions for path - // @todo + for _, prefix := range h.adminPaths { + if strings.HasPrefix(path, prefix) { + admin, err := h.users.IsAdmin(s.Username) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + if !admin { + http.Error(w, err.Error(), http.StatusForbidden) + } + return + } + } // Serve the requested page if permissions were granted h.mux.ServeHTTP(w, r) @@ -90,21 +109,21 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // AttachPublicHandler attaches given path and handler and makes it publicly available func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.Handler) { + // Add path as exception to user restriction h.publicPaths = append(h.publicPaths, path) - // @todo h.mux.Handle(path, handler) } // AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.Handler) { - // @todo + // By default, all paths are user restricted h.mux.Handle(path, handler) } // AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.Handler) { + // Add path as one that requires elevated permissions h.adminPaths = append(h.publicPaths, path) - // @todo h.mux.Handle(path, handler) } From 6a513f574d6246c7da4e0d3806a4433972dc76c8 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 17:17:25 -0700 Subject: [PATCH 21/73] Add users reset command to remove all users and end all sessions --- client/deployment.go | 9 +++++-- daemon/inertia/auth/permissions.go | 22 ++++++++++++++-- daemon/inertia/auth/users.go | 30 ++++++++++++++++++++++ deployment.go | 2 ++ deployment_users.go | 41 +++++++++++++++++++++++++++--- 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/client/deployment.go b/client/deployment.go index b36fa007..ce33f53f 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -19,7 +19,7 @@ type Deployment struct { *RemoteVPS Repository *git.Repository Auth string - Project string + Project string } // GetDeployment returns the local deployment setup @@ -58,7 +58,7 @@ func (d *Deployment) Up(project string, stream bool) (*http.Response, error) { } reqContent := &common.DaemonRequest{ - Stream: stream, + Stream: stream, Project: project, GitOptions: &common.GitOptions{ RemoteURL: common.GetSSHRemoteURL(origin.Config().URLs[0]), @@ -110,6 +110,11 @@ func (d *Deployment) RemoveUser(username string) (*http.Response, error) { return d.request("/web/removeuser", "POST", reqContent) } +// ResetUsers resets all users on the remote. +func (d *Deployment) ResetUsers() (*http.Response, error) { + return d.request("/web/resetusers", "POST", nil) +} + func (d *Deployment) request(endpoint, method string, requestBody interface{}) (*http.Response, error) { // Assemble URL url, err := url.Parse("https://" + d.RemoteVPS.GetIPAndPort()) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 0cbf41f3..605aa8b5 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -39,14 +39,20 @@ func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { adminPaths: make([]string, 0), } - // Set paths that don't require authentication. - handler.publicPaths = []string{"/login", "/adduser", "/removeuser"} + // Set paths that don't require session authentication. + handler.publicPaths = []string{ + "/login", + "/adduser", + "/removeuser", + "/resetusers", + } mux.HandleFunc("/login", handler.loginHandler) // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) + mux.HandleFunc("/resetusers", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) return handler, nil } @@ -181,6 +187,18 @@ func (h *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Re fmt.Fprintf(w, "[SUCCESS %d] User %s removed\n", http.StatusOK, userReq.Username) } +func (h *PermissionsHandler) resetUsersHandler(w http.ResponseWriter, r *http.Request) { + err := h.users.Reset() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + 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) loginHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 6820c5d7..862f8c6d 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -68,11 +68,26 @@ func newUserManager(dbPath string, timeout int64) (*userManager, error) { return manager, nil } +// Close ends the session cleanup job and releases the DB handler func (m *userManager) Close() error { m.endSessionCleanup <- true return m.db.Close() } +// Reset deletes all users and drops all active sessions +func (m *userManager) Reset() error { + m.sessions = make(map[string]*session) + 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 { @@ -93,13 +108,16 @@ func (m *userManager) AddUser(username, password string, admin bool) error { }) } +// RemoveUser removes user with given username and ends related sessions func (m *userManager) RemoveUser(username string) error { + m.endAllUserSessions(username) return m.db.Update(func(tx *bolt.Tx) error { users := tx.Bucket(m.usersBucket) return users.Delete([]byte(username)) }) } +// 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 { @@ -119,6 +137,8 @@ func (m *userManager) HasUser(username string) error { 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 err := m.db.View(func(tx *bolt.Tx) error { @@ -139,6 +159,7 @@ func (m *userManager) IsCorrectCredentials(username, password string) (bool, err return correct, err } +// 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 { @@ -228,6 +249,15 @@ func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*sessi return s, nil } +// endAllUserSessions removes all active sessions with given user +func (m *userManager) endAllUserSessions(username string) { + for id, s := range m.sessions { + if s.Username == username { + delete(m.sessions, id) + } + } +} + // isValidSession checks if session is expired func (m *userManager) isValidSession(s *session) bool { return s.Expires.Before(time.Now()) diff --git a/deployment.go b/deployment.go index 1f4fbc54..3395c63f 100644 --- a/deployment.go +++ b/deployment.go @@ -329,8 +329,10 @@ Run 'inertia [REMOTE] init' to gather this information.`, adduser := deepCopy(deploymentUserAddCmd) adduser.Flags().Bool("admin", false, "Create an admin user") removeuser := deepCopy(deploymentUserRemoveCmd) + resetusers := deepCopy(deploymentUsersResetCmd) user.AddCommand(adduser) user.AddCommand(removeuser) + user.AddCommand(resetusers) cmd.AddCommand(user) ssh := deepCopy(deploymentSSHCmd) diff --git a/deployment_users.go b/deployment_users.go index 873ab3fa..80cc4f31 100644 --- a/deployment_users.go +++ b/deployment_users.go @@ -63,8 +63,6 @@ Use the --admin flag to create an admin user.`, 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) - case http.StatusPreconditionFailed: - fmt.Printf("(Status code %d) Problem with deployment setup:\n%s\n", resp.StatusCode, body) default: fmt.Printf("(Status code %d) Unknown response from daemon:\n%s\n", resp.StatusCode, body) @@ -103,8 +101,43 @@ deployment from the web app.`, 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) - case http.StatusPreconditionFailed: - fmt.Printf("(Status code %d) Problem with deployment setup:\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) From c396d1411ec863e0f2c2d6a6baaff1bed74f77df Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 18:22:13 -0700 Subject: [PATCH 22/73] Move decorator test to separate file --- daemon/inertia/auth/auth_test.go | 59 ----------------------- daemon/inertia/auth/decorator_test.go | 69 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 59 deletions(-) create mode 100644 daemon/inertia/auth/decorator_test.go diff --git a/daemon/inertia/auth/auth_test.go b/daemon/inertia/auth/auth_test.go index 5f141081..54eb7e53 100644 --- a/daemon/inertia/auth/auth_test.go +++ b/daemon/inertia/auth/auth_test.go @@ -3,7 +3,6 @@ package auth import ( "fmt" "net/http" - "net/http/httptest" "os" "path" "testing" @@ -32,64 +31,6 @@ func TestGenerateToken(t *testing.T) { 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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusOK) - assert.Equal(t, rr.Body.String(), common.DaemonOkResp) -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) - assert.Equal(t, rr.Body.String(), malformedAuthStringErrorMsg+"\n") -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) -} - func TestGetGithubKey(t *testing.T) { inertiaKeyPath := path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test_env/test_key") pemFile, err := os.Open(inertiaKeyPath) diff --git a/daemon/inertia/auth/decorator_test.go b/daemon/inertia/auth/decorator_test.go new file mode 100644 index 00000000..35ae5318 --- /dev/null +++ b/daemon/inertia/auth/decorator_test.go @@ -0,0 +1,69 @@ +package auth + +import ( + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/ubclaunchpad/inertia/common" +) + +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(testHealthCheckHandler, getFakeAPIKey)) + handler.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusOK) + assert.Equal(t, rr.Body.String(), common.DaemonOkResp) +} + +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(testHealthCheckHandler, getFakeAPIKey)) + handler.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusForbidden) + assert.Equal(t, rr.Body.String(), malformedAuthStringErrorMsg+"\n") +} + +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(testHealthCheckHandler, getFakeAPIKey)) + handler.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusForbidden) +} + +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(testHealthCheckHandler, getFakeAPIKey)) + handler.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusForbidden) +} From c2f5b44c59a46f83576c1156077d35c9411d0989 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 19:20:44 -0700 Subject: [PATCH 23/73] Update cookie configuration and session flow, add tests * More flexible PermissionsHandler configuration * Tests, tests, tests * Various fixes to bad ideas --- daemon/inertia/auth/permissions.go | 10 +- daemon/inertia/auth/permissions_test.go | 199 +++++++++++++++++++++++- daemon/inertia/auth/users.go | 60 ++++--- daemon/inertia/auth/users_test.go | 20 +-- daemon/inertia/daemon.go | 16 +- 5 files changed, 249 insertions(+), 56 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 605aa8b5..24eede96 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -16,6 +16,7 @@ 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 mux *http.ServeMux publicPaths []string @@ -24,9 +25,9 @@ type PermissionsHandler struct { // NewPermissionsHandler returns a new handler for authenticating // users and handling user administration -func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { +func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*PermissionsHandler, error) { // Set up user manager - userManager, err := newUserManager(dbPath, 120) + userManager, err := newUserManager(dbPath, domain, path, timeout) if err != nil { return nil, err } @@ -34,6 +35,7 @@ func NewPermissionsHandler(dbPath string) (*PermissionsHandler, error) { // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ + domain: domain, users: userManager, mux: mux, adminPaths: make([]string, 0), @@ -70,6 +72,7 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { for _, prefix := range h.publicPaths { if strings.HasPrefix(path, prefix) { h.mux.ServeHTTP(w, r) + return } } @@ -103,7 +106,7 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) } if !admin { - http.Error(w, err.Error(), http.StatusForbidden) + http.Error(w, "Admin privileges required", http.StatusForbidden) } return } @@ -226,7 +229,6 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request } h.users.SessionBegin(userReq.Username, w, r) - w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "[SUCCESS %d] User %s logged in\n", http.StatusOK, userReq.Username) } diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 51e875c4..1719414c 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -1,18 +1,209 @@ package auth import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" "os" + "path" "testing" + "github.com/ubclaunchpad/inertia/common" + "github.com/stretchr/testify/assert" ) -func TestPermissionsHandlerConstructor(t *testing.T) { - dir := "./test" +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) +} + +func TestServeHTTPPublicPath(t *testing.T) { + dir := "./test" + 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.AttachPublicHandler("/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" + 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.AttachUserRestrictedHandler("/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 TestServeHTTPWithUserLoginAndAccept(t *testing.T) { + dir := "./test" + 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.AttachUserRestrictedHandler("/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+"/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" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + ph, err := getTestPermissionsHandler(dir) defer os.RemoveAll(dir) - ph, err := NewPermissionsHandler("./test/users.db", nil) assert.Nil(t, err) - assert.NotNil(t, ph) + defer ph.Close() + ts.Config.Handler = ph + ph.AttachAdminRestrictedHandler("/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+"/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" + 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.AttachAdminRestrictedHandler("/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+"/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) } diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 862f8c6d..b448684f 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -12,6 +12,7 @@ import ( var ( errSessionNotFound = errors.New("Session not found") + errCookieNotFound = errors.New("Cookie not found") errUserNotFound = errors.New("User not found") ) @@ -32,7 +33,9 @@ type session struct { // userManager administers sessions and user accounts type userManager struct { cookieName string - cookieTimeout int64 + cookieDomain string + cookiePath string + cookieTimeout time.Duration // db is a boltdb database, which is an embedded // key/value database where each "bucket" is a collection @@ -44,10 +47,12 @@ type userManager struct { endSessionCleanup chan bool } -func newUserManager(dbPath string, timeout int64) (*userManager, error) { +func newUserManager(dbPath, domain, path string, timeout int) (*userManager, error) { manager := &userManager{ - cookieName: "ubclaunchpad/inertia", - cookieTimeout: timeout, + cookieName: "ubclaunchpad-inertia", + cookieDomain: domain, + cookiePath: path, + cookieTimeout: time.Duration(timeout) * time.Minute, usersBucket: []byte("users"), sessions: make(map[string]*session), endSessionCleanup: make(chan bool), @@ -178,32 +183,24 @@ func (m *userManager) IsAdmin(username string) (bool, error) { return admin, err } -// SessionBegin starts and returns a new session or returns an existing session +// SessionBegin starts a new session with user by setting a cookie +// and adding session to memory func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *http.Request) { - cookie, err := r.Cookie(m.cookieName) - - if err != nil || cookie.Value == "" { - // Create new session and cookie if no cookie yet - expiration := time.Now().Add(time.Duration(m.cookieTimeout) * time.Minute) - s := &session{ - Username: username, - Expires: expiration, - } - id := generateSessionID() - m.sessions[id] = s - cookie := http.Cookie{ - Name: m.cookieName, - Value: url.QueryEscape(id), - Path: "/web", - Expires: expiration, - HttpOnly: true, - } - http.SetCookie(w, &cookie) - } else { - // Otherwise, end existing session and begin a new one - m.SessionEnd(w, r) - m.SessionBegin(username, w, r) + expiration := time.Now().Add(m.cookieTimeout) + id := generateSessionID() + s := &session{ + Username: username, + Expires: expiration, } + m.sessions[id] = s + http.SetCookie(w, &http.Cookie{ + Name: m.cookieName, + Value: url.QueryEscape(id), + Domain: m.cookieDomain, + Path: m.cookiePath, + HttpOnly: true, + Expires: expiration, + }) } // SessionEnd ends a session and sets cookie to expire @@ -220,7 +217,8 @@ func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { expiration := time.Now() newCookie := http.Cookie{ Name: m.cookieName, - Path: "/web", + Domain: m.cookieDomain, + Path: m.cookiePath, HttpOnly: true, Expires: expiration, MaxAge: -1, @@ -232,7 +230,7 @@ func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*session, error) { cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { - return nil, err + return nil, errSessionNotFound } id, err := url.QueryUnescape(cookie.Value) if err != nil { @@ -260,7 +258,7 @@ func (m *userManager) endAllUserSessions(username string) { // isValidSession checks if session is expired func (m *userManager) isValidSession(s *session) bool { - return s.Expires.Before(time.Now()) + return s.Expires.After(time.Now()) } // cleanSessions is a goroutine that continously cleans sessions diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index f8d3f36d..dc214f68 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -7,12 +7,18 @@ import ( "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("./test/test.db", "0.0.0.0", "/", 120) +} + func TestAddUserAndIsCorrectCredentials(t *testing.T) { dir := "./test" - err := os.Mkdir(dir, os.ModePerm) - assert.Nil(t, err) + manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) - manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) defer manager.Close() assert.NotNil(t, manager) @@ -31,10 +37,8 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { func TestAddDeleteAndHasUser(t *testing.T) { dir := "./test" - err := os.Mkdir(dir, os.ModePerm) - assert.Nil(t, err) + manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) - manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) defer manager.Close() assert.NotNil(t, manager) @@ -54,10 +58,8 @@ func TestAddDeleteAndHasUser(t *testing.T) { func TestIsAdmin(t *testing.T) { dir := "./test" - err := os.Mkdir(dir, os.ModePerm) - assert.Nil(t, err) + manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) - manager, err := newUserManager("./test/test.db", 120) assert.Nil(t, err) defer manager.Close() assert.NotNil(t, manager) diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 762a518a..c691ddee 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -68,14 +68,19 @@ func run(host, port, version string) { // Inertia web - PermissionsHandler is used to authenticate web // app access and manage users - permHandler, err := auth.NewPermissionsHandler(auth.UserDatabasePath, redirectToLogin) + webPrefix := "/web" + permHandler, err := auth.NewPermissionsHandler( + auth.UserDatabasePath, host, webPrefix, 120, + ) if err != nil { println(err.Error()) return } defer permHandler.Close() - permHandler.AttachUserRestrictedHandler("/", http.FileServer(http.Dir("/app/inertia-web"))) - mux.Handle("/web/", http.StripPrefix("/web", permHandler)) + permHandler.AttachUserRestrictedHandler( + "/", http.FileServer(http.Dir("/app/inertia-web")), + ) + mux.Handle(webPrefix, http.StripPrefix(webPrefix, permHandler)) // CLI API endpoints mux.HandleFunc("/up", auth.Authorized(upHandler, auth.GetAPIPrivateKey)) @@ -93,8 +98,3 @@ func run(host, port, version string) { mux, )) } - -func redirectToLogin(w http.ResponseWriter, r *http.Request) { - // @todo: direct to login page - http.Error(w, "Permission denied!", http.StatusForbidden) -} From 333bd5a642d22b5adc41bc16363c6241adf0facc Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 24 Mar 2018 19:31:38 -0700 Subject: [PATCH 24/73] Correct resetusers handler, check for cookie --- daemon/inertia/auth/permissions.go | 4 ++-- daemon/inertia/auth/users.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 24eede96..af03b60f 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -54,7 +54,7 @@ func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*Permissio // be used from the CLI and delivered with the daemon token. mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) - mux.HandleFunc("/resetusers", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) + mux.HandleFunc("/resetusers", Authorized(handler.resetUsersHandler, GetAPIPrivateKey)) return handler, nil } @@ -79,7 +79,7 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check if session is valid s, err := h.users.GetSession(w, r) if err != nil { - if err == errSessionNotFound { + if err == errSessionNotFound || err == errCookieNotFound { http.Error(w, err.Error(), http.StatusForbidden) } else { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index b448684f..6629651b 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -230,7 +230,7 @@ func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*session, error) { cookie, err := r.Cookie(m.cookieName) if err != nil || cookie.Value == "" { - return nil, errSessionNotFound + return nil, errCookieNotFound } id, err := url.QueryUnescape(cookie.Value) if err != nil { From 82657991b2f86448310f3801a0aab8de18ff5440 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 09:24:40 -0700 Subject: [PATCH 25/73] Fix strange infinite loop in cleanSessions * time.Duration(time.Duration*time.minute)*time.Minute seems to clock incorrectly, causing the cleanSessions goroutine to loop inifinitely and lock up the tests * Made test dir paths different just in case --- daemon/inertia/auth/permissions_test.go | 10 +++++----- daemon/inertia/auth/users.go | 5 +---- daemon/inertia/auth/users_test.go | 12 +++++------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 1719414c..350014d4 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -23,7 +23,7 @@ func getTestPermissionsHandler(dir string) (*PermissionsHandler, error) { } func TestServeHTTPPublicPath(t *testing.T) { - dir := "./test" + dir := "./test_perm" ts := httptest.NewServer(nil) defer ts.Close() @@ -47,7 +47,7 @@ func TestServeHTTPPublicPath(t *testing.T) { } func TestServeHTTPWithUserReject(t *testing.T) { - dir := "./test" + dir := "./test_perm" ts := httptest.NewServer(nil) defer ts.Close() @@ -71,7 +71,7 @@ func TestServeHTTPWithUserReject(t *testing.T) { } func TestServeHTTPWithUserLoginAndAccept(t *testing.T) { - dir := "./test" + dir := "./test_perm" ts := httptest.NewServer(nil) defer ts.Close() @@ -117,7 +117,7 @@ func TestServeHTTPWithUserLoginAndAccept(t *testing.T) { } func TestServeHTTPDenyNonAdmin(t *testing.T) { - dir := "./test" + dir := "./test_perm" ts := httptest.NewServer(nil) defer ts.Close() @@ -163,7 +163,7 @@ func TestServeHTTPDenyNonAdmin(t *testing.T) { } func TestServeHTTPAllowAdmin(t *testing.T) { - dir := "./test" + dir := "./test_perm" ts := httptest.NewServer(nil) defer ts.Close() diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 6629651b..2b842210 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -273,10 +273,7 @@ func (m *userManager) cleanSessions() { delete(m.sessions, id) } } - time.AfterFunc( - time.Duration(m.cookieTimeout)*time.Minute, - func() { m.cleanSessions() }, - ) + time.AfterFunc(m.cookieTimeout, func() { m.cleanSessions() }) } } } diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index dc214f68..425eaa91 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -2,6 +2,7 @@ package auth import ( "os" + "path" "testing" "github.com/stretchr/testify/assert" @@ -12,16 +13,15 @@ func getTestUserManager(dir string) (*userManager, error) { if err != nil { return nil, err } - return newUserManager("./test/test.db", "0.0.0.0", "/", 120) + return newUserManager(path.Join(dir, "users.db"), "127.0.0.1", "/", 120) } func TestAddUserAndIsCorrectCredentials(t *testing.T) { - dir := "./test" + dir := "./test_users" manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) assert.Nil(t, err) defer manager.Close() - assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) assert.Nil(t, err) @@ -36,12 +36,11 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { } func TestAddDeleteAndHasUser(t *testing.T) { - dir := "./test" + dir := "./test_users" manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) assert.Nil(t, err) defer manager.Close() - assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) assert.Nil(t, err) @@ -57,12 +56,11 @@ func TestAddDeleteAndHasUser(t *testing.T) { } func TestIsAdmin(t *testing.T) { - dir := "./test" + dir := "./test_users" manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) assert.Nil(t, err) defer manager.Close() - assert.NotNil(t, manager) err = manager.AddUser("bobheadxi", "best_person_ever", true) assert.Nil(t, err) From 8c39d06700848dbeac413ddc8caddde4ddd8931c Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 09:26:36 -0700 Subject: [PATCH 26/73] Method > Endpoint Swap method and endpoint parameters --- client/deployment.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/deployment.go b/client/deployment.go index ce33f53f..5b10970f 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -65,24 +65,24 @@ func (d *Deployment) Up(project string, stream bool) (*http.Response, error) { Branch: d.Branch, }, } - return d.request("/up", "POST", 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.request("/down", "POST", 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.request("/status", "GET", 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.request("/reset", "POST", nil) + return d.request("POST", "/reset", nil) } // Logs get logs of given container @@ -91,7 +91,7 @@ func (d *Deployment) Logs(stream bool, container string) (*http.Response, error) Stream: stream, Container: container, } - return d.request("/logs", "GET", reqContent) + return d.request("GET", "/logs", reqContent) } // AddUser adds an authorized user for access to Inertia Web @@ -101,21 +101,21 @@ func (d *Deployment) AddUser(username, password string, admin bool) (*http.Respo Password: password, Admin: admin, } - return d.request("/web/adduser", "POST", reqContent) + return d.request("POST", "/web/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("/web/removeuser", "POST", reqContent) + return d.request("POST", "/web/removeuser", reqContent) } // ResetUsers resets all users on the remote. func (d *Deployment) ResetUsers() (*http.Response, error) { - return d.request("/web/resetusers", "POST", nil) + return d.request("POST", "/web/resetusers", nil) } -func (d *Deployment) request(endpoint, method string, requestBody interface{}) (*http.Response, error) { +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 { From e75e1099e5e3f5ff6a81d244c872dd185004a26a Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 09:49:25 -0700 Subject: [PATCH 27/73] Update goveralls command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 072470bd..ba111223 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ script: - go vet ./... # Report suspicious constructs - megacheck ./... # Static analysis - gocyclo -over 19 $GO_FILES # Forbid code with huge functions - - goveralls -v -service=travis-ci -repotoken "$COVERALLS_TOKEN" + - goveralls -v -show -race -package=./... -service=travis-ci -repotoken "$COVERALLS_TOKEN" # Push version-tagged Docker image and build platform binaries before_deploy: From 063ef0815c33df659ed6e3724280bf39fe910136 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 10:18:37 -0700 Subject: [PATCH 28/73] Resolve session map race condition, fixed session cleanup * Turns out session cleanup was still looping infinitely, occasionally causing a race condition on the session map - switch to time.Ticker implementation * Protect sessions against race conditions (simultaneous session deletion + access) with x/sync.Map, an experimental native concurrent map implementation - see documentation: https://godoc.org/golang.org/x/sync/syncmap#Map.Store --- Gopkg.lock | 10 +++++- Gopkg.toml | 8 ++--- daemon/inertia/auth/users.go | 70 ++++++++++++++++++++---------------- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index d6b104a5..21f62c2a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -183,6 +183,8 @@ [[projects]] name = "golang.org/x/crypto" packages = [ + "bcrypt", + "blowfish", "cast5", "curve25519", "ed25519", @@ -212,6 +214,12 @@ ] revision = "d866cfc389cec985d6fda2859936a575a55a3ab6" +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = ["syncmap"] + revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" + [[projects]] branch = "master" name = "golang.org/x/sys" @@ -302,6 +310,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "327be67df8f02606e468ee931ddc33a045bf1422ccc9f3903acb143f3df39d39" + inputs-digest = "c5619a919aad6ebb7d08707dfc91e764d33cc622b05731d8e82c431eb93226b9" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index ed94db8b..f65f37de 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -26,10 +26,10 @@ name = "github.com/BurntSushi/toml" version = "0.3.0" -[[constraint]] - revision = "9de5f2eaf759b4c4550b3db39fed2e9e5f86f45c" - name = "golang.org/x/crypto" - [[constraint]] name = "github.com/boltdb/bolt" version = "1.3.1" + +[[constraint]] + branch = "master" + name = "golang.org/x/sync" diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 2b842210..0233dd13 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -8,6 +8,7 @@ import ( "time" "github.com/boltdb/bolt" + "golang.org/x/sync/syncmap" ) var ( @@ -43,7 +44,7 @@ type userManager struct { usersBucket []byte // sessions is a map of active user sessions - sessions map[string]*session + sessions *syncmap.Map endSessionCleanup chan bool } @@ -54,7 +55,7 @@ func newUserManager(dbPath, domain, path string, timeout int) (*userManager, err cookiePath: path, cookieTimeout: time.Duration(timeout) * time.Minute, usersBucket: []byte("users"), - sessions: make(map[string]*session), + sessions: &syncmap.Map{}, endSessionCleanup: make(chan bool), } @@ -68,7 +69,26 @@ func newUserManager(dbPath, domain, path string, timeout int) (*userManager, err return err }) manager.db = db - go manager.cleanSessions() + + // Set up session cleanup goroutine + ticker := time.NewTicker(manager.cookieTimeout) + go func() { + for { + select { + case <-manager.endSessionCleanup: + ticker.Stop() + return + case <-ticker.C: + manager.sessions.Range(func(id, s interface{}) bool { + session, ok := s.(*session) + if !ok || !manager.isValidSession(session) { + manager.sessions.Delete(id) + } + return true + }) + } + } + }() return manager, nil } @@ -81,7 +101,7 @@ func (m *userManager) Close() error { // Reset deletes all users and drops all active sessions func (m *userManager) Reset() error { - m.sessions = make(map[string]*session) + m.sessions = &syncmap.Map{} return m.db.Update(func(tx *bolt.Tx) error { err := tx.DeleteBucket(m.usersBucket) if err != nil { @@ -192,7 +212,7 @@ func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *ht Username: username, Expires: expiration, } - m.sessions[id] = s + m.sessions.Store(id, s) http.SetCookie(w, &http.Cookie{ Name: m.cookieName, Value: url.QueryEscape(id), @@ -213,7 +233,7 @@ func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { if err != nil { return } - delete(m.sessions, id) + m.sessions.Delete(id) expiration := time.Now() newCookie := http.Cookie{ Name: m.cookieName, @@ -236,44 +256,34 @@ func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*sessi if err != nil { return nil, err } - s, found := m.sessions[id] + s, found := m.sessions.Load(id) if !found { return nil, errSessionNotFound } - if !m.isValidSession(s) { + session, ok := s.(*session) + if !ok { + m.sessions.Delete(id) + return nil, errSessionNotFound + } + if !m.isValidSession(session) { m.SessionEnd(w, r) return nil, errSessionNotFound } - return s, nil + return session, nil } // endAllUserSessions removes all active sessions with given user func (m *userManager) endAllUserSessions(username string) { - for id, s := range m.sessions { - if s.Username == username { - delete(m.sessions, id) + m.sessions.Range(func(id, s interface{}) bool { + session, ok := s.(*session) + if !ok || session.Username == username { + m.sessions.Delete(id) } - } + return true + }) } // isValidSession checks if session is expired func (m *userManager) isValidSession(s *session) bool { return s.Expires.After(time.Now()) } - -// cleanSessions is a goroutine that continously cleans sessions -func (m *userManager) cleanSessions() { - for { - select { - case <-m.endSessionCleanup: - return - default: - for id, s := range m.sessions { - if !m.isValidSession(s) { - delete(m.sessions, id) - } - } - time.AfterFunc(m.cookieTimeout, func() { m.cleanSessions() }) - } - } -} From cd70fbb721eee42f8e15f0f78f62a8ef99dd3da7 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 11:31:24 -0700 Subject: [PATCH 29/73] Separate session management into separate class --- daemon/inertia/auth/permissions.go | 21 +++- daemon/inertia/auth/sessions.go | 168 +++++++++++++++++++++++++++++ daemon/inertia/auth/users.go | 138 +----------------------- daemon/inertia/auth/users_test.go | 2 +- 4 files changed, 188 insertions(+), 141 deletions(-) create mode 100644 daemon/inertia/auth/sessions.go diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index af03b60f..046d55a4 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -18,6 +18,7 @@ const UserDatabasePath = "/app/host/.inertia/users.db" type PermissionsHandler struct { domain string users *userManager + sessions *sessionManager mux *http.ServeMux publicPaths []string adminPaths []string @@ -27,16 +28,20 @@ type PermissionsHandler struct { // users and handling user administration func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*PermissionsHandler, error) { // Set up user manager - userManager, err := newUserManager(dbPath, domain, path, timeout) + userManager, err := newUserManager(dbPath) if err != nil { return nil, err } + // Set up session manager + sessionManager := newSessionManager(domain, path, timeout) + // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ domain: domain, users: userManager, + sessions: sessionManager, mux: mux, adminPaths: make([]string, 0), } @@ -61,6 +66,7 @@ func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*Permissio // Close releases resources held by the PermissionsHandler func (h *PermissionsHandler) Close() error { + h.sessions.Close() return h.users.Close() } @@ -77,7 +83,7 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // Check if session is valid - s, err := h.users.GetSession(w, r) + s, err := h.sessions.GetSession(w, r) if err != nil { if err == errSessionNotFound || err == errCookieNotFound { http.Error(w, err.Error(), http.StatusForbidden) @@ -178,25 +184,32 @@ func (h *PermissionsHandler) removeUserHandler(w http.ResponseWriter, r *http.Re return } - // Remove user + // 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) @@ -227,7 +240,7 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request http.Error(w, "Login failed", http.StatusForbidden) return } - h.users.SessionBegin(userReq.Username, w, r) + h.sessions.BeginSession(userReq.Username, w, r) w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "[SUCCESS %d] User %s logged in\n", http.StatusOK, userReq.Username) diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go new file mode 100644 index 00000000..bee1a134 --- /dev/null +++ b/daemon/inertia/auth/sessions.go @@ -0,0 +1,168 @@ +package auth + +import ( + "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 + cookiePath string + cookieTimeout time.Duration + internal map[string]*session + + sync.RWMutex + endSessionCleanup chan bool +} + +func newSessionManager(domain, path string, timeout int) *sessionManager { + manager := &sessionManager{ + cookieName: "ubclaunchpad-inertia", + cookieDomain: domain, + cookiePath: path, + 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) { + expiration := time.Now().Add(s.cookieTimeout) + id := generateSessionID() + + s.Lock() + s.internal[id] = &session{ + Username: username, + Expires: expiration, + } + s.Unlock() + + http.SetCookie(w, &http.Cookie{ + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + Path: s.cookiePath, + HttpOnly: true, + Expires: expiration, + }) +} + +// SessionEnd ends a session and sets cookie to expire +func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) { + cookie, err := r.Cookie(s.cookieName) + if err != nil || cookie.Value == "" { + return + } + id, err := url.QueryUnescape(cookie.Value) + if err != nil { + return + } + + s.Lock() + delete(s.internal, id) + s.Unlock() + + expiration := time.Now() + newCookie := http.Cookie{ + Name: s.cookieName, + Domain: s.cookieDomain, + Path: s.cookiePath, + HttpOnly: true, + Expires: expiration, + MaxAge: -1, + } + http.SetCookie(w, &newCookie) +} + +// 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 index 0233dd13..03d9224b 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -3,12 +3,8 @@ package auth import ( "encoding/json" "errors" - "net/http" - "net/url" - "time" "github.com/boltdb/bolt" - "golang.org/x/sync/syncmap" ) var ( @@ -24,39 +20,17 @@ type userProps struct { Admin bool `json:"admin"` } -// session are properties associated with session, -// used for database entries -type session struct { - Username string `json:"username"` - Expires time.Time `json:"created"` -} - // userManager administers sessions and user accounts type userManager struct { - cookieName string - cookieDomain string - cookiePath string - cookieTimeout time.Duration - // db is a boltdb database, which is an embedded // key/value database where each "bucket" is a collection db *bolt.DB usersBucket []byte - - // sessions is a map of active user sessions - sessions *syncmap.Map - endSessionCleanup chan bool } -func newUserManager(dbPath, domain, path string, timeout int) (*userManager, error) { +func newUserManager(dbPath string) (*userManager, error) { manager := &userManager{ - cookieName: "ubclaunchpad-inertia", - cookieDomain: domain, - cookiePath: path, - cookieTimeout: time.Duration(timeout) * time.Minute, - usersBucket: []byte("users"), - sessions: &syncmap.Map{}, - endSessionCleanup: make(chan bool), + usersBucket: []byte("users"), } // Set up database @@ -70,38 +44,16 @@ func newUserManager(dbPath, domain, path string, timeout int) (*userManager, err }) manager.db = db - // Set up session cleanup goroutine - ticker := time.NewTicker(manager.cookieTimeout) - go func() { - for { - select { - case <-manager.endSessionCleanup: - ticker.Stop() - return - case <-ticker.C: - manager.sessions.Range(func(id, s interface{}) bool { - session, ok := s.(*session) - if !ok || !manager.isValidSession(session) { - manager.sessions.Delete(id) - } - return true - }) - } - } - }() - return manager, nil } // Close ends the session cleanup job and releases the DB handler func (m *userManager) Close() error { - m.endSessionCleanup <- true return m.db.Close() } // Reset deletes all users and drops all active sessions func (m *userManager) Reset() error { - m.sessions = &syncmap.Map{} return m.db.Update(func(tx *bolt.Tx) error { err := tx.DeleteBucket(m.usersBucket) if err != nil { @@ -135,7 +87,6 @@ func (m *userManager) AddUser(username, password string, admin bool) error { // RemoveUser removes user with given username and ends related sessions func (m *userManager) RemoveUser(username string) error { - m.endAllUserSessions(username) return m.db.Update(func(tx *bolt.Tx) error { users := tx.Bucket(m.usersBucket) return users.Delete([]byte(username)) @@ -202,88 +153,3 @@ func (m *userManager) IsAdmin(username string) (bool, error) { }) return admin, err } - -// SessionBegin starts a new session with user by setting a cookie -// and adding session to memory -func (m *userManager) SessionBegin(username string, w http.ResponseWriter, r *http.Request) { - expiration := time.Now().Add(m.cookieTimeout) - id := generateSessionID() - s := &session{ - Username: username, - Expires: expiration, - } - m.sessions.Store(id, s) - http.SetCookie(w, &http.Cookie{ - Name: m.cookieName, - Value: url.QueryEscape(id), - Domain: m.cookieDomain, - Path: m.cookiePath, - HttpOnly: true, - Expires: expiration, - }) -} - -// SessionEnd ends a session and sets cookie to expire -func (m *userManager) SessionEnd(w http.ResponseWriter, r *http.Request) { - cookie, err := r.Cookie(m.cookieName) - if err != nil || cookie.Value == "" { - return - } - id, err := url.QueryUnescape(cookie.Value) - if err != nil { - return - } - m.sessions.Delete(id) - expiration := time.Now() - newCookie := http.Cookie{ - Name: m.cookieName, - Domain: m.cookieDomain, - Path: m.cookiePath, - HttpOnly: true, - Expires: expiration, - MaxAge: -1, - } - http.SetCookie(w, &newCookie) -} - -// GetSession verifies if given request is from a valid session and returns it -func (m *userManager) GetSession(w http.ResponseWriter, r *http.Request) (*session, error) { - cookie, err := r.Cookie(m.cookieName) - if err != nil || cookie.Value == "" { - return nil, errCookieNotFound - } - id, err := url.QueryUnescape(cookie.Value) - if err != nil { - return nil, err - } - s, found := m.sessions.Load(id) - if !found { - return nil, errSessionNotFound - } - session, ok := s.(*session) - if !ok { - m.sessions.Delete(id) - return nil, errSessionNotFound - } - if !m.isValidSession(session) { - m.SessionEnd(w, r) - return nil, errSessionNotFound - } - return session, nil -} - -// endAllUserSessions removes all active sessions with given user -func (m *userManager) endAllUserSessions(username string) { - m.sessions.Range(func(id, s interface{}) bool { - session, ok := s.(*session) - if !ok || session.Username == username { - m.sessions.Delete(id) - } - return true - }) -} - -// isValidSession checks if session is expired -func (m *userManager) isValidSession(s *session) bool { - return s.Expires.After(time.Now()) -} diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index 425eaa91..30b748f8 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -13,7 +13,7 @@ func getTestUserManager(dir string) (*userManager, error) { if err != nil { return nil, err } - return newUserManager(path.Join(dir, "users.db"), "127.0.0.1", "/", 120) + return newUserManager(path.Join(dir, "users.db")) } func TestAddUserAndIsCorrectCredentials(t *testing.T) { From dd375239d8fc364f931931a57627959be29b0401 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 11:58:10 -0700 Subject: [PATCH 30/73] Upgrade dependencies --- Gopkg.lock | 37 ++++++++++++++++++++++--------------- Gopkg.toml | 12 ++++-------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 21f62c2a..eee04f42 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -28,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" @@ -60,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" @@ -79,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"] @@ -142,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" @@ -214,12 +227,6 @@ ] revision = "d866cfc389cec985d6fda2859936a575a55a3ab6" -[[projects]] - branch = "master" - name = "golang.org/x/sync" - packages = ["syncmap"] - revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca" - [[projects]] branch = "master" name = "golang.org/x/sys" @@ -298,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" @@ -310,6 +317,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "c5619a919aad6ebb7d08707dfc91e764d33cc622b05731d8e82c431eb93226b9" + inputs-digest = "00c2d3d5757dba4a76cbd3006884e20477d9c43da5a2e471316e97cd8fa4fd8a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index f65f37de..463cb53a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -4,7 +4,7 @@ [[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,15 +12,15 @@ [[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" @@ -29,7 +29,3 @@ [[constraint]] name = "github.com/boltdb/bolt" version = "1.3.1" - -[[constraint]] - branch = "master" - name = "golang.org/x/sync" From f3851f77c4663cc55775a5a74543610691575c4e Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 15:51:08 -0700 Subject: [PATCH 31/73] Update test command --- .travis.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba111223..0d6f62f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,11 +31,9 @@ matrix: fast_finish: true before_install: - - GO_FILES=$(find . -iname '*.go' -type f | grep -v /vendor/) # All the .go files, excluding vendor/ - - go get -u honnef.co/go/tools/cmd/megacheck - - go get -u github.com/fzipp/gocyclo - - go get -u github.com/mattn/goveralls - - go get -u github.com/golang/dep/cmd/dep + - go get honnef.co/go/tools/cmd/megacheck + - go get github.com/mattn/goveralls + - go get github.com/golang/dep/cmd/dep - dep ensure # Run tests and various code quality checks @@ -44,8 +42,8 @@ script: - make testdaemon SSH_PORT=69 # Send test daemon to test VPS - go vet ./... # Report suspicious constructs - megacheck ./... # Static analysis - - gocyclo -over 19 $GO_FILES # Forbid code with huge functions - - goveralls -v -show -race -package=./... -service=travis-ci -repotoken "$COVERALLS_TOKEN" + - go test -v -race -coverprofile=coverage.out ./... + - goveralls -coverprofile=coverage.out -service=travis-ci -repotoken "$COVERALLS_TOKEN" # Push version-tagged Docker image and build platform binaries before_deploy: From 5f8b9365410aa9cdeba7fb2a482384663996977a Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 16:18:33 -0700 Subject: [PATCH 32/73] Update Travis script for more accurate coverage --- .travis.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d6f62f2..7666c038 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,19 +31,22 @@ matrix: fast_finish: true before_install: - - go get honnef.co/go/tools/cmd/megacheck + - 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 -# Run tests and various code quality checks +# 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 vet ./... # Report suspicious constructs - - megacheck ./... # Static analysis - go test -v -race -coverprofile=coverage.out ./... - 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 # Push version-tagged Docker image and build platform binaries before_deploy: From 41f97febf8528f896e1b5a703aa01316b14f1f57 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 25 Mar 2018 16:18:41 -0700 Subject: [PATCH 33/73] Prune dependencies --- Gopkg.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Gopkg.toml b/Gopkg.toml index 463cb53a..433bd5bf 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,3 +1,8 @@ +[prune] + non-go = true + unused-packages = true + go-tests = true + [[constraint]] name = "github.com/spf13/cobra" branch = "master" From 5550870738ede9b1ab71534199f4c47c8c4759d8 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 28 Mar 2018 21:59:07 -0700 Subject: [PATCH 34/73] Enforce min and max password and username lengths, remove strange chars --- daemon/inertia/auth/password.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go index c7bc76b5..66798886 100644 --- a/daemon/inertia/auth/password.go +++ b/daemon/inertia/auth/password.go @@ -24,14 +24,19 @@ 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 { + if len(password) < 5 || len(password) >= 128 { return errInvalidPassword } - validChars := "abcdefghijklmnopqrstuvwxyzæøåABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ_0123456789" + if len(username) < 3 || len(username) >= 128 { + return errInvalidUsername + } + validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" NEXT_USERNAME_CHAR: for _, char := range username { From bbbc01e855ee175c38fc2ef1bb703da32033c09c Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 29 Mar 2018 20:19:09 -0700 Subject: [PATCH 35/73] Update password tests and add underscore to allowed chars Also a plurality fix on error messages when referring to "underscore" --- daemon/inertia/auth/password.go | 6 +++--- daemon/inertia/auth/password_test.go | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go index 66798886..eeed8347 100644 --- a/daemon/inertia/auth/password.go +++ b/daemon/inertia/auth/password.go @@ -8,8 +8,8 @@ import ( var ( errSameUsernamePassword = errors.New("Username and password must be different") - errInvalidUsername = errors.New("Only letters, numbers and underscore are allowed in usernames") - errInvalidPassword = errors.New("Only letters, numbers and underscore are allowed in passwords, and password must be at least 5 characters") + errInvalidUsername = errors.New("Only letters, numbers and underscores are allowed in usernames") + errInvalidPassword = errors.New("Only letters, numbers and underscores are allowed in passwords, and password must be at least 5 characters") ) func hashPassword(password string) (string, error) { @@ -36,7 +36,7 @@ func validateCredentialValues(username, password string) error { if len(username) < 3 || len(username) >= 128 { return errInvalidUsername } - validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" NEXT_USERNAME_CHAR: for _, char := range username { diff --git a/daemon/inertia/auth/password_test.go b/daemon/inertia/auth/password_test.go index c5444e3f..477afdd6 100644 --- a/daemon/inertia/auth/password_test.go +++ b/daemon/inertia/auth/password_test.go @@ -33,12 +33,15 @@ func TestValidateCredentialValues(t *testing.T) { err = validateCredentialValues("ohnoitsme", "ohnoitsme") assert.Equal(t, errSameUsernamePassword, err) - err = validateCredentialValues("wow", "oh") + 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("wow", "oasdfasdfh!!!!") + err = validateCredentialValues("wowwow", "oasdfasdfh!!!!") assert.Equal(t, errInvalidPassword, err) } From f1e47ad5ea337fd197d245f85bfe7a345a84bac3 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 31 Mar 2018 13:44:35 -0700 Subject: [PATCH 36/73] Revert cmd renames --- deploy_cmd.go => deploy.go | 0 deployment_users.go => deploy_users.go | 0 init_cmd.go => init.go | 0 remote_cmd.go => remote.go | 0 remote_cmd_test.go => remote_test.go | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename deploy_cmd.go => deploy.go (100%) rename deployment_users.go => deploy_users.go (100%) rename init_cmd.go => init.go (100%) rename remote_cmd.go => remote.go (100%) rename remote_cmd_test.go => remote_test.go (100%) diff --git a/deploy_cmd.go b/deploy.go similarity index 100% rename from deploy_cmd.go rename to deploy.go diff --git a/deployment_users.go b/deploy_users.go similarity index 100% rename from deployment_users.go rename to deploy_users.go 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 100% rename from remote_cmd.go rename to remote.go 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 From 35f589a71d8c8a813eef9b28a783e465f6062cbd Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 1 Apr 2018 20:23:07 -0700 Subject: [PATCH 37/73] Fix install instructions --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f9eadc3b..c09927e5 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,12 @@ Inertia is a cross-platform command line tool that simplifies setup and manageme All you need to get started is a docker-compose project, the Inertia CLI, and access to a virtual private server. To download the CLI: -Inertia CLI binaries can be downloaded for various platforms in the [Releases](https://github.com/ubclaunchpad/inertia/releases) page. You can add this binary to your PATH or execute it directly to use the Inertia CLI: - ```bash $> brew install ubclaunchpad/tap/inertia $> inertia ``` -For other platforms, you can also [download the appropriate binary for your platform from the Releases page](https://github.com/ubclaunchpad/inertia/releases) or [install Inertia from source](#installing-from-source). +For other platforms, you can also [download the appropriate binary from the Releases page](https://github.com/ubclaunchpad/inertia/releases) or [install Inertia from source](#installing-from-source). ## Setup From bf32033aed1f05cbd55b2e72e542cc2be4be1f77 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 1 Apr 2018 22:42:48 -0700 Subject: [PATCH 38/73] Tests for auth.auth --- daemon/inertia/auth/auth.go | 20 +++++++---- daemon/inertia/auth/auth_test.go | 49 ++++++++++++++++++--------- daemon/inertia/auth/decorator_test.go | 5 +++ 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/daemon/inertia/auth/auth.go b/daemon/inertia/auth/auth.go index 2c378fa4..6ed04d6a 100644 --- a/daemon/inertia/auth/auth.go +++ b/daemon/inertia/auth/auth.go @@ -10,7 +10,7 @@ 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" @@ -20,9 +20,13 @@ var ( // 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 +55,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 54eb7e53..5d924b04 100644 --- a/daemon/inertia/auth/auth_test.go +++ b/daemon/inertia/auth/auth_test.go @@ -1,40 +1,57 @@ package auth import ( - "fmt" - "net/http" "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_env/test_key") ) -func testHealthCheckHandler(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, common.DaemonOkResp) -} - +// 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 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 TestGetGithubKey(t *testing.T) { - inertiaKeyPath := path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test_env/test_key") - pemFile, err := os.Open(inertiaKeyPath) + pemFile, err := os.Open(testInertiaKeyPath) assert.Nil(t, err) _, err = GetGithubKey(pemFile) assert.Nil(t, err) } + +func TestGenerateToken(t *testing.T) { + token, err := GenerateToken(testPrivateKey) + assert.Nil(t, err, "generateToken must not fail") + assert.Equal(t, token, testToken) + + otherToken, err := GenerateToken([]byte("another_sekrit_key")) + assert.Nil(t, err) + assert.NotEqual(t, token, otherToken) +} + +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 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/decorator_test.go b/daemon/inertia/auth/decorator_test.go index 35ae5318..36b25979 100644 --- a/daemon/inertia/auth/decorator_test.go +++ b/daemon/inertia/auth/decorator_test.go @@ -10,6 +10,11 @@ import ( "github.com/ubclaunchpad/inertia/common" ) +func testHealthCheckHandler(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, common.DaemonOkResp) +} + func TestAuthorizationOK(t *testing.T) { req, _ := http.NewRequest("GET", "/health-check", nil) From c04e201e7666921d8c9941bb7594e173a708cf9d Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 1 Apr 2018 22:43:01 -0700 Subject: [PATCH 39/73] Attach version to daemon CLI --- daemon/inertia/main.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/daemon/inertia/main.go b/daemon/inertia/main.go index 65b14e47..e4937e9e 100644 --- a/daemon/inertia/main.go +++ b/daemon/inertia/main.go @@ -15,12 +15,14 @@ var Version string // runCmd starts the daemon var runCmd = &cobra.Command{ - Use: "run", - Short: "Run the daemon", - Long: `Run the daemon on a port, default 8081. -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") @@ -36,7 +38,7 @@ 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 { From e9028f45477311da34b3508018b65392f3e74623 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 1 Apr 2018 22:59:01 -0700 Subject: [PATCH 40/73] Add list users command `inertia $VPS user list` lists all registered users on remote --- client/deployment.go | 5 +++++ daemon/inertia/auth/permissions.go | 13 +++++++++++ daemon/inertia/auth/users.go | 13 +++++++++++ daemon/inertia/auth/users_test.go | 8 ++++++- deploy.go | 2 ++ deploy_users.go | 35 ++++++++++++++++++++++++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/client/deployment.go b/client/deployment.go index 6035b393..fd34d3e8 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -116,6 +116,11 @@ func (d *Deployment) ResetUsers() (*http.Response, error) { return d.request("POST", "/web/resetusers", nil) } +// ListUsers lists all users on the remote. +func (d *Deployment) ListUsers() (*http.Response, error) { + return d.request("POST", "/web/listusers", nil) +} + func (d *Deployment) request(method, endpoint string, requestBody interface{}) (*http.Response, error) { // Assemble URL url, err := url.Parse("https://" + d.RemoteVPS.GetIPAndPort()) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 046d55a4..1c34a01b 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -60,6 +60,7 @@ func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*Permissio mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) mux.HandleFunc("/resetusers", Authorized(handler.resetUsersHandler, GetAPIPrivateKey)) + mux.HandleFunc("/listusers", Authorized(handler.listUsersHandler, GetAPIPrivateKey)) return handler, nil } @@ -215,6 +216,18 @@ func (h *PermissionsHandler) resetUsersHandler(w http.ResponseWriter, r *http.Re 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) + fmt.Fprintf(w, "[SUCCESS %d] Users: \n%s\n", http.StatusOK, userList) +} + func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index 03d9224b..e66a43e9 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -93,6 +93,19 @@ func (m *userManager) RemoveUser(username string) error { }) } +// 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 diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index 30b748f8..83894c53 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -35,7 +35,7 @@ func TestAddUserAndIsCorrectCredentials(t *testing.T) { assert.True(t, correct) } -func TestAddDeleteAndHasUser(t *testing.T) { +func TestAllUserManagementOperations(t *testing.T) { dir := "./test_users" manager, err := getTestUserManager(dir) defer os.RemoveAll(dir) @@ -45,6 +45,12 @@ func TestAddDeleteAndHasUser(t *testing.T) { 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) diff --git a/deploy.go b/deploy.go index 3395c63f..ffd42d01 100644 --- a/deploy.go +++ b/deploy.go @@ -330,9 +330,11 @@ Run 'inertia [REMOTE] init' to gather this information.`, 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) diff --git a/deploy_users.go b/deploy_users.go index 80cc4f31..f5c77ba6 100644 --- a/deploy_users.go +++ b/deploy_users.go @@ -144,3 +144,38 @@ from the web app.`, } }, } + +var deploymentUsersListCmd = &cobra.Command{ + Use: "list", + Short: "List all users registered on your remote.", + Long: `List all users with access to Inertia Web on your remote.`, + 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.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) + } + }, +} From dcae087b3b690c5c007efe932e4bc605fa299519 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sun, 1 Apr 2018 23:27:54 -0700 Subject: [PATCH 41/73] Test user management endpoints --- daemon/inertia/auth/permissions.go | 25 +++++++-- daemon/inertia/auth/permissions_test.go | 73 ++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 7 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 1c34a01b..cc36b15f 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -7,6 +7,7 @@ import ( "net/http" "strings" + jwt "github.com/dgrijalva/jwt-go" "github.com/ubclaunchpad/inertia/common" ) @@ -26,7 +27,10 @@ type PermissionsHandler struct { // NewPermissionsHandler returns a new handler for authenticating // users and handling user administration -func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*PermissionsHandler, error) { +func NewPermissionsHandler( + dbPath, domain, path string, timeout int, + keyLookup ...func(*jwt.Token) (interface{}, error), +) (*PermissionsHandler, error) { // Set up user manager userManager, err := newUserManager(dbPath) if err != nil { @@ -52,15 +56,20 @@ func NewPermissionsHandler(dbPath, domain, path string, timeout int) (*Permissio "/adduser", "/removeuser", "/resetusers", + "/listusers", } mux.HandleFunc("/login", handler.loginHandler) // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. - mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, GetAPIPrivateKey)) - mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, GetAPIPrivateKey)) - mux.HandleFunc("/resetusers", Authorized(handler.resetUsersHandler, GetAPIPrivateKey)) - mux.HandleFunc("/listusers", Authorized(handler.listUsersHandler, GetAPIPrivateKey)) + lookup := GetAPIPrivateKey + if len(keyLookup) > 0 { + lookup = keyLookup[0] + } + mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, lookup)) + mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, lookup)) + mux.HandleFunc("/resetusers", Authorized(handler.resetUsersHandler, lookup)) + mux.HandleFunc("/listusers", Authorized(handler.listUsersHandler, lookup)) return handler, nil } @@ -225,7 +234,11 @@ func (h *PermissionsHandler) listUsersHandler(w http.ResponseWriter, r *http.Req w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, "[SUCCESS %d] Users: \n%s\n", http.StatusOK, userList) + 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) { diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 350014d4..59115cf4 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -3,6 +3,7 @@ package auth import ( "bytes" "encoding/json" + "fmt" "net/http" "net/http/httptest" "os" @@ -19,7 +20,11 @@ func getTestPermissionsHandler(dir string) (*PermissionsHandler, error) { if err != nil { return nil, err } - return NewPermissionsHandler(path.Join(dir, "users.db"), "127.0.0.1", "/", 3000) + return NewPermissionsHandler( + path.Join(dir, "users.db"), + "127.0.0.1", "/", 3000, + getFakeAPIKey, + ) } func TestServeHTTPPublicPath(t *testing.T) { @@ -207,3 +212,69 @@ func TestServeHTTPAllowAdmin(t *testing.T) { 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+"/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+"/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+"/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+"/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) +} From 6f274896e78f31cf76659209132a2edbfe4ea1f8 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Mon, 2 Apr 2018 15:55:44 -0700 Subject: [PATCH 42/73] Improve credential validation, add dash as legal character --- daemon/inertia/auth/password.go | 40 ++++++++++------------------ daemon/inertia/auth/password_test.go | 2 +- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/daemon/inertia/auth/password.go b/daemon/inertia/auth/password.go index eeed8347..d0735570 100644 --- a/daemon/inertia/auth/password.go +++ b/daemon/inertia/auth/password.go @@ -8,10 +8,11 @@ import ( var ( errSameUsernamePassword = errors.New("Username and password must be different") - errInvalidUsername = errors.New("Only letters, numbers and underscores are allowed in usernames") - errInvalidPassword = errors.New("Only letters, numbers and underscores are allowed in passwords, and password must be at least 5 characters") + 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 { @@ -20,6 +21,7 @@ func hashPassword(password string) (string, 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 } @@ -30,35 +32,21 @@ func validateCredentialValues(username, password string) error { if username == password { return errSameUsernamePassword } - if len(password) < 5 || len(password) >= 128 { + if len(password) < 5 || len(password) >= 128 || !isLegalString(password) { return errInvalidPassword } - if len(username) < 3 || len(username) >= 128 { - return errInvalidUsername - } - validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" - -NEXT_USERNAME_CHAR: - for _, char := range username { - for _, validChar := range validChars { - // if valid, skip to next character - if char == validChar { - continue NEXT_USERNAME_CHAR - } - } + if len(username) < 3 || len(username) >= 128 || !isLegalString(username) { return errInvalidUsername } + return nil +} -NEXT_PASSWORD_CHAR: - for _, char := range password { - for _, validChar := range validChars { - // if valid, skip to next character - if char == validChar { - continue NEXT_PASSWORD_CHAR - } +// 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 errInvalidPassword } - - return nil + return true } diff --git a/daemon/inertia/auth/password_test.go b/daemon/inertia/auth/password_test.go index 477afdd6..2b9342b3 100644 --- a/daemon/inertia/auth/password_test.go +++ b/daemon/inertia/auth/password_test.go @@ -13,7 +13,7 @@ func TestHashPassword(t *testing.T) { assert.NotEqual(t, unhashed, hashed) } -func TestCorrectPassowrd(t *testing.T) { +func TestCorrectPassword(t *testing.T) { unhashed := "amazing" hashed, err := hashPassword(unhashed) assert.Nil(t, err) From ee09856929e401df506bb8c528e9bfa6a3f34722 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Mon, 2 Apr 2018 16:10:44 -0700 Subject: [PATCH 43/73] More explicit error handling for BeginSession and EndSession --- daemon/inertia/auth/permissions.go | 6 +++++- daemon/inertia/auth/sessions.go | 31 +++++++++++++++++++++--------- daemon/inertia/auth/util.go | 6 +++--- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index cc36b15f..c0e70190 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -266,7 +266,11 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request http.Error(w, "Login failed", http.StatusForbidden) return } - h.sessions.BeginSession(userReq.Username, w, r) + 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) diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go index bee1a134..9a4e0936 100644 --- a/daemon/inertia/auth/sessions.go +++ b/daemon/inertia/auth/sessions.go @@ -1,6 +1,7 @@ package auth import ( + "errors" "net/http" "net/url" "sync" @@ -69,10 +70,15 @@ func (s *sessionManager) Close() { // 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) { +func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r *http.Request) error { expiration := time.Now().Add(s.cookieTimeout) - id := generateSessionID() + id, err := generateSessionID() + if err != nil { + println("Failed to being session for " + username) + return errors.New("Failed to begin session for " + username + ": " + err.Error()) + } + // Add session to map s.Lock() s.internal[id] = &session{ Username: username, @@ -80,6 +86,7 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r } s.Unlock() + // Add cookie with session ID http.SetCookie(w, &http.Cookie{ Name: s.cookieName, Value: url.QueryEscape(id), @@ -88,33 +95,39 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r 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) { +func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) error { cookie, err := r.Cookie(s.cookieName) - if err != nil || cookie.Value == "" { - return + 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 + return errors.New("Invalid cookie: " + err.Error()) } + // Delete session from map s.Lock() delete(s.internal, id) s.Unlock() + // Set cookie to expire immediately expiration := time.Now() - newCookie := http.Cookie{ + http.SetCookie(w, &http.Cookie{ Name: s.cookieName, Domain: s.cookieDomain, Path: s.cookiePath, HttpOnly: true, Expires: expiration, MaxAge: -1, - } - http.SetCookie(w, &newCookie) + }) + return nil } // GetSession verifies if given request is from a valid session and returns it diff --git a/daemon/inertia/auth/util.go b/daemon/inertia/auth/util.go index db35f8e2..ccb7dc06 100644 --- a/daemon/inertia/auth/util.go +++ b/daemon/inertia/auth/util.go @@ -6,10 +6,10 @@ import ( "io" ) -func generateSessionID() string { +func generateSessionID() (string, error) { b := make([]byte, 32) if _, err := io.ReadFull(rand.Reader, b); err != nil { - return "" + return "", err } - return base64.URLEncoding.EncodeToString(b) + return base64.URLEncoding.EncodeToString(b), nil } From 489942dc983c5f986a144e842631dd8db971520d Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Mon, 2 Apr 2018 16:23:40 -0700 Subject: [PATCH 44/73] Add logout handler --- daemon/inertia/auth/permissions.go | 12 ++++++ daemon/inertia/auth/permissions_test.go | 51 +++++++++++++++++++++++++ daemon/inertia/auth/sessions.go | 2 + 3 files changed, 65 insertions(+) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index c0e70190..94b72684 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -53,12 +53,14 @@ func NewPermissionsHandler( // Set paths that don't require session authentication. handler.publicPaths = []string{ "/login", + "/logout", "/adduser", "/removeuser", "/resetusers", "/listusers", } mux.HandleFunc("/login", handler.loginHandler) + mux.HandleFunc("/logout", handler.logoutHandler) // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. @@ -275,3 +277,13 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request 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) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] Session ended\n", http.StatusOK) +} diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 59115cf4..8579ec9e 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -75,6 +75,57 @@ func TestServeHTTPWithUserReject(t *testing.T) { 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.AttachUserRestrictedHandler("/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+"/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) + + // Log out + req, err = http.NewRequest("POST", ts.URL+"/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) diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go index 9a4e0936..c3f228dc 100644 --- a/daemon/inertia/auth/sessions.go +++ b/daemon/inertia/auth/sessions.go @@ -127,6 +127,8 @@ func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) erro Expires: expiration, MaxAge: -1, }) + println("logging out") + println(expiration.Format("2006-01-02 15:04:05")) return nil } From 343fe9bb621e2cafda90fc37704421529c6d4e2d Mon Sep 17 00:00:00 2001 From: John Lee Date: Mon, 2 Apr 2018 21:55:16 -0700 Subject: [PATCH 45/73] login request proof of concept attempt --- daemon/inertia/auth/permissions.go | 5 ++ daemon/web/client.js | 8 ++- daemon/web/components/App.js | 87 ++++++++++++++++++++++-------- daemon/web/webpack.config.js | 80 +++++++++++++-------------- daemon/web/webpack.prod.js | 56 +++++++++---------- 5 files changed, 146 insertions(+), 90 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 046d55a4..d5a08cb3 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -216,6 +216,11 @@ func (h *PermissionsHandler) resetUsersHandler(w http.ResponseWriter, r *http.Re } func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { + // TODO: better way of handling cors + //w.Header().Set("Access-Control-Allow-Origin", "https://localhost:7900") + //w.Header().Set("Access-Control-Allow-Methods", "POST") + //w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { diff --git a/daemon/web/client.js b/daemon/web/client.js index c6b7be08..58ce6b5c 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -20,6 +20,12 @@ export default class InertiaClient { * @param {Object} params */ async _post(endpoint, params) { - // @todo + const request = new Request(endpoint, params); + + 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..a773fe4b 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -4,31 +4,76 @@ import PropTypes from 'prop-types'; import InertiaClient from '../client'; export default class App extends React.Component { - constructor(props) { - super(props); - } - - render() { - return ( -
-

- -

-

- This is the Inertia web client! -

-
- ); - } + 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 = 'https://localhost:8081/web/login'; + const params = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + Username: this.state.username, + Password: this.state.password + }) + }; + + const response = await this.props.client._post(endpoint, params).json(); + this.setState({ loginAlert: response.body }); + } + + handleUsernameBlur(e) { + this.setState({ username: e.target.value }); + } + + handlePasswordBlur(e) { + this.setState({ password: e.target.value }); + } + + render() { + return ( +
+

+ +

+

+ This is the Inertia web client! +

+
+ + + +

{this.state.loginAlert}

+
+
+ ); + } } App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) + client: PropTypes.instanceOf(InertiaClient) } const styles = { - container: { - display: 'flex', - }, + container: { + display: 'flex', + }, + login: { + display: 'flex', + flexFlow: 'column', + alignItems: 'center' + } }; diff --git a/daemon/web/webpack.config.js b/daemon/web/webpack.config.js index 7db8e0ec..1f618d51 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -3,48 +3,48 @@ const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const config = { - mode: 'development', - entry: './index.js', - output: { - path: `${__dirname}/public/`, - filename: 'bundle.js', - }, - devServer: { - port: 7900, - inline: true, - contentBase: './public', - publicPath: '/', - }, - devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.jsx?$/, - exclude: '/node_modules/', - use: [ - { - loader: 'babel-loader', - options: { - presets: ['es2015', 'react'], + mode: 'development', + entry: './index.js', + output: { + path: `${__dirname}/public/`, + filename: 'bundle.js', + }, + devServer: { + port: 7900, + inline: true, + contentBase: './public', + publicPath: '/', + }, + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.jsx?$/, + exclude: '/node_modules/', + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react', 'stage-3'], + }, + } + ], }, - } ], - }, - ], - }, - plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - new webpack.HotModuleReplacementPlugin(), - new webpack.DefinePlugin({ - // suppress react devtools console warning - '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' - }), - new HtmlWebpackPlugin({ - template: './index.html', - filename: 'index.html', - inject: 'body', - }) - ] + }, + plugins: [ + new webpack.EnvironmentPlugin(['NODE_ENV']), + new webpack.HotModuleReplacementPlugin(), + 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 = config; diff --git a/daemon/web/webpack.prod.js b/daemon/web/webpack.prod.js index 8ff28367..e83fa16d 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -3,39 +3,39 @@ 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', + template: './index.html', + filename: 'index.html', + inject: 'body', }); const config = { - mode: 'production', - entry: './index.js', - output: { - path: `${__dirname}/public/`, - filename: 'bundle.js', - }, - module: { - rules: [ - { - test: /\.jsx?$/, - exclude: '/node_modules/', - use: [ - { - loader: 'babel-loader', - options: { - presets: ['es2015', 'react'], + mode: 'production', + entry: './index.js', + output: { + path: `${__dirname}/public/`, + filename: 'bundle.js', + }, + module: { + rules: [ + { + test: /\.jsx?$/, + exclude: '/node_modules/', + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react', 'stage-3'], + }, + } + ], }, - } ], - }, - ], - }, - plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - HtmlWebpackPluginConfig, - new MinifyPlugin(), - ] + }, + plugins: [ + new webpack.EnvironmentPlugin(['NODE_ENV']), + HtmlWebpackPluginConfig, + new MinifyPlugin(), + ] }; module.exports = config; From 70b6902393405e55bc45b53bf3ee99553ee263c7 Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 3 Apr 2018 11:52:27 -0700 Subject: [PATCH 46/73] removing commented out code --- daemon/inertia/auth/permissions.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index d5a08cb3..046d55a4 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -216,11 +216,6 @@ func (h *PermissionsHandler) resetUsersHandler(w http.ResponseWriter, r *http.Re } func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { - // TODO: better way of handling cors - //w.Header().Set("Access-Control-Allow-Origin", "https://localhost:7900") - //w.Header().Set("Access-Control-Allow-Methods", "POST") - //w.Header().Set("Access-Control-Allow-Headers", "Content-Type") - // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { From fb19d1daf26a81d2d2cd97a94d488d2ffa3d617d Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 3 Apr 2018 11:56:22 -0700 Subject: [PATCH 47/73] tabs to 2 spaces --- daemon/web/client.js | 46 ++++++------- daemon/web/components/App.js | 122 +++++++++++++++++------------------ daemon/web/webpack.config.js | 80 +++++++++++------------ daemon/web/webpack.prod.js | 56 ++++++++-------- 4 files changed, 152 insertions(+), 152 deletions(-) diff --git a/daemon/web/client.js b/daemon/web/client.js index 58ce6b5c..b63be321 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -1,31 +1,31 @@ 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) { - // @todo - } + /** + * Makes a GET request to the given API endpoint with the given params. + * @param {String} endpoint + * @param {Object} params + */ + async _get(endpoint, params) { + // @todo + } - /** - * Makes a POST request to the given API endpoint with the given params. - * @param {String} endpoint - * @param {Object} params - */ - async _post(endpoint, params) { - const request = new Request(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) { + const request = new Request(endpoint, params); - try { - return await fetch(request); - } catch (e) { - return e; - } + try { + return await fetch(request); + } catch (e) { + return e; } + } } diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index a773fe4b..aeb4dc6f 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -4,76 +4,76 @@ import PropTypes from 'prop-types'; import InertiaClient from '../client'; export default class App 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); - } + 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 = 'https://localhost:8081/web/login'; - const params = { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - Username: this.state.username, - Password: this.state.password - }) - }; + async handleLoginSubmit() { + const endpoint = 'https://localhost:8081/web/login'; + const params = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + Username: this.state.username, + Password: this.state.password + }) + }; - const response = await this.props.client._post(endpoint, params).json(); - this.setState({ loginAlert: response.body }); - } + const response = await this.props.client._post(endpoint, params).json(); + this.setState({loginAlert: response.body}); + } - handleUsernameBlur(e) { - this.setState({ username: e.target.value }); - } + handleUsernameBlur(e) { + this.setState({username: e.target.value}); + } - handlePasswordBlur(e) { - this.setState({ password: e.target.value }); - } + handlePasswordBlur(e) { + this.setState({password: e.target.value}); + } - render() { - return ( -
-

- -

-

- This is the Inertia web client! -

-
- - - -

{this.state.loginAlert}

-
-
- ); - } + render() { + return ( +
+

+ +

+

+ This is the Inertia web client! +

+
+ + + +

{this.state.loginAlert}

+
+
+ ); + } } App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) + client: PropTypes.instanceOf(InertiaClient) } const styles = { - container: { - display: 'flex', - }, - login: { - display: 'flex', - flexFlow: 'column', - alignItems: 'center' - } + container: { + display: 'flex', + }, + login: { + display: 'flex', + flexFlow: 'column', + alignItems: 'center' + } }; diff --git a/daemon/web/webpack.config.js b/daemon/web/webpack.config.js index 1f618d51..a43c0397 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -3,48 +3,48 @@ const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const config = { - mode: 'development', - entry: './index.js', - output: { - path: `${__dirname}/public/`, - filename: 'bundle.js', - }, - devServer: { - port: 7900, - inline: true, - contentBase: './public', - publicPath: '/', - }, - devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.jsx?$/, - exclude: '/node_modules/', - use: [ - { - loader: 'babel-loader', - options: { - presets: ['es2015', 'react', 'stage-3'], - }, - } - ], + mode: 'development', + entry: './index.js', + output: { + path: `${__dirname}/public/`, + filename: 'bundle.js', + }, + devServer: { + port: 7900, + inline: true, + contentBase: './public', + publicPath: '/', + }, + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.jsx?$/, + exclude: '/node_modules/', + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react', 'stage-3'], }, + } ], - }, - plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - new webpack.HotModuleReplacementPlugin(), - new webpack.DefinePlugin({ - // suppress react devtools console warning - '__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })' - }), - new HtmlWebpackPlugin({ - template: './index.html', - filename: 'index.html', - inject: 'body', - }) - ] + }, + ], + }, + plugins: [ + new webpack.EnvironmentPlugin(['NODE_ENV']), + new webpack.HotModuleReplacementPlugin(), + 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 = config; diff --git a/daemon/web/webpack.prod.js b/daemon/web/webpack.prod.js index e83fa16d..2d9c8b3f 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -3,39 +3,39 @@ 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', + template: './index.html', + filename: 'index.html', + inject: 'body', }); const config = { - mode: 'production', - entry: './index.js', - output: { - path: `${__dirname}/public/`, - filename: 'bundle.js', - }, - module: { - rules: [ - { - test: /\.jsx?$/, - exclude: '/node_modules/', - use: [ - { - loader: 'babel-loader', - options: { - presets: ['es2015', 'react', 'stage-3'], - }, - } - ], + mode: 'production', + entry: './index.js', + output: { + path: `${__dirname}/public/`, + filename: 'bundle.js', + }, + module: { + rules: [ + { + test: /\.jsx?$/, + exclude: '/node_modules/', + use: [ + { + loader: 'babel-loader', + options: { + presets: ['es2015', 'react', 'stage-3'], }, + } ], - }, - plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - HtmlWebpackPluginConfig, - new MinifyPlugin(), - ] + }, + ], + }, + plugins: [ + new webpack.EnvironmentPlugin(['NODE_ENV']), + HtmlWebpackPluginConfig, + new MinifyPlugin(), + ] }; module.exports = config; From ebab0263f6940763ece253d4bfa36c275ff095b9 Mon Sep 17 00:00:00 2001 From: John Lee Date: Wed, 4 Apr 2018 03:25:12 -0700 Subject: [PATCH 48/73] babel-polyfill fixes, webpack env vars, and fixed https endpoints --- daemon/web/client.js | 2 +- daemon/web/components/App.js | 2 +- daemon/web/index.html | 1 - daemon/web/index.js | 2 +- daemon/web/package-lock.json | 19 +++++++++++++++++++ daemon/web/package.json | 2 ++ daemon/web/webpack.config.js | 14 +++++++++----- daemon/web/webpack.prod.js | 2 +- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/daemon/web/client.js b/daemon/web/client.js index b63be321..ca18f7a8 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -20,7 +20,7 @@ export default class InertiaClient { * @param {Object} params */ async _post(endpoint, params) { - const request = new Request(endpoint, params); + const request = new Request(this.url + endpoint, params); try { return await fetch(request); diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index aeb4dc6f..818cf23d 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -17,7 +17,7 @@ export default class App extends React.Component { } async handleLoginSubmit() { - const endpoint = 'https://localhost:8081/web/login'; + const endpoint = '/web/login'; const params = { method: 'POST', headers: { diff --git a/daemon/web/index.html b/daemon/web/index.html index be97268b..adb21e87 100644 --- a/daemon/web/index.html +++ b/daemon/web/index.html @@ -8,7 +8,6 @@
- diff --git a/daemon/web/index.js b/daemon/web/index.js index c217b3c2..1832d633 100644 --- a/daemon/web/index.js +++ b/daemon/web/index.js @@ -5,6 +5,6 @@ import App from './components/App'; import InertiaClient from './client'; // Define where the Inertia daemon is hosted. -const daemonAddress = window.location.host; +const daemonAddress = (process.env.NODE_ENV === 'development') ? '0.0.0.0:8081' : window.location.host; const client = new InertiaClient(daemonAddress); ReactDOM.render(, document.getElementById('app')); diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index 10d3f8cb..aeef6e07 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -1190,6 +1190,25 @@ "integrity": "sha512-AVDVEmp0S9mbF1O8zekWbsOOmqnR08PZah5NRZJqSvJnFgiL0ep4Lwo4EymH8OieJR2QgQdR3q71TNW+wiVn4g==", "dev": true }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "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=", + "dev": true + } + } + }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", diff --git a/daemon/web/package.json b/daemon/web/package.json index 3126bd30..e8e1d1ed 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -12,6 +12,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { + "prop-types": "^15.6.1", "react": "^16.2.0", "react-dom": "^16.2.0" }, @@ -19,6 +20,7 @@ "babel-core": "^6.26.0", "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", "babel-preset-stage-3": "^6.24.1", diff --git a/daemon/web/webpack.config.js b/daemon/web/webpack.config.js index a43c0397..16767c2a 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -4,7 +4,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin'); const config = { mode: 'development', - entry: './index.js', + entry: ['babel-polyfill', './index.js'], output: { path: `${__dirname}/public/`, filename: 'bundle.js', @@ -25,7 +25,7 @@ const config = { { loader: 'babel-loader', options: { - presets: ['es2015', 'react', 'stage-3'], + presets: ['es2015', 'stage-3', 'react'], }, } ], @@ -33,8 +33,12 @@ const config = { ], }, plugins: [ - new webpack.EnvironmentPlugin(['NODE_ENV']), - new webpack.HotModuleReplacementPlugin(), + 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 })' @@ -42,7 +46,7 @@ const config = { new HtmlWebpackPlugin({ template: './index.html', filename: 'index.html', - inject: 'body', + inject: 'body' }) ] }; diff --git a/daemon/web/webpack.prod.js b/daemon/web/webpack.prod.js index 2d9c8b3f..f9910c07 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -10,7 +10,7 @@ const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({ const config = { mode: 'production', - entry: './index.js', + entry: ['babel-polyfill', './index.js'], output: { path: `${__dirname}/public/`, filename: 'bundle.js', From 77aa884d0afa484b5b3f061a140c4dee5e9baf6e Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 7 Apr 2018 12:43:29 -0700 Subject: [PATCH 49/73] Kill containers after tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7666c038..4bd278a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,7 @@ script: - gocyclo -over 19 $GO_FILES # Forbid code with huge functions - go vet ./... # Report suspicious constructs - megacheck ./... # Static analysis + - docker kill $(docker ps -q) # Remove testvps, etc # Push version-tagged Docker image and build platform binaries before_deploy: From 2fa11e07dd22d77f4e9adce395148c1ed1442ed5 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 7 Apr 2018 13:08:29 -0700 Subject: [PATCH 50/73] Fix misnamed daemon response --- common/request.go | 4 ++-- daemon/inertia/auth/decorator_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/request.go b/common/request.go index 9d22f745..e08d4cb1 100644 --- a/common/request.go +++ b/common/request.go @@ -1,8 +1,8 @@ package common const ( - // DaemonOkResp is the OK response upon successfully reaching daemon - DaemonOkResp = "I'm a little Webhook, short and stout!" + // MsgDaemonOK is the OK response upon successfully reaching daemon + MsgDaemonOK = "I'm a little Webhook, short and stout!" ) // DaemonRequest is the configurable body of a request to the daemon. diff --git a/daemon/inertia/auth/decorator_test.go b/daemon/inertia/auth/decorator_test.go index 36b25979..c22b0b80 100644 --- a/daemon/inertia/auth/decorator_test.go +++ b/daemon/inertia/auth/decorator_test.go @@ -12,7 +12,7 @@ import ( func testHealthCheckHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - fmt.Fprint(w, common.DaemonOkResp) + fmt.Fprint(w, common.MsgDaemonOK) } func TestAuthorizationOK(t *testing.T) { @@ -29,7 +29,7 @@ func TestAuthorizationOK(t *testing.T) { handler.ServeHTTP(rr, req) assert.Equal(t, rr.Code, http.StatusOK) - assert.Equal(t, rr.Body.String(), common.DaemonOkResp) + assert.Equal(t, rr.Body.String(), common.MsgDaemonOK) } func TestAuthorizationMalformedBearerString(t *testing.T) { From d7a9a23a4af532ff0265cf883ace665e7a5dad9b Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 7 Apr 2018 14:42:49 -0700 Subject: [PATCH 51/73] Fix test key path --- daemon/inertia/auth/auth_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/inertia/auth/auth_test.go b/daemon/inertia/auth/auth_test.go index 5d924b04..7211162b 100644 --- a/daemon/inertia/auth/auth_test.go +++ b/daemon/inertia/auth/auth_test.go @@ -12,7 +12,7 @@ import ( var ( testPrivateKey = []byte("very_sekrit_key") testToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.AqFWnFeY9B8jj7-l3z0a9iaZdwIca7xhUF3fuaJjU90" - testInertiaKeyPath = path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test_env/test_key") + testInertiaKeyPath = path.Join(os.Getenv("GOPATH"), "/src/github.com/ubclaunchpad/inertia/test/keys/id_rsa") ) // Helper function that implements jwt.keyFunc From 15a3bb46097cb49edcc3e522b113516718bef6b4 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Sat, 7 Apr 2018 15:04:42 -0700 Subject: [PATCH 52/73] Fix nested PermissionsHandler pathing Add leading "/" if stripped out by functions like http.StripPrefix --- daemon/inertia/auth/permissions.go | 8 +++++ daemon/inertia/auth/permissions_test.go | 40 +++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 94b72684..c7045bc5 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -84,7 +84,15 @@ func (h *PermissionsHandler) Close() error { // Implement the ServeHTTP method to make a permissionHandler a http.Handler func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // 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 + } // Serve if path is public for _, prefix := range h.publicPaths { diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 8579ec9e..2a48ed37 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -15,14 +15,20 @@ import ( "github.com/stretchr/testify/assert" ) -func getTestPermissionsHandler(dir string) (*PermissionsHandler, error) { +func getTestPermissionsHandler(dir string, p ...string) (*PermissionsHandler, error) { err := os.Mkdir(dir, os.ModePerm) if err != nil { return nil, err } + var endpoint string + if len(p) > 0 { + endpoint = p[0] + } else { + endpoint = "/" + } return NewPermissionsHandler( path.Join(dir, "users.db"), - "127.0.0.1", "/", 3000, + "127.0.0.1", endpoint, 3000, getFakeAPIKey, ) } @@ -51,6 +57,36 @@ func TestServeHTTPPublicPath(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) } +func TestServeHTTPPublicPathOnNestedHandler(t *testing.T) { + // This test emulates the daemon's PermissionsHandler setup + dir := "./test_perm" + ts := httptest.NewServer(nil) + defer ts.Close() + + // Set up permission handler + webPrefix := "/web/" + ph, err := getTestPermissionsHandler(dir, webPrefix) + defer os.RemoveAll(dir) + assert.Nil(t, err) + defer ph.Close() + + // Daemon uses a nested handler + mux := http.NewServeMux() + mux.Handle(webPrefix, http.StripPrefix(webPrefix, ph)) + ts.Config.Handler = mux + ph.AttachPublicHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + req, err := http.NewRequest("POST", ts.URL+"/web/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) From 96f3d237ac1adc44f24d452b07a11588131b1b97 Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 10 Apr 2018 09:28:47 -0700 Subject: [PATCH 53/73] fixed cors for local development --- daemon/inertia/auth/permissions.go | 12 ++++++++++++ daemon/inertia/daemon.go | 2 +- daemon/web/components/App.js | 6 ++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index c7045bc5..4166484b 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -252,6 +252,18 @@ func (h *PermissionsHandler) listUsersHandler(w http.ResponseWriter, r *http.Req } func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { + // Handle CORS for local development + if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { + fmt.Println("setting cors") + w.Header().Set("Access-Control-Allow-Origin", origin) + w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + + if r.Method == "OPTIONS" { + return + } + } + // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 44340fdf..fb85e888 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -67,7 +67,7 @@ func run(host, port, version string) { // Inertia web - PermissionsHandler is used to authenticate web // app access and manage users - webPrefix := "/web" + webPrefix := "/web/" permHandler, err := auth.NewPermissionsHandler( auth.UserDatabasePath, host, webPrefix, 120, ) diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index 818cf23d..fd19c823 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -24,8 +24,10 @@ export default class App extends React.Component { 'Content-Type': 'application/json' }, body: JSON.stringify({ - Username: this.state.username, - Password: this.state.password + username: this.state.username, + password: this.state.password, + email: "", + admin: false }) }; From d6b67d0684b17fdfad71e05ca52068b01d298272 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 11 Apr 2018 23:10:03 -0700 Subject: [PATCH 54/73] Add login attempt limit --- daemon/inertia/auth/users.go | 55 +++++++++++++++++++++++++++---- daemon/inertia/auth/users_test.go | 44 +++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/daemon/inertia/auth/users.go b/daemon/inertia/auth/users.go index e66a43e9..82098392 100644 --- a/daemon/inertia/auth/users.go +++ b/daemon/inertia/auth/users.go @@ -13,11 +13,16 @@ var ( errUserNotFound = errors.New("User not found") ) +const ( + loginAttemptsLimit = 5 +) + // userProps are properties associated with user, used // for database entries type userProps struct { - HashedPassword string `json:"hashedPassword"` - Admin bool `json:"admin"` + HashedPassword string + Admin bool + LoginAttempts int } // userManager administers sessions and user accounts @@ -130,22 +135,58 @@ func (m *userManager) HasUser(username string) error { // in the database func (m *userManager) IsCorrectCredentials(username, password string) (bool, error) { correct := false - err := m.db.View(func(tx *bolt.Tx) error { + userbytes := []byte(username) + var userErr error + transactionErr := m.db.Update(func(tx *bolt.Tx) error { users := tx.Bucket(m.usersBucket) - propsBytes := users.Get([]byte(username)) + 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) - return nil + 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) }) - return correct, err + + if userErr != nil { + return correct, userErr + } + return correct, transactionErr } // IsAdmin checks if given user is has administrator priviledges diff --git a/daemon/inertia/auth/users_test.go b/daemon/inertia/auth/users_test.go index 83894c53..fb844aed 100644 --- a/daemon/inertia/auth/users_test.go +++ b/daemon/inertia/auth/users_test.go @@ -82,3 +82,47 @@ func TestIsAdmin(t *testing.T) { 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) +} From df1add02e048db071f434b59c024dd9b1f7b2401 Mon Sep 17 00:00:00 2001 From: John Lee Date: Sat, 14 Apr 2018 02:53:24 -0700 Subject: [PATCH 55/73] CORS for logs, react router implemented --- daemon/inertia/logs.go | 11 ++++ daemon/web/client.js | 12 +++- daemon/web/common/AuthService.js | 38 ++++++++++++ daemon/web/components/App.js | 78 ++++++------------------- daemon/web/components/Home.js | 20 +++++++ daemon/web/components/Login.js | 99 ++++++++++++++++++++++++++++++++ daemon/web/package-lock.json | 78 ++++++++++++++++++++++++- daemon/web/package.json | 3 +- 8 files changed, 274 insertions(+), 65 deletions(-) create mode 100644 daemon/web/common/AuthService.js create mode 100644 daemon/web/components/Home.js create mode 100644 daemon/web/components/Login.js diff --git a/daemon/inertia/logs.go b/daemon/inertia/logs.go index d8270926..72d99898 100644 --- a/daemon/inertia/logs.go +++ b/daemon/inertia/logs.go @@ -13,6 +13,17 @@ import ( // logHandler handles requests for container logs func logHandler(w http.ResponseWriter, r *http.Request) { + // Handle CORS for local development + if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { + w.Header().Set("Access-Control-Allow-Origin", origin) + w.Header().Set("Access-Control-Allow-Methods", "GET OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type Accept") + + if r.Method == "OPTIONS" { + return + } + } + // Get container name from request body, err := ioutil.ReadAll(r.Body) if err != nil { diff --git a/daemon/web/client.js b/daemon/web/client.js index ca18f7a8..86bea808 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -11,7 +11,15 @@ export default class InertiaClient { * @param {Object} params */ async _get(endpoint, params) { - // @todo + params.method = "GET"; + + const request = new Request(this.url + endpoint, params); + + try { + return await fetch(request); + } catch (e) { + return e; + } } /** @@ -20,6 +28,8 @@ export default class InertiaClient { * @param {Object} params */ async _post(endpoint, params) { + params.method = "POST"; + const request = new Request(this.url + endpoint, params); try { diff --git a/daemon/web/common/AuthService.js b/daemon/web/common/AuthService.js new file mode 100644 index 00000000..d3c2be1b --- /dev/null +++ b/daemon/web/common/AuthService.js @@ -0,0 +1,38 @@ + + +const TOKEN_KEY = 'inertia'; + +export const login = () => { + // set jwt +}; + +export const logout = () => { + // clear jwt +}; + +export const isAuthenticated = () => { + // verifies that jwt is still valid + return true; +}; + +export const guardRoute = () => { + if (!isAuthenticated()) { + // push route + } +}; + +export const setToken = (token) => { + // store jwt in cookie +}; + +export const getToken = () => { + // retrieve from cookie +}; + +export const removeToken = () => { + // clear from cookie +}; + +export const isExpired = () => { + // check if token is expired +}; diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index fd19c823..ccabc337 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -1,81 +1,35 @@ import React from 'react'; +import { Redirect, Router, Route } from 'react-router-dom'; import PropTypes from 'prop-types'; import InertiaClient from '../client'; +import Login from './Login'; +import Home from './Home'; +import { isAuthenticated } from '../common/AuthService'; + +const AuthRoute = ({ component: Component, ...rest }) => ( + ( + isAuthenticated() + ? + : + )}/> +); export default class App 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 = '/web/login'; - const params = { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - username: this.state.username, - password: this.state.password, - email: "", - admin: false - }) - }; - - const response = await this.props.client._post(endpoint, params).json(); - this.setState({loginAlert: response.body}); - } - - handleUsernameBlur(e) { - this.setState({username: e.target.value}); - } - - handlePasswordBlur(e) { - this.setState({password: e.target.value}); } render() { return ( -
-

- -

-

- This is the Inertia web client! -

-
- - - -

{this.state.loginAlert}

-
-
+ + + + ); } } App.propTypes = { client: PropTypes.instanceOf(InertiaClient) -} - -const styles = { - container: { - display: 'flex', - }, - login: { - display: 'flex', - flexFlow: 'column', - alignItems: 'center' - } }; diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js new file mode 100644 index 00000000..620c8ec4 --- /dev/null +++ b/daemon/web/components/Home.js @@ -0,0 +1,20 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export default class Home extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( +
+

Welcome to the Inertia dashboard!

+
+ ); + } +} + +App.propTypes = { + client: PropTypes.instanceOf(InertiaClient) +}; diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js new file mode 100644 index 00000000..d176342a --- /dev/null +++ b/daemon/web/components/Login.js @@ -0,0 +1,99 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import InertiaClient from '../client'; +import App from './App'; + +export default class Login extends React.Component { + constructor(props) { + super(props); + this.state = { + username: "", + password: "", + loginAlert: "" + }; + this.handleLoginSubmit = this.handleLoginSubmit.bind(this); + this.handleGetLogs = this.handleGetLogs.bind(this); + this.handleUsernameBlur = this.handleUsernameBlur.bind(this); + this.handlePasswordBlur = this.handlePasswordBlur.bind(this); + } + + async handleLoginSubmit() { + const endpoint = '/web/login'; + const params = { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: 'bear', + password: 'tree', + // username: this.state.username, + // password: this.state.password, + email: "", + admin: true + }) + }; + + const response = await this.props.client._post(endpoint, params); + console.log("Login response is: ", response); + // this.setState({loginAlert: response.body}); + } + + async handleGetLogs() { + const endpoint = '/logs'; + const params = { + headers: { + 'Accept': 'application/json' + } + }; + + const response = await this.props.client._get(endpoint, params); + console.log("Logs response is: ", response); + } + + handleUsernameBlur(e) { + this.setState({username: e.target.value}); + } + + handlePasswordBlur(e) { + this.setState({password: e.target.value}); + } + + render () { + return ( +
+

+ +

+

+ This is the Inertia web client! +

+
+ + + +

{this.state.loginAlert}

+ +
+
+ ) + } +} + +App.propTypes = { + client: PropTypes.instanceOf(InertiaClient) +}; + +const styles = { + container: { + display: 'flex', + }, + login: { + display: 'flex', + flexFlow: 'column', + alignItems: 'center' + } +}; + diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index aeef6e07..67b28592 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -4894,6 +4894,18 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "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", @@ -4905,6 +4917,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", @@ -5410,7 +5427,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "requires": { "loose-envify": "1.3.1" } @@ -7812,6 +7828,48 @@ "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", @@ -8142,6 +8200,11 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "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", @@ -9565,6 +9628,11 @@ "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", @@ -9622,6 +9690,14 @@ "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", diff --git a/daemon/web/package.json b/daemon/web/package.json index e8e1d1ed..4ce97df2 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -14,7 +14,8 @@ "dependencies": { "prop-types": "^15.6.1", "react": "^16.2.0", - "react-dom": "^16.2.0" + "react-dom": "^16.2.0", + "react-router-dom": "^4.2.2" }, "devDependencies": { "babel-core": "^6.26.0", From 1bde2f7d3e2d534fd42b389cd5e7fb5ae2f8f2c4 Mon Sep 17 00:00:00 2001 From: John Lee Date: Mon, 16 Apr 2018 03:37:19 -0700 Subject: [PATCH 56/73] layout changes for demo --- daemon/web/components/App.js | 34 +- daemon/web/components/Home.js | 137 +++- daemon/web/components/Login.js | 59 +- daemon/web/index.css | 36 + daemon/web/index.html | 1 + daemon/web/index.js | 1 + daemon/web/package-lock.json | 1164 ++++++++++++++++++++++++++++++-- daemon/web/package.json | 2 + daemon/web/webpack.config.js | 7 +- daemon/web/webpack.prod.js | 7 +- 10 files changed, 1359 insertions(+), 89 deletions(-) create mode 100644 daemon/web/index.css diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index ccabc337..318fcb88 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Redirect, Router, Route } from 'react-router-dom'; +import { Redirect, HashRouter, Route } from 'react-router-dom'; import PropTypes from 'prop-types'; import InertiaClient from '../client'; @@ -7,14 +7,21 @@ import Login from './Login'; import Home from './Home'; import { isAuthenticated } from '../common/AuthService'; -const AuthRoute = ({ component: Component, ...rest }) => ( - ( +const AuthRoute = ({ component: Component, props, ...rest }) => ( + ( isAuthenticated() - ? + ? : )}/> ); +// render a route component with props +const PropsRoute = ({ component: Component, props, ...rest }) => ( + ( + + )}/> +); + export default class App extends React.Component { constructor(props) { super(props); @@ -22,10 +29,13 @@ export default class App extends React.Component { render() { return ( - - - - + +
+ }/> + + +
+
); } } @@ -33,3 +43,11 @@ export default class App extends React.Component { App.propTypes = { client: PropTypes.instanceOf(InertiaClient) }; + +const styles = { + container: { + display: 'flex', + height: '100%', + width: '100%' + } +}; diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js index 620c8ec4..6b9c2d19 100644 --- a/daemon/web/components/Home.js +++ b/daemon/web/components/Home.js @@ -1,20 +1,147 @@ import React from 'react'; -import PropTypes from 'prop-types'; + +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); + } + + async handleGetLogs() { + const endpoint = '/logs'; + const params = { + headers: { + 'Accept': 'application/json' + } + }; + + const response = await this.props.client._get(endpoint, params); } render() { return ( -
-

Welcome to the Inertia dashboard!

+
+ +
+

Inertia Web

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

coming soon!

+
+
+ +
+
); } } -App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) +// 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 index d176342a..1ad766f5 100644 --- a/daemon/web/components/Login.js +++ b/daemon/web/components/Login.js @@ -1,7 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import InertiaClient from '../client'; -import App from './App'; export default class Login extends React.Component { constructor(props) { @@ -12,7 +9,6 @@ export default class Login extends React.Component { loginAlert: "" }; this.handleLoginSubmit = this.handleLoginSubmit.bind(this); - this.handleGetLogs = this.handleGetLogs.bind(this); this.handleUsernameBlur = this.handleUsernameBlur.bind(this); this.handlePasswordBlur = this.handlePasswordBlur.bind(this); } @@ -25,30 +21,21 @@ export default class Login extends React.Component { 'Content-Type': 'application/json' }, body: JSON.stringify({ - username: 'bear', - password: 'tree', - // username: this.state.username, - // password: this.state.password, + username: this.state.username, + password: this.state.password, email: "", admin: true }) }; const response = await this.props.client._post(endpoint, params); - console.log("Login response is: ", response); - // this.setState({loginAlert: response.body}); - } - async handleGetLogs() { - const endpoint = '/logs'; - const params = { - headers: { - 'Accept': 'application/json' - } - }; + if (response.status !== 200) { + this.setState({loginAlert: 'Username and/or password is incorrect'}); + return; + } - const response = await this.props.client._get(endpoint, params); - console.log("Logs response is: ", response); + this.props.history.push('/home'); } handleUsernameBlur(e) { @@ -61,39 +48,47 @@ export default class Login extends React.Component { render () { return ( -
+

+ width="20%"/>

-

- This is the Inertia web client! +

+ Inertia Web

- + -

{this.state.loginAlert}

- +

{this.state.loginAlert}

) } } -App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) -}; - const styles = { container: { display: 'flex', + flexFlow: 'column', + justifyContent: 'center', + height: '100%', + width: '100%' }, + login: { + position: 'relative', display: 'flex', flexFlow: 'column', - alignItems: 'center' + 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 adb21e87..54941cc7 100644 --- a/daemon/web/index.html +++ b/daemon/web/index.html @@ -3,6 +3,7 @@ + Inertia diff --git a/daemon/web/index.js b/daemon/web/index.js index 1832d633..e7dee220 100644 --- a/daemon/web/index.js +++ b/daemon/web/index.js @@ -3,6 +3,7 @@ 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 = (process.env.NODE_ENV === 'development') ? '0.0.0.0:8081' : window.location.host; diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index 67b28592..12f10762 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -69,6 +69,12 @@ "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", @@ -252,6 +258,20 @@ "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", "dev": true }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "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", @@ -1648,6 +1668,16 @@ "pako": "1.0.6" } }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "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", @@ -1799,6 +1829,24 @@ "map-obj": "1.0.1" } }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "dev": true, + "requires": { + "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=", + "dev": true + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1866,6 +1914,15 @@ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "dev": true, + "requires": { + "chalk": "1.1.3" + } + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -2090,6 +2147,15 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.5.1" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -2106,6 +2172,17 @@ "object-visit": "1.0.1" } }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "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", @@ -2121,6 +2198,26 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "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=", + "dev": true, + "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", @@ -2335,6 +2432,34 @@ "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=", + "dev": true + }, + "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==", + "dev": true, + "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", @@ -2347,12 +2472,92 @@ "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=", + "dev": true, + "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=", + "dev": true, + "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=", "dev": true }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "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=", + "dev": true, + "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", @@ -2460,6 +2665,12 @@ "isobject": "3.0.1" } }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, "del": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", @@ -2670,6 +2881,12 @@ "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", "dev": true }, + "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=", + "dev": true + }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -3327,6 +3544,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", @@ -3498,6 +3721,12 @@ } } }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, "flow-parser": { "version": "0.68.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.68.0.tgz", @@ -4959,6 +5188,12 @@ "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=", + "dev": true + }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", @@ -5253,6 +5488,69 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, + "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=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "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" + } + } + } + }, "ieee754": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", @@ -5296,6 +5594,12 @@ "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=", + "dev": true + }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -5449,6 +5753,12 @@ "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", "dev": true }, + "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=", + "dev": true + }, "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", @@ -5739,6 +6049,15 @@ "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=", + "dev": true, + "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", @@ -5811,6 +6130,12 @@ "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==", + "dev": true + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -6238,18 +6563,36 @@ "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, "lodash.some": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -6391,6 +6734,12 @@ "yallist": "2.1.2" } }, + "macaddress": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "dev": true + }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", @@ -6421,6 +6770,12 @@ "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=", + "dev": true + }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", @@ -6955,6 +7310,12 @@ "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=", + "dev": true + }, "normalize-url": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", @@ -6984,6 +7345,12 @@ "boolbase": "1.0.0" } }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -7563,59 +7930,642 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "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==", + "dev": true, + "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=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "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=", + "dev": true, + "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=", - "dev": true + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", "dev": true, "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==", - "dev": true + "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=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true + "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=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } }, - "process-nextick-args": { + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "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" + } + } + } + }, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "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" + } + } + } + }, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "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" + } + } + } + }, + "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=", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "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" + } + } + } + }, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "dev": true, + "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=", + "dev": true + }, + "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 + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.11.1.tgz", + "integrity": "sha512-T/KD65Ot0PB97xTrG8afQ46x3oiVhnfGjGESSI9NWYcG92+OUPZKkwHqGWXH2t9jK1crnQjubECW0FuOth+hxw==", + "dev": true + }, + "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 + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "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==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", @@ -7713,6 +8663,12 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", @@ -7988,6 +8944,42 @@ "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=", + "dev": true, + "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=", + "dev": true + } + } + }, + "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=", + "dev": true, + "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=", + "dev": true + } + } + }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", @@ -8312,6 +9304,12 @@ "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==", + "dev": true + }, "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", @@ -9056,12 +10054,61 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "style-loader": { + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz", + "integrity": "sha512-2I7AVP73MvK33U7B9TKlYZAqdROyMXDYSMvHLX43qy3GCOaJNiV6i0v/sv9idWIaQ42Yn2dNv79Q5mKXbKhAZg==", + "dev": true, + "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=", "dev": true }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "dev": true, + "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=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "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", @@ -9399,6 +10446,27 @@ } } }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqid": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", + "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "dev": true, + "requires": { + "macaddress": "0.2.8" + } + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, "unique-filename": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", @@ -9639,6 +10707,12 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "vendors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", + "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", + "dev": true + }, "vinyl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", @@ -10204,6 +11278,12 @@ "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=", + "dev": true + }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", diff --git a/daemon/web/package.json b/daemon/web/package.json index 4ce97df2..bd4aa2eb 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -25,9 +25,11 @@ "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-3": "^6.24.1", + "css-loader": "^0.28.11", "eslint": "^4.19.1", "eslint-plugin-react": "^7.6.0", "html-webpack-plugin": "^3.1.0", + "style-loader": "^0.20.3", "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 16767c2a..bba8e4a1 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -20,7 +20,7 @@ const config = { rules: [ { test: /\.jsx?$/, - exclude: '/node_modules/', + exclude: /node_modules/, use: [ { loader: 'babel-loader', @@ -30,6 +30,11 @@ const config = { } ], }, + { + test: /\.css/, + exclude: /node_modules/, + use: ['style-loader', 'css-loader'], + } ], }, plugins: [ diff --git a/daemon/web/webpack.prod.js b/daemon/web/webpack.prod.js index f9910c07..6da67222 100644 --- a/daemon/web/webpack.prod.js +++ b/daemon/web/webpack.prod.js @@ -19,7 +19,7 @@ const config = { rules: [ { test: /\.jsx?$/, - exclude: '/node_modules/', + exclude: /node_modules/, use: [ { loader: 'babel-loader', @@ -29,6 +29,11 @@ const config = { } ], }, + { + test: /\.css/, + exclude: /node_modules/, + use: ['style-loader', 'css-loader'], + } ], }, plugins: [ From f8b2008412fe9d38f9014713ddb7a0fb2e99fae6 Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 17 Apr 2018 21:05:00 -0700 Subject: [PATCH 57/73] delete unused authservice.js file --- daemon/web/common/AuthService.js | 38 -------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 daemon/web/common/AuthService.js diff --git a/daemon/web/common/AuthService.js b/daemon/web/common/AuthService.js deleted file mode 100644 index d3c2be1b..00000000 --- a/daemon/web/common/AuthService.js +++ /dev/null @@ -1,38 +0,0 @@ - - -const TOKEN_KEY = 'inertia'; - -export const login = () => { - // set jwt -}; - -export const logout = () => { - // clear jwt -}; - -export const isAuthenticated = () => { - // verifies that jwt is still valid - return true; -}; - -export const guardRoute = () => { - if (!isAuthenticated()) { - // push route - } -}; - -export const setToken = (token) => { - // store jwt in cookie -}; - -export const getToken = () => { - // retrieve from cookie -}; - -export const removeToken = () => { - // clear from cookie -}; - -export const isExpired = () => { - // check if token is expired -}; From 776bd547d3582678ed3ea460e25fab958bf0a0ad Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 17 Apr 2018 21:25:00 -0700 Subject: [PATCH 58/73] fix webpack error --- daemon/web/components/App.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index 318fcb88..1e061fc4 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -5,7 +5,11 @@ import PropTypes from 'prop-types'; import InertiaClient from '../client'; import Login from './Login'; import Home from './Home'; -import { isAuthenticated } from '../common/AuthService'; + +const isAuthenticated = () => { + // TODO: authentication check prior to route change + return true; +}; const AuthRoute = ({ component: Component, props, ...rest }) => ( ( From dd5a6866e75b5ab39708bbf78693a87c23a94eb3 Mon Sep 17 00:00:00 2001 From: John Lee Date: Tue, 17 Apr 2018 22:03:46 -0700 Subject: [PATCH 59/73] fixing ci errors --- daemon/web/package-lock.json | 2295 ++++++++-------------------------- daemon/web/package.json | 10 +- 2 files changed, 516 insertions(+), 1789 deletions(-) diff --git a/daemon/web/package-lock.json b/daemon/web/package-lock.json index 12f10762..5d9407c3 100644 --- a/daemon/web/package-lock.json +++ b/daemon/web/package-lock.json @@ -7,14 +7,12 @@ "@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", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, "requires": { "mime-types": "2.1.18", "negotiator": "0.6.1" @@ -23,14 +21,12 @@ "acorn": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", - "dev": true + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" }, "acorn-dynamic-import": { "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==", - "dev": true, "requires": { "acorn": "5.5.3" } @@ -39,7 +35,6 @@ "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" }, @@ -47,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=" } } }, @@ -56,7 +50,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.3.0.tgz", "integrity": "sha1-FlCkERTvAFdMrBC4Ay2PTBSBLac=", - "dev": true, "requires": { "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", @@ -66,50 +59,42 @@ "ajv-keywords": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", - "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", - "dev": true + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=" }, "alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true + "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", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "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==", - "dev": true, "requires": { "micromatch": "3.1.10", "normalize-path": "2.1.1" @@ -118,14 +103,12 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true + "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" } @@ -133,44 +116,37 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, "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", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, "array-flatten": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", - "dev": true + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=" }, "array-includes": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, "requires": { "define-properties": "1.1.2", "es-abstract": "1.10.0" @@ -180,7 +156,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -188,20 +163,17 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "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", @@ -212,7 +184,6 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, "requires": { "bn.js": "4.11.8", "inherits": "2.0.3", @@ -223,7 +194,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, "requires": { "util": "0.10.3" } @@ -231,38 +201,32 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, "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": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, "atob": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", - "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", - "dev": true + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=" }, "autoprefixer": { "version": "6.7.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, "requires": { "browserslist": "1.7.7", "caniuse-db": "1.0.30000830", @@ -276,7 +240,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, "requires": { "chalk": "1.1.3", "esutils": "2.0.2", @@ -287,7 +250,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-generator": "6.26.1", @@ -314,7 +276,6 @@ "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -330,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", @@ -341,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", @@ -352,7 +311,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -363,7 +321,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -375,7 +332,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -386,14 +342,12 @@ "babel-helper-evaluate-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.3.0.tgz", - "integrity": "sha512-dRFlMTqUJRGzx5a2smKxmptDdNCXKSkPcXWzKLwAV72hvIZumrd/0z9RcewHkr7PmAEq+ETtpD1GK6wZ6ZUXzw==", - "dev": true + "integrity": "sha512-dRFlMTqUJRGzx5a2smKxmptDdNCXKSkPcXWzKLwAV72hvIZumrd/0z9RcewHkr7PmAEq+ETtpD1GK6wZ6ZUXzw==" }, "babel-helper-explode-assignable-expression": { "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", @@ -404,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", @@ -415,14 +368,12 @@ "babel-helper-flip-expressions": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.3.0.tgz", - "integrity": "sha512-kNGohWmtAG3b7tN1xocRQ5rsKkH/hpvZsMiGOJ1VwGJKhnwzR5KlB3rvKBaBPl5/IGHcopB2JN+r1SUEX1iMAw==", - "dev": true + "integrity": "sha512-kNGohWmtAG3b7tN1xocRQ5rsKkH/hpvZsMiGOJ1VwGJKhnwzR5KlB3rvKBaBPl5/IGHcopB2JN+r1SUEX1iMAw==" }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, "requires": { "babel-helper-get-function-arity": "6.24.1", "babel-runtime": "6.26.0", @@ -435,7 +386,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -445,7 +395,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -454,26 +403,22 @@ "babel-helper-is-nodes-equiv": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", - "dev": true + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=" }, "babel-helper-is-void-0": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.3.0.tgz", - "integrity": "sha512-JVqdX8y7Rf/x4NwbqtUI7mdQjL9HWoDnoAEQ8Gv8oxzjvbJv+n75f7l36m9Y8C7sCUltX3V5edndrp7Hp1oSXQ==", - "dev": true + "integrity": "sha512-JVqdX8y7Rf/x4NwbqtUI7mdQjL9HWoDnoAEQ8Gv8oxzjvbJv+n75f7l36m9Y8C7sCUltX3V5edndrp7Hp1oSXQ==" }, "babel-helper-mark-eval-scopes": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.3.0.tgz", - "integrity": "sha512-nrho5Dg4vl0VUgURVpGpEGiwbst5JX7efIyDHFxmkCx/ocQFnrPt8ze9Kxl6TKjR29bJ7D/XKY1NMlSxOQJRbQ==", - "dev": true + "integrity": "sha512-nrho5Dg4vl0VUgURVpGpEGiwbst5JX7efIyDHFxmkCx/ocQFnrPt8ze9Kxl6TKjR29bJ7D/XKY1NMlSxOQJRbQ==" }, "babel-helper-optimise-call-expression": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -483,7 +428,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -494,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", @@ -506,14 +449,12 @@ "babel-helper-remove-or-void": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.3.0.tgz", - "integrity": "sha512-D68W1M3ibCcbg0ysh3ww4/O0g10X1CXK720oOuR8kpfY7w0yP4tVcpK7zDmI1JecynycTQYAZ1rhLJo9aVtIKQ==", - "dev": true + "integrity": "sha512-D68W1M3ibCcbg0ysh3ww4/O0g10X1CXK720oOuR8kpfY7w0yP4tVcpK7zDmI1JecynycTQYAZ1rhLJo9aVtIKQ==" }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, "requires": { "babel-helper-optimise-call-expression": "6.24.1", "babel-messages": "6.23.0", @@ -526,14 +467,12 @@ "babel-helper-to-multiple-sequence-expressions": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.3.0.tgz", - "integrity": "sha512-1uCrBD+EAaMnAYh7hc944n8Ga19y3daEnoXWPYDvFVsxMCc1l8aDjksApaCEaNSSuewq8BEcff47Cy1PbLg2Gw==", - "dev": true + "integrity": "sha512-1uCrBD+EAaMnAYh7hc944n8Ga19y3daEnoXWPYDvFVsxMCc1l8aDjksApaCEaNSSuewq8BEcff47Cy1PbLg2Gw==" }, "babel-helpers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -543,7 +482,6 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", - "dev": true, "requires": { "find-cache-dir": "1.0.0", "loader-utils": "1.1.0", @@ -554,7 +492,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -563,7 +500,6 @@ "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==", - "dev": true, "requires": { "babel-core": "6.26.0", "babel-preset-minify": "0.3.0", @@ -574,7 +510,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -583,7 +518,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.3.0.tgz", "integrity": "sha512-MqhSHlxkmgURqj3144qPksbZ/qof1JWdumcbucc4tysFcf3P3V3z3munTevQgKEFNMd8F5/ECGnwb63xogLjAg==", - "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -592,7 +526,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.3.0.tgz", "integrity": "sha512-1XeRpx+aY1BuNY6QU/cm6P+FtEi3ar3XceYbmC+4q4W+2Ewq5pL7V68oHg1hKXkBIE0Z4/FjSoHz6vosZLOe/A==", - "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -601,7 +534,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.3.0.tgz", "integrity": "sha512-SjM2Fzg85YZz+q/PNJ/HU4O3W98FKFOiP9K5z3sfonlamGOzvZw3Eup2OTiEBsbbqTeY8yzNCAv3qpJRYCgGmw==", - "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0", "babel-helper-mark-eval-scopes": "0.3.0", @@ -613,7 +545,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.3.0.tgz", "integrity": "sha512-B8lK+ekcpSNVH7PZpWDe5nC5zxjRiiT4nTsa6h3QkF3Kk6y9qooIFLemdGlqBq6j0zALEnebvCpw8v7gAdpgnw==", - "dev": true, "requires": { "babel-helper-is-void-0": "0.3.0" } @@ -622,7 +553,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.3.0.tgz", "integrity": "sha512-O+6CvF5/Ttsth3LMg4/BhyvVZ82GImeKMXGdVRQGK/8jFiP15EjRpdgFlxv3cnqRjqdYxLCS6r28VfLpb9C/kA==", - "dev": true, "requires": { "babel-helper-flip-expressions": "0.3.0" } @@ -630,14 +560,12 @@ "babel-plugin-minify-infinity": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.3.0.tgz", - "integrity": "sha512-Sj8ia3/w9158DWieUxU6/VvnYVy59geeFEkVgLZYBE8EBP+sN48tHtBM/jSgz0ejEdBlcfqJ6TnvPmVXTzR2BQ==", - "dev": true + "integrity": "sha512-Sj8ia3/w9158DWieUxU6/VvnYVy59geeFEkVgLZYBE8EBP+sN48tHtBM/jSgz0ejEdBlcfqJ6TnvPmVXTzR2BQ==" }, "babel-plugin-minify-mangle-names": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.3.0.tgz", "integrity": "sha512-PYTonhFWURsfAN8achDwvR5Xgy6EeTClLz+fSgGRqjAIXb0OyFm3/xfccbQviVi1qDXmlSnt6oJhBg8KE4Fn7Q==", - "dev": true, "requires": { "babel-helper-mark-eval-scopes": "0.3.0" } @@ -645,20 +573,17 @@ "babel-plugin-minify-numeric-literals": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.3.0.tgz", - "integrity": "sha512-TgZj6ay8zDw74AS3yiIfoQ8vRSNJisYO/Du60S8nPV7EW7JM6fDMx5Sar6yVHlVuuwNgvDUBh191K33bVrAhpg==", - "dev": true + "integrity": "sha512-TgZj6ay8zDw74AS3yiIfoQ8vRSNJisYO/Du60S8nPV7EW7JM6fDMx5Sar6yVHlVuuwNgvDUBh191K33bVrAhpg==" }, "babel-plugin-minify-replace": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.3.0.tgz", - "integrity": "sha512-VR6tTg2Lt0TicHIOw04fsUtpPw7RaRP8PC8YzSFwEixnzvguZjZJoL7TgG7ZyEWQD1cJ96UezswECmFNa815bg==", - "dev": true + "integrity": "sha512-VR6tTg2Lt0TicHIOw04fsUtpPw7RaRP8PC8YzSFwEixnzvguZjZJoL7TgG7ZyEWQD1cJ96UezswECmFNa815bg==" }, "babel-plugin-minify-simplify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.3.0.tgz", "integrity": "sha512-2M16ytQOCqBi7bYMu4DCWn8e6KyFCA108F6+tVrBJxOmm5u2sOmTFEa8s94tR9RHRRNYmcUf+rgidfnzL3ik9Q==", - "dev": true, "requires": { "babel-helper-flip-expressions": "0.3.0", "babel-helper-is-nodes-equiv": "0.0.1", @@ -669,7 +594,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.3.0.tgz", "integrity": "sha512-XRXpvsUCPeVw9YEUw+9vSiugcSZfow81oIJT0yR9s8H4W7yJ6FHbImi5DJHoL8KcDUjYnL9wYASXk/fOkbyR6Q==", - "dev": true, "requires": { "babel-helper-is-void-0": "0.3.0" } @@ -677,80 +601,67 @@ "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", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" }, "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" }, "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", @@ -761,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", @@ -772,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", @@ -783,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", @@ -795,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", @@ -808,7 +715,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -817,7 +723,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -826,7 +731,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0", @@ -839,7 +743,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, "requires": { "babel-helper-define-map": "6.26.0", "babel-helper-function-name": "6.24.1", @@ -856,7 +759,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-template": "6.26.0" @@ -866,7 +768,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -875,7 +776,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -885,7 +785,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -894,7 +793,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, "requires": { "babel-helper-function-name": "6.24.1", "babel-runtime": "6.26.0", @@ -905,7 +803,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -914,7 +811,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", "babel-runtime": "6.26.0", @@ -925,7 +821,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "dev": true, "requires": { "babel-plugin-transform-strict-mode": "6.24.1", "babel-runtime": "6.26.0", @@ -937,7 +832,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, "requires": { "babel-helper-hoist-variables": "6.24.1", "babel-runtime": "6.26.0", @@ -948,7 +842,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, "requires": { "babel-plugin-transform-es2015-modules-amd": "6.24.1", "babel-runtime": "6.26.0", @@ -959,7 +852,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, "requires": { "babel-helper-replace-supers": "6.24.1", "babel-runtime": "6.26.0" @@ -969,7 +861,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, "requires": { "babel-helper-call-delegate": "6.24.1", "babel-helper-get-function-arity": "6.24.1", @@ -983,7 +874,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -993,7 +883,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1002,7 +891,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -1013,7 +901,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1022,7 +909,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1031,7 +917,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, "requires": { "babel-helper-regex": "6.26.0", "babel-runtime": "6.26.0", @@ -1042,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", @@ -1053,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" @@ -1063,7 +946,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, "requires": { "babel-plugin-syntax-flow": "6.18.0", "babel-runtime": "6.26.0" @@ -1072,32 +954,27 @@ "babel-plugin-transform-inline-consecutive-adds": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.3.0.tgz", - "integrity": "sha512-iZsYAIjYLLfLK0yN5WVT7Xf7Y3wQ9Z75j9A8q/0IglQSpUt2ppTdHlwl/GeaXnxdaSmsxBu861klbTBbv2n+RA==", - "dev": true + "integrity": "sha512-iZsYAIjYLLfLK0yN5WVT7Xf7Y3wQ9Z75j9A8q/0IglQSpUt2ppTdHlwl/GeaXnxdaSmsxBu861klbTBbv2n+RA==" }, "babel-plugin-transform-member-expression-literals": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.0.tgz", - "integrity": "sha512-bxtac+8w755ctVeDs4vU98RhWY49eW1wO02HAN+eirZYSKk/dVrKONIznXbHmxWKxT4UX1rpTKOCyezuzLpbTw==", - "dev": true + "integrity": "sha512-bxtac+8w755ctVeDs4vU98RhWY49eW1wO02HAN+eirZYSKk/dVrKONIznXbHmxWKxT4UX1rpTKOCyezuzLpbTw==" }, "babel-plugin-transform-merge-sibling-variables": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.0.tgz", - "integrity": "sha512-9G1URVEEKoQLDqe0GwqYudECN7kE/q0OCNo5TiD1iwWnnaKi97xY915l5r2KKUvNflXEm9c3faNWknSXYQ7h6Q==", - "dev": true + "integrity": "sha512-9G1URVEEKoQLDqe0GwqYudECN7kE/q0OCNo5TiD1iwWnnaKi97xY915l5r2KKUvNflXEm9c3faNWknSXYQ7h6Q==" }, "babel-plugin-transform-minify-booleans": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.0.tgz", - "integrity": "sha512-JtpyTRyF+wF/r7GSxpRbNCrVve5M/aCC8xoGcnFItaPUDqjxKmFYvBzMc9u+g0lgo8NWjuZLc16MYaIwkHKD/A==", - "dev": true + "integrity": "sha512-JtpyTRyF+wF/r7GSxpRbNCrVve5M/aCC8xoGcnFItaPUDqjxKmFYvBzMc9u+g0lgo8NWjuZLc16MYaIwkHKD/A==" }, "babel-plugin-transform-object-rest-spread": { "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" @@ -1107,7 +984,6 @@ "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.0.tgz", "integrity": "sha512-B8s+71+4DPye9+pmZiPGgLPy3YqcmIuvE/9UcZLczPlwL5ALwF6qRUdLC3Fk17NhL6jxp4u33ZVZ8R4kvASPzw==", - "dev": true, "requires": { "esutils": "2.0.2" } @@ -1116,7 +992,6 @@ "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, "requires": { "babel-runtime": "6.26.0" } @@ -1125,7 +1000,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, "requires": { "babel-helper-builder-react-jsx": "6.26.0", "babel-plugin-syntax-jsx": "6.18.0", @@ -1136,7 +1010,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -1146,7 +1019,6 @@ "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-runtime": "6.26.0" @@ -1156,7 +1028,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, "requires": { "regenerator-transform": "0.10.1" } @@ -1164,26 +1035,22 @@ "babel-plugin-transform-regexp-constructors": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.3.0.tgz", - "integrity": "sha512-h92YHzyl042rb0naKO8frTHntpRFwRgKkfWD8602kFHoQingjJNtbvZzvxqHncJ6XmKVyYvfrBpDOSkCTDIIxw==", - "dev": true + "integrity": "sha512-h92YHzyl042rb0naKO8frTHntpRFwRgKkfWD8602kFHoQingjJNtbvZzvxqHncJ6XmKVyYvfrBpDOSkCTDIIxw==" }, "babel-plugin-transform-remove-console": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.0.tgz", - "integrity": "sha512-mck9//yGTwObqqqDzY/sISO88/5/XfIB3ILb4uJLXk2xq124NT4yQVjFSRgVSbLcNq8OyBAn2acxKUqg4W/okQ==", - "dev": true + "integrity": "sha512-mck9//yGTwObqqqDzY/sISO88/5/XfIB3ILb4uJLXk2xq124NT4yQVjFSRgVSbLcNq8OyBAn2acxKUqg4W/okQ==" }, "babel-plugin-transform-remove-debugger": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.0.tgz", - "integrity": "sha512-i/HWGjsmL2d1N2dl+eIzf44XpSP5v7hi1/GXB0xzom9kjrU8js3T8Kadizn95ZxfHK592Vg8P4JJWP/fvimEWw==", - "dev": true + "integrity": "sha512-i/HWGjsmL2d1N2dl+eIzf44XpSP5v7hi1/GXB0xzom9kjrU8js3T8Kadizn95ZxfHK592Vg8P4JJWP/fvimEWw==" }, "babel-plugin-transform-remove-undefined": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.3.0.tgz", "integrity": "sha512-TYGQucc8iP3LJwN3kDZLEz5aa/2KuFrqpT+s8f8NnHsBU1sAgR3y8Opns0xhC+smyDYWscqFCKM1gbkWQOhhnw==", - "dev": true, "requires": { "babel-helper-evaluate-path": "0.3.0" } @@ -1191,14 +1058,12 @@ "babel-plugin-transform-simplify-comparison-operators": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.0.tgz", - "integrity": "sha512-EJyfYeph0CSekwQuwWVwJqy2go/bETkR95iaWQ/HTUis7tkCGNYmXngaFzuIXdmoPXfvmXYCvAXR4/93hqHVjw==", - "dev": true + "integrity": "sha512-EJyfYeph0CSekwQuwWVwJqy2go/bETkR95iaWQ/HTUis7tkCGNYmXngaFzuIXdmoPXfvmXYCvAXR4/93hqHVjw==" }, "babel-plugin-transform-strict-mode": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0" @@ -1207,14 +1072,12 @@ "babel-plugin-transform-undefined-to-void": { "version": "6.9.0", "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==", - "dev": true + "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=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "core-js": "2.5.3", @@ -1224,8 +1087,7 @@ "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" } } }, @@ -1233,7 +1095,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", @@ -1265,7 +1126,6 @@ "version": "6.23.0", "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, "requires": { "babel-plugin-transform-flow-strip-types": "6.22.0" } @@ -1274,7 +1134,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.3.0.tgz", "integrity": "sha512-+VV2GWEyak3eDOmzT1DDMuqHrw3VbE9nBNkx2LLVs4pH/Me32ND8DRpVDd8IRvk1xX5p75nygyRPtkMh6GIAbQ==", - "dev": true, "requires": { "babel-plugin-minify-builtins": "0.3.0", "babel-plugin-minify-constant-folding": "0.3.0", @@ -1305,7 +1164,6 @@ "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, "requires": { "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-react-display-name": "6.25.0", @@ -1319,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", @@ -1330,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", @@ -1342,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", @@ -1355,7 +1210,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, "requires": { "babel-core": "6.26.0", "babel-runtime": "6.26.0", @@ -1370,7 +1224,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "2.5.3", "regenerator-runtime": "0.11.1" @@ -1380,7 +1233,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-traverse": "6.26.0", @@ -1393,7 +1245,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, "requires": { "babel-code-frame": "6.26.0", "babel-messages": "6.23.0", @@ -1410,7 +1261,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", @@ -1421,20 +1271,17 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "1.0.1", "class-utils": "0.3.6", @@ -1449,7 +1296,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -1459,50 +1305,42 @@ "base64-js": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", - "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", - "dev": true + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" }, "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==", - "dev": true + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "body-parser": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, "requires": { "bytes": "3.0.0", "content-type": "1.0.4", @@ -1520,7 +1358,6 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", - "dev": true, "requires": { "array-flatten": "2.1.1", "deep-equal": "1.0.1", @@ -1533,14 +1370,12 @@ "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -1550,7 +1385,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", - "dev": true, "requires": { "arr-flatten": "1.1.0", "array-unique": "0.3.2", @@ -1570,7 +1404,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -1579,7 +1412,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -1587,22 +1419,19 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browserify-aes": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", - "dev": true, "requires": { "buffer-xor": "1.0.3", "cipher-base": "1.0.4", @@ -1616,7 +1445,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "dev": true, "requires": { "browserify-aes": "1.1.1", "browserify-des": "1.0.0", @@ -1627,7 +1455,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dev": true, "requires": { "cipher-base": "1.0.4", "des.js": "1.0.0", @@ -1638,7 +1465,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, "requires": { "bn.js": "4.11.8", "randombytes": "2.0.6" @@ -1648,7 +1474,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, "requires": { "bn.js": "4.11.8", "browserify-rsa": "4.0.1", @@ -1663,7 +1488,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, "requires": { "pako": "1.0.6" } @@ -1672,7 +1496,6 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, "requires": { "caniuse-db": "1.0.30000830", "electron-to-chromium": "1.3.42" @@ -1682,7 +1505,6 @@ "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, "requires": { "base64-js": "1.2.3", "ieee754": "1.1.11", @@ -1692,38 +1514,32 @@ "buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", - "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", - "dev": true + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, "cacache": { "version": "10.0.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, "requires": { "bluebird": "3.5.1", "chownr": "1.0.1", @@ -1743,8 +1559,7 @@ "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==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" } } }, @@ -1752,7 +1567,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "1.0.0", "component-emitter": "1.2.1", @@ -1769,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", @@ -1783,8 +1596,7 @@ "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 + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" } } }, @@ -1792,7 +1604,6 @@ "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" } @@ -1800,14 +1611,12 @@ "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", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, "requires": { "no-case": "2.3.2", "upper-case": "1.1.3" @@ -1816,14 +1625,12 @@ "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, "requires": { "camelcase": "2.1.1", "map-obj": "1.0.1" @@ -1833,7 +1640,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, "requires": { "browserslist": "1.7.7", "caniuse-db": "1.0.30000830", @@ -1844,14 +1650,12 @@ "caniuse-db": { "version": "1.0.30000830", "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000830.tgz", - "integrity": "sha1-bkUlWzRWSf0V/1kHLaHhK7PeLxM=", - "dev": true + "integrity": "sha1-bkUlWzRWSf0V/1kHLaHhK7PeLxM=" }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", @@ -1863,14 +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.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", - "dev": true, "requires": { "anymatch": "2.0.0", "async-each": "1.0.1", @@ -1889,20 +1691,17 @@ "chownr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true + "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=", - "dev": true + "integrity": "sha1-kPNohdU0WlBiEzLwcXtZWIPV2YI=" }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -1911,14 +1710,12 @@ "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==", - "dev": true, "requires": { "chalk": "1.1.3" } @@ -1927,7 +1724,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "3.1.0", "define-property": "0.2.5", @@ -1939,7 +1735,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -1948,7 +1743,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -1957,7 +1751,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -1968,7 +1761,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -1977,7 +1769,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -1988,7 +1779,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -1998,8 +1788,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -2007,7 +1796,6 @@ "version": "4.1.11", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", - "dev": true, "requires": { "source-map": "0.5.7" } @@ -2016,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" } @@ -2024,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" }, @@ -2039,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=" } } }, @@ -2048,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" @@ -2057,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", @@ -2076,14 +1857,12 @@ "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": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1", @@ -2094,7 +1873,6 @@ "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", @@ -2106,20 +1884,17 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true + "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" } @@ -2127,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", @@ -2144,14 +1917,12 @@ "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=", - "dev": true, "requires": { "q": "1.5.1" } @@ -2159,14 +1930,12 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "1.0.0", "object-visit": "1.0.1" @@ -2176,7 +1945,6 @@ "version": "0.11.4", "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, "requires": { "clone": "1.0.4", "color-convert": "1.9.1", @@ -2187,7 +1955,6 @@ "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" } @@ -2195,14 +1962,12 @@ "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=", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -2211,7 +1976,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, "requires": { "color": "0.11.4", "css-color-names": "0.0.4", @@ -2221,32 +1985,27 @@ "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.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, "compressible": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", - "dev": true, "requires": { "mime-db": "1.33.0" } @@ -2255,7 +2014,6 @@ "version": "1.7.2", "resolved": "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz", "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", - "dev": true, "requires": { "accepts": "1.3.5", "bytes": "3.0.0", @@ -2269,14 +2027,12 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "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", @@ -2286,14 +2042,12 @@ "connect-history-api-fallback": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", - "dev": true + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=" }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, "requires": { "date-now": "0.1.4" } @@ -2301,44 +2055,37 @@ "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true + "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==", - "dev": true, "requires": { "aproba": "1.2.0", "fs-write-stream-atomic": "1.0.10", @@ -2351,26 +2098,22 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", - "dev": true + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "create-ecdh": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dev": true, "requires": { "bn.js": "4.11.8", "elliptic": "6.4.0" @@ -2380,7 +2123,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dev": true, "requires": { "cipher-base": "1.0.4", "inherits": "2.0.3", @@ -2392,7 +2134,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "dev": true, "requires": { "cipher-base": "1.0.4", "create-hash": "1.1.3", @@ -2406,7 +2147,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, "requires": { "lru-cache": "4.1.2", "shebang-command": "1.2.0", @@ -2417,7 +2157,6 @@ "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, "requires": { "browserify-cipher": "1.0.0", "browserify-sign": "4.0.4", @@ -2435,14 +2174,12 @@ "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=", - "dev": true + "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==", - "dev": true, "requires": { "babel-code-frame": "6.26.0", "css-selector-tokenizer": "0.7.0", @@ -2464,7 +2201,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, "requires": { "boolbase": "1.0.0", "css-what": "2.1.0", @@ -2476,7 +2212,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, "requires": { "cssesc": "0.1.0", "fastparse": "1.1.1", @@ -2487,7 +2222,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, "requires": { "regenerate": "1.3.3", "regjsgen": "0.2.0", @@ -2499,20 +2233,17 @@ "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=", - "dev": true + "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=", - "dev": true + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" }, "cssnano": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, "requires": { "autoprefixer": "6.7.7", "decamelize": "1.2.0", @@ -2552,7 +2283,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, "requires": { "clap": "1.2.3", "source-map": "0.5.7" @@ -2562,7 +2292,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, "requires": { "array-find-index": "1.0.2" } @@ -2570,38 +2299,32 @@ "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true + "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", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, "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", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -2609,20 +2332,17 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress-response": { "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" } @@ -2630,26 +2350,22 @@ "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, "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", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, "requires": { "foreach": "2.0.5", "object-keys": "1.0.11" @@ -2659,7 +2375,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "1.0.2", "isobject": "3.0.1" @@ -2668,14 +2383,12 @@ "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "del": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, "requires": { "globby": "6.1.0", "is-path-cwd": "1.0.0", @@ -2688,14 +2401,12 @@ "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -2704,20 +2415,17 @@ "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "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", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -2725,20 +2433,17 @@ "detect-node": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", - "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", - "dev": true + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=" }, "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", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dev": true, "requires": { "bn.js": "4.11.8", "miller-rabin": "4.0.1", @@ -2748,14 +2453,12 @@ "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", - "dev": true + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" }, "dns-packet": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", - "dev": true, "requires": { "ip": "1.1.5", "safe-buffer": "5.1.1" @@ -2765,7 +2468,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", - "dev": true, "requires": { "buffer-indexof": "1.1.1" } @@ -2774,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" } @@ -2783,7 +2484,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", - "dev": true, "requires": { "utila": "0.3.3" }, @@ -2791,8 +2491,7 @@ "utila": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" } } }, @@ -2800,7 +2499,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, "requires": { "domelementtype": "1.1.3", "entities": "1.1.1" @@ -2809,28 +2507,24 @@ "domelementtype": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" } } }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" }, "domhandler": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", - "dev": true, "requires": { "domelementtype": "1.3.0" } @@ -2839,7 +2533,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, "requires": { "dom-serializer": "0.1.0", "domelementtype": "1.3.0" @@ -2848,14 +2541,12 @@ "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==", - "dev": true, "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", @@ -2866,38 +2557,32 @@ "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", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "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=", - "dev": true + "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", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, "requires": { "bn.js": "4.11.8", "brorand": "1.1.0", @@ -2911,14 +2596,12 @@ "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "encoding": { "version": "0.1.12", @@ -2932,7 +2615,6 @@ "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==", - "dev": true, "requires": { "once": "1.4.0" } @@ -2941,7 +2623,6 @@ "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", @@ -2951,14 +2632,12 @@ "entities": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, "requires": { "prr": "1.0.1" } @@ -2967,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" @@ -2977,7 +2655,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, "requires": { "is-arrayish": "0.2.1" } @@ -2986,7 +2663,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", - "dev": true, "requires": { "es-to-primitive": "1.1.1", "function-bind": "1.1.1", @@ -2999,7 +2675,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, "requires": { "is-callable": "1.1.3", "is-date-object": "1.0.1", @@ -3009,20 +2684,17 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, "requires": { "ajv": "5.5.2", "babel-code-frame": "6.26.0", @@ -3068,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", @@ -3079,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" } @@ -3095,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", @@ -3106,7 +2774,6 @@ "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" } @@ -3114,14 +2781,12 @@ "globals": { "version": "11.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", - "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", - "dev": true + "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" } @@ -3130,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" } @@ -3141,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", @@ -3153,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" @@ -3162,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" @@ -3178,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" } @@ -3194,7 +2852,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, "requires": { "estraverse": "4.2.0" } @@ -3202,38 +2859,32 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eventemitter3": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", - "dev": true + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=" }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, "eventsource": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", - "dev": true, "requires": { "original": "1.0.0" } @@ -3242,7 +2893,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, "requires": { "md5.js": "1.3.4", "safe-buffer": "5.1.1" @@ -3252,7 +2902,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, "requires": { "cross-spawn": "5.1.0", "get-stream": "3.0.0", @@ -3266,14 +2915,12 @@ "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", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, "requires": { "debug": "2.6.9", "define-property": "0.2.5", @@ -3288,7 +2935,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -3297,7 +2943,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -3306,7 +2951,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -3315,7 +2959,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3326,7 +2969,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -3335,7 +2977,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3346,7 +2987,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -3356,8 +2996,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -3365,7 +3004,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, "requires": { "fill-range": "2.2.3" }, @@ -3374,7 +3012,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -3387,7 +3024,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -3396,7 +3032,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -3407,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" } @@ -3416,7 +3050,6 @@ "version": "4.16.3", "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "dev": true, "requires": { "accepts": "1.3.5", "array-flatten": "1.1.1", @@ -3453,8 +3086,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" } } }, @@ -3462,7 +3094,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "1.0.0", "is-extendable": "1.0.1" @@ -3472,7 +3103,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "2.0.4" } @@ -3483,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", @@ -3494,7 +3123,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, "requires": { "array-unique": "0.3.2", "define-property": "1.0.0", @@ -3510,7 +3138,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -3519,7 +3146,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -3529,32 +3155,27 @@ "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "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=", - "dev": true + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, "requires": { "websocket-driver": "0.7.0" } @@ -3584,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" } @@ -3593,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" @@ -3602,14 +3221,12 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "2.0.1", "is-number": "3.0.0", @@ -3621,7 +3238,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -3632,7 +3248,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "1.0.2", @@ -3647,7 +3262,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, "requires": { "commondir": "1.0.1", "make-dir": "1.2.0", @@ -3658,7 +3272,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, "requires": { "locate-path": "2.0.0" } @@ -3667,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" } @@ -3676,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", @@ -3688,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", @@ -3703,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", @@ -3716,28 +3325,24 @@ "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=", - "dev": true + "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==", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5" @@ -3746,14 +3351,12 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, "requires": { "for-in": "1.0.2" } @@ -3761,20 +3364,17 @@ "foreach": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, "requires": { "map-cache": "0.2.2" } @@ -3782,14 +3382,12 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from2": { "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" @@ -3799,7 +3397,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "iferr": "0.1.5", @@ -3810,14 +3407,12 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", - "dev": true, "optional": true, "requires": { "nan": "2.10.0", @@ -3827,13 +3422,11 @@ "abbrev": { "version": "1.1.0", "bundled": true, - "dev": true, "optional": true }, "ajv": { "version": "4.11.8", "bundled": true, - "dev": true, "optional": true, "requires": { "co": "4.6.0", @@ -3842,19 +3435,16 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "dev": true + "bundled": true }, "aproba": { "version": "1.1.1", "bundled": true, - "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", "bundled": true, - "dev": true, "optional": true, "requires": { "delegates": "1.0.0", @@ -3864,42 +3454,35 @@ "asn1": { "version": "0.2.3", "bundled": true, - "dev": true, "optional": true }, "assert-plus": { "version": "0.2.0", "bundled": true, - "dev": true, "optional": true }, "asynckit": { "version": "0.4.0", "bundled": true, - "dev": true, "optional": true }, "aws-sign2": { "version": "0.6.0", "bundled": true, - "dev": true, "optional": true }, "aws4": { "version": "1.6.0", "bundled": true, - "dev": true, "optional": true }, "balanced-match": { "version": "0.4.2", - "bundled": true, - "dev": true + "bundled": true }, "bcrypt-pbkdf": { "version": "1.0.1", "bundled": true, - "dev": true, "optional": true, "requires": { "tweetnacl": "0.14.5" @@ -3908,7 +3491,6 @@ "block-stream": { "version": "0.0.9", "bundled": true, - "dev": true, "requires": { "inherits": "2.0.3" } @@ -3916,7 +3498,6 @@ "boom": { "version": "2.10.1", "bundled": true, - "dev": true, "requires": { "hoek": "2.16.3" } @@ -3924,7 +3505,6 @@ "brace-expansion": { "version": "1.1.7", "bundled": true, - "dev": true, "requires": { "balanced-match": "0.4.2", "concat-map": "0.0.1" @@ -3932,53 +3512,44 @@ }, "buffer-shims": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "caseless": { "version": "0.12.0", "bundled": true, - "dev": true, "optional": true }, "co": { "version": "4.6.0", "bundled": true, - "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "dev": true + "bundled": true }, "combined-stream": { "version": "1.0.5", "bundled": true, - "dev": true, "requires": { "delayed-stream": "1.0.0" } }, "concat-map": { "version": "0.0.1", - "bundled": true, - "dev": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "dev": true + "bundled": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true }, "cryptiles": { "version": "2.0.5", "bundled": true, - "dev": true, "requires": { "boom": "2.10.1" } @@ -3986,7 +3557,6 @@ "dashdash": { "version": "1.14.1", "bundled": true, - "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0" @@ -3995,7 +3565,6 @@ "assert-plus": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true } } @@ -4003,7 +3572,6 @@ "debug": { "version": "2.6.8", "bundled": true, - "dev": true, "optional": true, "requires": { "ms": "2.0.0" @@ -4012,30 +3580,25 @@ "deep-extend": { "version": "0.4.2", "bundled": true, - "dev": true, "optional": true }, "delayed-stream": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "delegates": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true }, "detect-libc": { "version": "1.0.2", "bundled": true, - "dev": true, "optional": true }, "ecc-jsbn": { "version": "0.1.1", "bundled": true, - "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -4044,24 +3607,20 @@ "extend": { "version": "3.0.1", "bundled": true, - "dev": true, "optional": true }, "extsprintf": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true }, "forever-agent": { "version": "0.6.1", "bundled": true, - "dev": true, "optional": true }, "form-data": { "version": "2.1.4", "bundled": true, - "dev": true, "optional": true, "requires": { "asynckit": "0.4.0", @@ -4071,13 +3630,11 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "fstream": { "version": "1.0.11", "bundled": true, - "dev": true, "requires": { "graceful-fs": "4.1.11", "inherits": "2.0.3", @@ -4088,7 +3645,6 @@ "fstream-ignore": { "version": "1.0.5", "bundled": true, - "dev": true, "optional": true, "requires": { "fstream": "1.0.11", @@ -4099,7 +3655,6 @@ "gauge": { "version": "2.7.4", "bundled": true, - "dev": true, "optional": true, "requires": { "aproba": "1.1.1", @@ -4115,7 +3670,6 @@ "getpass": { "version": "0.1.7", "bundled": true, - "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0" @@ -4124,7 +3678,6 @@ "assert-plus": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true } } @@ -4132,7 +3685,6 @@ "glob": { "version": "7.1.2", "bundled": true, - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4144,19 +3696,16 @@ }, "graceful-fs": { "version": "4.1.11", - "bundled": true, - "dev": true + "bundled": true }, "har-schema": { "version": "1.0.5", "bundled": true, - "dev": true, "optional": true }, "har-validator": { "version": "4.2.1", "bundled": true, - "dev": true, "optional": true, "requires": { "ajv": "4.11.8", @@ -4166,13 +3715,11 @@ "has-unicode": { "version": "2.0.1", "bundled": true, - "dev": true, "optional": true }, "hawk": { "version": "3.1.3", "bundled": true, - "dev": true, "requires": { "boom": "2.10.1", "cryptiles": "2.0.5", @@ -4182,13 +3729,11 @@ }, "hoek": { "version": "2.16.3", - "bundled": true, - "dev": true + "bundled": true }, "http-signature": { "version": "1.1.1", "bundled": true, - "dev": true, "optional": true, "requires": { "assert-plus": "0.2.0", @@ -4199,7 +3744,6 @@ "inflight": { "version": "1.0.6", "bundled": true, - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -4207,19 +3751,16 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "dev": true + "bundled": true }, "ini": { "version": "1.3.4", "bundled": true, - "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -4227,24 +3768,20 @@ "is-typedarray": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true }, "isarray": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "isstream": { "version": "0.1.2", "bundled": true, - "dev": true, "optional": true }, "jodid25519": { "version": "1.0.2", "bundled": true, - "dev": true, "optional": true, "requires": { "jsbn": "0.1.1" @@ -4253,19 +3790,16 @@ "jsbn": { "version": "0.1.1", "bundled": true, - "dev": true, "optional": true }, "json-schema": { "version": "0.2.3", "bundled": true, - "dev": true, "optional": true }, "json-stable-stringify": { "version": "1.0.1", "bundled": true, - "dev": true, "optional": true, "requires": { "jsonify": "0.0.0" @@ -4274,19 +3808,16 @@ "json-stringify-safe": { "version": "5.0.1", "bundled": true, - "dev": true, "optional": true }, "jsonify": { "version": "0.0.0", "bundled": true, - "dev": true, "optional": true }, "jsprim": { "version": "1.4.0", "bundled": true, - "dev": true, "optional": true, "requires": { "assert-plus": "1.0.0", @@ -4298,20 +3829,17 @@ "assert-plus": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true } } }, "mime-db": { "version": "1.27.0", - "bundled": true, - "dev": true + "bundled": true }, "mime-types": { "version": "2.1.15", "bundled": true, - "dev": true, "requires": { "mime-db": "1.27.0" } @@ -4319,20 +3847,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "dev": true, "requires": { "brace-expansion": "1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "dev": true + "bundled": true }, "mkdirp": { "version": "0.5.1", "bundled": true, - "dev": true, "requires": { "minimist": "0.0.8" } @@ -4340,13 +3865,11 @@ "ms": { "version": "2.0.0", "bundled": true, - "dev": true, "optional": true }, "node-pre-gyp": { "version": "0.6.39", "bundled": true, - "dev": true, "optional": true, "requires": { "detect-libc": "1.0.2", @@ -4365,7 +3888,6 @@ "nopt": { "version": "4.0.1", "bundled": true, - "dev": true, "optional": true, "requires": { "abbrev": "1.1.0", @@ -4375,7 +3897,6 @@ "npmlog": { "version": "4.1.0", "bundled": true, - "dev": true, "optional": true, "requires": { "are-we-there-yet": "1.1.4", @@ -4386,25 +3907,21 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "dev": true + "bundled": true }, "oauth-sign": { "version": "0.8.2", "bundled": true, - "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", "bundled": true, - "dev": true, "optional": true }, "once": { "version": "1.4.0", "bundled": true, - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -4412,19 +3929,16 @@ "os-homedir": { "version": "1.0.2", "bundled": true, - "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", "bundled": true, - "dev": true, "optional": true }, "osenv": { "version": "0.1.4", "bundled": true, - "dev": true, "optional": true, "requires": { "os-homedir": "1.0.2", @@ -4433,36 +3947,30 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, - "dev": true + "bundled": true }, "performance-now": { "version": "0.2.0", "bundled": true, - "dev": true, "optional": true }, "process-nextick-args": { "version": "1.0.7", - "bundled": true, - "dev": true + "bundled": true }, "punycode": { "version": "1.4.1", "bundled": true, - "dev": true, "optional": true }, "qs": { "version": "6.4.0", "bundled": true, - "dev": true, "optional": true }, "rc": { "version": "1.2.1", "bundled": true, - "dev": true, "optional": true, "requires": { "deep-extend": "0.4.2", @@ -4474,7 +3982,6 @@ "minimist": { "version": "1.2.0", "bundled": true, - "dev": true, "optional": true } } @@ -4482,7 +3989,6 @@ "readable-stream": { "version": "2.2.9", "bundled": true, - "dev": true, "requires": { "buffer-shims": "1.0.0", "core-util-is": "1.0.2", @@ -4496,7 +4002,6 @@ "request": { "version": "2.81.0", "bundled": true, - "dev": true, "optional": true, "requires": { "aws-sign2": "0.6.0", @@ -4526,38 +4031,32 @@ "rimraf": { "version": "2.6.1", "bundled": true, - "dev": true, "requires": { "glob": "7.1.2" } }, "safe-buffer": { "version": "5.0.1", - "bundled": true, - "dev": true + "bundled": true }, "semver": { "version": "5.3.0", "bundled": true, - "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", "bundled": true, - "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", "bundled": true, - "dev": true, "optional": true }, "sntp": { "version": "1.0.9", "bundled": true, - "dev": true, "requires": { "hoek": "2.16.3" } @@ -4565,7 +4064,6 @@ "sshpk": { "version": "1.13.0", "bundled": true, - "dev": true, "optional": true, "requires": { "asn1": "0.2.3", @@ -4582,7 +4080,6 @@ "assert-plus": { "version": "1.0.0", "bundled": true, - "dev": true, "optional": true } } @@ -4590,7 +4087,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "dev": true, "requires": { "code-point-at": "1.1.0", "is-fullwidth-code-point": "1.0.0", @@ -4600,7 +4096,6 @@ "string_decoder": { "version": "1.0.1", "bundled": true, - "dev": true, "requires": { "safe-buffer": "5.0.1" } @@ -4608,13 +4103,11 @@ "stringstream": { "version": "0.0.5", "bundled": true, - "dev": true, "optional": true }, "strip-ansi": { "version": "3.0.1", "bundled": true, - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -4622,13 +4115,11 @@ "strip-json-comments": { "version": "2.0.1", "bundled": true, - "dev": true, "optional": true }, "tar": { "version": "2.2.1", "bundled": true, - "dev": true, "requires": { "block-stream": "0.0.9", "fstream": "1.0.11", @@ -4638,7 +4129,6 @@ "tar-pack": { "version": "3.4.0", "bundled": true, - "dev": true, "optional": true, "requires": { "debug": "2.6.8", @@ -4654,7 +4144,6 @@ "tough-cookie": { "version": "2.3.2", "bundled": true, - "dev": true, "optional": true, "requires": { "punycode": "1.4.1" @@ -4663,7 +4152,6 @@ "tunnel-agent": { "version": "0.6.0", "bundled": true, - "dev": true, "optional": true, "requires": { "safe-buffer": "5.0.1" @@ -4672,30 +4160,25 @@ "tweetnacl": { "version": "0.14.5", "bundled": true, - "dev": true, "optional": true }, "uid-number": { "version": "0.0.6", "bundled": true, - "dev": true, "optional": true }, "util-deprecate": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true }, "uuid": { "version": "3.0.1", "bundled": true, - "dev": true, "optional": true }, "verror": { "version": "1.3.6", "bundled": true, - "dev": true, "optional": true, "requires": { "extsprintf": "1.0.2" @@ -4704,7 +4187,6 @@ "wide-align": { "version": "1.1.2", "bundled": true, - "dev": true, "optional": true, "requires": { "string-width": "1.0.2" @@ -4712,52 +4194,44 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "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", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "gh-got": { "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" @@ -4767,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", @@ -4788,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" } @@ -4803,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" } @@ -4821,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" } @@ -4830,7 +4298,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4844,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" @@ -4853,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" } @@ -4871,7 +4335,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -4881,7 +4344,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, "requires": { "is-glob": "2.0.1" } @@ -4889,14 +4351,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" } @@ -4907,7 +4367,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, "requires": { "is-glob": "3.1.0", "path-dirname": "1.0.2" @@ -4917,7 +4376,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -4928,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", @@ -4939,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", @@ -4951,14 +4407,12 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, "requires": { "array-union": "1.0.2", "glob": "7.1.2", @@ -4970,8 +4424,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -4979,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", @@ -5003,14 +4455,12 @@ "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "grouped-queue": { "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" } @@ -5018,14 +4468,12 @@ "handle-thing": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", - "dev": true + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=" }, "has": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, "requires": { "function-bind": "1.1.1" } @@ -5034,7 +4482,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -5042,26 +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": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "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" } @@ -5070,7 +4513,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "2.0.6", "has-values": "1.0.0", @@ -5081,7 +4523,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -5091,7 +4532,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -5102,7 +4542,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dev": true, "requires": { "inherits": "2.0.3" } @@ -5111,7 +4550,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.0" @@ -5120,8 +4558,7 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "history": { "version": "4.7.2", @@ -5139,7 +4576,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, "requires": { "hash.js": "1.1.3", "minimalistic-assert": "1.0.0", @@ -5155,7 +4591,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, "requires": { "os-homedir": "1.0.2", "os-tmpdir": "1.0.2" @@ -5165,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" } @@ -5173,14 +4607,12 @@ "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, "requires": { "inherits": "2.0.3", "obuf": "1.1.2", @@ -5191,20 +4623,17 @@ "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=", - "dev": true + "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=", - "dev": true + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" }, "html-minifier": { "version": "3.5.12", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.12.tgz", "integrity": "sha512-+N778qLf0RWBscD0TPGoYdeGNDZ0s76/0pQhY1/409EOudcENkm9IbSkk37RDyPdg/09GVHTKotU4ya93RF1Gg==", - "dev": true, "requires": { "camel-case": "3.0.0", "clean-css": "4.1.11", @@ -5219,14 +4648,12 @@ "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==" }, "uglify-js": { "version": "3.3.16", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.16.tgz", "integrity": "sha512-FMh5SRqJRGhv9BbaTffENIpDDQIoPDR8DBraunGORGhySArsXlw9++CN+BWzPBLpoI4RcSnpfGPnilTxWL3Vvg==", - "dev": true, "requires": { "commander": "2.15.1", "source-map": "0.6.1" @@ -5238,7 +4665,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.1.0.tgz", "integrity": "sha1-bgK6rtsekGMQkX8DI5x5OnWvKIU=", - "dev": true, "requires": { "html-minifier": "3.5.12", "loader-utils": "0.2.17", @@ -5253,7 +4679,6 @@ "version": "0.2.17", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -5267,7 +4692,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "dev": true, "requires": { "domelementtype": "1.3.0", "domhandler": "2.1.0", @@ -5279,7 +4703,6 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "dev": true, "requires": { "domelementtype": "1.3.0" } @@ -5287,14 +4710,12 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -5305,28 +4726,24 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" } } }, "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", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, "requires": { "depd": "1.1.1", "inherits": "2.0.3", @@ -5337,28 +4754,24 @@ "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" } } }, "http-parser-js": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", - "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", - "dev": true + "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==" }, "http-proxy": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", - "dev": true, "requires": { "eventemitter3": "1.2.0", "requires-port": "1.0.0" @@ -5368,7 +4781,6 @@ "version": "0.17.4", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", - "dev": true, "requires": { "http-proxy": "1.16.2", "is-glob": "3.1.0", @@ -5380,7 +4792,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" } @@ -5388,14 +4799,12 @@ "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=" }, "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", @@ -5406,7 +4815,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" } @@ -5415,7 +4823,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" }, @@ -5423,8 +4830,7 @@ "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=" } } }, @@ -5432,7 +4838,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -5441,7 +4846,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", @@ -5461,14 +4865,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" } @@ -5480,8 +4882,7 @@ "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "iconv-lite": { "version": "0.4.19", @@ -5491,14 +4892,12 @@ "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=", - "dev": true + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" }, "icss-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, "requires": { "postcss": "6.0.21" }, @@ -5507,7 +4906,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" } @@ -5516,7 +4914,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", @@ -5527,7 +4924,6 @@ "version": "6.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", - "dev": true, "requires": { "chalk": "2.3.2", "source-map": "0.6.1", @@ -5537,14 +4933,12 @@ "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==" }, "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" } @@ -5554,26 +4948,22 @@ "ieee754": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", - "dev": true + "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=", - "dev": true + "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==", - "dev": true + "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==", - "dev": true, "requires": { "pkg-dir": "2.0.0", "resolve-cwd": "2.0.0" @@ -5582,14 +4972,12 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "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=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -5597,20 +4985,17 @@ "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -5619,20 +5004,17 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "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", @@ -5653,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" } @@ -5669,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", @@ -5679,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" } @@ -5695,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" } @@ -5706,7 +5082,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", - "dev": true, "requires": { "meow": "3.7.0" } @@ -5714,14 +5089,12 @@ "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" }, "into-stream": { "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" @@ -5738,32 +5111,27 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" }, "ipaddr.js": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", - "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", - "dev": true + "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=", - "dev": true + "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", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -5771,22 +5139,19 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, "requires": { "binary-extensions": "1.11.0" } @@ -5794,14 +5159,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, "requires": { "builtin-modules": "1.1.1" } @@ -5809,14 +5172,12 @@ "is-callable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -5824,22 +5185,19 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "1.0.0", "is-data-descriptor": "1.0.0", @@ -5849,22 +5207,19 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -5872,20 +5227,17 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -5894,7 +5246,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "1.0.1" } @@ -5903,7 +5254,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, "requires": { "is-extglob": "2.1.1" } @@ -5912,7 +5262,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -5920,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" }, @@ -5935,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=" } } }, @@ -5944,7 +5290,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, "requires": { "is-number": "4.0.0" }, @@ -5952,22 +5297,19 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" } } }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" }, "is-path-in-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, "requires": { "is-path-inside": "1.0.1" } @@ -5976,7 +5318,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, "requires": { "path-is-inside": "1.0.2" } @@ -5984,14 +5325,12 @@ "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", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "3.0.1" } @@ -5999,26 +5338,22 @@ "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "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", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "1.0.1" } @@ -6026,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" } @@ -6053,7 +5385,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, "requires": { "html-comment-regex": "1.1.1" } @@ -6061,44 +5392,37 @@ "is-symbol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isomorphic-fetch": { "version": "2.2.1", @@ -6113,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", @@ -6124,7 +5447,6 @@ "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" @@ -6133,8 +5455,7 @@ "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==", - "dev": true + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" }, "js-tokens": { "version": "3.0.2", @@ -6145,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" @@ -6155,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", @@ -6178,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" } @@ -6186,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", @@ -6210,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" } @@ -6219,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" } @@ -6227,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" } @@ -6243,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", @@ -6265,50 +5575,42 @@ "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "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 + "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", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" }, "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", "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsx-ast-utils": { "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" } @@ -6317,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" } @@ -6325,14 +5626,12 @@ "killable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", - "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", - "dev": true + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -6341,7 +5640,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "1.0.0" } @@ -6350,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" @@ -6360,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", @@ -6385,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" @@ -6395,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" } @@ -6405,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", @@ -6428,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" @@ -6437,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" } @@ -6455,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", @@ -6467,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" } @@ -6476,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" @@ -6485,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" @@ -6504,7 +5788,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -6516,14 +5799,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" } @@ -6533,14 +5814,12 @@ "loader-runner": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=" }, "loader-utils": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, "requires": { "big.js": "3.2.0", "emojis-list": "2.1.0", @@ -6551,7 +5830,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" @@ -6560,44 +5838,37 @@ "lodash": { "version": "4.17.5", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", - "dev": true + "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=", - "dev": true + "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=", - "dev": true + "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=", - "dev": true + "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=", - "dev": true + "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=", - "dev": true + "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" }, @@ -6606,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" } @@ -6615,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", @@ -6625,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" } @@ -6643,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" @@ -6652,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" } @@ -6667,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" @@ -6685,14 +5947,12 @@ "loglevel": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", - "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", - "dev": true + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=" }, "loglevelnext": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.3.tgz", - "integrity": "sha512-OCxd/b78TijTB4b6zVqLbMrxhebyvdZKwqpL0VHUZ0pYhavXaPD4l6Xrr4n5xqTYWiqtb0i7ikSoJY/myQ/Org==", - "dev": true + "integrity": "sha512-OCxd/b78TijTB4b6zVqLbMrxhebyvdZKwqpL0VHUZ0pYhavXaPD4l6Xrr4n5xqTYWiqtb0i7ikSoJY/myQ/Org==" }, "loose-envify": { "version": "1.3.1", @@ -6706,7 +5966,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, "requires": { "currently-unhandled": "0.4.1", "signal-exit": "3.0.2" @@ -6715,20 +5974,17 @@ "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, "lru-cache": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", - "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -6737,14 +5993,12 @@ "macaddress": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", - "dev": true + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=" }, "make-dir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", - "dev": true, "requires": { "pify": "3.0.0" } @@ -6752,20 +6006,17 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "1.0.1" } @@ -6773,14 +6024,12 @@ "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=", - "dev": true + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" }, "md5.js": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, "requires": { "hash-base": "3.0.4", "inherits": "2.0.3" @@ -6790,7 +6039,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -6801,14 +6049,12 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -6817,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", @@ -6828,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", @@ -6845,26 +6089,22 @@ "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true + "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.2", "clone-buffer": "1.0.0", @@ -6880,7 +6120,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, "requires": { "errno": "0.1.7", "readable-stream": "2.3.5" @@ -6890,7 +6129,6 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, "requires": { "camelcase-keys": "2.1.0", "decamelize": "1.2.0", @@ -6907,28 +6145,24 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -6948,8 +6182,7 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -6957,7 +6190,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, "requires": { "bn.js": "4.11.8", "brorand": "1.1.0" @@ -6966,20 +6198,17 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", - "dev": true + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { "version": "2.1.18", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "dev": true, "requires": { "mime-db": "1.33.0" } @@ -6987,32 +6216,27 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "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", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", - "dev": true + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" }, "minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "1.1.11" } @@ -7020,14 +6244,12 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "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==", - "dev": true, "requires": { "concat-stream": "1.6.1", "duplexify": "3.5.4", @@ -7045,7 +6267,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, "requires": { "for-in": "1.0.2", "is-extendable": "1.0.1" @@ -7055,7 +6276,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "2.0.4" } @@ -7066,7 +6286,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -7075,7 +6294,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, "requires": { "aproba": "1.2.0", "copy-concurrently": "1.0.5", @@ -7088,14 +6306,12 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multicast-dns": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", - "dev": true, "requires": { "dns-packet": "1.3.1", "thunky": "1.0.2" @@ -7104,14 +6320,12 @@ "multicast-dns-service-types": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", - "dev": true + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, "multimatch": { "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", @@ -7122,21 +6336,18 @@ "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", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, "optional": true }, "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -7155,22 +6366,19 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "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", "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", - "dev": true, "requires": { "xml-char-classes": "1.0.0" } @@ -7178,26 +6386,22 @@ "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, "neo-async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", - "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", - "dev": true + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==" }, "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", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, "requires": { "lower-case": "1.1.4" } @@ -7205,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", @@ -7220,14 +6423,12 @@ "node-forge": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", - "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", - "dev": true + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=" }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, "requires": { "assert": "1.4.1", "browserify-zlib": "0.2.0", @@ -7258,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" @@ -7267,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", @@ -7284,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=" } } }, @@ -7293,7 +6490,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, "requires": { "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", @@ -7305,7 +6501,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "1.1.0" } @@ -7313,14 +6508,12 @@ "normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true + "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", @@ -7331,7 +6524,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "2.0.1" } @@ -7340,7 +6532,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, "requires": { "boolbase": "1.0.0" } @@ -7348,14 +6539,12 @@ "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true + "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", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-assign": { "version": "4.1.1", @@ -7366,7 +6555,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "0.1.1", "define-property": "0.2.5", @@ -7377,7 +6565,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -7386,7 +6573,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -7395,7 +6581,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -7404,7 +6589,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -7414,8 +6598,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } } @@ -7424,14 +6607,12 @@ "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "3.0.1" } @@ -7440,7 +6621,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, "requires": { "define-properties": "1.1.2", "es-abstract": "1.10.0" @@ -7450,7 +6630,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" @@ -7460,7 +6639,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "3.0.1" } @@ -7468,14 +6646,12 @@ "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, "requires": { "ee-first": "1.1.1" } @@ -7483,14 +6659,12 @@ "on-headers": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -7499,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" } @@ -7508,7 +6681,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, "requires": { "is-wsl": "1.1.0" } @@ -7517,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", @@ -7531,7 +6702,6 @@ "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", @@ -7543,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" } @@ -7551,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" @@ -7570,7 +6737,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", - "dev": true, "requires": { "url-parse": "1.0.5" }, @@ -7579,7 +6745,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", - "dev": true, "requires": { "querystringify": "0.0.4", "requires-port": "1.0.0" @@ -7590,20 +6755,17 @@ "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -7613,20 +6775,17 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "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" } @@ -7634,26 +6793,22 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "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", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true, "requires": { "p-try": "1.0.0" } @@ -7662,7 +6817,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "1.2.0" } @@ -7670,20 +6824,17 @@ "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" }, "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" } @@ -7691,20 +6842,17 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true + "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=", - "dev": true, "requires": { "cyclist": "0.2.2", "inherits": "2.0.3", @@ -7715,7 +6863,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, "requires": { "no-case": "2.3.2" } @@ -7724,7 +6871,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dev": true, "requires": { "asn1.js": "4.10.1", "browserify-aes": "1.1.1", @@ -7737,7 +6883,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -7748,14 +6893,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" } @@ -7766,7 +6909,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "1.3.1" } @@ -7774,74 +6916,62 @@ "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", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "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", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "pify": "2.3.0", @@ -7851,8 +6981,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, @@ -7860,7 +6989,6 @@ "version": "3.0.14", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", - "dev": true, "requires": { "create-hash": "1.1.3", "create-hmac": "1.1.6", @@ -7872,20 +7000,17 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, "requires": { "pinkie": "2.0.4" } @@ -7894,7 +7019,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, "requires": { "find-up": "2.1.0" } @@ -7902,14 +7026,12 @@ "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", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", - "dev": true, "requires": { "async": "1.5.2", "debug": "2.6.9", @@ -7919,22 +7041,19 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" } } }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, "requires": { "chalk": "1.1.3", "js-base64": "2.4.3", @@ -7945,14 +7064,12 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "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=", - "dev": true, "requires": { "has-flag": "1.0.0" } @@ -7963,7 +7080,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, "requires": { "postcss": "5.2.18", "postcss-message-helpers": "2.0.0", @@ -7974,7 +7090,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, "requires": { "colormin": "1.1.2", "postcss": "5.2.18", @@ -7985,7 +7100,6 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, "requires": { "postcss": "5.2.18", "postcss-value-parser": "3.3.0" @@ -7995,7 +7109,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8004,7 +7117,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8013,7 +7125,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8022,7 +7133,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8031,7 +7141,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, "requires": { "postcss": "5.2.18", "uniqs": "2.0.0" @@ -8041,7 +7150,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", - "dev": true, "requires": { "postcss": "5.2.18", "uniqid": "4.1.1" @@ -8051,7 +7159,6 @@ "version": "2.1.7", "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, "requires": { "has": "1.0.1", "postcss": "5.2.18", @@ -8062,7 +7169,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8071,7 +7177,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, "requires": { "browserslist": "1.7.7", "caniuse-api": "1.6.1", @@ -8083,14 +7188,12 @@ "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=", - "dev": true + "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=", - "dev": true, "requires": { "object-assign": "4.1.1", "postcss": "5.2.18", @@ -8101,7 +7204,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, "requires": { "postcss": "5.2.18", "postcss-value-parser": "3.3.0" @@ -8111,7 +7213,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, "requires": { "alphanum-sort": "1.0.2", "postcss": "5.2.18", @@ -8123,7 +7224,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, "requires": { "alphanum-sort": "1.0.2", "has": "1.0.1", @@ -8135,7 +7235,6 @@ "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=", - "dev": true, "requires": { "postcss": "6.0.21" }, @@ -8144,7 +7243,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" } @@ -8153,7 +7251,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", @@ -8164,7 +7261,6 @@ "version": "6.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", - "dev": true, "requires": { "chalk": "2.3.2", "source-map": "0.6.1", @@ -8174,14 +7270,12 @@ "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==" }, "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" } @@ -8192,7 +7286,6 @@ "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=", - "dev": true, "requires": { "css-selector-tokenizer": "0.7.0", "postcss": "6.0.21" @@ -8202,7 +7295,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" } @@ -8211,7 +7303,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", @@ -8222,7 +7313,6 @@ "version": "6.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", - "dev": true, "requires": { "chalk": "2.3.2", "source-map": "0.6.1", @@ -8232,14 +7322,12 @@ "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==" }, "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" } @@ -8250,7 +7338,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, "requires": { "css-selector-tokenizer": "0.7.0", "postcss": "6.0.21" @@ -8260,7 +7347,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" } @@ -8269,7 +7355,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", @@ -8280,7 +7365,6 @@ "version": "6.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", - "dev": true, "requires": { "chalk": "2.3.2", "source-map": "0.6.1", @@ -8290,14 +7374,12 @@ "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==" }, "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" } @@ -8308,7 +7390,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, "requires": { "icss-replace-symbols": "1.1.0", "postcss": "6.0.21" @@ -8318,7 +7399,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" } @@ -8327,7 +7407,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", @@ -8338,7 +7417,6 @@ "version": "6.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", - "dev": true, "requires": { "chalk": "2.3.2", "source-map": "0.6.1", @@ -8348,14 +7426,12 @@ "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==" }, "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" } @@ -8366,7 +7442,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8375,7 +7450,6 @@ "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=", - "dev": true, "requires": { "is-absolute-url": "2.1.0", "normalize-url": "1.9.1", @@ -8387,7 +7461,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, "requires": { "object-assign": "4.1.1", "prepend-http": "1.0.4", @@ -8398,14 +7471,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=" }, "query-string": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, "requires": { "object-assign": "4.1.1", "strict-uri-encode": "1.1.0" @@ -8415,7 +7486,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, "requires": { "is-plain-obj": "1.1.0" } @@ -8426,7 +7496,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, "requires": { "postcss": "5.2.18", "postcss-value-parser": "3.3.0" @@ -8436,7 +7505,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, "requires": { "postcss": "5.2.18", "postcss-value-parser": "3.3.0" @@ -8446,7 +7514,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, "requires": { "postcss": "5.2.18" } @@ -8455,7 +7522,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, "requires": { "has": "1.0.1", "postcss": "5.2.18", @@ -8466,7 +7532,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, "requires": { "flatten": "1.0.2", "indexes-of": "1.0.1", @@ -8477,7 +7542,6 @@ "version": "2.1.6", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, "requires": { "is-svg": "2.1.0", "postcss": "5.2.18", @@ -8489,7 +7553,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, "requires": { "alphanum-sort": "1.0.2", "postcss": "5.2.18", @@ -8499,14 +7562,12 @@ "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=", - "dev": true + "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=", - "dev": true, "requires": { "has": "1.0.1", "postcss": "5.2.18", @@ -8516,38 +7577,32 @@ "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 + "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=", - "dev": true + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "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==", - "dev": true + "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=", - "dev": true + "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=", - "dev": true, "requires": { "renderkid": "2.0.1", "utila": "0.4.0" @@ -8556,26 +7611,22 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "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", @@ -8588,8 +7639,7 @@ "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, "prop-types": { "version": "15.6.1", @@ -8605,7 +7655,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", - "dev": true, "requires": { "forwarded": "0.1.2", "ipaddr.js": "1.6.0" @@ -8614,20 +7663,17 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "public-encrypt": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "dev": true, "requires": { "bn.js": "4.11.8", "browserify-rsa": "4.0.1", @@ -8640,7 +7686,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, "requires": { "end-of-stream": "1.4.1", "once": "1.4.0" @@ -8650,7 +7695,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", - "dev": true, "requires": { "duplexify": "3.5.4", "inherits": "2.0.3", @@ -8660,26 +7704,22 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "query-string": { "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", @@ -8689,26 +7729,22 @@ "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, "querystringify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", - "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", - "dev": true + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=" }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -8718,7 +7754,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8729,7 +7764,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -8738,7 +7772,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, "requires": { "randombytes": "2.0.6", "safe-buffer": "5.1.1" @@ -8747,14 +7780,12 @@ "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", @@ -8830,7 +7861,6 @@ "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" @@ -8840,7 +7870,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, "requires": { "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", @@ -8851,7 +7880,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" @@ -8861,7 +7889,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, "requires": { "path-exists": "2.1.0", "pinkie-promise": "2.0.1" @@ -8871,7 +7898,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, "requires": { "pinkie-promise": "2.0.1" } @@ -8882,7 +7908,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", - "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -8897,7 +7922,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "minimatch": "3.0.4", @@ -8909,7 +7933,6 @@ "version": "0.14.7", "resolved": "https://registry.npmjs.org/recast/-/recast-0.14.7.tgz", "integrity": "sha512-/nwm9pkrcWagN40JeJhkPaRxiHXBRkXyRh/hgU088Z/v+qCy+zIHHY6bC6o7NaKAxPqtE6nD8zBH1LfU0/Wx6A==", - "dev": true, "requires": { "ast-types": "0.11.3", "esprima": "4.0.0", @@ -8920,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==" } } }, @@ -8929,7 +7951,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, "requires": { "resolve": "1.6.0" } @@ -8938,7 +7959,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, "requires": { "indent-string": "2.1.0", "strip-indent": "1.0.1" @@ -8948,7 +7968,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, "requires": { "balanced-match": "0.4.2", "math-expression-evaluator": "1.2.17", @@ -8958,8 +7977,7 @@ "balanced-match": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" } } }, @@ -8967,7 +7985,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, "requires": { "balanced-match": "0.4.2" }, @@ -8975,28 +7992,24 @@ "balanced-match": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" } } }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -9007,7 +8020,6 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, "requires": { "is-equal-shallow": "0.1.3" } @@ -9016,7 +8028,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "3.0.2", "safe-regex": "1.1.0" @@ -9025,14 +8036,12 @@ "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", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, "requires": { "regenerate": "1.3.3", "regjsgen": "0.2.0", @@ -9042,14 +8051,12 @@ "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, "requires": { "jsesc": "0.5.0" }, @@ -9057,28 +8064,24 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" } } }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "renderkid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", - "dev": true, "requires": { "css-select": "1.2.0", "dom-converter": "0.1.4", @@ -9090,28 +8093,24 @@ "utila": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=" } } }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, "requires": { "is-finite": "1.0.2" } @@ -9119,26 +8118,22 @@ "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", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "require-uncached": { "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" @@ -9147,22 +8142,19 @@ "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=" } } }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", - "dev": true, "requires": { "path-parse": "1.0.5" } @@ -9171,7 +8163,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, "requires": { "resolve-from": "3.0.0" } @@ -9180,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" @@ -9189,8 +8179,7 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "resolve-pathname": { "version": "2.2.0", @@ -9200,14 +8189,12 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "responselike": { "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.1" } @@ -9216,7 +8203,6 @@ "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" @@ -9225,14 +8211,12 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, "requires": { "glob": "7.1.2" } @@ -9241,7 +8225,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "dev": true, "requires": { "hash-base": "2.0.2", "inherits": "2.0.3" @@ -9251,7 +8234,6 @@ "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" } @@ -9260,7 +8242,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, "requires": { "aproba": "1.2.0" } @@ -9268,14 +8249,12 @@ "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" } @@ -9284,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" } @@ -9292,14 +8270,12 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "0.1.15" } @@ -9307,14 +8283,12 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true + "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==", - "dev": true, "requires": { "ajv": "6.3.0", "ajv-keywords": "3.1.0" @@ -9323,20 +8297,17 @@ "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", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" }, "selfsigned": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", - "dev": true, "requires": { "node-forge": "0.7.1" } @@ -9344,14 +8315,12 @@ "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -9371,14 +8340,12 @@ "serialize-javascript": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", - "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=", - "dev": true + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=" }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, "requires": { "accepts": "1.3.5", "batch": "0.6.1", @@ -9393,7 +8360,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, "requires": { "encodeurl": "1.0.2", "escape-html": "1.0.3", @@ -9404,20 +8370,17 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, "requires": { "extend-shallow": "2.0.1", "is-extendable": "0.1.1", @@ -9429,7 +8392,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -9444,14 +8406,12 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" @@ -9461,7 +8421,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "1.0.0" } @@ -9469,14 +8428,12 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "shelljs": { "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", @@ -9486,20 +8443,17 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { "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" }, @@ -9507,22 +8461,19 @@ "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", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "0.11.2", "debug": "2.6.9", @@ -9538,7 +8489,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -9547,7 +8497,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -9556,7 +8505,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -9565,7 +8513,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -9576,7 +8523,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -9585,7 +8531,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -9596,7 +8541,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -9606,8 +8550,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -9615,7 +8558,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "1.0.0", "isobject": "3.0.1", @@ -9626,7 +8568,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "1.0.2" } @@ -9637,7 +8578,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -9646,7 +8586,6 @@ "version": "0.3.19", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", - "dev": true, "requires": { "faye-websocket": "0.10.0", "uuid": "3.2.1" @@ -9656,7 +8595,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", - "dev": true, "requires": { "debug": "2.6.9", "eventsource": "0.1.6", @@ -9670,7 +8608,6 @@ "version": "0.11.1", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "dev": true, "requires": { "websocket-driver": "0.7.0" } @@ -9681,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" } @@ -9689,20 +8625,17 @@ "source-list-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", - "dev": true + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true, "requires": { "atob": "2.0.3", "decode-uri-component": "0.2.0", @@ -9715,7 +8648,6 @@ "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, "requires": { "source-map": "0.5.7" } @@ -9723,14 +8655,12 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.0" @@ -9739,14 +8669,12 @@ "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "2.1.0", "spdx-license-ids": "3.0.0" @@ -9755,14 +8683,12 @@ "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "spdy": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", - "dev": true, "requires": { "debug": "2.6.9", "handle-thing": "1.2.5", @@ -9776,7 +8702,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", - "dev": true, "requires": { "debug": "2.6.9", "detect-node": "2.0.3", @@ -9791,7 +8716,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "3.0.2" } @@ -9799,14 +8723,12 @@ "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==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -9815,7 +8737,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "0.2.5", "object-copy": "0.1.0" @@ -9825,7 +8746,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "0.1.6" } @@ -9834,7 +8754,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -9843,7 +8762,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -9854,7 +8772,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -9863,7 +8780,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -9874,7 +8790,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "0.1.6", "is-data-descriptor": "0.1.4", @@ -9884,22 +8799,19 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.5" @@ -9909,7 +8821,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", - "dev": true, "requires": { "end-of-stream": "1.4.1", "stream-shift": "1.0.0" @@ -9919,7 +8830,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", - "dev": true, "requires": { "builtin-status-codes": "3.0.0", "inherits": "2.0.3", @@ -9931,14 +8841,12 @@ "stream-shift": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true + "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" } @@ -9946,20 +8854,17 @@ "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", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -9968,20 +8873,17 @@ "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=" }, "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=" }, "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" } @@ -9992,7 +8894,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, "requires": { "safe-buffer": "5.1.1" } @@ -10001,7 +8902,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -10009,14 +8909,12 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" }, "strip-bom-stream": { "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" @@ -10026,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" } @@ -10036,14 +8933,12 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, "requires": { "get-stdin": "4.0.1" } @@ -10051,14 +8946,12 @@ "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==", - "dev": true, "requires": { "loader-utils": "1.1.0", "schema-utils": "0.4.5" @@ -10067,14 +8960,12 @@ "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "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=", - "dev": true, "requires": { "coa": "1.0.4", "colors": "1.1.2", @@ -10088,20 +8979,17 @@ "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" }, "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "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=", - "dev": true, "requires": { "argparse": "1.0.10", "esprima": "2.7.3" @@ -10112,14 +9000,12 @@ "symbol-observable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true + "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", @@ -10133,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", @@ -10144,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" } @@ -10160,7 +9043,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", @@ -10171,7 +9053,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" } @@ -10181,14 +9062,12 @@ "tapable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true + "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" @@ -10197,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" @@ -10233,20 +9107,17 @@ "thunky": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", - "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", - "dev": true + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=" }, "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", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", - "dev": true, "requires": { "setimmediate": "1.0.5" } @@ -10255,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" } @@ -10263,20 +9133,17 @@ "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "3.2.2" } @@ -10285,7 +9152,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "2.0.2", "extend-shallow": "3.0.2", @@ -10297,7 +9163,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "3.0.0", "repeat-string": "1.6.1" @@ -10306,32 +9171,27 @@ "toposort": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz", - "integrity": "sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw=", - "dev": true + "integrity": "sha1-wxdI5V0hDv/AD9zcfW5o19e7nOw=" }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" }, "type-check": { "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" } @@ -10340,7 +9200,6 @@ "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, "requires": { "media-typer": "0.3.0", "mime-types": "2.1.18" @@ -10349,8 +9208,7 @@ "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", @@ -10361,7 +9219,6 @@ "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "dev": true, "requires": { "commander": "2.13.0", "source-map": "0.6.1" @@ -10370,14 +9227,12 @@ "commander": { "version": "2.13.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true + "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==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -10385,7 +9240,6 @@ "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==", - "dev": true, "requires": { "cacache": "10.0.4", "find-cache-dir": "1.0.0", @@ -10400,22 +9254,19 @@ "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==" } } }, "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", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, "requires": { "arr-union": "3.1.0", "get-value": "2.0.6", @@ -10427,7 +9278,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "0.1.1" } @@ -10436,7 +9286,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, "requires": { "extend-shallow": "2.0.1", "is-extendable": "0.1.1", @@ -10449,14 +9298,12 @@ "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" }, "uniqid": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", - "dev": true, "requires": { "macaddress": "0.2.8" } @@ -10464,14 +9311,12 @@ "uniqs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true + "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=", - "dev": true, "requires": { "unique-slug": "2.0.0" } @@ -10480,7 +9325,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", - "dev": true, "requires": { "imurmurhash": "0.1.4" } @@ -10488,14 +9332,12 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "0.3.1", "isobject": "3.0.1" @@ -10505,7 +9347,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "2.0.6", "has-values": "0.1.4", @@ -10516,7 +9357,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -10526,40 +9366,34 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" } } }, "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", "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", - "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", - "dev": true + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==" }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, "requires": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -10568,22 +9402,19 @@ "punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" } } }, "url-join": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", - "dev": true + "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" }, "url-parse": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", - "dev": true, "requires": { "querystringify": "1.0.0", "requires-port": "1.0.0" @@ -10592,8 +9423,7 @@ "querystringify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", - "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", - "dev": true + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" } } }, @@ -10601,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" } @@ -10609,14 +9438,12 @@ "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", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true, "requires": { "kind-of": "6.0.2" }, @@ -10624,8 +9451,7 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -10633,7 +9459,6 @@ "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, "requires": { "inherits": "2.0.1" }, @@ -10641,22 +9466,19 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" } } }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, "requires": { "define-properties": "1.1.2", "object.getownpropertydescriptors": "2.0.3" @@ -10665,32 +9487,27 @@ "utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", - "dev": true + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, "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", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true, "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" @@ -10704,20 +9521,17 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vendors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", - "dev": true + "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.4", "clone-stats": "0.0.1", @@ -10728,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", @@ -10741,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" } @@ -10759,7 +9570,6 @@ "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, "requires": { "indexof": "0.0.1" } @@ -10776,7 +9586,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", - "dev": true, "requires": { "chokidar": "2.0.3", "graceful-fs": "4.1.11", @@ -10787,7 +9596,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, "requires": { "minimalistic-assert": "1.0.0" } @@ -10796,7 +9604,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.2.0.tgz", "integrity": "sha512-O/KmJ2MYoSfsZzq3//RyyYICYTb1gPAuYSIoD4XbxWFqkDrZCkF8BIAwPuFjA8SFqTcsIL3gTS7hiTZaUN2Tjw==", - "dev": true, "requires": { "acorn": "5.5.3", "acorn-dynamic-import": "3.0.0", @@ -10823,7 +9630,6 @@ "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" }, @@ -10832,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" } @@ -10840,20 +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 + "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", @@ -10864,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" } @@ -10873,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" } @@ -10881,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" } @@ -10897,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", @@ -10920,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", @@ -10941,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", @@ -10953,8 +9748,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==" } } }, @@ -10962,7 +9756,6 @@ "version": "2.0.13", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.0.13.tgz", "integrity": "sha512-0lnOi3yla8FsZVuMsbfnNRB/8DlfuDugKdekC+4ykydZG0+UOidMi5J5LLWN4c0VJ8PqC19yMXXkYyCq78OuqA==", - "dev": true, "requires": { "chalk": "2.3.2", "cross-spawn": "6.0.5", @@ -10994,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" } @@ -11009,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", @@ -11027,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", @@ -11038,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", @@ -11051,7 +9838,6 @@ "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", @@ -11072,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" } @@ -11081,7 +9866,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" } @@ -11090,7 +9874,6 @@ "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", @@ -11110,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" } @@ -11121,7 +9903,6 @@ "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==", - "dev": true, "requires": { "loud-rejection": "1.6.0", "memory-fs": "0.4.1", @@ -11135,8 +9916,7 @@ "mime": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==", - "dev": true + "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==" } } }, @@ -11144,7 +9924,6 @@ "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==", - "dev": true, "requires": { "ansi-html": "0.0.7", "array-includes": "3.0.3", @@ -11180,7 +9959,6 @@ "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" } @@ -11189,7 +9967,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" } @@ -11200,7 +9977,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.1.2.tgz", "integrity": "sha512-B53SD4N4BHpZdUwZcj4st2QT7gVfqZtqHDruC1N+K2sciq0Rt/3F1Dx6RlylVkcrToMLTaiaeT48k9Lq4iDVDA==", - "dev": true, "requires": { "chalk": "2.3.2", "log-symbols": "2.2.0", @@ -11212,7 +9988,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" } @@ -11221,7 +9996,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", @@ -11232,7 +10006,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" } @@ -11243,7 +10016,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true, "requires": { "source-list-map": "2.0.0", "source-map": "0.6.1" @@ -11252,8 +10024,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==" } } }, @@ -11261,7 +10032,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, "requires": { "http-parser-js": "0.4.11", "websocket-extensions": "0.1.3" @@ -11270,8 +10040,7 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" }, "whatwg-fetch": { "version": "2.0.3", @@ -11281,14 +10050,12 @@ "whet.extend": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "2.0.0" } @@ -11296,20 +10063,17 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "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==", - "dev": true, "requires": { "errno": "0.1.7" } @@ -11318,7 +10082,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" @@ -11328,7 +10091,6 @@ "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", @@ -11340,14 +10102,12 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "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" } @@ -11356,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", @@ -11366,32 +10125,27 @@ "xml-char-classes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", - "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", - "dev": true + "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=" }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "dev": true, "requires": { "camelcase": "4.1.0", "cliui": "3.2.0", @@ -11411,14 +10165,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=" }, "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=", - "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", @@ -11430,7 +10182,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, "requires": { "pify": "2.3.0" } @@ -11438,14 +10189,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=" }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, "requires": { "load-json-file": "2.0.0", "normalize-package-data": "2.4.0", @@ -11456,7 +10205,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, "requires": { "find-up": "2.1.0", "read-pkg": "2.0.0" @@ -11468,7 +10216,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, "requires": { "camelcase": "4.1.0" }, @@ -11476,8 +10223,7 @@ "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=" } } }, @@ -11485,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", @@ -11506,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" } @@ -11515,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", @@ -11526,7 +10269,6 @@ "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" } @@ -11535,7 +10277,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" } @@ -11546,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", @@ -11579,7 +10319,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" } @@ -11588,7 +10327,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -11597,7 +10335,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", @@ -11608,7 +10345,6 @@ "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" } @@ -11617,7 +10353,6 @@ "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", @@ -11628,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" @@ -11645,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" } @@ -11654,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", @@ -11665,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" @@ -11675,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 bd4aa2eb..5d403807 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -12,12 +12,6 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "prop-types": "^15.6.1", - "react": "^16.2.0", - "react-dom": "^16.2.0", - "react-router-dom": "^4.2.2" - }, - "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.4", "babel-minify-webpack-plugin": "^0.3.1", @@ -29,6 +23,10 @@ "eslint": "^4.19.1", "eslint-plugin-react": "^7.6.0", "html-webpack-plugin": "^3.1.0", + "prop-types": "^15.6.1", + "react": "^16.2.0", + "react-dom": "^16.2.0", + "react-router-dom": "^4.2.2", "style-loader": "^0.20.3", "webpack": "^4.2.0", "webpack-cli": "^2.0.13", From 6876de539af7d7fe869852bb3e2df31a87ae6e43 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 18 Apr 2018 00:54:26 -0700 Subject: [PATCH 60/73] Make web app handler public --- daemon/inertia/daemon.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index fb85e888..4967a2dc 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -76,7 +76,7 @@ func run(host, port, version string) { return } defer permHandler.Close() - permHandler.AttachUserRestrictedHandler( + permHandler.AttachPublicHandler( "/", http.FileServer(http.Dir("/app/inertia-web")), ) mux.Handle(webPrefix, http.StripPrefix(webPrefix, permHandler)) From 0151a39e07f538124a953c934d56fb4ecc82a26c Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 18 Apr 2018 01:14:03 -0700 Subject: [PATCH 61/73] Remove user and admin path restrictions from permissionshandler --- daemon/inertia/auth/permissions.go | 92 ++----------- daemon/inertia/auth/permissions_test.go | 164 +----------------------- 2 files changed, 10 insertions(+), 246 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 4166484b..5ec67977 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -17,12 +17,10 @@ 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 - publicPaths []string - adminPaths []string + domain string + users *userManager + sessions *sessionManager + mux *http.ServeMux } // NewPermissionsHandler returns a new handler for authenticating @@ -43,21 +41,10 @@ func NewPermissionsHandler( // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ - domain: domain, - users: userManager, - sessions: sessionManager, - mux: mux, - adminPaths: make([]string, 0), - } - - // Set paths that don't require session authentication. - handler.publicPaths = []string{ - "/login", - "/logout", - "/adduser", - "/removeuser", - "/resetusers", - "/listusers", + domain: domain, + users: userManager, + sessions: sessionManager, + mux: mux, } mux.HandleFunc("/login", handler.loginHandler) mux.HandleFunc("/logout", handler.logoutHandler) @@ -93,72 +80,11 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { path = "/" + path r.URL.Path = path } - - // Serve if path is public - for _, prefix := range h.publicPaths { - if strings.HasPrefix(path, prefix) { - 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 is valid - err = h.users.HasUser(s.Username) - if err != nil { - if err == errUserNotFound { - http.Error(w, err.Error(), http.StatusForbidden) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - - // Check if user has sufficient permissions for path - for _, prefix := range h.adminPaths { - if strings.HasPrefix(path, prefix) { - 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) { - // Add path as exception to user restriction - h.publicPaths = append(h.publicPaths, path) - h.mux.Handle(path, handler) -} - -// AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. -func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.Handler) { - // By default, all paths are user restricted - h.mux.Handle(path, handler) -} - -// AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. -func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.Handler) { - // Add path as one that requires elevated permissions - h.adminPaths = append(h.publicPaths, path) h.mux.Handle(path, handler) } @@ -257,7 +183,7 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request fmt.Println("setting cors") w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == "OPTIONS" { return diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 2a48ed37..21ed9eb9 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -87,30 +87,6 @@ func TestServeHTTPPublicPathOnNestedHandler(t *testing.T) { 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.AttachUserRestrictedHandler("/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) @@ -122,7 +98,7 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachUserRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachPublicHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -162,144 +138,6 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { 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.AttachUserRestrictedHandler("/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+"/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.AttachAdminRestrictedHandler("/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+"/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.AttachAdminRestrictedHandler("/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+"/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) From ef78370b63fa79dc944c1e0f41aa458dc4d3dfc1 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 18 Apr 2018 01:56:37 -0700 Subject: [PATCH 62/73] Add validate endpoint, experimental auth check --- daemon/inertia/auth/permissions.go | 36 ++++++++++++++++ daemon/web/components/App.js | 66 ++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 21 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 5ec67977..597a9a8b 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -48,6 +48,7 @@ func NewPermissionsHandler( } mux.HandleFunc("/login", handler.loginHandler) mux.HandleFunc("/logout", handler.logoutHandler) + mux.HandleFunc("/validate", handler.validateHandler) // The following endpoints are for user administration and must // be used from the CLI and delivered with the daemon token. @@ -233,3 +234,38 @@ func (h *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Reques w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "[SUCCESS %d] Session ended\n", http.StatusOK) } + +func (h *PermissionsHandler) validateHandler(w http.ResponseWriter, r *http.Request) { + // 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 exists + err = h.users.HasUser(s.Username) + if err != nil { + if err == errUserNotFound { + http.Error(w, err.Error(), http.StatusForbidden) + } else { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + return + } + + // Check if user is admin + /* + admin, err := h.users.IsAdmin(s.Username) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + */ + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "[SUCCESS %d] Session ended\n", http.StatusOK) +} diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index 1e061fc4..af825e63 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -6,41 +6,65 @@ import InertiaClient from '../client'; import Login from './Login'; import Home from './Home'; -const isAuthenticated = () => { - // TODO: authentication check prior to route change - return true; -}; - -const AuthRoute = ({ component: Component, props, ...rest }) => ( +const AuthRoute = ({ authenticated, component: Component, props, ...rest }) => ( ( - isAuthenticated() - ? - : - )}/> + 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) + } + + async isAuthenticated() { + const params = { + headers: { 'Accept': 'application/json' }, + }; + const response = await this.props.client._get("/validate", params); + return (response.status === 200); + }; + + componentDidMount() { + this.isAuthenticated().then((authenticated) => { + this.setState({ + loading: false, + authenticated, + }); + }); } render() { - return ( - -
- }/> - - -
-
- ); + const { component: Component, ...rest } = this.props; + if (this.state.loading) { + return
Loading...
; + } else { + return ( + +
+ } /> + + +
+
+ ) + } } } From 95b93857e771c09d81a987c1502eb34ffd104782 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 18 Apr 2018 17:18:56 -0700 Subject: [PATCH 63/73] Logout handling, cosmetic changes --- daemon/web/components/App.js | 2 +- daemon/web/components/Home.js | 22 +++++++++++++++++----- daemon/web/components/Login.js | 3 --- daemon/web/index.html | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index af825e63..2684b7c6 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -35,7 +35,7 @@ export default class App extends React.Component { const params = { headers: { 'Accept': 'application/json' }, }; - const response = await this.props.client._get("/validate", params); + const response = await this.props.client._get("/web/validate", params); return (response.status === 200); }; diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js index 6b9c2d19..4e252a20 100644 --- a/daemon/web/components/Home.js +++ b/daemon/web/components/Home.js @@ -2,8 +2,8 @@ import React from 'react'; const SidebarHeader = ({ children }) => ( ); @@ -24,8 +24,8 @@ const sidebarHeaderStyles = { const SidebarButton = ({ children }) => ( ); @@ -49,6 +49,7 @@ 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() { @@ -62,13 +63,24 @@ export default class Home extends React.Component { const response = await this.props.client._get(endpoint, params); } + async handleLogOut() { + const endpoint = '/web/logout'; + const params = { + headers: { + 'Accept': 'application/json' + } + }; + + const response = await this.props.client._get(endpoint, params); + } + render() { return (

Inertia Web

- logout + logout
diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js index 1ad766f5..f31ece63 100644 --- a/daemon/web/components/Login.js +++ b/daemon/web/components/Login.js @@ -54,9 +54,6 @@ export default class Login extends React.Component { src="https://github.com/ubclaunchpad/inertia/blob/master/.static/inertia-with-name.png?raw=true" width="20%"/>

-

- Inertia Web -

diff --git a/daemon/web/index.html b/daemon/web/index.html index 54941cc7..41a96e35 100644 --- a/daemon/web/index.html +++ b/daemon/web/index.html @@ -4,7 +4,7 @@ - Inertia + Inertia Web From 72b877930ac759f0b2cf37205919bd1216e904c9 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 18 Apr 2018 01:14:03 -0700 Subject: [PATCH 64/73] Revert "Remove user and admin path restrictions from permissionshandler" This reverts commit 0151a39e07f538124a953c934d56fb4ecc82a26c. --- daemon/inertia/auth/permissions.go | 92 +++++++++++-- daemon/inertia/auth/permissions_test.go | 164 +++++++++++++++++++++++- 2 files changed, 246 insertions(+), 10 deletions(-) diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 597a9a8b..b2644768 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -17,10 +17,12 @@ 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 + domain string + users *userManager + sessions *sessionManager + mux *http.ServeMux + publicPaths []string + adminPaths []string } // NewPermissionsHandler returns a new handler for authenticating @@ -41,10 +43,21 @@ func NewPermissionsHandler( // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ - domain: domain, - users: userManager, - sessions: sessionManager, - mux: mux, + domain: domain, + users: userManager, + sessions: sessionManager, + mux: mux, + adminPaths: make([]string, 0), + } + + // Set paths that don't require session authentication. + handler.publicPaths = []string{ + "/login", + "/logout", + "/adduser", + "/removeuser", + "/resetusers", + "/listusers", } mux.HandleFunc("/login", handler.loginHandler) mux.HandleFunc("/logout", handler.logoutHandler) @@ -81,11 +94,72 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { path = "/" + path r.URL.Path = path } + + // Serve if path is public + for _, prefix := range h.publicPaths { + if strings.HasPrefix(path, prefix) { + 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 is valid + err = h.users.HasUser(s.Username) + if err != nil { + if err == errUserNotFound { + http.Error(w, err.Error(), http.StatusForbidden) + } else { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + return + } + + // Check if user has sufficient permissions for path + for _, prefix := range h.adminPaths { + if strings.HasPrefix(path, prefix) { + 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) { + // Add path as exception to user restriction + h.publicPaths = append(h.publicPaths, path) + h.mux.Handle(path, handler) +} + +// AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. +func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.Handler) { + // By default, all paths are user restricted + h.mux.Handle(path, handler) +} + +// AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. +func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.Handler) { + // Add path as one that requires elevated permissions + h.adminPaths = append(h.publicPaths, path) h.mux.Handle(path, handler) } @@ -184,7 +258,7 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request fmt.Println("setting cors") w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == "OPTIONS" { return diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 21ed9eb9..2a48ed37 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -87,6 +87,30 @@ func TestServeHTTPPublicPathOnNestedHandler(t *testing.T) { 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.AttachUserRestrictedHandler("/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) @@ -98,7 +122,7 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachPublicHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachUserRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -138,6 +162,144 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { 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.AttachUserRestrictedHandler("/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+"/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.AttachAdminRestrictedHandler("/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+"/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.AttachAdminRestrictedHandler("/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+"/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) From 7769c416865dbfc80747eaf77566cb65f3a03c44 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 19 Apr 2018 00:51:52 -0700 Subject: [PATCH 65/73] Unify all authentication under PermissionsHandler --- daemon/inertia/auth/decorator.go | 42 --------- daemon/inertia/auth/decorator_test.go | 74 ---------------- daemon/inertia/auth/permissions.go | 119 +++++++++++++++++--------- daemon/inertia/daemon.go | 33 ++++--- 4 files changed, 94 insertions(+), 174 deletions(-) delete mode 100644 daemon/inertia/auth/decorator.go delete mode 100644 daemon/inertia/auth/decorator_test.go diff --git a/daemon/inertia/auth/decorator.go b/daemon/inertia/auth/decorator.go deleted file mode 100644 index dcc11497..00000000 --- a/daemon/inertia/auth/decorator.go +++ /dev/null @@ -1,42 +0,0 @@ -package auth - -import ( - "net/http" - "strings" - - jwt "github.com/dgrijalva/jwt-go" -) - -// 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) - } -} diff --git a/daemon/inertia/auth/decorator_test.go b/daemon/inertia/auth/decorator_test.go deleted file mode 100644 index c22b0b80..00000000 --- a/daemon/inertia/auth/decorator_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package auth - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/ubclaunchpad/inertia/common" -) - -func testHealthCheckHandler(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, common.MsgDaemonOK) -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusOK) - assert.Equal(t, rr.Body.String(), common.MsgDaemonOK) -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) - assert.Equal(t, rr.Body.String(), malformedAuthStringErrorMsg+"\n") -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) -} - -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(testHealthCheckHandler, getFakeAPIKey)) - handler.ServeHTTP(rr, req) - - assert.Equal(t, rr.Code, http.StatusForbidden) -} diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index b2644768..803148e1 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -21,14 +21,16 @@ type PermissionsHandler struct { users *userManager sessions *sessionManager mux *http.ServeMux + keyLookup func(*jwt.Token) (interface{}, error) publicPaths []string adminPaths []string } // NewPermissionsHandler returns a new handler for authenticating -// users and handling user administration +// users and handling user administration. Param userlandPath is +// used to set cookie domain. func NewPermissionsHandler( - dbPath, domain, path string, timeout int, + dbPath, domain, userlandPath string, timeout int, keyLookup ...func(*jwt.Token) (interface{}, error), ) (*PermissionsHandler, error) { // Set up user manager @@ -38,41 +40,45 @@ func NewPermissionsHandler( } // Set up session manager - sessionManager := newSessionManager(domain, path, timeout) + sessionManager := newSessionManager(domain, userlandPath, timeout) // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ - domain: domain, - users: userManager, - sessions: sessionManager, - mux: mux, - adminPaths: make([]string, 0), + domain: domain, + users: userManager, + sessions: sessionManager, + mux: mux, } - // Set paths that don't require session authentication. + userPrefix := "/user/" + userHandler := http.NewServeMux() + + // The following endpoints are for user administration and session + // administration handler.publicPaths = []string{ - "/login", - "/logout", - "/adduser", - "/removeuser", - "/resetusers", - "/listusers", + "/user/login", + "/user/logout", + "/user/validate", } - mux.HandleFunc("/login", handler.loginHandler) - mux.HandleFunc("/logout", handler.logoutHandler) - mux.HandleFunc("/validate", handler.validateHandler) - - // The following endpoints are for user administration and must - // be used from the CLI and delivered with the daemon token. - lookup := GetAPIPrivateKey + userHandler.HandleFunc("/login", handler.loginHandler) + userHandler.HandleFunc("/logout", handler.logoutHandler) + userHandler.HandleFunc("/validate", handler.validateHandler) + handler.adminPaths = []string{ + "/user/adduser", + "/user/removeuser", + "/user/resetusers", + "/user/listusers", + } + handler.keyLookup = GetAPIPrivateKey if len(keyLookup) > 0 { - lookup = keyLookup[0] + handler.keyLookup = keyLookup[0] } - mux.HandleFunc("/adduser", Authorized(handler.addUserHandler, lookup)) - mux.HandleFunc("/removeuser", Authorized(handler.removeUserHandler, lookup)) - mux.HandleFunc("/resetusers", Authorized(handler.resetUsersHandler, lookup)) - mux.HandleFunc("/listusers", Authorized(handler.listUsersHandler, lookup)) + userHandler.HandleFunc("/adduser", handler.addUserHandler) + userHandler.HandleFunc("/removeuser", handler.removeUserHandler) + userHandler.HandleFunc("/resetusers", handler.resetUsersHandler) + userHandler.HandleFunc("/listusers", handler.listUsersHandler) + mux.Handle(userPrefix, http.StripPrefix(userPrefix, userHandler)) return handler, nil } @@ -103,6 +109,39 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } + // Check if this path is for admins + adminRestricted := false + for _, prefix := range h.adminPaths { + if strings.HasPrefix(path, prefix) { + adminRestricted = true + } + } + + // 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) + } + // Check if session is valid s, err := h.sessions.GetSession(w, r) if err != nil { @@ -126,17 +165,15 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // Check if user has sufficient permissions for path - for _, prefix := range h.adminPaths { - if strings.HasPrefix(path, prefix) { - 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 + 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 @@ -144,20 +181,20 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // AttachPublicHandler attaches given path and handler and makes it publicly available -func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.Handler) { +func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.HandlerFunc) { // Add path as exception to user restriction h.publicPaths = append(h.publicPaths, path) h.mux.Handle(path, handler) } // AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. -func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.Handler) { +func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.HandlerFunc) { // By default, all paths are user restricted h.mux.Handle(path, handler) } // AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. -func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.Handler) { +func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.HandlerFunc) { // Add path as one that requires elevated permissions h.adminPaths = append(h.publicPaths, path) h.mux.Handle(path, handler) @@ -258,7 +295,7 @@ func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request fmt.Println("setting cors") w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") if r.Method == "OPTIONS" { return diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 4967a2dc..820afc0c 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -61,32 +61,31 @@ func run(host, port, version string) { } } - // GitHub webhook endpoint - mux := http.NewServeMux() - mux.HandleFunc("/", gitHubWebHookHandler) - - // Inertia web - PermissionsHandler is used to authenticate web - // app access and manage users webPrefix := "/web/" - permHandler, err := auth.NewPermissionsHandler( + handler, err := auth.NewPermissionsHandler( auth.UserDatabasePath, host, webPrefix, 120, ) if err != nil { println(err.Error()) return } - defer permHandler.Close() - permHandler.AttachPublicHandler( - "/", http.FileServer(http.Dir("/app/inertia-web")), + defer handler.Close() + + // Inertia web + handler.AttachPublicHandler( + webPrefix, + http.FileServer(http.Dir("/app/inertia-web")).(http.HandlerFunc), ) - mux.Handle(webPrefix, http.StripPrefix(webPrefix, permHandler)) + + // GitHub webhook endpoint + handler.AttachPublicHandler("/webhook", gitHubWebHookHandler) // CLI API endpoints - 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)) + handler.AttachUserRestrictedHandler("/status", statusHandler) + handler.AttachAdminRestrictedHandler("/up", upHandler) + handler.AttachAdminRestrictedHandler("/down", downHandler) + handler.AttachAdminRestrictedHandler("/reset", resetHandler) + handler.AttachUserRestrictedHandler("/logs", logHandler) // Serve daemon on port println("Serving daemon on port " + port) @@ -94,7 +93,7 @@ func run(host, port, version string) { ":"+port, daemonSSLCert, daemonSSLKey, - mux, + handler, )) } From a2e58ca37e9388c20ed76b59b0dd8320d2207280 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 19 Apr 2018 02:30:07 -0700 Subject: [PATCH 66/73] Reroute routes, minor fixes and updates --- client/deployment.go | 8 +-- daemon/inertia/auth/permissions.go | 88 ++++++++++++------------- daemon/inertia/auth/permissions_test.go | 41 +++++++----- daemon/inertia/auth/sessions.go | 25 +++---- daemon/inertia/daemon.go | 23 ++++--- daemon/inertia/logs.go | 23 +++---- daemon/inertia/mock_test.go | 5 -- daemon/inertia/project/deployment.go | 21 +----- daemon/inertia/project/docker.go | 17 +++++ daemon/web/components/App.js | 2 +- daemon/web/components/Home.js | 2 +- daemon/web/components/Login.js | 2 +- deploy_users.go | 3 +- 13 files changed, 129 insertions(+), 131 deletions(-) diff --git a/client/deployment.go b/client/deployment.go index 41fb1c37..54f432aa 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -109,23 +109,23 @@ func (d *Deployment) AddUser(username, password string, admin bool) (*http.Respo Password: password, Admin: admin, } - return d.request("POST", "/web/adduser", reqContent) + 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", "/web/removeuser", reqContent) + 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", "/web/resetusers", nil) + return d.request("POST", "/user/resetusers", nil) } // ListUsers lists all users on the remote. func (d *Deployment) ListUsers() (*http.Response, error) { - return d.request("POST", "/web/listusers", nil) + return d.request("POST", "/user/listusers", nil) } func (d *Deployment) request(method, endpoint string, requestBody interface{}) (*http.Response, error) { diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 803148e1..508f43d4 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -17,13 +17,13 @@ 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) - publicPaths []string - adminPaths []string + 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 @@ -50,17 +50,14 @@ func NewPermissionsHandler( sessions: sessionManager, mux: mux, } - - userPrefix := "/user/" - userHandler := http.NewServeMux() + handler.keyLookup = GetAPIPrivateKey + if len(keyLookup) > 0 { + handler.keyLookup = keyLookup[0] + } // The following endpoints are for user administration and session // administration - handler.publicPaths = []string{ - "/user/login", - "/user/logout", - "/user/validate", - } + userHandler := http.NewServeMux() userHandler.HandleFunc("/login", handler.loginHandler) userHandler.HandleFunc("/logout", handler.logoutHandler) userHandler.HandleFunc("/validate", handler.validateHandler) @@ -70,15 +67,11 @@ func NewPermissionsHandler( "/user/resetusers", "/user/listusers", } - handler.keyLookup = GetAPIPrivateKey - if len(keyLookup) > 0 { - handler.keyLookup = keyLookup[0] - } userHandler.HandleFunc("/adduser", handler.addUserHandler) userHandler.HandleFunc("/removeuser", handler.removeUserHandler) userHandler.HandleFunc("/resetusers", handler.resetUsersHandler) userHandler.HandleFunc("/listusers", handler.listUsersHandler) - mux.Handle(userPrefix, http.StripPrefix(userPrefix, userHandler)) + mux.Handle("/user/", http.StripPrefix("/user", userHandler)) return handler, nil } @@ -101,21 +94,25 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.URL.Path = path } - // Serve if path is public - for _, prefix := range h.publicPaths { - if strings.HasPrefix(path, prefix) { - h.mux.ServeHTTP(w, r) - return - } - } - - // Check if this path is for admins + // 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") @@ -140,6 +137,7 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Serve the requested endpoint to token holders h.mux.ServeHTTP(w, r) + return } // Check if session is valid @@ -181,22 +179,26 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // AttachPublicHandler attaches given path and handler and makes it publicly available -func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.HandlerFunc) { - // Add path as exception to user restriction - h.publicPaths = append(h.publicPaths, path) +func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.Handler) { h.mux.Handle(path, handler) } -// AttachUserRestrictedHandler attaches and restricts given path and handler to logged in users. -func (h *PermissionsHandler) AttachUserRestrictedHandler(path string, handler http.HandlerFunc) { - // By default, all paths are user restricted +// AttachPublicHandlerFunc attaches given path and handler and makes it publicly available +func (h *PermissionsHandler) AttachPublicHandlerFunc(path string, handler http.HandlerFunc) { h.mux.Handle(path, handler) } -// AttachAdminRestrictedHandler attaches and restricts given path and handler to logged in admins. -func (h *PermissionsHandler) AttachAdminRestrictedHandler(path string, handler http.HandlerFunc) { +// 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.Handle(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.publicPaths, path) + h.adminPaths = append(h.adminPaths, path) h.mux.Handle(path, handler) } @@ -351,6 +353,7 @@ func (h *PermissionsHandler) validateHandler(w http.ResponseWriter, r *http.Requ s, err := h.sessions.GetSession(w, r) if err != nil { if err == errSessionNotFound || err == errCookieNotFound { + println(err.Error()) // http.Error(w, err.Error(), http.StatusForbidden) } else { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -369,14 +372,5 @@ func (h *PermissionsHandler) validateHandler(w http.ResponseWriter, r *http.Requ return } - // Check if user is admin - /* - admin, err := h.users.IsAdmin(s.Username) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - */ - w.WriteHeader(http.StatusOK) - fmt.Fprintf(w, "[SUCCESS %d] Session ended\n", http.StatusOK) } diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 2a48ed37..55930553 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -44,7 +44,7 @@ func TestServeHTTPPublicPath(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachPublicHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachPublicHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -74,7 +74,7 @@ func TestServeHTTPPublicPathOnNestedHandler(t *testing.T) { mux := http.NewServeMux() mux.Handle(webPrefix, http.StripPrefix(webPrefix, ph)) ts.Config.Handler = mux - ph.AttachPublicHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachPublicHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -98,7 +98,7 @@ func TestServeHTTPWithUserReject(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachUserRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -122,7 +122,7 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachUserRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -134,7 +134,7 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} body, err := json.Marshal(user) assert.Nil(t, err) - req, err := http.NewRequest("POST", ts.URL+"/login", bytes.NewReader(body)) + 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) @@ -146,8 +146,17 @@ func TestServeHTTPWithUserLoginAndLogout(t *testing.T) { 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+"/logout", nil) + req, err = http.NewRequest("POST", ts.URL+"/user/logout", nil) assert.Nil(t, err) req.AddCookie(cookie) logoutResp, err := http.DefaultClient.Do(req) @@ -173,7 +182,7 @@ func TestServeHTTPWithUserLoginAndAccept(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachUserRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachUserRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -185,7 +194,7 @@ func TestServeHTTPWithUserLoginAndAccept(t *testing.T) { user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} body, err := json.Marshal(user) assert.Nil(t, err) - req, err := http.NewRequest("POST", ts.URL+"/login", bytes.NewReader(body)) + 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) @@ -219,7 +228,7 @@ func TestServeHTTPDenyNonAdmin(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachAdminRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachAdminRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -231,7 +240,7 @@ func TestServeHTTPDenyNonAdmin(t *testing.T) { user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} body, err := json.Marshal(user) assert.Nil(t, err) - req, err := http.NewRequest("POST", ts.URL+"/login", bytes.NewReader(body)) + 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) @@ -265,7 +274,7 @@ func TestServeHTTPAllowAdmin(t *testing.T) { assert.Nil(t, err) defer ph.Close() ts.Config.Handler = ph - ph.AttachAdminRestrictedHandler("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ph.AttachAdminRestrictedHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) @@ -277,7 +286,7 @@ func TestServeHTTPAllowAdmin(t *testing.T) { user := &common.UserRequest{Username: "bobheadxi", Password: "wowgreat"} body, err := json.Marshal(user) assert.Nil(t, err) - req, err := http.NewRequest("POST", ts.URL+"/login", bytes.NewReader(body)) + 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) @@ -324,7 +333,7 @@ func TestUserControlHandlers(t *testing.T) { }) assert.Nil(t, err) payload := bytes.NewReader(body) - req, err := http.NewRequest("POST", ts.URL+"/adduser", payload) + 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) @@ -339,7 +348,7 @@ func TestUserControlHandlers(t *testing.T) { }) assert.Nil(t, err) payload = bytes.NewReader(body) - req, err = http.NewRequest("POST", ts.URL+"/removeuser", payload) + 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) @@ -348,7 +357,7 @@ func TestUserControlHandlers(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) // List users - req, err = http.NewRequest("POST", ts.URL+"/listusers", nil) + 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) @@ -357,7 +366,7 @@ func TestUserControlHandlers(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) // Reset all users - req, err = http.NewRequest("POST", ts.URL+"/resetusers", nil) + 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) diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go index c3f228dc..448cca3c 100644 --- a/daemon/inertia/auth/sessions.go +++ b/daemon/inertia/auth/sessions.go @@ -74,7 +74,6 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r expiration := time.Now().Add(s.cookieTimeout) id, err := generateSessionID() if err != nil { - println("Failed to being session for " + username) return errors.New("Failed to begin session for " + username + ": " + err.Error()) } @@ -88,12 +87,11 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r // Add cookie with session ID http.SetCookie(w, &http.Cookie{ - Name: s.cookieName, - Value: url.QueryEscape(id), - Domain: s.cookieDomain, - Path: s.cookiePath, - HttpOnly: true, - Expires: expiration, + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + Path: s.cookiePath, + Expires: expiration, }) return nil } @@ -120,15 +118,12 @@ func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) erro // Set cookie to expire immediately expiration := time.Now() http.SetCookie(w, &http.Cookie{ - Name: s.cookieName, - Domain: s.cookieDomain, - Path: s.cookiePath, - HttpOnly: true, - Expires: expiration, - MaxAge: -1, + Name: s.cookieName, + Domain: s.cookieDomain, + Path: s.cookiePath, + Expires: expiration, + MaxAge: -1, }) - println("logging out") - println(expiration.Format("2006-01-02 15:04:05")) return nil } diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 820afc0c..962ab038 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -63,7 +63,7 @@ func run(host, port, version string) { webPrefix := "/web/" handler, err := auth.NewPermissionsHandler( - auth.UserDatabasePath, host, webPrefix, 120, + auth.UserDatabasePath, host, "/web", 120, ) if err != nil { println(err.Error()) @@ -74,18 +74,25 @@ func run(host, port, version string) { // Inertia web handler.AttachPublicHandler( webPrefix, - http.FileServer(http.Dir("/app/inertia-web")).(http.HandlerFunc), + http.StripPrefix( + webPrefix, http.FileServer(http.Dir("/app/inertia-web")), + ), ) // GitHub webhook endpoint - handler.AttachPublicHandler("/webhook", gitHubWebHookHandler) + handler.AttachPublicHandlerFunc("/webhook", gitHubWebHookHandler) // CLI API endpoints - handler.AttachUserRestrictedHandler("/status", statusHandler) - handler.AttachAdminRestrictedHandler("/up", upHandler) - handler.AttachAdminRestrictedHandler("/down", downHandler) - handler.AttachAdminRestrictedHandler("/reset", resetHandler) - handler.AttachUserRestrictedHandler("/logs", logHandler) + 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) diff --git a/daemon/inertia/logs.go b/daemon/inertia/logs.go index 72d99898..5b3586c6 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" @@ -13,16 +14,16 @@ import ( // logHandler handles requests for container logs func logHandler(w http.ResponseWriter, r *http.Request) { - // Handle CORS for local development - if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { - w.Header().Set("Access-Control-Allow-Origin", origin) - w.Header().Set("Access-Control-Allow-Methods", "GET OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type Accept") + /* // Handle CORS for local development + if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { + w.Header().Set("Access-Control-Allow-Origin", origin) + w.Header().Set("Access-Control-Allow-Methods", "GET OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type Accept") - if r.Method == "OPTIONS" { - return - } - } + if r.Method == "OPTIONS" { + return + } + } */ // Get container name from request body, err := ioutil.ReadAll(r.Body) @@ -41,7 +42,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 } @@ -53,7 +54,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/web/components/App.js b/daemon/web/components/App.js index 2684b7c6..493f681b 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -35,7 +35,7 @@ export default class App extends React.Component { const params = { headers: { 'Accept': 'application/json' }, }; - const response = await this.props.client._get("/web/validate", params); + const response = await this.props.client._get("/user/validate", params); return (response.status === 200); }; diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js index 4e252a20..cd61ce56 100644 --- a/daemon/web/components/Home.js +++ b/daemon/web/components/Home.js @@ -64,7 +64,7 @@ export default class Home extends React.Component { } async handleLogOut() { - const endpoint = '/web/logout'; + const endpoint = '/user/logout'; const params = { headers: { 'Accept': 'application/json' diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js index f31ece63..aba5d976 100644 --- a/daemon/web/components/Login.js +++ b/daemon/web/components/Login.js @@ -14,7 +14,7 @@ export default class Login extends React.Component { } async handleLoginSubmit() { - const endpoint = '/web/login'; + const endpoint = '/user/login'; const params = { headers: { 'Accept': 'application/json', diff --git a/deploy_users.go b/deploy_users.go index f5c77ba6..934ad2de 100644 --- a/deploy_users.go +++ b/deploy_users.go @@ -146,10 +146,9 @@ from the web app.`, } var deploymentUsersListCmd = &cobra.Command{ - Use: "list", + Use: "ls", Short: "List all users registered on your remote.", Long: `List all users with access to Inertia Web on your remote.`, - Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { remoteName := strings.Split(cmd.Parent().Parent().Use, " ")[0] deployment, err := client.GetDeployment(remoteName) From e0ff19acc6626e653f07071c8a67cb9242765bac Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 19 Apr 2018 20:59:10 -0700 Subject: [PATCH 67/73] Add deps script, add eslint config --- .eslintrc | 38 ++++++++++++++++++++++++++++++++++++++ .github/CONTRIBUTING.md | 3 +-- Makefile | 9 +++++++-- daemon/web/package.json | 4 ++-- 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 .eslintrc 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..dea5a9a4 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 +$> dep deps # Install all dependencies $> make RELEASE=test # installs Inertia build tagged as "test" $> inertia --version # check what version you have installed ``` diff --git a/Makefile b/Makefile index 15e89a47..c6c267a2 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,11 @@ 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: + dep ensure + make web-deps + # Install Inertia with release version inertia: go install -ldflags "-X main.Version=$(RELEASE)" @@ -86,9 +91,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/daemon/web/package.json b/daemon/web/package.json index 5d403807..b84c0083 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -21,13 +21,13 @@ "babel-preset-stage-3": "^6.24.1", "css-loader": "^0.28.11", "eslint": "^4.19.1", - "eslint-plugin-react": "^7.6.0", + "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", "react-router-dom": "^4.2.2", - "style-loader": "^0.20.3", + "style-loader": "^0.21.0", "webpack": "^4.2.0", "webpack-cli": "^2.0.13", "webpack-dev-server": "^3.1.1" From be7d4f47bf025bf2055379e228f323c65d01997d Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 19 Apr 2018 21:07:39 -0700 Subject: [PATCH 68/73] Lint and update authentication validation --- daemon/web/client.js | 6 ++-- daemon/web/components/App.js | 60 ++++++++++++++++++++++++---------- daemon/web/components/Login.js | 24 +++++++------- daemon/web/index.js | 7 ++-- 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/daemon/web/client.js b/daemon/web/client.js index 86bea808..938102a0 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -2,7 +2,7 @@ import React from 'react'; export default class InertiaClient { constructor(url) { - this.url = "https://" + url; + this.url = 'https://' + url; } /** @@ -11,7 +11,7 @@ export default class InertiaClient { * @param {Object} params */ async _get(endpoint, params) { - params.method = "GET"; + params.method = 'GET'; const request = new Request(this.url + endpoint, params); @@ -28,7 +28,7 @@ export default class InertiaClient { * @param {Object} params */ async _post(endpoint, params) { - params.method = "POST"; + params.method = 'POST'; const request = new Request(this.url + endpoint, params); diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index 493f681b..e53e2598 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -1,14 +1,16 @@ 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'; -const AuthRoute = ({ authenticated, component: Component, props, ...rest }) => ( +// render a route component that requires authentication +const AuthRoute = ({ component: Component, props, ...rest }) => ( ( - authenticated + props.authenticated ? : )} /> @@ -24,52 +26,74 @@ 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) - } - async isAuthenticated() { - const params = { - headers: { 'Accept': 'application/json' }, - }; - const response = await this.props.client._get("/user/validate", params); - return (response.status === 200); - }; + this.isAuthenticated = this.isAuthenticated.bind(this); - componentDidMount() { this.isAuthenticated().then((authenticated) => { this.setState({ loading: false, - authenticated, + authenticated: authenticated, + }); + }); + + const history = createHistory(); + history.listen(() => { + 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 + ); + console.log('checking auth', response.status); + return (response.status === 200); + } + render() { const { component: Component, ...rest } = this.props; if (this.state.loading) { - return
Loading...
; + return ( +

+ Loading... +

+ ); } else { return (
- } /> - + } /> +
- ) + ); } } } App.propTypes = { - client: PropTypes.instanceOf(InertiaClient) + client: PropTypes.instanceOf(InertiaClient), + authenticated: PropTypes.instanceOf(Boolean), + loading: PropTypes.instanceOf(Boolean), }; const styles = { diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js index aba5d976..4460f8c6 100644 --- a/daemon/web/components/Login.js +++ b/daemon/web/components/Login.js @@ -4,9 +4,9 @@ export default class Login extends React.Component { constructor(props) { super(props); this.state = { - username: "", - password: "", - loginAlert: "" + username: '', + password: '', + loginAlert: '' }; this.handleLoginSubmit = this.handleLoginSubmit.bind(this); this.handleUsernameBlur = this.handleUsernameBlur.bind(this); @@ -23,7 +23,7 @@ export default class Login extends React.Component { body: JSON.stringify({ username: this.state.username, password: this.state.password, - email: "", + email: '', admin: true }) }; @@ -31,7 +31,7 @@ export default class Login extends React.Component { const response = await this.props.client._post(endpoint, params); if (response.status !== 200) { - this.setState({loginAlert: 'Username and/or password is incorrect'}); + this.setState({ loginAlert: 'Username and/or password is incorrect' }); return; } @@ -39,29 +39,29 @@ export default class Login extends React.Component { } handleUsernameBlur(e) { - this.setState({username: e.target.value}); + this.setState({ username: e.target.value }); } handlePasswordBlur(e) { - this.setState({password: e.target.value}); + this.setState({ password: e.target.value }); } - render () { + render() { return (

+ width="20%" />

- - + +

{this.state.loginAlert}

- ) + ); } } diff --git a/daemon/web/index.js b/daemon/web/index.js index e7dee220..ee1a4a2e 100644 --- a/daemon/web/index.js +++ b/daemon/web/index.js @@ -6,6 +6,9 @@ import InertiaClient from './client'; import './index.css'; // Define where the Inertia daemon is hosted. -const daemonAddress = (process.env.NODE_ENV === 'development') ? '0.0.0.0:8081' : 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') +); From 780e4a9d4adb562efa932714d20694b2b7a19f23 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Thu, 19 Apr 2018 21:13:24 -0700 Subject: [PATCH 69/73] Use GET for listusers --- client/deployment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/deployment.go b/client/deployment.go index 54f432aa..5a902932 100644 --- a/client/deployment.go +++ b/client/deployment.go @@ -125,7 +125,7 @@ func (d *Deployment) ResetUsers() (*http.Response, error) { // ListUsers lists all users on the remote. func (d *Deployment) ListUsers() (*http.Response, error) { - return d.request("POST", "/user/listusers", nil) + return d.request("GET", "/user/listusers", nil) } func (d *Deployment) request(method, endpoint string, requestBody interface{}) (*http.Response, error) { From 8e4a185ac806d0d9bda742d74fa9145f667e2961 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 20 Apr 2018 00:47:26 -0700 Subject: [PATCH 70/73] Functional web app authentication - login, logout, redirect to login --- daemon/inertia/auth/auth.go | 3 +- daemon/inertia/auth/permissions.go | 78 ++++++++----------------- daemon/inertia/auth/permissions_test.go | 40 +------------ daemon/inertia/auth/sessions.go | 27 +++++---- daemon/inertia/daemon.go | 2 +- daemon/inertia/logs.go | 11 ---- daemon/web/client.js | 4 +- daemon/web/components/App.js | 6 +- daemon/web/components/Home.js | 10 ++-- daemon/web/components/Login.js | 4 +- daemon/web/package.json | 2 +- daemon/web/webpack.config.js | 2 +- 12 files changed, 55 insertions(+), 134 deletions(-) diff --git a/daemon/inertia/auth/auth.go b/daemon/inertia/auth/auth.go index 5a63cd1c..f543ccd3 100644 --- a/daemon/inertia/auth/auth.go +++ b/daemon/inertia/auth/auth.go @@ -14,8 +14,7 @@ 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 diff --git a/daemon/inertia/auth/permissions.go b/daemon/inertia/auth/permissions.go index 508f43d4..7465e730 100644 --- a/daemon/inertia/auth/permissions.go +++ b/daemon/inertia/auth/permissions.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "net/http" + "net/url" "strings" jwt "github.com/dgrijalva/jwt-go" @@ -30,7 +31,7 @@ type PermissionsHandler struct { // users and handling user administration. Param userlandPath is // used to set cookie domain. func NewPermissionsHandler( - dbPath, domain, userlandPath string, timeout int, + dbPath, hostDomain string, timeout int, keyLookup ...func(*jwt.Token) (interface{}, error), ) (*PermissionsHandler, error) { // Set up user manager @@ -40,12 +41,12 @@ func NewPermissionsHandler( } // Set up session manager - sessionManager := newSessionManager(domain, userlandPath, timeout) + sessionManager := newSessionManager(hostDomain, timeout) // Set up permissions handler mux := http.NewServeMux() handler := &PermissionsHandler{ - domain: domain, + domain: hostDomain, users: userManager, sessions: sessionManager, mux: mux, @@ -60,6 +61,9 @@ func NewPermissionsHandler( 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", @@ -82,8 +86,21 @@ func (h *PermissionsHandler) Close() error { return h.users.Close() } -// Implement the ServeHTTP method to make a permissionHandler a http.Handler +// 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 @@ -151,17 +168,6 @@ func (h *PermissionsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - // Check if user is valid - err = h.users.HasUser(s.Username) - if err != nil { - if err == errUserNotFound { - 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) @@ -185,21 +191,21 @@ func (h *PermissionsHandler) AttachPublicHandler(path string, handler http.Handl // AttachPublicHandlerFunc attaches given path and handler and makes it publicly available func (h *PermissionsHandler) AttachPublicHandlerFunc(path string, handler http.HandlerFunc) { - h.mux.Handle(path, handler) + 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.Handle(path, handler) + 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.Handle(path, handler) + h.mux.HandleFunc(path, handler) } func (h *PermissionsHandler) addUserHandler(w http.ResponseWriter, r *http.Request) { @@ -292,18 +298,6 @@ func (h *PermissionsHandler) listUsersHandler(w http.ResponseWriter, r *http.Req } func (h *PermissionsHandler) loginHandler(w http.ResponseWriter, r *http.Request) { - // Handle CORS for local development - if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { - fmt.Println("setting cors") - w.Header().Set("Access-Control-Allow-Origin", origin) - w.Header().Set("Access-Control-Allow-Methods", "POST OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type") - - if r.Method == "OPTIONS" { - return - } - } - // Retrieve user details from request body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -342,6 +336,7 @@ func (h *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Reques err := h.sessions.EndSession(w, r) if err != nil { http.Error(w, "Logout failed: "+err.Error(), http.StatusInternalServerError) + return } w.WriteHeader(http.StatusOK) @@ -349,28 +344,5 @@ func (h *PermissionsHandler) logoutHandler(w http.ResponseWriter, r *http.Reques } func (h *PermissionsHandler) validateHandler(w http.ResponseWriter, r *http.Request) { - // Check if session is valid - s, err := h.sessions.GetSession(w, r) - if err != nil { - if err == errSessionNotFound || err == errCookieNotFound { - println(err.Error()) // - http.Error(w, err.Error(), http.StatusForbidden) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - - // Check if user exists - err = h.users.HasUser(s.Username) - if err != nil { - if err == errUserNotFound { - http.Error(w, err.Error(), http.StatusForbidden) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - w.WriteHeader(http.StatusOK) } diff --git a/daemon/inertia/auth/permissions_test.go b/daemon/inertia/auth/permissions_test.go index 55930553..7736cc4e 100644 --- a/daemon/inertia/auth/permissions_test.go +++ b/daemon/inertia/auth/permissions_test.go @@ -15,20 +15,14 @@ import ( "github.com/stretchr/testify/assert" ) -func getTestPermissionsHandler(dir string, p ...string) (*PermissionsHandler, error) { +func getTestPermissionsHandler(dir string) (*PermissionsHandler, error) { err := os.Mkdir(dir, os.ModePerm) if err != nil { return nil, err } - var endpoint string - if len(p) > 0 { - endpoint = p[0] - } else { - endpoint = "/" - } return NewPermissionsHandler( path.Join(dir, "users.db"), - "127.0.0.1", endpoint, 3000, + "127.0.0.1", 3000, getFakeAPIKey, ) } @@ -57,36 +51,6 @@ func TestServeHTTPPublicPath(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) } -func TestServeHTTPPublicPathOnNestedHandler(t *testing.T) { - // This test emulates the daemon's PermissionsHandler setup - dir := "./test_perm" - ts := httptest.NewServer(nil) - defer ts.Close() - - // Set up permission handler - webPrefix := "/web/" - ph, err := getTestPermissionsHandler(dir, webPrefix) - defer os.RemoveAll(dir) - assert.Nil(t, err) - defer ph.Close() - - // Daemon uses a nested handler - mux := http.NewServeMux() - mux.Handle(webPrefix, http.StripPrefix(webPrefix, ph)) - ts.Config.Handler = mux - ph.AttachPublicHandlerFunc("/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - })) - - req, err := http.NewRequest("POST", ts.URL+"/web/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) diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go index 448cca3c..9ac5b23a 100644 --- a/daemon/inertia/auth/sessions.go +++ b/daemon/inertia/auth/sessions.go @@ -18,7 +18,6 @@ type session struct { type sessionManager struct { cookieName string cookieDomain string - cookiePath string cookieTimeout time.Duration internal map[string]*session @@ -26,11 +25,10 @@ type sessionManager struct { endSessionCleanup chan bool } -func newSessionManager(domain, path string, timeout int) *sessionManager { +func newSessionManager(domain string, timeout int) *sessionManager { manager := &sessionManager{ cookieName: "ubclaunchpad-inertia", cookieDomain: domain, - cookiePath: path, cookieTimeout: time.Duration(timeout) * time.Minute, internal: make(map[string]*session), @@ -87,11 +85,11 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r // Add cookie with session ID http.SetCookie(w, &http.Cookie{ - Name: s.cookieName, - Value: url.QueryEscape(id), - Domain: s.cookieDomain, - Path: s.cookiePath, - Expires: expiration, + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + HttpOnly: true, + Expires: expiration, }) return nil } @@ -116,19 +114,20 @@ func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) erro s.Unlock() // Set cookie to expire immediately - expiration := time.Now() http.SetCookie(w, &http.Cookie{ - Name: s.cookieName, - Domain: s.cookieDomain, - Path: s.cookiePath, - Expires: expiration, - MaxAge: -1, + Name: s.cookieName, + Value: url.QueryEscape(id), + Domain: s.cookieDomain, + MaxAge: int(s.cookieTimeout / time.Second), + 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 diff --git a/daemon/inertia/daemon.go b/daemon/inertia/daemon.go index 962ab038..cec2cda7 100644 --- a/daemon/inertia/daemon.go +++ b/daemon/inertia/daemon.go @@ -63,7 +63,7 @@ func run(host, port, version string) { webPrefix := "/web/" handler, err := auth.NewPermissionsHandler( - auth.UserDatabasePath, host, "/web", 120, + auth.UserDatabasePath, host, 120, ) if err != nil { println(err.Error()) diff --git a/daemon/inertia/logs.go b/daemon/inertia/logs.go index 5b3586c6..6ed39ecd 100644 --- a/daemon/inertia/logs.go +++ b/daemon/inertia/logs.go @@ -14,17 +14,6 @@ import ( // logHandler handles requests for container logs func logHandler(w http.ResponseWriter, r *http.Request) { - /* // Handle CORS for local development - if origin := r.Header.Get("Origin"); origin == "http://localhost:7900" { - w.Header().Set("Access-Control-Allow-Origin", origin) - w.Header().Set("Access-Control-Allow-Methods", "GET OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Content-Type Accept") - - if r.Method == "OPTIONS" { - return - } - } */ - // Get container name from request body, err := ioutil.ReadAll(r.Body) if err != nil { diff --git a/daemon/web/client.js b/daemon/web/client.js index 938102a0..3c1bb322 100644 --- a/daemon/web/client.js +++ b/daemon/web/client.js @@ -12,7 +12,7 @@ export default class InertiaClient { */ async _get(endpoint, params) { params.method = 'GET'; - + params.credentials = 'include'; const request = new Request(this.url + endpoint, params); try { @@ -29,7 +29,7 @@ export default class InertiaClient { */ async _post(endpoint, params) { params.method = 'POST'; - + params.credentials = 'include'; const request = new Request(this.url + endpoint, params); try { diff --git a/daemon/web/components/App.js b/daemon/web/components/App.js index e53e2598..209a53f0 100644 --- a/daemon/web/components/App.js +++ b/daemon/web/components/App.js @@ -8,9 +8,9 @@ import Login from './Login'; import Home from './Home'; // render a route component that requires authentication -const AuthRoute = ({ component: Component, props, ...rest }) => ( +const AuthRoute = ({ authenticated, component: Component, props, ...rest }) => ( ( - props.authenticated + authenticated ? : )} /> @@ -43,6 +43,7 @@ export default class App extends React.Component { const history = createHistory(); history.listen(() => { + this.setState({ loading: true, authenticated: false }); this.isAuthenticated().then((authenticated) => { this.setState({ loading: false, @@ -59,7 +60,6 @@ export default class App extends React.Component { const response = await this.props.client._get( '/user/validate', params ); - console.log('checking auth', response.status); return (response.status === 200); } diff --git a/daemon/web/components/Home.js b/daemon/web/components/Home.js index cd61ce56..735a7dfe 100644 --- a/daemon/web/components/Home.js +++ b/daemon/web/components/Home.js @@ -49,7 +49,7 @@ export default class Home extends React.Component { constructor(props) { super(props); this.handleGetLogs = this.handleGetLogs.bind(this); - this.handleLogOut = this.handleLogOut.bind(this); + this.handleLogout = this.handleLogout.bind(this); } async handleGetLogs() { @@ -59,11 +59,10 @@ export default class Home extends React.Component { 'Accept': 'application/json' } }; - const response = await this.props.client._get(endpoint, params); } - async handleLogOut() { + async handleLogout() { const endpoint = '/user/logout'; const params = { headers: { @@ -71,7 +70,8 @@ export default class Home extends React.Component { } }; - const response = await this.props.client._get(endpoint, params); + const response = await this.props.client._post(endpoint, params); + this.props.history.push('/login'); } render() { @@ -80,7 +80,7 @@ export default class Home extends React.Component {

Inertia Web

- logout + logout
diff --git a/daemon/web/components/Login.js b/daemon/web/components/Login.js index 4460f8c6..cbe212e0 100644 --- a/daemon/web/components/Login.js +++ b/daemon/web/components/Login.js @@ -18,7 +18,7 @@ export default class Login extends React.Component { const params = { headers: { 'Accept': 'application/json', - 'Content-Type': 'application/json' + 'Content-Type': 'application/x-www-form-urlencoded' }, body: JSON.stringify({ username: this.state.username, @@ -27,9 +27,7 @@ export default class Login extends React.Component { 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; diff --git a/daemon/web/package.json b/daemon/web/package.json index b84c0083..5714f018 100644 --- a/daemon/web/package.json +++ b/daemon/web/package.json @@ -7,7 +7,7 @@ "license": "MIT", "main": "index.js", "scripts": { - "start": "NODE_ENV=development webpack-dev-server", + "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" }, diff --git a/daemon/web/webpack.config.js b/daemon/web/webpack.config.js index bba8e4a1..766ba164 100644 --- a/daemon/web/webpack.config.js +++ b/daemon/web/webpack.config.js @@ -13,7 +13,7 @@ const config = { port: 7900, inline: true, contentBase: './public', - publicPath: '/', + publicPath: '/web/', }, devtool: 'inline-source-map', module: { From c4364d59cbe5efc6e08957bad19265d727975472 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 20 Apr 2018 02:40:31 -0700 Subject: [PATCH 71/73] New Go linter (gometalinter) --- .github/CONTRIBUTING.md | 2 +- .gitignore | 1 + .gometalinter.json | 15 +++++++++++++++ .travis.yml | 18 ++++++------------ Makefile | 11 ++++++++++- daemon/inertia/auth/sessions.go | 3 ++- daemon/inertia/project/git.go | 9 ++++----- 7 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 .gometalinter.json diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index dea5a9a4..b39db661 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -35,7 +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 deps # Install all 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 20143cf7..537cc98d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.dylib /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 4bd278a3..f1f1071e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,23 +31,17 @@ 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/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 test VPS + - 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 - - docker kill $(docker ps -q) # Remove testvps, etc + - ./bin/gometalinter --vendor ./... # 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/Makefile b/Makefile index c6c267a2..e754a0fe 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,9 @@ VPS_VERSION = latest VPS_OS = ubuntu RELEASE = canary +METALINTER_VERSION = 2.0.5 +METALINTER_PLATFORM = linux + all: inertia # List all commands @@ -14,6 +17,7 @@ ls: # Sets up all dependencies deps: + curl -sfL https://install.goreleaser.com/github.com/alecthomas/gometalinter.sh | bash dep ensure make web-deps @@ -25,11 +29,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: + ./bin/gometalinter --vendor ./... + # Run unit test suite test: go test ./... -short -ldflags "-X main.Version=test" --cover @@ -39,7 +46,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 diff --git a/daemon/inertia/auth/sessions.go b/daemon/inertia/auth/sessions.go index 9ac5b23a..9d49fa70 100644 --- a/daemon/inertia/auth/sessions.go +++ b/daemon/inertia/auth/sessions.go @@ -88,6 +88,7 @@ func (s *sessionManager) BeginSession(username string, w http.ResponseWriter, r Name: s.cookieName, Value: url.QueryEscape(id), Domain: s.cookieDomain, + MaxAge: int(s.cookieTimeout / time.Second), HttpOnly: true, Expires: expiration, }) @@ -118,7 +119,7 @@ func (s *sessionManager) EndSession(w http.ResponseWriter, r *http.Request) erro Name: s.cookieName, Value: url.QueryEscape(id), Domain: s.cookieDomain, - MaxAge: int(s.cookieTimeout / time.Second), + MaxAge: -1, HttpOnly: true, Expires: time.Unix(0, 0), }) 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 From 7b731c11cc706aebf6f441d056e0f812e1fc0d95 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 20 Apr 2018 02:50:47 -0700 Subject: [PATCH 72/73] Remove unused vars, update Dockerignore --- .dockerignore | 19 ++++++++----------- Makefile | 3 --- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.dockerignore b/.dockerignore index 759de7a8..d64bff9c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,22 +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 + +# Dependencies +bin diff --git a/Makefile b/Makefile index e754a0fe..bfe15e59 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,6 @@ VPS_VERSION = latest VPS_OS = ubuntu RELEASE = canary -METALINTER_VERSION = 2.0.5 -METALINTER_PLATFORM = linux - all: inertia # List all commands From 182ff2e1b79a6914714d50e22634fa653c735bb2 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 20 Apr 2018 03:00:02 -0700 Subject: [PATCH 73/73] Update lint scripts --- .travis.yml | 7 ++++--- Makefile | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index f1f1071e..ce68d759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,17 +31,18 @@ matrix: fast_finish: true before_install: + - 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 + - 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" - - ./bin/gometalinter --vendor ./... # Static code analysis - - docker kill $(docker ps -q) # Remove testvps, etc + - 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/Makefile b/Makefile index bfe15e59..3291be8a 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ clean: find . -type f -name inertia.\* -exec rm {} \; lint: - ./bin/gometalinter --vendor ./... + PATH=$(PATH):./bin bash -c './bin/gometalinter --vendor ./...' # Run unit test suite test: