From: jloup Date: Wed, 14 Feb 2018 13:19:09 +0000 (+0100) Subject: initial commit X-Git-Tag: v0.0.1~1 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=7a9e5112eaaea58d55f181d3e5296e4ff839921c;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FCryptoportfolio%2FFront.git initial commit --- 7a9e5112eaaea58d55f181d3e5296e4ff839921c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad02220 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +vendor/ +cmd/app/dist +cmd/app/cryptoportfolio-app \ No newline at end of file diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..7f0f166 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,143 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/BurntSushi/toml" + packages = ["."] + revision = "b26d9c308763d68093482582cea63d69be07a0f0" + version = "v0.3.0" + +[[projects]] + name = "github.com/Sirupsen/logrus" + packages = ["."] + revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba" + version = "v1.0.4" + +[[projects]] + name = "github.com/boombuler/barcode" + packages = [ + ".", + "qr", + "utils" + ] + revision = "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d" + version = "v1.0.0" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" + version = "v3.1.0" + +[[projects]] + name = "github.com/gin-contrib/cors" + packages = ["."] + revision = "cf4846e6a636a76237a28d9286f163c132e841bc" + version = "v1.2" + +[[projects]] + branch = "master" + name = "github.com/gin-contrib/sse" + packages = ["."] + revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae" + +[[projects]] + name = "github.com/gin-gonic/gin" + packages = [ + ".", + "binding", + "render" + ] + revision = "d459835d2b077e44f7c9b453505ee29881d5d12d" + version = "v1.2" + +[[projects]] + name = "github.com/go-pg/pg" + packages = [ + ".", + "internal", + "internal/parser", + "internal/pool", + "orm", + "types" + ] + revision = "eff1632b1caea7c554b174d5551ff2791021810c" + version = "v6.9.3" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/jinzhu/inflection" + packages = ["."] + revision = "1c35d901db3da928c72a72d8458480cc9ade058f" + +[[projects]] + branch = "master" + name = "github.com/jloup/utils" + packages = ["."] + revision = "6055a8f761d5892502228aa62249e122f8bd392d" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/pquerna/otp" + packages = [ + ".", + "hotp", + "totp" + ] + revision = "b7b89250c468c06871d3837bee02e2d5c155ae19" + version = "v1.0.0" + +[[projects]] + name = "github.com/ugorji/go" + packages = ["codec"] + revision = "9831f2c3ac1068a78f50999a30db84270f647af6" + version = "v1.1" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = [ + "bcrypt", + "blowfish", + "ssh/terminal" + ] + revision = "650f4a345ab4e5b245a3034b110ebc7299e68186" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" + +[[projects]] + name = "gopkg.in/go-playground/validator.v8" + packages = ["."] + revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf" + version = "v8.18.2" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "c9af022a586632799c6259f6c48eef8dad7080e36b96e8cb5cb905b316c4cb9b" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..f4686b5 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,58 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "3.1.0" + +[[constraint]] + name = "github.com/gin-contrib/cors" + version = "1.2.0" + +[[constraint]] + name = "github.com/gin-gonic/gin" + version = "1.2.0" + +[[constraint]] + name = "github.com/go-pg/pg" + version = "6.9.3" + +[[constraint]] + branch = "master" + name = "github.com/jloup/utils" + +[[constraint]] + name = "github.com/pquerna/otp" + version = "1.0.0" + +[[constraint]] + branch = "master" + name = "golang.org/x/crypto" + +[prune] + go-tests = true + unused-packages = true diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d7fe209 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +install: + go get -u github.com/golang/dep/cmd/dep + dep ensure + go get github.com/aktau/github-release + +clean: + rm -rf vendor diff --git a/README.md b/README.md new file mode 100644 index 0000000..84e6304 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Crypto diff --git a/api/api.go b/api/api.go new file mode 100644 index 0000000..7b7be49 --- /dev/null +++ b/api/api.go @@ -0,0 +1,130 @@ +package api + +import ( + "net/http" + "unicode" + + "github.com/gin-gonic/gin" +) + +type Error struct { + Code ErrorCode + UserMessage string + err error +} + +func (e Error) Err() error { + if e.err != nil { + return e + } + + return nil +} + +func (e Error) Error() string { + if e.err != nil { + return e.err.Error() + } + + return "" +} + +func NewInternalError(err error) *Error { + return &Error{InternalError, "internal error", err} +} + +func ToSnake(in string) string { + runes := []rune(in) + length := len(runes) + + var out []rune + for i := 0; i < length; i++ { + if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) { + out = append(out, '_') + } + out = append(out, unicode.ToLower(runes[i])) + } + + return string(out) +} + +type Response struct { + StatusCode Status `json:"-"` + ErrorCode ErrorCode `json:"-"` + + Status string `json:"status"` + Code string `json:"code,omitempty"` + Response interface{} `json:"response,omitempty"` + Message string `json:"message,omitempty"` +} + +func (r Response) populateStatus() Response { + r.Status = ToSnake(r.StatusCode.String()) + + if r.ErrorCode != 0 { + r.Code = ToSnake(r.ErrorCode.String()) + } + + return r +} + +func ErrorResponse(code ErrorCode, message string) Response { + return Response{ + StatusCode: NOK, + ErrorCode: code, + Message: message, + } +} + +func SuccessResponse(data interface{}) Response { + return Response{ + StatusCode: OK, + Response: data, + } +} + +func WriteJsonResponse(response Response, c *gin.Context) { + response = response.populateStatus() + + c.JSON(StatusToHttpCode(response.StatusCode, response.ErrorCode), response) +} + +func WriteBinary(contentType string, b []byte, c *gin.Context) { + c.Data(http.StatusOK, contentType, b) +} + +type Middleware func(*gin.Context) *Error + +func M(handler Middleware) gin.HandlerFunc { + return func(c *gin.Context) { + err := handler(c) + + if err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + c.Abort() + } else { + c.Next() + } + } +} + +type Query interface { + ValidateParams() *Error + Run() (interface{}, *Error) +} + +func RunQuery(query Query, c *gin.Context) { + if err := query.ValidateParams(); err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + return + } + + if out, err := query.Run(); err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + } else { + WriteJsonResponse(SuccessResponse(out), c) + } +} diff --git a/api/auth_jwt.go b/api/auth_jwt.go new file mode 100644 index 0000000..f713f4e --- /dev/null +++ b/api/auth_jwt.go @@ -0,0 +1,107 @@ +package api + +import ( + "fmt" + "strings" + "time" + + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" + + "github.com/dgrijalva/jwt-go" + "github.com/gin-gonic/gin" +) + +// Static secret. +var JWT_SECRET []byte + +type JwtClaims struct { + Authorized bool `json:"authorized"` + Subject int64 `json:"sub,omitempty"` + jwt.StandardClaims +} + +func SetJwtSecretKey(secret string) { + JWT_SECRET = []byte(secret) +} + +func VerifyJwtToken(token string) (JwtClaims, error) { + if len(JWT_SECRET) == 0 { + return JwtClaims{}, fmt.Errorf("not initialized jwt secret") + } + + t, err := jwt.ParseWithClaims(token, &JwtClaims{}, func(t *jwt.Token) (interface{}, error) { + if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("Unexpected signing method: %v", t.Header["alg"]) + } + + return JWT_SECRET, nil + }) + + claims, ok := t.Claims.(*JwtClaims) + + if !ok || !t.Valid || err != nil { + return JwtClaims{}, fmt.Errorf("invalid token (err: %v, claimsok: %v)", err, ok) + } + + return *claims, nil +} + +func SignJwt(claims JwtClaims) (string, error) { + if len(JWT_SECRET) == 0 { + return "", fmt.Errorf("not initialized jwt secret") + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, &claims) + + return token.SignedString(JWT_SECRET) +} + +func CreateJwtToken(userId int64) (string, error) { + claims := JwtClaims{ + false, + userId, + jwt.StandardClaims{ + ExpiresAt: time.Now().Add(time.Hour * 24).Unix(), + }, + } + + return SignJwt(claims) +} + +func GetBearerToken(header string) (string, error) { + const prefix = "Bearer " + + if !strings.HasPrefix(header, prefix) { + return "", fmt.Errorf("invalid authorization token") + } + + return header[len(prefix):], nil +} + +func JwtAuth(c *gin.Context) *Error { + token, err := GetBearerToken(c.GetHeader("Authorization")) + if err != nil { + return &Error{NotAuthorized, "not authorized", err} + } + + claims, err := VerifyJwtToken(token) + if err != nil { + return &Error{NotAuthorized, "not authorized", err} + } + + user, err := db.GetUserById(claims.Subject) + if err != nil { + return &Error{NotAuthorized, "not authorized", err} + } + + c.Set("user", *user) + c.Set("claims", claims) + + return nil +} + +func GetClaims(c *gin.Context) JwtClaims { + claims, _ := c.Get("claims") + + return claims.(JwtClaims) +} diff --git a/api/auth_otp.go b/api/auth_otp.go new file mode 100644 index 0000000..de1cf24 --- /dev/null +++ b/api/auth_otp.go @@ -0,0 +1,122 @@ +package api + +import ( + "bytes" + "fmt" + "image/png" + + "github.com/gin-gonic/gin" + "github.com/pquerna/otp/totp" + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" +) + +func GenerateSecret(user db.User) (bytes.Buffer, string, error) { + var buf bytes.Buffer + key, err := totp.Generate(totp.GenerateOpts{ + Issuer: "cryptoportfolio", + AccountName: user.Email, + Period: 30, + }) + + if err != nil { + return buf, "", err + } + + qrImage, err := key.Image(200, 200) + if err != nil { + return buf, "", err + } + + png.Encode(&buf, qrImage) + if err != nil { + return buf, "", err + } + + return buf, key.Secret(), nil +} + +type OtpEnrollmentQuery struct { + In struct { + User db.User + } +} + +func (q OtpEnrollmentQuery) ValidateParams() *Error { + return nil +} + +func (q OtpEnrollmentQuery) Run() (*bytes.Buffer, string, *Error) { + if q.In.User.OtpSecret != "" && q.In.User.IsOtpSetup == true { + return nil, "", &Error{OtpAlreadySetup, "otp is already setup", fmt.Errorf("otp already setup")} + } + + buf, secret, err := GenerateSecret(q.In.User) + if err != nil { + return nil, "", NewInternalError(err) + } + + err = db.SetOtpSecret(&q.In.User, secret, true) + if err != nil { + return nil, "", NewInternalError(err) + } + + return &buf, secret, nil +} + +type OtpValidateQuery struct { + In struct { + Pass string + User db.User + Claims JwtClaims + } + + Out struct { + Token string `json:"token"` + } +} + +func (q OtpValidateQuery) ValidateParams() *Error { + if q.In.Pass == "" { + return &Error{InvalidOtp, "invalid otp", fmt.Errorf("invalid otp '%v'", q.In.Pass)} + } + + return nil +} + +func (q OtpValidateQuery) Run() (interface{}, *Error) { + var err error + + if q.In.User.OtpSecret == "" { + return nil, &Error{OtpNotSetup, "otp is not setup", fmt.Errorf("otp is not setup")} + } + + if !totp.Validate(q.In.Pass, q.In.User.OtpSecret) { + return nil, &Error{InvalidOtp, "invalid otp", fmt.Errorf("invalid otp '%v'", q.In.Pass)} + + } else if err := db.SetOtpSecret(&q.In.User, q.In.User.OtpSecret, false); err != nil { + return nil, NewInternalError(err) + } + + q.In.Claims.Authorized = true + q.Out.Token, err = SignJwt(q.In.Claims) + if err != nil { + return nil, NewInternalError(err) + } + + return q.Out, nil +} + +func OtpAuth(c *gin.Context) *Error { + claims := GetClaims(c) + user := GetUser(c) + + if user.IsOtpSetup == false || user.OtpSecret == "" { + return &Error{OtpNotSetup, "otp is not setup", fmt.Errorf("otp is not setup")} + } + + if !claims.Authorized { + return &Error{NeedOtpValidation, "not authorized", fmt.Errorf("otp not authorized")} + } + + return nil +} diff --git a/api/const.go b/api/const.go new file mode 100644 index 0000000..2edd6f4 --- /dev/null +++ b/api/const.go @@ -0,0 +1,51 @@ +package api + +import "net/http" + +//go:generate stringer -type=Status,ErrorCode -output const_string.go +type Status uint32 +type ErrorCode uint32 + +const ( + OK Status = iota + NOK + + BadRequest ErrorCode = iota + 1 + EmailExists + InternalError + InvalidCredentials + InvalidEmail + InvalidOtp + InvalidPassword + NeedOtpValidation + NotAuthorized + NotFound + OtpAlreadySetup + OtpNotSetup + UserNotConfirmed +) + +func StatusToHttpCode(status Status, code ErrorCode) int { + if status == OK { + return http.StatusOK + } + + switch code { + case BadRequest, InvalidPassword, InvalidEmail: + return http.StatusBadRequest + + case InvalidCredentials, InvalidOtp: + return http.StatusUnauthorized + + case UserNotConfirmed, NotAuthorized, OtpAlreadySetup, OtpNotSetup, NeedOtpValidation: + return http.StatusForbidden + + case EmailExists: + return http.StatusConflict + + case NotFound: + return http.StatusNotFound + } + + return http.StatusInternalServerError +} diff --git a/api/const_string.go b/api/const_string.go new file mode 100644 index 0000000..611db40 --- /dev/null +++ b/api/const_string.go @@ -0,0 +1,28 @@ +// Code generated by "stringer -type=Status,ErrorCode -output const_string.go"; DO NOT EDIT + +package api + +import "fmt" + +const _Status_name = "OKNOK" + +var _Status_index = [...]uint8{0, 2, 5} + +func (i Status) String() string { + if i >= Status(len(_Status_index)-1) { + return fmt.Sprintf("Status(%d)", i) + } + return _Status_name[_Status_index[i]:_Status_index[i+1]] +} + +const _ErrorCode_name = "BadRequestEmailExistsInternalErrorInvalidCredentialsInvalidEmailInvalidOtpInvalidPasswordNeedOtpValidationNotAuthorizedNotFoundOtpAlreadySetupOtpNotSetupUserNotConfirmed" + +var _ErrorCode_index = [...]uint8{0, 10, 21, 34, 52, 64, 74, 89, 106, 119, 127, 142, 153, 169} + +func (i ErrorCode) String() string { + i -= 3 + if i >= ErrorCode(len(_ErrorCode_index)-1) { + return fmt.Sprintf("ErrorCode(%d)", i+3) + } + return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]] +} diff --git a/api/logger.go b/api/logger.go new file mode 100644 index 0000000..7057a30 --- /dev/null +++ b/api/logger.go @@ -0,0 +1,27 @@ +package api + +import ( + "github.com/gin-gonic/gin" + "github.com/jloup/utils" +) + +var log = utils.StandardL().WithField("module", "api") + +func Logger() gin.HandlerFunc { + return func(c *gin.Context) { + path := c.Request.URL.Path + rawQuery := c.Request.URL.RawQuery + + c.Next() + + for _, err := range c.Errors { + l := log.WithField("path", path) + + if rawQuery != "" { + l = l.WithField("query", rawQuery) + } + + l.Errorf("%s", err.Err) + } + } +} diff --git a/api/market_config.go b/api/market_config.go new file mode 100644 index 0000000..3fd10ae --- /dev/null +++ b/api/market_config.go @@ -0,0 +1,77 @@ +package api + +import ( + "fmt" + + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" +) + +type MarketConfigQuery struct { + In struct { + User db.User + Market string + } +} + +func (q MarketConfigQuery) ValidateParams() *Error { + if q.In.Market != "poloniex" { + return &Error{BadRequest, "invalid market name", fmt.Errorf("'%v' is not a valid market name", q.In.Market)} + } + + return nil +} + +func (q MarketConfigQuery) Run() (interface{}, *Error) { + config, err := db.GetUserMarketConfig(q.In.User.Id, q.In.Market) + if err != nil { + return nil, NewInternalError(err) + } + + if config == nil { + configMap := make(map[string]string) + configMap["key"] = "" + configMap["secret"] = "" + + config, err = db.SetUserMarketConfig(q.In.User.Id, q.In.Market, configMap) + if err != nil { + return nil, NewInternalError(err) + } + + } + + return config.Config, nil +} + +type UpdateMarketConfigQuery struct { + In struct { + User db.User + Market string + Key string + Secret string + } +} + +func (q UpdateMarketConfigQuery) ValidateParams() *Error { + if q.In.Market == "" { + return &Error{BadRequest, "invalid market name", fmt.Errorf("'%v' is not a valid market name", q.In.Market)} + } + + return nil +} + +func (q UpdateMarketConfigQuery) Run() (interface{}, *Error) { + configMap := make(map[string]string) + if q.In.Key != "" { + configMap["key"] = q.In.Key + } + if q.In.Secret != "" { + configMap["secret"] = q.In.Secret + } + + _, err := db.SetUserMarketConfig(q.In.User.Id, q.In.Market, configMap) + if err != nil { + return nil, NewInternalError(err) + } + + return nil, nil +} diff --git a/api/routes.go b/api/routes.go new file mode 100644 index 0000000..d7e712c --- /dev/null +++ b/api/routes.go @@ -0,0 +1,123 @@ +package api + +import ( + "encoding/base64" + + "github.com/gin-gonic/gin" +) + +type Route struct { + Method string + Handlers []gin.HandlerFunc + Path string +} + +type Group struct { + Root string + Middlewares []Middleware + Routes []Route +} + +var Groups = []Group{ + { + "", + nil, + []Route{ + {"POST", []gin.HandlerFunc{Signup}, "/signup"}, + {"POST", []gin.HandlerFunc{Signin}, "/signin"}, + }, + }, + { + "/otp", + []Middleware{JwtAuth, UserConfirmed}, + []Route{ + {"GET", []gin.HandlerFunc{OtpEnrollment}, "/enroll"}, + {"POST", []gin.HandlerFunc{OtpValidate}, "/validate"}, + }, + }, + { + "/market", + []Middleware{JwtAuth, UserConfirmed, OtpAuth}, + []Route{ + {"GET", []gin.HandlerFunc{GetMarketConfig}, "/:name"}, + {"POST", []gin.HandlerFunc{UpdateMarketConfig}, "/:name/update"}, + }, + }, +} + +func Signup(c *gin.Context) { + query := &SignupQuery{} + + query.In.Email = c.PostForm("email") + query.In.Password = c.PostForm("password") + + RunQuery(query, c) +} + +func Signin(c *gin.Context) { + query := &SigninQuery{} + + query.In.Email = c.PostForm("email") + query.In.Password = c.PostForm("password") + + RunQuery(query, c) +} + +func OtpValidate(c *gin.Context) { + query := &OtpValidateQuery{} + + query.In.Pass = c.PostForm("pass") + query.In.User = GetUser(c) + query.In.Claims = GetClaims(c) + + RunQuery(query, c) +} + +func OtpEnrollment(c *gin.Context) { + query := &OtpEnrollmentQuery{} + + query.In.User = GetUser(c) + + qrPng, secret, err := query.Run() + if err != nil { + WriteJsonResponse(ErrorResponse(err.Code, err.UserMessage), c) + c.Error(err) + return + } + + if c.Query("format") == "png" { + c.Header("X-OTP-Secret", secret) + WriteBinary("image/png", qrPng.Bytes(), c) + } else { + response := struct { + Base64img string `json:"base64img"` + OtpSecret string `json:"secret"` + }{ + base64.StdEncoding.EncodeToString(qrPng.Bytes()), + secret, + } + + WriteJsonResponse(SuccessResponse(response), c) + } + +} + +func GetMarketConfig(c *gin.Context) { + query := &MarketConfigQuery{} + + query.In.User = GetUser(c) + query.In.Market = c.Param("name") + + RunQuery(query, c) +} + +func UpdateMarketConfig(c *gin.Context) { + query := &UpdateMarketConfigQuery{} + + query.In.User = GetUser(c) + query.In.Market = c.Param("name") + query.In.Key = c.PostForm("key") + query.In.Secret = c.PostForm("secret") + + RunQuery(query, c) +} diff --git a/api/user.go b/api/user.go new file mode 100644 index 0000000..4d4edba --- /dev/null +++ b/api/user.go @@ -0,0 +1,133 @@ +package api + +import ( + "fmt" + "regexp" + + "github.com/gin-gonic/gin" + + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" +) + +const ( + VALID_EMAIL_REGEX = `(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$` +) + +func IsValidEmailAddress(email string) bool { + r := regexp.MustCompile(VALID_EMAIL_REGEX) + + return r.MatchString(email) +} + +type SignParams struct { + Email string + Password string +} + +type SignResult struct { + Token string `json:"token"` +} + +func (s SignParams) Validate() *Error { + if !IsValidEmailAddress(s.Email) { + return &Error{InvalidEmail, "invalid email", fmt.Errorf("'%v' is not a valid email", s.Email)} + } + + if s.Password == "" { + return &Error{InvalidPassword, "invalid password", fmt.Errorf("invalid password")} + } + + return nil +} + +type SignupQuery struct { + In SignParams +} + +func (q SignupQuery) ValidateParams() *Error { + return q.In.Validate() +} + +func (q SignupQuery) Run() (interface{}, *Error) { + user, err := db.GetUserByEmail(q.In.Email) + if err != nil { + return nil, NewInternalError(err) + } + + if user != nil { + return nil, &Error{EmailExists, "email already taken", fmt.Errorf("'%v' is already registered '%v'", q.In.Email, user)} + } + + newUser := db.User{Email: q.In.Email, Status: db.AwaitingConfirmation} + newUser.PasswordHash, err = db.HashPassword(q.In.Password) + if err != nil { + return nil, NewInternalError(err) + } + + err = db.InsertUser(&newUser) + if err != nil { + return nil, NewInternalError(err) + } + + token, err := CreateJwtToken(newUser.Id) + if err != nil { + return nil, NewInternalError(fmt.Errorf("cannot create jwt token %v", err)) + } + + return SignResult{token}, nil +} + +type SigninQuery struct { + In SignParams +} + +func (q SigninQuery) ValidateParams() *Error { + return q.In.Validate() +} + +func (q SigninQuery) Run() (interface{}, *Error) { + user, err := db.GetUserByEmail(q.In.Email) + if err != nil { + return nil, NewInternalError(err) + } + + if user == nil { + return nil, &Error{InvalidCredentials, "invalid credentials", fmt.Errorf("no email '%v' found", q.In.Email)} + } + + err = db.ValidatePassword(q.In.Password, user.PasswordHash) + if err != nil { + return nil, &Error{InvalidCredentials, "invalid credentials", err} + } + + if user.Status != db.Confirmed { + return nil, &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} + } + + token, err := CreateJwtToken(user.Id) + if err != nil { + return nil, NewInternalError(err) + } + + return SignResult{token}, nil +} + +func UserConfirmed(c *gin.Context) *Error { + user, exists := c.Get("user") + + if !exists { + return &Error{NotAuthorized, "not authorized", fmt.Errorf("no user key in context")} + } + + if user.(db.User).Status != db.Confirmed { + return &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} + } + + return nil +} + +func GetUser(c *gin.Context) db.User { + user, _ := c.Get("user") + + return user.(db.User) +} diff --git a/cmd/ansible/.gitignore b/cmd/ansible/.gitignore new file mode 100644 index 0000000..eeb2d6a --- /dev/null +++ b/cmd/ansible/.gitignore @@ -0,0 +1,3 @@ +*.retry* +roles/nginx +roles/certbot diff --git a/cmd/ansible/ansible.cfg b/cmd/ansible/ansible.cfg new file mode 100644 index 0000000..d48a88f --- /dev/null +++ b/cmd/ansible/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +inventory = hosts +roles_path = roles/ diff --git a/cmd/ansible/conf.toml.j2 b/cmd/ansible/conf.toml.j2 new file mode 100644 index 0000000..5f08a26 --- /dev/null +++ b/cmd/ansible/conf.toml.j2 @@ -0,0 +1,17 @@ +log_level="info" +mode="production" +log_out="/var/cryptoportfolio-app/app.log" +port="8080" + +[db] +user="{{ postgres_user }}" +password="{{ postgres_password }}" +database="{{ postgres_database }}" +address="localhost:5432" + +[api] +domain="{{ app_domain }}" +jwt_secret="{{ jwt_secret }}" + +[app] +public_dir="/var/cryptoportfolio-app/static" diff --git a/cmd/ansible/cryptoportfolio-app.j2 b/cmd/ansible/cryptoportfolio-app.j2 new file mode 100644 index 0000000..40979d6 --- /dev/null +++ b/cmd/ansible/cryptoportfolio-app.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=Cryptoportfolio app + +[Service] +Type=simple + +User={{ app_user }} +Group={{ app_user }} +UMask=007 + +ExecStart=/usr/bin/cryptoportfolio-app -conf /var/cryptoportfolio-app/conf.toml + +Restart=on-failure diff --git a/cmd/ansible/deploy.yml b/cmd/ansible/deploy.yml new file mode 100644 index 0000000..b56c581 --- /dev/null +++ b/cmd/ansible/deploy.yml @@ -0,0 +1,105 @@ +--- +- hosts: jloup-home + + tasks: + - include_vars: vars.yml + + - name: install myservice systemd unit file + template: src=cryptoportfolio-app.j2 dest=/etc/systemd/system/cryptoportfolio-app.service + become: yes + + - name: stop cryptoportfolio-app + systemd: state=stopped name=cryptoportfolio-app + become: yes + + - name: Creates cryptoportfolio-app directory + file: path=/var/cryptoportfolio-app state=directory owner={{ app_user }} + become: yes + + - name: Set log file. + file: path=/var/cryptoportfolio-app/app.log owner={{ app_user }} state=touch + become: yes + + - name: Copy server app binary from github 'https://github.com/jloup/dist/releases/download/crypto-v{{ version }}/cryptoportfolio-linux-{{ linux_arch }}'. + get_url: + url: "https://github.com/jloup/dist/releases/download/crypto-v{{ version }}/cryptoportfolio-linux-{{ linux_arch }}" + dest: /usr/bin/cryptoportfolio-app + owner: "{{ app_user }}" + mode: "u=rwx,g=r,o=r" + become: yes + + - name: Copy server app configuration file. + template: + src: conf.toml.j2 + dest: /var/cryptoportfolio-app/conf.toml + owner: "{{ app_user }}" + become: yes + + - name: Create webapp directory. + file: path=/var/cryptoportfolio-app/static state=directory owner={{ app_user }} + become: yes + + - name: Copy webapp files from github 'https://github.com/jloup/dist/releases/download/crypto-v{{ version }}/webapp.tar.gz'. + unarchive: + src: "https://github.com/jloup/dist/releases/download/crypto-v{{ version }}/webapp.tar.gz" + dest: /var/cryptoportfolio-app/static + remote_src: yes + owner: "{{ app_user }}" + mode: "u=rwx,g=r,o=r" + become: yes + + - import_role: + name: nginx + become: yes + vars: + nginx_vhosts: + - listen: "443 ssl" + server_name: "{{ app_domain }}" + filename: "{{ app_domain }}.443.conf" + extra_parameters: | + ssl_certificate /etc/letsencrypt/live/{{ app_domain }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ app_domain }}/privkey.pem; + location / { + proxy_pass "http://127.0.0.1:8080"; + } + + - listen: "80" + server_name: "{{ app_domain }}" + filename: "{{ app_domain}}.80.conf" + return: "301 https://{{ app_domain }}$request_uri" + + - import_role: + name: certbot + become: yes + vars: + certbot_admin_email: jeanloup.jamet@gmail.com + certbot_create_if_missing: yes + certbot_create_standalone_stop_services: [] + certbot_create_method: standalone + certbot_certs: + - domains: + - "{{ app_domain }}" + + - name: Create postgres user. + user: name=postgres + + - name: Add cryptoportfolio database. + postgresql_db: name={{ postgres_database }} + become: yes + become_user: postgres + vars: + ansible_ssh_pipelining: true + + - name: Add cryptoportfolio user. + postgresql_user: user={{ postgres_user }} db={{ postgres_database }} password={{ postgres_password }} + become: yes + become_user: postgres + vars: + ansible_ssh_pipelining: true + + - file: path=/www/{{ app_user }} state=directory owner={{ app_user }} + become: yes + + - name: start cryptoportfolio-app + systemd: state=started name=cryptoportfolio-app daemon_reload=yes + become: yes diff --git a/cmd/ansible/hosts b/cmd/ansible/hosts new file mode 100644 index 0000000..64969e8 --- /dev/null +++ b/cmd/ansible/hosts @@ -0,0 +1,15 @@ +[jloup-home] +jlj.am + +[jloup-home:vars] + ansible_port=21 + ansible_user=ansible-deploy + + app_user=jloup + app_domain=jlj.am + + postgres_database=cryptoportfolio + postgres_user=cryptoportfolio + postgres_password=cryptoportfolio-dev + + linux_arch=386 \ No newline at end of file diff --git a/cmd/ansible/release.yml b/cmd/ansible/release.yml new file mode 100644 index 0000000..4cd005c --- /dev/null +++ b/cmd/ansible/release.yml @@ -0,0 +1,59 @@ +--- +- name: Release to github repo + hosts: 127.0.0.1 + connection: local + tasks: + - include_vars: vars.yml + + # Create release. + - github_release: + token: "{{ github_release_token }}" + user: jloup + repo: dist + action: create_release + tag: "crypto-v{{ version }}" + target: master + name: Crypto Release + body: "NOTE: this repo does not include any source code." + + # Build server app. + - make: + chdir: ../app + target: release + - shell: + github-release upload \ + -s "{{ github_release_token }}" \ + -u jloup \ + -r dist \ + -t crypto-v{{ version }} \ + -n "cryptoportfolio-linux-amd64" \ + -l "cryptoportfolio binary (linux amd64)" \ + -R \ + -f ../app/dist/linux_amd64/cryptoportfolio-app + - shell: + github-release upload \ + -s "{{ github_release_token }}" \ + -u jloup \ + -r dist \ + -t crypto-v{{ version }} \ + -n "cryptoportfolio-linux-386" \ + -l "cryptoportfolio binary (linux 386)" \ + -R \ + -f ../app/dist/linux_386/cryptoportfolio-app + + # Build webapp. + - make: + chdir: ../web + target: release + params: + ENV: prod + - shell: + github-release upload \ + -s "{{ github_release_token }}" \ + -u jloup \ + -r dist \ + -t crypto-v{{ version }} \ + -n "webapp.tar.gz" \ + -R \ + -f ../web/build/webapp.tar.gz + diff --git a/cmd/ansible/requirements.yml b/cmd/ansible/requirements.yml new file mode 100644 index 0000000..bacd7a8 --- /dev/null +++ b/cmd/ansible/requirements.yml @@ -0,0 +1,7 @@ +- src: geerlingguy.nginx + name: nginx + version: 2.5.0 + +- src: geerlingguy.certbot + name: certbot + version: 3.0.0 diff --git a/cmd/ansible/vars.yml b/cmd/ansible/vars.yml new file mode 100644 index 0000000..1de7413 --- /dev/null +++ b/cmd/ansible/vars.yml @@ -0,0 +1,22 @@ +$ANSIBLE_VAULT;1.1;AES256 +63613535333830393037646665363566636635366534636261623839326130663431653839346266 +3832643338623561313362663837323234663537663439350a313034326663383235663964626132 +38343964396265323539396439383731336464393337383833653666643736303539626136383431 +6536316338376538360a343862626636363031353037626462333364623433613861393137353336 +37396664663030363530333364633266653862393538313835326138663465626638326363656561 +30393836386664633834663838666432383836623432363936343635313835303166393531643966 +33313361383565363232373066306534613465386534386266306564383365373762613361366365 +61366530623863623336643531346463323233323539333139336335383439373132373233663031 +39666535633362383135376534376532333663636136366130653762643164333436313261646137 +37353139633361636163326366616234613466393731373631616138386263383131663537633533 +31393763316561623134623063623735356334363833623939313437386330323837626131356332 +30383863373535366137366138633832623566613061313138396539306536633763633934313562 +35383763653532336539346632623935303634353866636264373262363839326439313837313765 +36303539613734646238636432393166616438666665363363323331373437633362613838653564 +64393639346661646333383466363162633638643838386666383564366665656266333836363435 +35643231323362323566303535303561626139333830393538383635326631656666323166343863 +31393566346531653535393738326166303261376238316532373833616432306638326139353234 +32653132323764316231393634663262313765393230656232343833373438636430643663353965 +36333931303731646333316430646534383531313264353936396565336338663530303434643036 +34356663373533663137636235386164646334356262336464363862643332636661313339303531 +35663833656564393331636139663738323834373862623436633666306661373166 diff --git a/cmd/app/Makefile b/cmd/app/Makefile new file mode 100644 index 0000000..628910f --- /dev/null +++ b/cmd/app/Makefile @@ -0,0 +1,30 @@ +# Go parameters +GOCMD=go +GOBUILD=$(GOCMD) build +GOCLEAN=$(GOCMD) clean +GOTEST=$(GOCMD) test +BINARY_NAME=cryptoportfolio-app +LINUX_ARCHES=amd64 386 +DIST_DIR ?= dist + +build: + $(GOBUILD) -o $(BINARY_NAME) -v + +test: + $(GOTEST) -v ./... + +clean: + $(GOCLEAN) + rm -f $(BINARY_NAME) + rm -rf dist + +run: build + ./$(BINARY_NAME) + +$(addprefix $(DIST_DIR)/linux_, $(LINUX_ARCHES)): + mkdir -p $(@) + CGO_ENABLED=0 GOOS=linux GOARCH=$(subst linux_,,$(notdir $@)) $(GOBUILD) -o $@/$(BINARY_NAME) -v + +release: $(addprefix $(DIST_DIR)/linux_, $(LINUX_ARCHES)) + +.PHONY: clean release diff --git a/cmd/app/conf.toml b/cmd/app/conf.toml new file mode 100644 index 0000000..47964b4 --- /dev/null +++ b/cmd/app/conf.toml @@ -0,0 +1,16 @@ +log_level="info" +mode="dev" +log_out="stdout" + +[db] +user="cryptoportfolio" +password="cryptoportfolio-dev" +database="cryptoportfolio" +address="localhost:5432" + +[api] +domain="localhost" +jwt_secret="secret" + +[app] +public_dir="../web/build/static" diff --git a/cmd/app/main.go b/cmd/app/main.go new file mode 100644 index 0000000..e769401 --- /dev/null +++ b/cmd/app/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "fmt" + "path" + "strings" + "time" + + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/api" + "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" + + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "github.com/jloup/utils" +) + +var log = utils.StandardL().WithField("module", "api") + +type AppConfig struct { + PublicDir string `toml:"public_dir"` +} + +type ApiConfig struct { + Domain string `toml:"domain"` + JwtSecret string `toml:"jwt_secret"` +} + +type Config struct { + App AppConfig + Api ApiConfig + Db db.DBConfig + + utils.LogConfiguration + Address string + Port string + Mode string +} + +func (c *Config) SetToDefaults() { + *c = Config{ + Address: "localhost", + Port: "8000", + Mode: "dev", + App: AppConfig{ + PublicDir: "./public", + }, + Api: ApiConfig{ + JwtSecret: "secret", + }, + } + + c.LogConfiguration.SetToDefaults() +} + +var C Config + +func init() { + utils.MustParseStdConfigFile(&C) + + err := utils.ConfigureStdLogger(C.LogConfiguration) + if err != nil { + panic(err) + } + + api.SetJwtSecretKey(C.Api.JwtSecret) + + db.Init(C.Db) + + if C.Mode == "production" { + gin.SetMode(gin.ReleaseMode) + } + + log.Infof("CONFIG:") + log.Infof("LISTEN: %s", strings.Join([]string{C.Address, C.Port}, ":")) + log.Infof("PUBLIC_DIR: %s", C.App.PublicDir) +} + +func SetApiRoute(router *gin.RouterGroup, route api.Route) { + switch route.Method { + case "GET": + router.GET(route.Path, route.Handlers...) + case "POST": + router.POST(route.Path, route.Handlers...) + case "OPTIONS": + router.OPTIONS(route.Path, route.Handlers...) + default: + panic(fmt.Errorf("%s method not handled", route.Method)) + } +} + +func SetGroup(router *gin.RouterGroup, group api.Group) { + var r *gin.RouterGroup + if group.Root == "" { + r = router + } else { + r = router.Group(group.Root) + } + + if group.Middlewares != nil { + for _, middleware := range group.Middlewares { + r.Use(api.M(middleware)) + } + } + + for _, route := range group.Routes { + SetApiRoute(r, route) + } +} + +func main() { + engine := gin.New() + + apiGroup := engine.Group("/api") + appGroup := engine + + engine.Use(gin.Recovery()) + + if C.Mode == "production" { + engine.Use(api.Logger()) + apiGroup.Use(api.Logger()) + } else { + engine.Use(gin.Logger()) + apiGroup.Use(gin.Logger()) + } + + apiGroup.Use(cors.New(cors.Config{ + AllowOrigins: []string{fmt.Sprintf("https://%s", C.Api.Domain)}, + AllowMethods: []string{"POST", "GET", "OPTIONS"}, + AllowHeaders: []string{"Authorization"}, + ExposeHeaders: []string{"Authorization"}, + AllowCredentials: true, + MaxAge: 12 * time.Hour, + })) + + for _, group := range api.Groups { + SetGroup(apiGroup, group) + } + + appGroup.Static("/public", C.App.PublicDir) + availableRoutes := []string{ + "/", + "/signup", + "/signin", + "/signout", + "/me", + "/otp/enroll", + "/otp/validate", + } + + for _, route := range availableRoutes { + appGroup.StaticFile(route, path.Join(C.App.PublicDir, "/index.html")) + } + + engine.Run(strings.Join([]string{C.Address, C.Port}, ":")) +} diff --git a/cmd/web/.babelrc b/cmd/web/.babelrc new file mode 100644 index 0000000..4ffef06 --- /dev/null +++ b/cmd/web/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env", "react"] +} diff --git a/cmd/web/.gitignore b/cmd/web/.gitignore new file mode 100644 index 0000000..7a7ecee --- /dev/null +++ b/cmd/web/.gitignore @@ -0,0 +1,4 @@ +bower_components/ +node_modules/ +build/ +npm-debug.log diff --git a/cmd/web/.jscsrc b/cmd/web/.jscsrc new file mode 100644 index 0000000..4ee5db6 --- /dev/null +++ b/cmd/web/.jscsrc @@ -0,0 +1,5 @@ +{ + "preset": "google", + "maximumLineLength": null, + "requireUseStrict": false +} diff --git a/cmd/web/.jshintrc b/cmd/web/.jshintrc new file mode 100644 index 0000000..8e41200 --- /dev/null +++ b/cmd/web/.jshintrc @@ -0,0 +1,16 @@ +{ + "eqeqeq": true, + "undef": true, + "unused": "vars", + "globals": { + "React": true, + "ReactDOM": true, + "Modernizr": true, + "$": true, + "ga": true + }, + "browser": true, + "strict": "true", + "browserify": true, + "devel": true +} diff --git a/cmd/web/Makefile b/cmd/web/Makefile new file mode 100644 index 0000000..1d98085 --- /dev/null +++ b/cmd/web/Makefile @@ -0,0 +1,52 @@ +SHELL=/bin/bash +ENV ?= dev +export PATH := $(PATH):./node_modules/.bin + +SRC_DIR=js +BUILD_DIR=build/js +JSX_SRC= main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx +JS_SRC= cookies.js app.js api.js +JSX_OBJS=$(addprefix $(BUILD_DIR)/,$(JSX_SRC:.jsx=.js)) +JS_OBJS=$(addprefix $(BUILD_DIR)/,$(JS_SRC)) +STATIC_BUILD_DIR=build/static + +install: + node --version + npm --version + yarn --version + yarn install + +static: js $(STATIC_BUILD_DIR)/index.html $(STATIC_BUILD_DIR)/style.css + +js: build/static/main.js + +$(STATIC_BUILD_DIR)/index.html: static/index.html + cp static/index.html $@ + +$(STATIC_BUILD_DIR)/style.css: static/style.css + cp static/style.css $@ + +$(BUILD_DIR)/%.js: $(SRC_DIR)/%.jsx + mkdir -p $(@D) + jscs --fix $< + babel $< -o $@ + jshint $@ + +$(BUILD_DIR)/%.js: $(SRC_DIR)/%.js + jscs --fix $< + cp $< $@ + jshint $@ + +build/static/main.js: $(JSX_OBJS) $(JS_OBJS) env/$(ENV).env + browserify -t [ localenvify --envfile env/$(ENV).env ] \ + -t [ debowerify ] \ + $(BUILD_DIR)/main.js -o $@ + +build/webapp.tar.gz: $(STATIC_BUILD_DIR)/main.js $(STATIC_BUILD_DIR)/index.html $(STATIC_BUILD_DIR)/style.css + tar czf $@ --directory=$(dir $<) $(notdir $^) + +release: build/webapp.tar.gz + +clean: + rm -rf build + rm -rf node_modules \ No newline at end of file diff --git a/cmd/web/env/dev.env b/cmd/web/env/dev.env new file mode 100644 index 0000000..6b87b74 --- /dev/null +++ b/cmd/web/env/dev.env @@ -0,0 +1,4 @@ +API_HOST=localhost +API_PORT=8000 +API_HTTPS=false + diff --git a/cmd/web/env/prod.env b/cmd/web/env/prod.env new file mode 100644 index 0000000..9b056c1 --- /dev/null +++ b/cmd/web/env/prod.env @@ -0,0 +1,4 @@ +API_HOST=jlj.am +API_PORT="" +API_HTTPS=true + diff --git a/cmd/web/js/api.js b/cmd/web/js/api.js new file mode 100644 index 0000000..e2acd1d --- /dev/null +++ b/cmd/web/js/api.js @@ -0,0 +1,176 @@ +'use strict'; + +var App = require('./app.js'); + +var Api = {}; + +Api.API_HOST = process.env.API_HOST; +Api.API_PORT = process.env.API_PORT; + +if (process.env.API_HTTPS === 'true') { + Api.API_ROOT = 'https://'; +} else { + Api.API_ROOT = 'http://'; +} + +Api.API_ROOT += Api.API_HOST; +if (Api.API_PORT !== '80') { + Api.API_ROOT += ':' + Api.API_PORT; +} + +Api.API_ROOT += '/api'; + +var ApiEndpoints = { + 'SIGNUP': { + 'type': 'POST', + 'auth': false, + 'parameters': [ + {'name': 'email', 'mandatory': true, 'inquery': true}, + {'name': 'password', 'mandatory': true, 'inquery': true} + ], + 'buildUrl': function(params) { + return '/signup'; + } + }, + 'SIGNIN': { + 'type': 'POST', + 'auth': false, + 'parameters': [ + {'name': 'email', 'mandatory': true, 'inquery': true}, + {'name': 'password', 'mandatory': true, 'inquery': true} + ], + 'buildUrl': function(params) { + return '/signin'; + } + }, + 'MARKET': { + 'type': 'GET', + 'auth': true, + 'parameters': [ + {'name': 'name', 'mandatory': true, 'inquery': false}, + ], + 'buildUrl': function(params) { + return '/market/' + params.name; + } + }, + 'UPDATE_MARKET': { + 'type': 'POST', + 'auth': true, + 'parameters': [ + {'name': 'name', 'mandatory': true, 'inquery': false}, + {'name': 'key', 'mandatory': true, 'inquery': true}, + {'name': 'secret', 'mandatory': true, 'inquery': true}, + ], + 'buildUrl': function(params) { + return '/market/' + params.name + '/update'; + } + }, + 'OTP_ENROLL': { + 'type': 'GET', + 'auth': true, + 'parameters': [], + 'buildUrl': function(params) { + return '/otp/enroll'; + } + }, + 'OTP_VALIDATE': { + 'type': 'POST', + 'auth': true, + 'parameters': [ + {'name': 'pass', 'mandatory': true, 'inquery': true}, + ], + 'buildUrl': function(params) { + return '/otp/validate'; + } + }, +}; + +Api.BuildRequest = function(endpointId, params) { + var endpoint = ApiEndpoints[endpointId]; + var query = {}; + var url = ''; + var headers = {}; + var jwt = App.getUserToken(); + + if (endpoint === undefined) { + return {'err': 'cannot find endpoint ' + endpointId}; + } + + if (endpoint.auth === true && (jwt === undefined || jwt === null)) { + return {'err': 'this endpoint needs auth'}; + } + + if (jwt !== undefined && jwt !== null) { + headers.Authorization = 'Bearer ' + jwt; + } + + for (var i = 0; i < endpoint.parameters.length; i++) { + var parameter = endpoint.parameters[i]; + if (parameter.mandatory === true && params[parameter.name] === undefined) { + return {'err': 'parameter \'' + parameter.name + '\' is mandatory'}; + } + + if (parameter.inquery === true) { + query[parameter.name] = params[parameter.name]; + } + } + + url = endpoint.buildUrl(params); + + return {'err': null, 'url': Api.API_ROOT + url, 'headers': headers, 'params': query, 'type': endpoint.type}; +}; + +Api.Call = function(endpointId, params, fn) { + var request = Api.BuildRequest(endpointId, params); + + if (request.err !== null) { + console.error('Api BuildRequest error', request.err); + fn({'err': request.err}, -1, {}); + return null; + } + + return Api.DoRequest(request.type, request.url, request.params, request.headers, fn); +}; + +Api.DoRequest = function(type, url, params, headers, callback) { + return $.ajax({ + data: params, + headers: headers, + timeout: 30000, + dataType: 'json', + error: function(xhr, status, err) { + if (status === 'abort') { + return; + } + + var apiStatus = null; + var apiResponse = null; + var apiCode = null; + if (xhr.responseJSON) { + apiStatus = xhr.responseJSON.status; + apiResponse = xhr.responseJSON.response; + apiCode = xhr.responseJSON.code; + } + + if (xhr.status === 401 || xhr.status === 403) { + if (App.onUserNotAuthorized(xhr.status, apiCode) === false) { + return; + } + } + + callback({'url': url, 'err': err, 'status': status, 'code': apiCode, 'xhr': xhr}, apiStatus, apiResponse); + }, + success: function(data) { + var err = null; + if (data.status !== 'ok') { + err = {'url': url, 'status': status}; + } + callback(err, data.status, data.response); + }, + type: type, + url: url + }); +}; + +module.exports.Api = Api; + diff --git a/cmd/web/js/app.js b/cmd/web/js/app.js new file mode 100644 index 0000000..4946dcc --- /dev/null +++ b/cmd/web/js/app.js @@ -0,0 +1,121 @@ +'use strict'; + +var cookies = require('./cookies.js'); +var page = require('page'); + +var App = {}; +var cookieExpire = 60 * 30; + +App.errorCodeToMessage = function(code) { + switch (code) { + case 'invalid_email': + return 'The email is not valid'; + case 'invalid_password': + return 'The password is not valid'; + case 'email_exists': + return 'This email is already registered'; + case 'invalid_credentials': + return 'Invalid credentials'; + case 'invalid_otp': + return 'Invalid code !'; + case 'user_not_confirmed': + return 'Your account is being confirmed. Should be very soon !'; + } + + return code; +}; + +App.isUserSignedIn = function() { + return cookies.hasItem('jwt'); +}; + +App.getUserToken = function() { + return cookies.getItem('jwt'); +}; + +App.onUserSignIn = function(token) { + if (!token || token === '') { + page('/signin'); + return; + } + + cookies.setItem('jwt', token, cookieExpire); + page('/me'); +}; + +App.onUserValidateOtp = function(token) { + if (!token || token === '') { + page('/signin'); + return; + } + + cookies.setItem('jwt', token, cookieExpire); + page('/me'); +}; + +App.onUserSignUp = function(token) { + if (!token || token === '') { + page('/signin'); + return; + } + + cookies.setItem('jwt', token, cookieExpire); +}; + +App.getUserJWT = function() { + return cookies.getItem('jwt'); +}; + +App.page = function(path, needsAuth, fn) { + page(path, function(context) { + if (needsAuth && !App.isUserSignedIn()) { + page('/signin'); + return; + } + + fn(context); + }); +}; + +App.go = function(path) { + page(path); +}; + +App.start = function() { + page(); +}; + +App.onInternNavigation = function(href, e) { + e.preventDefault(); + page(href); +}; + +App.onUserNotAuthorized = function(httpCode, apiCode) { + switch (apiCode) { + case 'not_authorized': + cookies.removeItem('jwt'); + page('/signin'); + return false; + case 'otp_not_setup': + page('/otp/setup'); + return false; + case 'need_otp_validation': + page('/otp/validate'); + return false; + default: + return true; + } +}; + +App.mount = function(app) { + var root = React.createElement( + 'div', + {className: 'container'}, + app + ); + + ReactDOM.unmountComponentAtNode(document.getElementById('app')); + ReactDOM.render(root, document.getElementById('app')); +}; + +module.exports = App; diff --git a/cmd/web/js/cookies.js b/cmd/web/js/cookies.js new file mode 100644 index 0000000..9cc7ca9 --- /dev/null +++ b/cmd/web/js/cookies.js @@ -0,0 +1,65 @@ +'use strict'; + +/*\ +|*| +|*| :: cookies.js :: +|*| +|*| A complete cookies reader/writer framework with full unicode support. +|*| +|*| Revision #1 - September 4, 2014 +|*| +|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie +|*| https://developer.mozilla.org/User:fusionchess +|*| +|*| This framework is released under the GNU Public License, version 3 or later. +|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html +|*| +|*| Syntaxes: +|*| +|*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]]) +|*| * docCookies.getItem(name) +|*| * docCookies.removeItem(name[, path[, domain]]) +|*| * docCookies.hasItem(name) +|*| * docCookies.keys() +|*| +\*/ + +module.exports = { + getItem: function(sKey) { + if (!sKey) { return null; } + return decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; + }, + setItem: function(sKey, sValue, vEnd, sPath, sDomain, bSecure) { + if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; } + var sExpires = ''; + if (vEnd) { + switch (vEnd.constructor) { + case Number: + sExpires = vEnd === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + vEnd; + break; + case String: + sExpires = '; expires=' + vEnd; + break; + case Date: + sExpires = '; expires=' + vEnd.toUTCString(); + break; + } + } + document.cookie = encodeURIComponent(sKey) + '=' + encodeURIComponent(sValue) + sExpires + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : ''); + return true; + }, + removeItem: function(sKey, sPath, sDomain) { + if (!this.hasItem(sKey)) { return false; } + document.cookie = encodeURIComponent(sKey) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : ''); + return true; + }, + hasItem: function(sKey) { + if (!sKey) { return false; } + return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(document.cookie); + }, + keys: function() { + var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '').split(/\s*(?:\=[^;]*)?;\s*/); + for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); } + return aKeys; + } +}; diff --git a/cmd/web/js/main.jsx b/cmd/web/js/main.jsx new file mode 100644 index 0000000..eb53057 --- /dev/null +++ b/cmd/web/js/main.jsx @@ -0,0 +1,101 @@ +var SignupForm = require('./signup.js').SignupForm; +var SigninForm = require('./signin.js').SigninForm; +var OtpEnrollForm = require('./otp.js').OtpEnrollForm; +var PoloniexForm = require('./poloniex.js').PoloniexForm; +var App = require('./app.js'); +var Api = require('./api.js').Api; +var cookies = require('./cookies.js'); + +var Logo = React.createClass({ + render: function() { + return (); + } +}); + +App.page('/signup', false, function(context) { + if (App.isUserSignedIn()) { + App.go('/me'); + return; + } + + App.mount( +
+ + +
+ ); +}); + +App.page('/signin', false, function(context) { + if (App.isUserSignedIn()) { + App.go('/me'); + return; + } + + App.mount( +
+ + +
+ ); +}); + +App.page('/signout', true, function(context) { + cookies.removeItem('jwt'); + + App.go('/'); +}); + +App.page('/me', true, function(context) { + Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { + if (err) { + console.error(err, data); + return; + } + + App.mount( +
+ +

Poloniex

+ +
+ ); + + }.bind(this)); +}); + +App.page('/otp/setup', true, function(context) { + Api.Call('OTP_ENROLL', {}, function(err, status, data) { + if (err) { + console.error(err, data); + return; + } + + App.mount( +
+ + +
+ ); + + }.bind(this)); +}); + +App.page('/otp/validate', true, function(context) { + App.mount( +
+ + +
+ ); +}); + +App.page('/', false, function(context) { + App.go('/me'); +}); + +$(document).ready(function() { + App.start(); +}); diff --git a/cmd/web/js/otp.jsx b/cmd/web/js/otp.jsx new file mode 100644 index 0000000..2717d9f --- /dev/null +++ b/cmd/web/js/otp.jsx @@ -0,0 +1,70 @@ +var Api = require('./api.js').Api; +var App = require('./app.js'); +var classNames = require('classnames'); + +var OtpQrCode = React.createClass({ + render: function() { + return ( +
+ +

{this.props.secret}

+
+ ); + } +}); + +module.exports.OtpEnrollForm = React.createClass({ + getInitialState: function() { + return {'hideMsg': true, 'msg': '', 'msgOk': false, 'pass': ''}; + }, + handleSubmit: function(e) { + Api.Call('OTP_VALIDATE', {'pass': this.state.pass}, function(err, status, data) { + if (err) { + console.error(err, data); + this.displayMessage(App.errorCodeToMessage(err.code), false); + return; + } + + this.displayMessage('OK', true); + this.props.onSuccess(data.token); + + }.bind(this)); + + e.preventDefault(); + }, + handlePassChange: function(event) { + this.setState({'pass': event.target.value}); + }, + hideMessage: function() { + this.setState({'hideMsg': true}); + }, + displayMessage: function(msg, ok) { + this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); + }, + render: function() { + var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); + var qrCode = null; + + if (this.props.img) { + qrCode = ( +
+ +
+ ); + } + return ( +
+
+ {qrCode} +
+
+ + +
{this.state.msg}
+
+
+
+
+ ); + } +}); diff --git a/cmd/web/js/poloniex.jsx b/cmd/web/js/poloniex.jsx new file mode 100644 index 0000000..877198d --- /dev/null +++ b/cmd/web/js/poloniex.jsx @@ -0,0 +1,49 @@ +var Api = require('./api.js').Api; +var App = require('./app.js'); +var classNames = require('classnames'); + +module.exports.PoloniexForm = React.createClass({ + getInitialState: function() { + return {'hideMsg': true, 'msg': '', 'msgOk': false, 'apiSecret': this.props.apiSecret, 'apiKey': this.props.apiKey}; + }, + handleSubmit: function(e) { + Api.Call('UPDATE_MARKET', {'key': this.state.apiKey, 'secret': this.state.apiSecret, 'name': 'poloniex'}, function(err, status, data) { + if (err) { + console.error(err, data); + this.displayMessage(App.errorCodeToMessage(err.code), false); + return; + } + + this.displayMessage('OK', true); + + }.bind(this)); + e.preventDefault(); + }, + handleApiKeyChange: function(event) { + this.setState({'apiKey': event.target.value}); + }, + handleApiSecretChange: function(event) { + this.setState({'apiSecret': event.target.value}); + }, + hideMessage: function() { + this.setState({'hideMsg': true}); + }, + displayMessage: function(msg, ok) { + this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); + }, + render: function() { + var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); + return ( +
+
+
+ + + +
{this.state.msg}
+
+
+
+ ); + } +}); diff --git a/cmd/web/js/signin.jsx b/cmd/web/js/signin.jsx new file mode 100644 index 0000000..443a461 --- /dev/null +++ b/cmd/web/js/signin.jsx @@ -0,0 +1,52 @@ +var Api = require('./api.js').Api; +var App = require('./app.js'); +var classNames = require('classnames'); + +module.exports.SigninForm = React.createClass({ + getInitialState: function() { + return {'hideMsg': true, 'msg': '', 'msgOk': false, 'password': '', 'email': ''}; + }, + handleSubmit: function(e) { + Api.Call('SIGNIN', {'password': this.state.password, 'email': this.state.email}, function(err, status, data) { + if (err) { + console.error(err, data); + this.displayMessage(App.errorCodeToMessage(err.code), false); + return; + } + + this.displayMessage('OK', true); + this.props.onSuccess(data.token); + + }.bind(this)); + e.preventDefault(); + }, + handlePasswordChange: function(event) { + this.setState({'password': event.target.value}); + }, + handleEmailChange: function(event) { + this.setState({'email': event.target.value}); + }, + hideMessage: function() { + this.setState({'hideMsg': true}); + }, + displayMessage: function(msg, ok) { + this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); + }, + render: function() { + var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); + return ( +
+
+
+ + + +
{this.state.msg}
+
+ Sign up +
+
+ ); + } +}); + diff --git a/cmd/web/js/signup.jsx b/cmd/web/js/signup.jsx new file mode 100644 index 0000000..149125a --- /dev/null +++ b/cmd/web/js/signup.jsx @@ -0,0 +1,56 @@ +var Api = require('./api.js').Api; +var App = require('./app.js'); +var classNames = require('classnames'); + +module.exports.SignupForm = React.createClass({ + getInitialState: function() { + return {'hideMsg': true, 'msg': '', 'msgOk': false, 'password': '', 'email': ''}; + }, + handleSubmit: function(e) { + Api.Call('SIGNUP', + { + 'password': this.state.password, + 'email': this.state.email + }, + function(err, status, data) { + if (err) { + console.error(err, data); + this.displayMessage(App.errorCodeToMessage(err.code), false); + return; + } + + this.displayMessage('Thank You. Your account is being confirmed. Check your mailbox soon', true); + this.props.onSuccess(data.token); + + }.bind(this)); + e.preventDefault(); + }, + handlePasswordChange: function(event) { + this.setState({'password': event.target.value}); + }, + handleEmailChange: function(event) { + this.setState({'email': event.target.value}); + }, + hideMessage: function() { + this.setState({'hideMsg': true}); + }, + displayMessage: function(msg, ok) { + this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); + }, + render: function() { + var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); + return ( +
+
+
+ + + +
{this.state.msg}
+ Sign In +
+
+
+ ); + } +}); diff --git a/cmd/web/package.json b/cmd/web/package.json new file mode 100644 index 0000000..84aac37 --- /dev/null +++ b/cmd/web/package.json @@ -0,0 +1,26 @@ +{ + "name": "cryptoportfolio", + "version": "0.1", + "description": "cryptoportfolio js", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "jloup", + "license": "ISC", + "dependencies": { + "classnames": "^2.2.5", + "debowerify": "^1.3.1", + "localenvify": "^1.0.1", + "page": "^1.8.3", + "path-to-regexp": "^1.2.1" + }, + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.6.1", + "babel-preset-react": "^6.24.1", + "browserify": "^15.2.0", + "jscs": "^3.0.3", + "jshint": "^2.9.2" + } +} diff --git a/cmd/web/static/index.html b/cmd/web/static/index.html new file mode 100644 index 0000000..9a70074 --- /dev/null +++ b/cmd/web/static/index.html @@ -0,0 +1,31 @@ + + + + + + + + + + + Cryptoportfolio + + + + + + + + + +
+ + + + + + + diff --git a/cmd/web/static/style.css b/cmd/web/static/style.css new file mode 100644 index 0000000..12af379 --- /dev/null +++ b/cmd/web/static/style.css @@ -0,0 +1,100 @@ +@charset "UTF-8"; + +body { + font-family: 'Fira Mono', 'Helvetica Neue', Arial, Helvetica, sans-serif; + background-color: rgb(246, 248, 251); + text-align: center; +} + +ul { + list-style-type: none; +} + +a { + text-decoration: none; + color: inherit; +} + +a:hover { + text-decoration: none; + color: inherit; +} + +a:focus { + text-decoration: none; + color: inherit; +} + +#logo { + text-align: center; + display: inline-block; + color: white; + font-size: 28px; + background-color: rgb(20, 20, 20); + border-radius: 4px; + font-weight: bold; + padding: 10px 10px 10px 10px; + vertical-align: middle; + margin-bottom: 30px; + margin-top: 20px; +} + +.sign-in .form-control { + margin-bottom: 20px; + border-radius: 2px; + border: none; + background-color: white; +} + +.sign-in .submit { + background-color: rgb(20, 20, 20); + color: white; +} + +.api-credentials-form .form-control { + margin-bottom: 20px; + border-radius: 2px; + border: none; + background-color: white; +} + +.api-credentials-form .submit { + background-color: rgb(20, 20, 20); + color: white; +} + +.otp-enroll .form-control { + margin-bottom: 20px; + border-radius: 2px; + border: none; + background-color: white; +} + +.otp-enroll .submit { + background-color: rgb(20, 20, 20); + color: white; +} +.form-message { + background-color: rgba(255, 6, 6, .33); + border-radius: 2px; + line-height: 50px; +} + +.form-message.message-ok { + background-color: rgba(33, 255, 72, .33); +} + +#main { + padding-top: 100px; +} + +.box { + position: relative; + background-color: rgb(250, 250, 250); + box-shadow: 0 2px 6px 2px rgba(0,0,0,.05); + border-radius: 4px; +} + +.box:hover { + box-shadow: 0 4px 15px 2px rgba(0,0,0,.20); +} diff --git a/cmd/web/yarn.lock b/cmd/web/yarn.lock new file mode 100644 index 0000000..e8d57da --- /dev/null +++ b/cmd/web/yarn.lock @@ -0,0 +1,3978 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@browserify/acorn5-object-spread@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@browserify/acorn5-object-spread/-/acorn5-object-spread-5.0.1.tgz#92e9b37f97beac9ec429a3cc479ded380297540c" + dependencies: + acorn "^5.2.1" + +JSONStream@^1.0.3: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +"JSV@>= 4.0.x": + version "4.0.2" + resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57" + +abbrev@1, abbrev@~1.0.4: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + +acorn@^4.0.3: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + +acorn@^5.2.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-regex@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.1.0.tgz#55ca60db6900857c423ae9297980026f941ed903" + +ansi-regex@^0.2.0, ansi-regex@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" + +ansi-regex@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-1.1.1.tgz#41c847194646375e6a1a5d10c3ca054ef9fc980d" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +archy@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/archy/-/archy-0.0.2.tgz#910f43bf66141fc335564597abc189df44b3d35e" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.2: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +asn1.js@^4.0.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a" + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +ast-types@0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" + +astw@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917" + dependencies: + acorn "^4.0.3" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async@0.2.x, async@~0.2.6, async@~0.2.8, async@~0.2.9: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +async@^0.9.0, async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-cli@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" + dependencies: + babel-core "^6.26.0" + babel-polyfill "^6.26.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + commander "^2.11.0" + convert-source-map "^1.5.0" + fs-readdir-recursive "^1.0.0" + glob "^7.1.2" + lodash "^4.17.4" + output-file-sync "^1.1.2" + path-is-absolute "^1.0.1" + slash "^1.0.0" + source-map "^0.5.6" + v8flags "^2.1.1" + optionalDependencies: + chokidar "^1.6.1" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-display-name@^6.23.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + +babel-preset-env@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^2.1.2" + invariant "^2.2.2" + semver "^5.3.0" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.9.2: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0, babylon@^6.8.1: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base62@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base62/-/base62-1.2.1.tgz#95a5a22350b0a557f3f081247fc2c398803ecb0c" + +base64-js@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +binary@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" + dependencies: + buffers "~0.1.1" + chainsaw "~0.1.0" + +bl@^0.9.0, bl@~0.9.0: + version "0.9.5" + resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" + dependencies: + readable-stream "~1.0.26" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + +boom@0.4.x: + version "0.4.2" + resolved "https://registry.yarnpkg.com/boom/-/boom-0.4.2.tgz#7a636e9ded4efcefb19cef4947a3c67dfaee911b" + dependencies: + hoek "0.9.x" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +bower-config@~0.5.0, bower-config@~0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/bower-config/-/bower-config-0.5.3.tgz#98fc5b41a87870ef9cbb9297635cf81f5505fdb1" + dependencies: + graceful-fs "~2.0.0" + mout "~0.9.0" + optimist "~0.6.0" + osenv "0.0.3" + +bower-endpoint-parser@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/bower-endpoint-parser/-/bower-endpoint-parser-0.2.2.tgz#00b565adbfab6f2d35addde977e97962acbcb3f6" + +bower-json@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/bower-json/-/bower-json-0.4.0.tgz#a99c3ccf416ef0590ed0ded252c760f1c6d93766" + dependencies: + deep-extend "~0.2.5" + graceful-fs "~2.0.0" + intersect "~0.0.3" + +bower-logger@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/bower-logger/-/bower-logger-0.2.2.tgz#39be07e979b2fc8e03a94634205ed9422373d381" + +bower-registry-client@~0.2.0: + version "0.2.4" + resolved "https://registry.yarnpkg.com/bower-registry-client/-/bower-registry-client-0.2.4.tgz#269fc7e898b627fb939d1144a593254d7fbbeebc" + dependencies: + async "~0.2.8" + bower-config "~0.5.0" + graceful-fs "~2.0.0" + lru-cache "~2.3.0" + mkdirp "~0.3.5" + request "~2.51.0" + request-replay "~0.2.0" + rimraf "~2.2.0" + +bower@~1.3.12: + version "1.3.12" + resolved "https://registry.yarnpkg.com/bower/-/bower-1.3.12.tgz#37de0edb3904baf90aee13384a1a379a05ee214c" + dependencies: + abbrev "~1.0.4" + archy "0.0.2" + bower-config "~0.5.2" + bower-endpoint-parser "~0.2.2" + bower-json "~0.4.0" + bower-logger "~0.2.2" + bower-registry-client "~0.2.0" + cardinal "0.4.0" + chalk "0.5.0" + chmodr "0.1.0" + decompress-zip "0.0.8" + fstream "~1.0.2" + fstream-ignore "~1.0.1" + glob "~4.0.2" + graceful-fs "~3.0.1" + handlebars "~2.0.0" + inquirer "0.7.1" + insight "0.4.3" + is-root "~1.0.0" + junk "~1.0.0" + lockfile "~1.0.0" + lru-cache "~2.5.0" + mkdirp "0.5.0" + mout "~0.9.0" + nopt "~3.0.0" + opn "~1.0.0" + osenv "0.1.0" + p-throttler "0.1.0" + promptly "0.2.0" + q "~1.0.1" + request "~2.42.0" + request-progress "0.3.0" + retry "0.6.0" + rimraf "~2.2.0" + semver "~2.3.0" + shell-quote "~1.4.1" + stringify-object "~1.0.0" + tar-fs "0.5.2" + tmp "0.0.23" + update-notifier "0.2.0" + which "~1.0.5" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + +browser-pack@^6.0.1: + version "6.0.3" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.3.tgz#91ca96518583ef580ab063a309de62e407767a39" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.8.0" + defined "^1.0.0" + safe-buffer "^5.1.1" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^1.11.0, browser-resolve@^1.7.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + dependencies: + resolve "1.1.7" + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + dependencies: + pako "~1.0.5" + +browserify@^15.2.0: + version "15.2.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-15.2.0.tgz#1e121ba1fa72cf9fd2d8df002f8674b68b45df89" + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.2.0" + buffer "^5.0.2" + cached-path-relative "^1.0.0" + concat-stream "~1.5.1" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "~1.1.0" + duplexer2 "~0.1.2" + events "~1.1.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + mkdirp "^0.5.0" + module-deps "^5.0.1" + os-browserify "~0.3.0" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "~1.0.0" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "~0.0.0" + url "~0.11.0" + util "~0.10.1" + vm-browserify "~0.0.1" + xtend "^4.0.0" + +browserslist@^2.1.2: + version "2.11.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" + dependencies: + caniuse-lite "^1.0.30000792" + electron-to-chromium "^1.3.30" + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + +buffer@^5.0.2: + version "5.0.8" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +buffers@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +cached-path-relative@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" + +caniuse-lite@^1.0.30000792: + version "1.0.30000803" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000803.tgz#9939c37149d38d5f4540430490d240c03106a0f5" + +cardinal@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-0.4.0.tgz#7d10aafb20837bde043c45e43a0c8c28cdaae45e" + dependencies: + redeyed "~0.4.0" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +caseless@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.6.0.tgz#8167c1ab8397fb5bb95f96d28e5a81c50f247ac4" + +caseless@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.8.0.tgz#5bca2881d41437f54b2407ebe34888c7b9ad4f7d" + +chainsaw@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" + dependencies: + traverse ">=0.3.0 <0.4" + +chalk@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.0.tgz#375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f" + dependencies: + ansi-styles "^1.1.0" + escape-string-regexp "^1.0.0" + has-ansi "^0.1.0" + strip-ansi "^0.3.0" + supports-color "^0.2.0" + +chalk@^0.5.0, chalk@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" + dependencies: + ansi-styles "^1.1.0" + escape-string-regexp "^1.0.0" + has-ansi "^0.1.0" + strip-ansi "^0.3.0" + supports-color "^0.2.0" + +chalk@^1.1.3, chalk@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" + dependencies: + ansi-styles "~1.0.0" + has-color "~0.1.0" + strip-ansi "~0.1.0" + +chmodr@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chmodr/-/chmodr-0.1.0.tgz#e09215a1d51542db2a2576969765bcf6125583eb" + +chokidar@^1.6.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +classnames@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" + +cli-color@~0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-0.3.3.tgz#12d5bdd158ff8a0b0db401198913c03df069f6f5" + dependencies: + d "~0.1.1" + es5-ext "~0.10.6" + memoizee "~0.3.8" + timers-ext "0.1" + +cli-table@~0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + dependencies: + colors "1.0.3" + +cli@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" + dependencies: + exit "0.1.2" + glob "^7.1.1" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +colors@0.6.x: + version "0.6.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + +combine-source-map@~0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + +combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +combined-stream@~0.0.4, combined-stream@~0.0.5: + version "0.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-0.0.7.tgz#0137e657baa5a7541c57ac37ac5fc07d73b4dc1f" + dependencies: + delayed-stream "0.0.5" + +commander@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.5.0.tgz#d777b6a4d847d423e5d475da864294ac1ff5aa9d" + +commander@^2.11.0, commander@^2.5.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.0.tgz#7b25325963e6aace20d3a9285b09379b0c2208b5" + +commander@~2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +comment-parser@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.3.2.tgz#3c03f0776b86a36dfd9a0a2c97c6307f332082fe" + dependencies: + readable-stream "^2.0.4" + +commoner@^0.10.1: + version "0.10.8" + resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5" + dependencies: + commander "^2.5.0" + detective "^4.3.1" + glob "^5.0.15" + graceful-fs "^4.1.2" + iconv-lite "^0.4.5" + mkdirp "^0.5.0" + private "^0.1.6" + q "^1.1.2" + recast "^0.11.17" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@~1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" + dependencies: + inherits "~2.0.1" + readable-stream "~2.0.0" + typedarray "~0.0.5" + +concat-stream@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@~1.1.8: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^0.3.0, configstore@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-0.3.2.tgz#25e4c16c3768abf75c5a65bc61761f495055b459" + dependencies: + graceful-fs "^3.0.1" + js-yaml "^3.1.0" + mkdirp "^0.5.0" + object-assign "^2.0.0" + osenv "^0.1.0" + user-home "^1.0.0" + uuid "^2.0.1" + xdg-basedir "^1.0.0" + +console-browserify@1.1.x, console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +constants-browserify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +convert-source-map@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +create-ecdh@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + ripemd160 "^2.0.0" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.6" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cryptiles@0.2.x: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-0.2.2.tgz#ed91ff1f17ad13d3748288594f8a48a0d26f325c" + dependencies: + boom "0.4.x" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +crypto-browserify@^3.0.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +cst@^0.4.3: + version "0.4.10" + resolved "https://registry.yarnpkg.com/cst/-/cst-0.4.10.tgz#9c05c825290a762f0a85c0aabb8c0fe035ae8516" + dependencies: + babel-runtime "^6.9.2" + babylon "^6.8.1" + source-map-support "^0.4.0" + +ctype@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" + +cycle@1.0.x: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" + +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + +d@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" + dependencies: + es5-ext "~0.10.2" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +debowerify@^1.3.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/debowerify/-/debowerify-1.5.0.tgz#0813bd5b8fee8f5fb77ebafd62e2979a17dcdaff" + dependencies: + bower "~1.3.12" + esprima "^2.0.0" + ordered-ast-traverse "^1.1.1" + through "~2.3.4" + +debug@^2.2.0, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +decompress-zip@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/decompress-zip/-/decompress-zip-0.0.8.tgz#4a265b22c7b209d7b24fa66f2b2dfbced59044f3" + dependencies: + binary "~0.3.0" + graceful-fs "~3.0.0" + mkpath "~0.1.0" + nopt "~2.2.0" + q "~1.0.0" + readable-stream "~1.1.8" + touch "0.0.2" + +deep-equal@*: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +deep-extend@~0.2.5: + version "0.2.11" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.2.11.tgz#7a16ba69729132340506170494bc83f7076fe08f" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +delayed-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +deps-sort@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" + dependencies: + JSONStream "^1.0.3" + shasum "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +detective@^4.3.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +detective@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.0.2.tgz#84ec2e1c581e74211e2ae4ffce1edf52c3263f84" + dependencies: + "@browserify/acorn5-object-spread" "^5.0.1" + acorn "^5.2.1" + defined "^1.0.0" + +diffie-hellman@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domain-browser@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + dependencies: + readable-stream "^2.0.2" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +electron-to-chromium@^1.3.30: + version "1.3.32" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.32.tgz#11d0684c0840e003c4be8928f8ac5f35dbc2b4e6" + +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +end-of-stream@^1.0.0, end-of-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e" + dependencies: + once "~1.3.0" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +envify@^3.2.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/envify/-/envify-3.4.1.tgz#d7122329e8df1688ba771b12501917c9ce5cbce8" + dependencies: + jstransform "^11.0.3" + through "~2.3.4" + +es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.11, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.5, es5-ext@~0.10.6: + version "0.10.38" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.38.tgz#fa7d40d65bbc9bb8a67e1d3f9cc656a00530eed3" + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.1" + +es6-iterator@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-0.1.3.tgz#d6f58b8c4fc413c249b4baa19768f8e4d7c8944e" + dependencies: + d "~0.1.1" + es5-ext "~0.10.5" + es6-symbol "~2.0.1" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-symbol@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-2.0.1.tgz#761b5c67cfd4f1d18afb234f691d678682cb3bf3" + dependencies: + d "~0.1.1" + es5-ext "~0.10.5" + +es6-weak-map@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-0.1.4.tgz#706cef9e99aa236ba7766c239c8b9e286ea7d228" + dependencies: + d "~0.1.1" + es5-ext "~0.10.6" + es6-iterator "~0.1.3" + es6-symbol "~2.0.1" + +escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esprima-fb@^15001.1.0-dev-harmony-fb: + version "15001.1.0-dev-harmony-fb" + resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz#30a947303c6b8d5e955bee2b99b1d233206a6901" + +esprima@^2.0.0, esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + +esprima@~3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +estraverse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-emitter@~0.3.4: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + +events@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exit@0.1.2, exit@0.1.x, exit@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extend@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.3.0, extsprintf@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +eyes@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + +figures@^1.3.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +forever-agent@~0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.5.2.tgz#6d0e09c4921f94a27f63d3b49c5feff1ea4c5130" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~0.1.0: + version "0.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.1.4.tgz#91abd788aba9702b1aabfa8bc01031a2ac9e3b12" + dependencies: + async "~0.9.0" + combined-stream "~0.0.4" + mime "~1.2.11" + +form-data@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.2.0.tgz#26f8bc26da6440e299cbdcfb69035c4f77a6e466" + dependencies: + async "~0.9.0" + combined-stream "~0.0.4" + mime-types "~2.0.3" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +fs-readdir-recursive@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.39" + +fstream-ignore@^1.0.5, fstream-ignore@~1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^5.0.1, glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~4.0.2: + version "4.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.0.6.tgz#695c50bdd4e2fb5c5d370b091f388d3707e291a7" + dependencies: + graceful-fs "^3.0.2" + inherits "2" + minimatch "^1.0.0" + once "^1.3.0" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +got@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/got/-/got-0.3.0.tgz#888ec66ca4bc735ab089dbe959496d0f79485493" + dependencies: + object-assign "^0.3.0" + +graceful-fs@^3.0.1, graceful-fs@^3.0.2, graceful-fs@~3.0.0, graceful-fs@~3.0.1: + version "3.0.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" + dependencies: + natives "^1.1.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.4: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +graceful-fs@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +handlebars@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-2.0.0.tgz#6e9d7f8514a3467fa5e9f82cc158ecfc1d5ac76f" + dependencies: + optimist "~0.3" + optionalDependencies: + uglify-js "~2.3" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +has-ansi@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" + dependencies: + ansi-regex "^0.2.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-color@~0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hash-base@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" + dependencies: + inherits "^2.0.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hawk@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-1.1.1.tgz#87cd491f9b46e4e2aeaca335416766885d2d1ed9" + dependencies: + boom "0.4.x" + cryptiles "0.2.x" + hoek "0.9.x" + sntp "0.2.x" + +hawk@3.1.3, hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoek@0.9.x: + version "0.9.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-0.9.1.tgz#3d322462badf07716ea7eb85baf88079cddce505" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" + +htmlparser2@3.8.3, htmlparser2@3.8.x: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +http-signature@~0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66" + dependencies: + asn1 "0.1.11" + assert-plus "^0.1.5" + ctype "0.5.3" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + +i@0.3.x: + version "0.3.6" + resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" + +iconv-lite@^0.4.5: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +ieee754@^1.1.4: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherit@^2.2.2: + version "2.2.6" + resolved "https://registry.yarnpkg.com/inherit/-/inherit-2.2.6.tgz#f1614b06c8544e8128e4229c86347db73ad9788d" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@^1.2.0, ini@^1.3.4, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" + dependencies: + source-map "~0.5.3" + +inquirer@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.7.1.tgz#b8acf140165bd581862ed1198fb6d26430091fac" + dependencies: + chalk "^0.5.0" + cli-color "~0.3.2" + figures "^1.3.2" + lodash "~2.4.1" + mute-stream "0.0.4" + readline2 "~0.1.0" + rx "^2.2.27" + through "~2.3.4" + +inquirer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.6.0.tgz#614d7bb3e48f9e6a8028e94a0c38f23ef29823d3" + dependencies: + chalk "^0.5.0" + cli-color "~0.3.2" + lodash "~2.4.1" + mute-stream "0.0.4" + readline2 "~0.1.0" + rx "^2.2.27" + through "~2.3.4" + +insert-module-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.7.1" + concat-stream "~1.5.1" + is-buffer "^1.1.0" + lexical-scope "^1.2.0" + process "~0.11.0" + through2 "^2.0.0" + xtend "^4.0.0" + +insight@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/insight/-/insight-0.4.3.tgz#76d653c5c0d8048b03cdba6385a6948f74614af0" + dependencies: + async "^0.9.0" + chalk "^0.5.1" + configstore "^0.3.1" + inquirer "^0.6.0" + lodash.debounce "^2.4.1" + object-assign "^1.0.0" + os-name "^1.0.0" + request "^2.40.0" + tough-cookie "^0.12.1" + +intersect@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/intersect/-/intersect-0.0.3.tgz#c1a4a5e5eac6ede4af7504cc07e0ada7bc9f4920" + +invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.0, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-root@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-root/-/is-root-1.0.0.tgz#07b6c233bc394cd9d02ba15c966bd6660d6342d5" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +isarray@0.0.1, isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@0.1.x, isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.1.0, js-yaml@~3.4.0: + version "3.4.6" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.4.6.tgz#6be1b23f6249f53d293370fd4d1aaa63ce1b4eb0" + dependencies: + argparse "^1.0.2" + esprima "^2.6.0" + inherit "^2.2.2" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jscs-jsdoc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jscs-jsdoc/-/jscs-jsdoc-2.0.0.tgz#f53ebce029aa3125bd88290ba50d64d4510a4871" + dependencies: + comment-parser "^0.3.1" + jsdoctypeparser "~1.2.0" + +jscs-preset-wikimedia@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jscs-preset-wikimedia/-/jscs-preset-wikimedia-1.0.0.tgz#fff563342038fc2e8826b7bb7309c3ae3406fc7e" + +jscs@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/jscs/-/jscs-3.0.7.tgz#7141b4dff5b86e32d0e99d764b836767c30d201a" + dependencies: + chalk "~1.1.0" + cli-table "~0.3.1" + commander "~2.9.0" + cst "^0.4.3" + estraverse "^4.1.0" + exit "~0.1.2" + glob "^5.0.1" + htmlparser2 "3.8.3" + js-yaml "~3.4.0" + jscs-jsdoc "^2.0.0" + jscs-preset-wikimedia "~1.0.0" + jsonlint "~1.6.2" + lodash "~3.10.0" + minimatch "~3.0.0" + natural-compare "~1.2.2" + pathval "~0.1.1" + prompt "~0.2.14" + reserved-words "^0.1.1" + resolve "^1.1.6" + strip-bom "^2.0.0" + strip-json-comments "~1.0.2" + to-double-quotes "^2.0.0" + to-single-quotes "^2.0.0" + vow "~0.4.8" + vow-fs "~0.3.4" + xmlbuilder "^3.1.0" + +jsdoctypeparser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-1.2.0.tgz#e7dedc153a11849ffc5141144ae86a7ef0c25392" + dependencies: + lodash "^3.7.0" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +jshint@^2.9.2: + version "2.9.5" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.9.5.tgz#1e7252915ce681b40827ee14248c46d34e9aa62c" + dependencies: + cli "~1.0.0" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.8.x" + lodash "3.7.x" + minimatch "~3.0.2" + shelljs "0.3.x" + strip-json-comments "1.0.x" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonlint@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/jsonlint/-/jsonlint-1.6.2.tgz#5737045085f55eb455c68b1ff4ebc01bd50e8830" + dependencies: + JSV ">= 4.0.x" + nomnom ">= 1.5.x" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jstransform@^11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223" + dependencies: + base62 "^1.1.0" + commoner "^0.10.1" + esprima-fb "^15001.1.0-dev-harmony-fb" + object-assign "^2.0.0" + source-map "^0.4.2" + +junk@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/junk/-/junk-1.0.3.tgz#87be63488649cbdca6f53ab39bec9ccd2347f592" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +labeled-stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59" + dependencies: + inherits "^2.0.1" + isarray "~0.0.1" + stream-splicer "^2.0.0" + +latest-version@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-0.2.0.tgz#adaf898d5f22380d3f9c45386efdff0a1b5b7501" + dependencies: + package-json "^0.2.0" + +lexical-scope@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/lexical-scope/-/lexical-scope-1.2.0.tgz#fcea5edc704a4b3a8796cdca419c3a0afaf22df4" + dependencies: + astw "^2.0.0" + +localenv@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/localenv/-/localenv-0.2.2.tgz#c508f29d3485bdc9341d3ead17f61c5abd1b0bab" + dependencies: + commander "2.5.0" + +localenvify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/localenvify/-/localenvify-1.0.1.tgz#0db4aa46d55628dfd24e438fbb0627b275968943" + dependencies: + envify "^3.2.0" + localenv "^0.2.2" + +lockfile@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.3.tgz#2638fc39a0331e9cac1a04b71799931c9c50df79" + +lodash._isnative@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c" + +lodash._objecttypes@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11" + +lodash.debounce@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-2.4.1.tgz#d8cead246ec4b926e8b85678fc396bfeba8cc6fc" + dependencies: + lodash.isfunction "~2.4.1" + lodash.isobject "~2.4.1" + lodash.now "~2.4.1" + +lodash.isfunction@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz#2cfd575c73e498ab57e319b77fa02adef13a94d1" + +lodash.isobject@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5" + dependencies: + lodash._objecttypes "~2.4.1" + +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" + +lodash.now@~2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/lodash.now/-/lodash.now-2.4.1.tgz#6872156500525185faf96785bb7fe7fe15b562c6" + dependencies: + lodash._isnative "~2.4.1" + +lodash@3.7.x: + version "3.7.0" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" + +lodash@^3.5.0, lodash@^3.7.0, lodash@~3.10.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +lodash@^4.17.4: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + +lodash@~2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +lru-cache@2, lru-cache@~2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.5.2.tgz#1fddad938aae1263ce138680be1b3f591c0ab41c" + +lru-cache@~2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.3.1.tgz#b3adf6b3d856e954e2c390e6cef22081245a53d6" + +lru-queue@0.1: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + dependencies: + es5-ext "~0.10.2" + +md5.js@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +memoizee@~0.3.8: + version "0.3.10" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.3.10.tgz#4eca0d8aed39ec9d017f4c5c2f2f6432f42e5c8f" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-weak-map "~0.1.4" + event-emitter "~0.3.4" + lru-queue "0.1" + next-tick "~0.2.2" + timers-ext "0.1" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@^2.1.12, mime-types@~2.1.7: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime-types@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-1.0.2.tgz#995ae1392ab8affcbfcb2641dd054e943c0d5dce" + +mime-types@~2.0.3: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.0.14.tgz#310e159db23e077f8bb22b748dabfa4957140aa6" + dependencies: + mime-db "~1.12.0" + +mime@~1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" + +minimalistic-assert@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.0, minimatch@~3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimatch@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-1.0.0.tgz#e0dd2120b49e1b724ce8d714c520822a9438576d" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimist@0.0.8, minimist@~0.0.1: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + dependencies: + minimist "0.0.8" + +mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mkdirp@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" + +mkpath@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/mkpath/-/mkpath-0.1.0.tgz#7554a6f8d871834cc97b5462b122c4c124d6de91" + +module-deps@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-5.0.1.tgz#3bc47c14b0a6d925aff2ec4a177b456a96ae0396" + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" + concat-stream "~1.6.0" + defined "^1.0.0" + detective "^5.0.2" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.1.3" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + +mout@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/mout/-/mout-0.9.1.tgz#84f0f3fd6acc7317f63de2affdcc0cee009b0477" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +mute-stream@0.0.4, mute-stream@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.4.tgz#a9219960a6d5d5d046597aee51252c6655f7177e" + +nan@^2.3.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" + +natives@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.1.tgz#011acce1f7cbd87f7ba6b3093d6cd9392be1c574" + +natural-compare@~1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.2.2.tgz#1f96d60e3141cac1b6d05653ce0daeac763af6aa" + +ncp@0.4.x: + version "0.4.2" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-0.4.2.tgz#abcc6cbd3ec2ed2a729ff6e7c1fa8f01784a8574" + +next-tick@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + +next-tick@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-0.2.2.tgz#75da4a927ee5887e39065880065b7336413b310d" + +node-pre-gyp@^0.6.39: + version "0.6.39" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" + dependencies: + detect-libc "^1.0.2" + hawk "3.1.3" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +node-uuid@~1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" + +"nomnom@>= 1.5.x": + version "1.8.1" + resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" + dependencies: + chalk "~0.4.0" + underscore "~1.6.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + dependencies: + abbrev "1" + +nopt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-2.2.1.tgz#2aa09b7d1768487b3b89a9c5aa52335bff0baea7" + dependencies: + abbrev "1" + +nopt@~3.0.0, nopt@~3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npmconf@^2.0.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.2.tgz#66606a4a736f1e77a059aa071a79c94ab781853a" + dependencies: + config-chain "~1.1.8" + inherits "~2.0.0" + ini "^1.2.0" + mkdirp "^0.5.0" + nopt "~3.0.1" + once "~1.3.0" + osenv "^0.1.0" + semver "2 || 3 || 4" + uid-number "0.0.5" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.4.0.tgz#f22956f31ea7151a821e5f2fb32c113cad8b9f69" + +oauth-sign@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.5.0.tgz#d767f5169325620eab2e087ef0c472e773db6461" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-0.3.1.tgz#060e2a2a27d7c0d77ec77b78f11aa47fd88008d2" + +object-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-1.0.0.tgz#e65dc8766d3b47b4b8307465c8311da030b070a6" + +object-assign@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0, once@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.2.0.tgz#de1905c636af874a8fba862d9aabddd1f920461c" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +opn@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/opn/-/opn-1.0.2.tgz#b909643346d00a1abc977a8b96f3ce3c53d5cf5f" + +optimist@~0.3, optimist@~0.3.5: + version "0.3.7" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" + dependencies: + wordwrap "~0.0.2" + +optimist@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +ordered-ast-traverse@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ordered-ast-traverse/-/ordered-ast-traverse-1.1.1.tgz#6843a170bc0eee8b520cc8ddc1ddd3aa30fa057c" + dependencies: + ordered-esprima-props "~1.1.0" + +ordered-esprima-props@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ordered-esprima-props/-/ordered-esprima-props-1.1.0.tgz#a9827086df5f010aa60e9bd02b6e0335cea2ffcb" + +os-browserify@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-name@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf" + dependencies: + osx-release "^1.0.0" + win-release "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.0.3.tgz#cd6ad8ddb290915ad9e22765576025d411f29cb6" + +osenv@0.1.0, osenv@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.0.tgz#61668121eec584955030b9f470b1d2309504bfcb" + +osenv@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +osx-release@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c" + dependencies: + minimist "^1.1.0" + +output-file-sync@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" + dependencies: + graceful-fs "^4.1.4" + mkdirp "^0.5.1" + object-assign "^4.1.0" + +p-throttler@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/p-throttler/-/p-throttler-0.1.0.tgz#1b16907942c333e6f1ddeabcb3479204b8c417c4" + dependencies: + q "~0.9.2" + +package-json@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-0.2.0.tgz#0316e177b8eb149985d34f706b4a5543b274bec5" + dependencies: + got "^0.3.0" + registry-url "^0.1.0" + +page@^1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/page/-/page-1.8.3.tgz#cc46fd6e614f5a60ebc68d0e0e3570301dae7c0e" + dependencies: + path-to-regexp "~1.2.1" + +pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + dependencies: + path-platform "~0.11.15" + +parse-asn1@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +path-browserify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + +path-to-regexp@^1.2.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-to-regexp@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.2.1.tgz#b33705c140234d873c8721c7b9fd8b541ed3aff9" + dependencies: + isarray "0.0.1" + +pathval@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-0.1.1.tgz#08f911cdca9cce5942880da7817bc0b723b66d82" + +pbkdf2@^3.0.3: + version "3.0.14" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade" + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pkginfo@0.3.x: + version "0.3.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21" + +pkginfo@0.x.x: + version "0.4.1" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +private@^0.1.6, private@^0.1.7, private@~0.1.5: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process@~0.11.0: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +prompt@~0.2.14: + version "0.2.14" + resolved "https://registry.yarnpkg.com/prompt/-/prompt-0.2.14.tgz#57754f64f543fd7b0845707c818ece618f05ffdc" + dependencies: + pkginfo "0.x.x" + read "1.0.x" + revalidator "0.1.x" + utile "0.2.x" + winston "0.8.x" + +promptly@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/promptly/-/promptly-0.2.0.tgz#73ef200fa8329d5d3a8df41798950b8646ca46d9" + dependencies: + read "~1.0.4" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + +public-encrypt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + +pump@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/pump/-/pump-0.3.5.tgz#ae5ff8c1f93ed87adc6530a97565b126f585454b" + dependencies: + end-of-stream "~1.0.0" + once "~1.2.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@>=0.2.0, punycode@^1.3.2, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +q@~0.9.2: + version "0.9.7" + resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" + +q@~1.0.0, q@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.0.1.tgz#11872aeedee89268110b10a718448ffb10112a14" + +qs@~1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.2.tgz#19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88" + +qs@~2.3.1: + version "2.3.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +querystring-es3@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +randomatic@^1.1.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62" + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +rc@^1.1.7: + version "1.2.5" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" + dependencies: + readable-stream "^2.0.2" + +read@1.0.x, read@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + +readable-stream@1.1, readable-stream@^1.0.27-1, readable-stream@~1.1.8: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readable-stream@~1.0.26: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +readline2@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-0.1.1.tgz#99443ba6e83b830ef3051bfd7dc241a82728d568" + dependencies: + mute-stream "0.0.4" + strip-ansi "^2.0.1" + +recast@^0.11.17: + version "0.11.23" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" + dependencies: + ast-types "0.9.6" + esprima "~3.1.0" + private "~0.1.5" + source-map "~0.5.0" + +redeyed@~0.4.0: + version "0.4.4" + resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-0.4.4.tgz#37e990a6f2b21b2a11c2e6a48fd4135698cba97f" + dependencies: + esprima "~1.0.4" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +registry-url@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-0.1.1.tgz#1739427b81b110b302482a1c7cd727ffcc82d5be" + dependencies: + npmconf "^2.0.1" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request-progress@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.0.tgz#bdf2062bfc197c5d492500d44cb3aff7865b492e" + dependencies: + throttleit "~0.0.2" + +request-replay@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/request-replay/-/request-replay-0.2.0.tgz#9b693a5d118b39f5c596ead5ed91a26444057f60" + dependencies: + retry "~0.6.0" + +request@2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +request@^2.40.0, request@~2.51.0: + version "2.51.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.51.0.tgz#35d00bbecc012e55f907b1bd9e0dbd577bfef26e" + dependencies: + aws-sign2 "~0.5.0" + bl "~0.9.0" + caseless "~0.8.0" + combined-stream "~0.0.5" + forever-agent "~0.5.0" + form-data "~0.2.0" + hawk "1.1.1" + http-signature "~0.10.0" + json-stringify-safe "~5.0.0" + mime-types "~1.0.1" + node-uuid "~1.4.0" + oauth-sign "~0.5.0" + qs "~2.3.1" + stringstream "~0.0.4" + tough-cookie ">=0.12.0" + tunnel-agent "~0.4.0" + +request@~2.42.0: + version "2.42.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.42.0.tgz#572bd0148938564040ac7ab148b96423a063304a" + dependencies: + bl "~0.9.0" + caseless "~0.6.0" + forever-agent "~0.5.0" + json-stringify-safe "~5.0.0" + mime-types "~1.0.1" + node-uuid "~1.4.0" + qs "~1.2.0" + tunnel-agent "~0.4.0" + optionalDependencies: + aws-sign2 "~0.5.0" + form-data "~0.1.0" + hawk "1.1.1" + http-signature "~0.10.0" + oauth-sign "~0.4.0" + stringstream "~0.0.4" + tough-cookie ">=0.12.0" + +reserved-words@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +retry@0.6.0, retry@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.6.0.tgz#1c010713279a6fd1e8def28af0c3ff1871caa537" + +revalidator@0.1.x: + version "0.1.8" + resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" + +rimraf@2, rimraf@2.x.x, rimraf@~2.2.0: + version "2.2.8" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + +rimraf@^2.5.1, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" + dependencies: + hash-base "^2.0.0" + inherits "^2.0.1" + +rx@^2.2.27: + version "2.5.3" + resolved "https://registry.yarnpkg.com/rx/-/rx-2.5.3.tgz#21adc7d80f02002af50dae97fd9dbf248755f566" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +semver-diff@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-0.1.0.tgz#4f6057ca3eba23cc484b51f64aaf88b131a3855d" + dependencies: + semver "^2.2.1" + +"semver@2 || 3 || 4", semver@^2.2.1, semver@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + +semver@^5.0.1, semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + version "2.4.10" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +shell-quote@~1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.4.3.tgz#952c44e0b1ed9013ef53958179cc643e8777466b" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +sntp@0.2.x: + version "0.2.4" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-0.2.4.tgz#fb885f18b0f3aad189f824862536bceeec750900" + dependencies: + hoek "0.9.x" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +source-map-support@^0.4.0, source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@~0.1.7: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + +stream-browserify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + +stream-http@^2.0.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.3" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" + +string-length@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-0.1.2.tgz#ab04bb33867ee74beed7fb89bb7f089d392780f2" + dependencies: + strip-ansi "^0.2.1" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.0.0, string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +stringify-object@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-1.0.1.tgz#86d35e7dbfbce9aa45637d7ecdd7847e159db8a2" + +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.2.2.tgz#854d290c981525fc8c397a910b025ae2d54ffc08" + dependencies: + ansi-regex "^0.1.0" + +strip-ansi@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" + dependencies: + ansi-regex "^0.2.1" + +strip-ansi@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-2.0.1.tgz#df62c1aa94ed2f114e1d0f21fd1d50482b79a60e" + dependencies: + ansi-regex "^1.0.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-json-comments@1.0.x, strip-json-comments@~1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + dependencies: + minimist "^1.1.0" + +supports-color@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +syntax-error@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.3.0.tgz#1ed9266c4d40be75dc55bf9bb1cb77062bb96ca1" + dependencies: + acorn "^4.0.3" + +tar-fs@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-0.5.2.tgz#0f59424be7eeee45232316e302f66d3f6ea6db3e" + dependencies: + mkdirp "^0.5.0" + pump "^0.3.5" + tar-stream "^0.4.6" + +tar-pack@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar-stream@^0.4.6: + version "0.4.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-0.4.7.tgz#1f1d2ce9ebc7b42765243ca0e8f1b7bfda0aadcd" + dependencies: + bl "^0.9.0" + end-of-stream "^1.0.0" + readable-stream "^1.0.27-1" + xtend "^4.0.0" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +throttleit@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" + +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +"through@>=2.2.7 <3", through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timers-browserify@^1.0.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" + dependencies: + process "~0.11.0" + +timers-ext@0.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.2.tgz#61cc47a76c1abd3195f14527f978d58ae94c5204" + dependencies: + es5-ext "~0.10.14" + next-tick "1" + +tmp@0.0.23: + version "0.0.23" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.23.tgz#de874aa5e974a85f0a32cdfdbd74663cb3bd9c74" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-double-quotes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-double-quotes/-/to-double-quotes-2.0.0.tgz#aaf231d6fa948949f819301bbab4484d8588e4a7" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-single-quotes@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/to-single-quotes/-/to-single-quotes-2.0.1.tgz#7cc29151f0f5f2c41946f119f5932fe554170125" + +touch@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/touch/-/touch-0.0.2.tgz#a65a777795e5cbbe1299499bdc42281ffb21b5f4" + dependencies: + nopt "~1.0.10" + +tough-cookie@>=0.12.0, tough-cookie@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-0.12.1.tgz#8220c7e21abd5b13d96804254bd5a81ebf2c7d62" + dependencies: + punycode ">=0.2.0" + +tough-cookie@~2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + +"traverse@>=0.3.0 <0.4": + version "0.3.9" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tty-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tunnel-agent@~0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +typedarray@^0.0.6, typedarray@~0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@~2.3: + version "2.3.6" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.3.6.tgz#fa0984770b428b7a9b2a8058f46355d14fef211a" + dependencies: + async "~0.2.6" + optimist "~0.3.5" + source-map "~0.1.7" + +uid-number@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.5.tgz#5a3db23ef5dbd55b81fce0ec9a2ac6fccdebb81e" + +uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +umd@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e" + +underscore@~1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" + +update-notifier@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.2.0.tgz#a010c928adcf02090b8e0ce7fef6fb0a7cacc34a" + dependencies: + chalk "^0.5.0" + configstore "^0.3.0" + latest-version "^0.2.0" + semver-diff "^0.1.0" + string-length "^0.1.2" + +url@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +user-home@^1.0.0, user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util@0.10.3, util@~0.10.1: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +utile@0.2.x: + version "0.2.1" + resolved "https://registry.yarnpkg.com/utile/-/utile-0.2.1.tgz#930c88e99098d6220834c356cbd9a770522d90d7" + dependencies: + async "~0.2.9" + deep-equal "*" + i "0.3.x" + mkdirp "0.x.x" + ncp "0.4.x" + rimraf "2.x.x" + +uuid@^2.0.1, uuid@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" + +uuid@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + +v8flags@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + dependencies: + user-home "^1.1.1" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vm-browserify@~0.0.1: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +vow-fs@~0.3.4: + version "0.3.6" + resolved "https://registry.yarnpkg.com/vow-fs/-/vow-fs-0.3.6.tgz#2d4c59be22e2bf2618ddf597ab4baa923be7200d" + dependencies: + glob "^7.0.5" + uuid "^2.0.2" + vow "^0.4.7" + vow-queue "^0.4.1" + +vow-queue@^0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/vow-queue/-/vow-queue-0.4.3.tgz#4ba8f64b56e9212c0dbe57f1405aeebd54cce78d" + dependencies: + vow "^0.4.17" + +vow@^0.4.17, vow@^0.4.7, vow@~0.4.8: + version "0.4.17" + resolved "https://registry.yarnpkg.com/vow/-/vow-0.4.17.tgz#b16e08fae58c52f3ebc6875f2441b26a92682904" + +which@~1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/which/-/which-1.0.9.tgz#460c1da0f810103d0321a9b633af9e575e64486f" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +win-release@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209" + dependencies: + semver "^5.0.1" + +winston@0.8.x: + version "0.8.3" + resolved "https://registry.yarnpkg.com/winston/-/winston-0.8.3.tgz#64b6abf4cd01adcaefd5009393b1d8e8bec19db0" + dependencies: + async "0.2.x" + colors "0.6.x" + cycle "1.0.x" + eyes "0.1.x" + isstream "0.1.x" + pkginfo "0.3.x" + stack-trace "0.0.x" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xdg-basedir@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-1.0.1.tgz#14ff8f63a4fdbcb05d5b6eea22b36f3033b9f04e" + dependencies: + user-home "^1.0.0" + +xmlbuilder@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-3.1.0.tgz#2c86888f2d4eade850fa38ca7f7223f7209516e1" + dependencies: + lodash "^3.5.0" + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" diff --git a/db/db.go b/db/db.go new file mode 100644 index 0000000..bc4b8b3 --- /dev/null +++ b/db/db.go @@ -0,0 +1,75 @@ +package db + +import ( + "fmt" + "strings" + + "github.com/go-pg/pg" + "github.com/go-pg/pg/orm" + "github.com/jloup/utils" +) + +var DB *pg.DB + +var log = utils.StandardL().WithField("module", "db") + +type DBConfig struct { + Address string + Database string + User string + Password string +} + +func Init(config DBConfig) { + var err error + + DB = connect(config) + + err = createSchema(DB) + if err != nil { + log.Errorf("cannot create schemas %v\n", err) + } + + err = createIndexes(DB) + if err != nil { + log.Errorf("cannot create indexes %v\n", err) + } +} + +func connect(config DBConfig) *pg.DB { + return pg.Connect(&pg.Options{ + User: config.User, + Password: config.Password, + Database: config.Database, + Addr: config.Address, + }) +} + +func createSchema(db *pg.DB) error { + for _, model := range []interface{}{&User{}, &MarketConfig{}} { + err := db.CreateTable(model, &orm.CreateTableOptions{IfNotExists: true}) + if err != nil { + return err + } + } + return nil +} + +func createIndexes(db *pg.DB) error { + indexes := []struct { + TableName string + Name string + Columns []string + }{ + {"market_configs", "market_name_user_id_idx", []string{"user_id", "market_name"}}, + } + + for _, index := range indexes { + _, err := db.Exec(fmt.Sprintf("CREATE UNIQUE INDEX IF NOT EXISTS %s ON %s (%s)", index.Name, index.TableName, strings.Join(index.Columns, ","))) + if err != nil { + return err + } + } + + return nil +} diff --git a/db/db_test.go b/db/db_test.go new file mode 100644 index 0000000..0481915 --- /dev/null +++ b/db/db_test.go @@ -0,0 +1,35 @@ +package db + +import "testing" + +func TestInit(t *testing.T) { + Init(DBConfig{"localhost:5432", "cryptoportfolio", "cryptoportfolio", "cryptoportfolio-dev"}) +} + +func TestUpdateUser(t *testing.T) { + Init(DBConfig{"localhost:5432", "cryptoportfolio", "cryptoportfolio", "cryptoportfolio-dev"}) + t.Log(InsertUser(&User{Email: "j@test.com", PasswordHash: "yp"})) + err := InsertUser(&User{Email: "t2@test.com", PasswordHash: "yp"}) + + t.Log(err, IsDup(err)) + + t.Log(GetUserByEmail("testyo")) +} + +func TestMarketConfig(t *testing.T) { + Init(DBConfig{"localhost:5432", "cryptoportfolio", "cryptoportfolio", "cryptoportfolio-dev"}) + + config := MarketConfig{UserId: 1, MarketName: "poloniex"} + config.Config = make(map[string]string) + + config.Config["secret"] = "key" + + t.Log(InsertMarketConfig(&config)) + t.Log(config) + + t.Log(GetUserMarketConfig(1, "poloniex")) + + config.Config["secret2"] = "key2" + t.Log(SetUserMarketConfig(1, "poloniex", config.Config)) + t.Log(SetUserMarketConfig(1, "bifinance", config.Config)) +} diff --git a/db/errors.go b/db/errors.go new file mode 100644 index 0000000..ed5f371 --- /dev/null +++ b/db/errors.go @@ -0,0 +1,23 @@ +package db + +import ( + "strings" + + "github.com/go-pg/pg" +) + +func PGCode(err error) string { + if _, ok := err.(pg.Error); !ok { + return "" + } + + return err.(pg.Error).Field('C') +} + +func IsDup(err error) bool { + return PGCode(err) == "23505" +} + +func IsSQLError(err error) bool { + return strings.HasPrefix(err.Error(), "ERROR #") +} diff --git a/db/market_config.go b/db/market_config.go new file mode 100644 index 0000000..b26c092 --- /dev/null +++ b/db/market_config.go @@ -0,0 +1,45 @@ +package db + +import "github.com/go-pg/pg" + +type MarketConfig struct { + Id int64 + MarketName string `sql:",notnull"` + UserId int64 `sql:",notnull"` + Config map[string]string +} + +func InsertMarketConfig(config *MarketConfig) error { + return DB.Insert(config) +} + +func GetUserMarketConfig(userId int64, market string) (*MarketConfig, error) { + var config MarketConfig + + err := DB.Model(&config).Where("user_id = ?", userId).Where("market_name = ?", market).First() + + if err != nil && err != pg.ErrNoRows { + return nil, err + } + + if err == pg.ErrNoRows { + return nil, nil + } else { + return &config, nil + } +} + +func SetUserMarketConfig(userId int64, market string, newConfig map[string]string) (*MarketConfig, error) { + config := MarketConfig{ + UserId: userId, + MarketName: market, + Config: newConfig, + } + + _, err := DB.Model(&config). + OnConflict("(user_id, market_name) DO UPDATE"). + Set("config = ?", newConfig). + Insert() + + return &config, err +} diff --git a/db/user.go b/db/user.go new file mode 100644 index 0000000..aed0ac1 --- /dev/null +++ b/db/user.go @@ -0,0 +1,72 @@ +package db + +import ( + "golang.org/x/crypto/bcrypt" +) + +type UserStatus uint8 + +const ( + Confirmed UserStatus = iota + 1 + AwaitingConfirmation +) + +type User struct { + Id int64 + Email string `sql:",unique,notnull"` + PasswordHash string `sql:",notnull"` + OtpSecret string + IsOtpSetup bool + Status UserStatus +} + +func HashPassword(password string) (string, error) { + b, err := bcrypt.GenerateFromPassword([]byte(password), 10) + + return string(b), err +} + +func ValidatePassword(password string, hash string) error { + return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) +} + +func InsertUser(user *User) error { + return DB.Insert(user) +} + +func ConfirmUserByEmail(email string) error { + _, err := DB.Model(&User{}).Set("status=?", Confirmed).Where("email=?", email).Returning("*").Update() + + return err +} + +func GetUserById(id int64) (*User, error) { + user := User{Id: id} + + err := DB.Select(&user) + + return &user, err +} + +func GetUserByEmail(email string) (*User, error) { + var users []User + + err := DB.Model(&users).Where("email = ?", email).Select() + + if err != nil { + return nil, err + } + + if len(users) == 0 { + return nil, nil + } + + return &users[0], nil +} + +func SetOtpSecret(user *User, secret string, temporary bool) error { + user.OtpSecret = secret + user.IsOtpSetup = !temporary + + return DB.Update(user) +}