From 31ad6ec1e5cd590283cc7310ad436c41b2078fc1 Mon Sep 17 00:00:00 2001 From: lukas Date: Sat, 22 May 2021 21:33:32 +0200 Subject: [PATCH 1/3] new apihandler mechanics to allow asynchronous api calls document some api nodes with apidoc --- apiGo/api/Actors.go | 128 +++- apiGo/api/ApiBase.go | 78 ++- apiGo/api/Helpers.go | 44 ++ apiGo/api/Settings.go | 29 +- apiGo/api/TVShows.go | 49 +- apiGo/api/Tags.go | 55 +- apiGo/api/Video.go | 236 +++++-- apiGo/api/oauth/Oauth.go | 7 +- package.json | 6 +- .../VideoContainer/VideoContainer.tsx | 2 +- src/pages/CategoryPage/CategoryView.tsx | 2 +- src/pages/HomePage/HomePage.tsx | 2 +- src/pages/RandomPage/RandomPage.tsx | 3 +- yarn.lock | 627 +++++++++++++++++- 14 files changed, 1105 insertions(+), 163 deletions(-) diff --git a/apiGo/api/Actors.go b/apiGo/api/Actors.go index 3d405e9..1cc511f 100644 --- a/apiGo/api/Actors.go +++ b/apiGo/api/Actors.go @@ -12,32 +12,83 @@ func AddActorsHandlers() { } func getActorsFromDB() { - AddHandler("getAllActors", ActorNode, nil, func() []byte { + /** + * @api {post} /api/actor [getAllActors] + * @apiDescription Get all available Actors + * @apiName getAllActors + * @apiGroup Actor + * + * @apiSuccess {Object[]} . Array of Actors available + * @apiSuccess {uint32} .ActorId Actor Id + * @apiSuccess {string} .Name Actor Name + * @apiSuccess {string} .Thumbnail Portrait Thumbnail + */ + AddHandler("getAllActors", ActorNode, func(info *HandlerInfo) []byte { query := "SELECT actor_id, name, thumbnail FROM actors" return jsonify(readActorsFromResultset(database.Query(query))) }) - var gaov struct { - MovieId int - } - AddHandler("getActorsOfVideo", ActorNode, &gaov, func() []byte { + /** + * @api {post} /api/actor [getActorsOfVideo] + * @apiDescription Get all actors playing in one video + * @apiName getActorsOfVideo + * @apiGroup Actor + * + * @apiParam {int} MovieId ID of video + * + * @apiSuccess {Object[]} . Array of Actors available + * @apiSuccess {uint32} .ActorId Actor Id + * @apiSuccess {string} .Name Actor Name + * @apiSuccess {string} .Thumbnail Portrait Thumbnail + */ + AddHandler("getActorsOfVideo", ActorNode, func(info *HandlerInfo) []byte { + var args struct { + MovieId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos JOIN actors a on actors_videos.actor_id = a.actor_id - WHERE actors_videos.video_id=%d`, gaov.MovieId) + WHERE actors_videos.video_id=%d`, args.MovieId) return jsonify(readActorsFromResultset(database.Query(query))) }) - var gai struct { - ActorId int - } - AddHandler("getActorInfo", ActorNode, &gai, func() []byte { + /** + * @api {post} /api/actor [getActorInfo] + * @apiDescription Get all infos for an actor + * @apiName getActorInfo + * @apiGroup Actor + * + * @apiParam {int} ActorId ID of Actor + * + * @apiSuccess {VideoUnloadedType[]} Videos Array of Videos this actor plays in + * @apiSuccess {uint32} Videos.MovieId Video Id + * @apiSuccess {string} Videos.MovieName Video Name + * + * @apiSuccess {Info} Info Infos about the actor + * @apiSuccess {uint32} Info.ActorId Actor Id + * @apiSuccess {string} Info.Name Actor Name + * @apiSuccess {string} Info.Thumbnail Actor Thumbnail + */ + AddHandler("getActorInfo", ActorNode, func(info *HandlerInfo) []byte { + var args struct { + ActorId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := fmt.Sprintf(`SELECT movie_id, movie_name FROM actors_videos JOIN videos v on v.movie_id = actors_videos.video_id - WHERE actors_videos.actor_id=%d`, gai.ActorId) + WHERE actors_videos.actor_id=%d`, args.ActorId) videos := readVideosFromResultset(database.Query(query)) - query = fmt.Sprintf("SELECT actor_id, name, thumbnail FROM actors WHERE actor_id=%d", gai.ActorId) + query = fmt.Sprintf("SELECT actor_id, name, thumbnail FROM actors WHERE actor_id=%d", args.ActorId) actor := readActorsFromResultset(database.Query(query))[0] var result = struct { @@ -53,20 +104,51 @@ func getActorsFromDB() { } func saveActorsToDB() { - var ca struct { - ActorName string - } - AddHandler("createActor", ActorNode, &ca, func() []byte { + /** + * @api {post} /api/video [createActor] + * @apiDescription Create a new Actor + * @apiName createActor + * @apiGroup Actor + * + * @apiParam {string} ActorName Name of new Actor + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ + AddHandler("createActor", ActorNode, func(info *HandlerInfo) []byte { + var args struct { + ActorName string + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := "INSERT IGNORE INTO actors (name) VALUES (?)" - return database.SuccessQuery(query, ca.ActorName) + return database.SuccessQuery(query, args.ActorName) }) - var aatv struct { - ActorId int - MovieId int - } - AddHandler("addActorToVideo", ActorNode, &aatv, func() []byte { - query := fmt.Sprintf("INSERT IGNORE INTO actors_videos (actor_id, video_id) VALUES (%d,%d)", aatv.ActorId, aatv.MovieId) + /** + * @api {post} /api/video [addActorToVideo] + * @apiDescription Add Actor to Video + * @apiName addActorToVideo + * @apiGroup Actor + * + * @apiParam {int} ActorId Id of Actor + * @apiParam {int} MovieId Id of Movie to add to + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ + AddHandler("addActorToVideo", ActorNode, func(info *HandlerInfo) []byte { + var args struct { + ActorId int + MovieId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + + query := fmt.Sprintf("INSERT IGNORE INTO actors_videos (actor_id, video_id) VALUES (%d,%d)", args.ActorId, args.MovieId) return database.SuccessQuery(query) }) } diff --git a/apiGo/api/ApiBase.go b/apiGo/api/ApiBase.go index bc83d1f..5120559 100644 --- a/apiGo/api/ApiBase.go +++ b/apiGo/api/ApiBase.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "gopkg.in/oauth2.v3" "net/http" "openmediacenter/apiGo/api/oauth" ) @@ -18,22 +19,27 @@ const ( TVShowNode = iota ) +type HandlerInfo struct { + ID string + Token string + Data map[string]interface{} +} + type actionStruct struct { Action string } type Handler struct { - action string - handler func() []byte - arguments interface{} - apiNode int + action string + handler func(info *HandlerInfo) []byte + apiNode int } -var handlers []Handler +var handlers = make(map[string]Handler) -func AddHandler(action string, apiNode int, n interface{}, h func() []byte) { +func AddHandler(action string, apiNode int, h func(info *HandlerInfo) []byte) { // append new handler to the handlers - handlers = append(handlers, Handler{action, h, n, apiNode}) + handlers[fmt.Sprintf("%s/%d", action, apiNode)] = Handler{action, h, apiNode} } func ServerInit() { @@ -47,27 +53,39 @@ func ServerInit() { oauth.InitOAuth() } -func handleAPICall(action string, requestBody string, apiNode int) []byte { - for i := range handlers { - if handlers[i].action == action && handlers[i].apiNode == apiNode { - // call the handler and return - - if handlers[i].arguments != nil { - // decode the arguments to the corresponding arguments object - err := json.Unmarshal([]byte(requestBody), &handlers[i].arguments) - if err != nil { - fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody) - } - } - - return handlers[i].handler() - } +func handleAPICall(action string, requestBody string, apiNode int, info *HandlerInfo) []byte { + handler, ok := handlers[fmt.Sprintf("%s/%d", action, apiNode)] + if !ok { + // handler doesn't exist! + fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action) + return nil } - fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action) - return nil + + // check if info even exists + if info == nil { + info = &HandlerInfo{} + } + + // parse the arguments + var args map[string]interface{} + err := json.Unmarshal([]byte(requestBody), &args) + + if err != nil { + fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody) + } else { + // check if map has an action + if _, ok := args["action"]; ok { + delete(args, "action") + } + + info.Data = args + } + + // call the handler + return handler.handler(info) } -func handlefunc(rw http.ResponseWriter, req *http.Request, node int) { +func handlefunc(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo) { // only allow post requests if req.Method != "POST" { return @@ -83,5 +101,13 @@ func handlefunc(rw http.ResponseWriter, req *http.Request, node int) { fmt.Println("failed to read action from request! :: " + body) } - rw.Write(handleAPICall(t.Action, body, node)) + // load userid from received token object + id := (*tokenInfo).GetClientID() + + userinfo := &HandlerInfo{ + ID: id, + Token: (*tokenInfo).GetCode(), + } + + rw.Write(handleAPICall(t.Action, body, node, userinfo)) } diff --git a/apiGo/api/Helpers.go b/apiGo/api/Helpers.go index 2407997..259f955 100644 --- a/apiGo/api/Helpers.go +++ b/apiGo/api/Helpers.go @@ -3,8 +3,10 @@ package api import ( "database/sql" "encoding/json" + "errors" "fmt" "openmediacenter/apiGo/api/types" + "reflect" ) // MovieId - MovieName : pay attention to the order! @@ -85,3 +87,45 @@ func jsonify(v interface{}) []byte { } return str } + +// setField set a specific field of an object with an object provided +func setField(obj interface{}, name string, value interface{}) error { + structValue := reflect.ValueOf(obj).Elem() + structFieldValue := structValue.FieldByName(name) + + if !structFieldValue.IsValid() { + return fmt.Errorf("no such field: %s in obj", name) + } + + if !structFieldValue.CanSet() { + return fmt.Errorf("cannot set %s field value", name) + } + + structFieldType := structFieldValue.Type() + val := reflect.ValueOf(value) + + if structFieldType != val.Type() { + if val.Type().ConvertibleTo(structFieldType) { + // if type is convertible - convert and set + structFieldValue.Set(val.Convert(structFieldType)) + } else { + return errors.New("provided value type didn't match obj field type and isn't convertible") + } + } else { + // set value if type is the same + structFieldValue.Set(val) + } + + return nil +} + +// FillStruct fill a custom struct with objects of a map +func FillStruct(i interface{}, m map[string]interface{}) error { + for k, v := range m { + err := setField(i, k, v) + if err != nil { + return err + } + } + return nil +} diff --git a/apiGo/api/Settings.go b/apiGo/api/Settings.go index b54cfca..ddb8c13 100644 --- a/apiGo/api/Settings.go +++ b/apiGo/api/Settings.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "fmt" "openmediacenter/apiGo/api/types" "openmediacenter/apiGo/database" "openmediacenter/apiGo/database/settings" @@ -17,11 +18,12 @@ func AddSettingsHandlers() { } func getSettingsFromDB() { - AddHandler("loadGeneralSettings", SettingsNode, nil, func() []byte { + AddHandler("loadGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { result := database.GetSettings() return jsonify(result) }) - AddHandler("loadInitialData", SettingsNode, nil, func() []byte { + + AddHandler("loadInitialData", SettingsNode, func(info *HandlerInfo) []byte { sett := settings.LoadSettings() type InitialDataTypeResponse struct { @@ -52,10 +54,15 @@ func getSettingsFromDB() { } func saveSettingsToDB() { - var sgs struct { - Settings types.SettingsType - } - AddHandler("saveGeneralSettings", SettingsNode, &sgs, func() []byte { + AddHandler("saveGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { + var args struct { + Settings types.SettingsType + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := ` UPDATE settings SET video_path=?, @@ -66,24 +73,24 @@ func saveSettingsToDB() { DarkMode=? WHERE 1` return database.SuccessQuery(query, - sgs.Settings.VideoPath, sgs.Settings.EpisodePath, sgs.Settings.Password, - sgs.Settings.MediacenterName, sgs.Settings.TMDBGrabbing, sgs.Settings.DarkMode) + args.Settings.VideoPath, args.Settings.EpisodePath, args.Settings.Password, + args.Settings.MediacenterName, args.Settings.TMDBGrabbing, args.Settings.DarkMode) }) } // methods for handling reindexing and cleanup of db gravity func reIndexHandling() { - AddHandler("startReindex", SettingsNode, nil, func() []byte { + AddHandler("startReindex", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartReindex() return database.ManualSuccessResponse(nil) }) - AddHandler("startTVShowReindex", SettingsNode, nil, func() []byte { + AddHandler("startTVShowReindex", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartTVShowReindex() return database.ManualSuccessResponse(nil) }) - AddHandler("cleanupGravity", SettingsNode, nil, func() []byte { + AddHandler("cleanupGravity", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartCleanup() return nil }) diff --git a/apiGo/api/TVShows.go b/apiGo/api/TVShows.go index d536938..99fea75 100644 --- a/apiGo/api/TVShows.go +++ b/apiGo/api/TVShows.go @@ -6,17 +6,22 @@ import ( ) func AddTvshowHandlers() { - AddHandler("getTVShows", TVShowNode, nil, func() []byte { + AddHandler("getTVShows", TVShowNode, func(info *HandlerInfo) []byte { query := "SELECT id, name FROM tvshow" rows := database.Query(query) return jsonify(readTVshowsFromResultset(rows)) }) - var ge struct { - ShowID uint32 - } - AddHandler("getEpisodes", TVShowNode, &ge, func() []byte { - query := fmt.Sprintf("SELECT id, name, season, episode FROM tvshow_episodes WHERE tvshow_id=%d", ge.ShowID) + AddHandler("getEpisodes", TVShowNode, func(info *HandlerInfo) []byte { + var args struct { + ShowID uint32 + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + + query := fmt.Sprintf("SELECT id, name, season, episode FROM tvshow_episodes WHERE tvshow_id=%d", args.ShowID) rows := database.Query(query) type Episode struct { @@ -41,15 +46,20 @@ func AddTvshowHandlers() { return jsonify(episodes) }) - var le struct { - ID uint32 - } - AddHandler("loadEpisode", TVShowNode, &le, func() []byte { + AddHandler("loadEpisode", TVShowNode, func(info *HandlerInfo) []byte { + var args struct { + ID uint32 + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := fmt.Sprintf(` SELECT tvshow_episodes.name, season, tvshow_id, episode, filename, t.foldername FROM tvshow_episodes JOIN tvshow t on t.id = tvshow_episodes.tvshow_id -WHERE tvshow_episodes.id=%d`, le.ID) +WHERE tvshow_episodes.id=%d`, args.ID) row := database.QueryRow(query) var ret struct { @@ -73,17 +83,22 @@ WHERE tvshow_episodes.id=%d`, le.ID) return jsonify(ret) }) - var rtn struct { - Id int - } - AddHandler("readThumbnail", TVShowNode, &rtn, func() []byte { + AddHandler("readThumbnail", TVShowNode, func(info *HandlerInfo) []byte { + var args struct { + Id int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + var pic []byte - query := fmt.Sprintf("SELECT thumbnail FROM tvshow WHERE id=%d", rtn.Id) + query := fmt.Sprintf("SELECT thumbnail FROM tvshow WHERE id=%d", args.Id) err := database.QueryRow(query).Scan(&pic) if err != nil { - fmt.Printf("the thumbnail of movie id %d couldn't be found", rtn.Id) + fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Id) return nil } diff --git a/apiGo/api/Tags.go b/apiGo/api/Tags.go index 8701731..71bc977 100644 --- a/apiGo/api/Tags.go +++ b/apiGo/api/Tags.go @@ -13,14 +13,19 @@ func AddTagHandlers() { } func deleteFromDB() { - var dT struct { - TagId int - Force bool - } - AddHandler("deleteTag", TagNode, &dT, func() []byte { + AddHandler("deleteTag", TagNode, func(info *HandlerInfo) []byte { + var args struct { + TagId int + Force bool + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + // delete key constraints first - if dT.Force { - query := fmt.Sprintf("DELETE FROM video_tags WHERE tag_id=%d", dT.TagId) + if args.Force { + query := fmt.Sprintf("DELETE FROM video_tags WHERE tag_id=%d", args.TagId) err := database.Edit(query) // respond only if result not successful @@ -29,7 +34,7 @@ func deleteFromDB() { } } - query := fmt.Sprintf("DELETE FROM tags WHERE tag_id=%d", dT.TagId) + query := fmt.Sprintf("DELETE FROM tags WHERE tag_id=%d", args.TagId) err := database.Edit(query) if err == nil { @@ -48,27 +53,37 @@ func deleteFromDB() { } func getFromDB() { - AddHandler("getAllTags", TagNode, nil, func() []byte { + AddHandler("getAllTags", TagNode, func(info *HandlerInfo) []byte { query := "SELECT tag_id,tag_name from tags" return jsonify(readTagsFromResultset(database.Query(query))) }) } func addToDB() { - var ct struct { - TagName string - } - AddHandler("createTag", TagNode, &ct, func() []byte { + AddHandler("createTag", TagNode, func(info *HandlerInfo) []byte { + var args struct { + TagName string + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := "INSERT IGNORE INTO tags (tag_name) VALUES (?)" - return database.SuccessQuery(query, ct.TagName) + return database.SuccessQuery(query, args.TagName) }) - var at struct { - MovieId int - TagId int - } - AddHandler("addTag", TagNode, &at, func() []byte { + AddHandler("addTag", TagNode, func(info *HandlerInfo) []byte { + var args struct { + MovieId int + TagId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := "INSERT IGNORE INTO video_tags(tag_id, video_id) VALUES (?,?)" - return database.SuccessQuery(query, at.TagId, at.MovieId) + return database.SuccessQuery(query, args.TagId, args.MovieId) }) } diff --git a/apiGo/api/Video.go b/apiGo/api/Video.go index 9ddca40..3ca7de7 100644 --- a/apiGo/api/Video.go +++ b/apiGo/api/Video.go @@ -16,18 +16,35 @@ func AddVideoHandlers() { } func getVideoHandlers() { - var mrq struct { - Tag int - } - AddHandler("getMovies", VideoNode, &mrq, func() []byte { + /** + * @api {post} /api/video [getMovies] + * @apiDescription Request available Videos + * @apiName GetMovies + * @apiGroup video + * + * @apiParam {int} [Tag=all] id of VideoTag to get videos + * + * @apiSuccess {Object[]} . List of Videos + * @apiSuccess {number} .MovieId Id of Video + * @apiSuccess {String} .MovieName Name of video + */ + AddHandler("getMovies", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + Tag int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + var query string // 1 is the id of the ALL tag - if mrq.Tag != 1 { + if args.Tag != 1 { query = fmt.Sprintf(`SELECT movie_id,movie_name FROM videos INNER JOIN video_tags vt on videos.movie_id = vt.video_id INNER JOIN tags t on vt.tag_id = t.tag_id WHERE t.tag_id = '%d' - ORDER BY likes DESC, create_date, movie_name`, mrq.Tag) + ORDER BY likes DESC, create_date, movie_name`, args.Tag) } else { query = "SELECT movie_id,movie_name FROM videos ORDER BY create_date DESC, movie_name" } @@ -38,33 +55,69 @@ func getVideoHandlers() { return str }) - var rtn struct { - Movieid int - } - AddHandler("readThumbnail", VideoNode, &rtn, func() []byte { + /** + * @api {post} /api/video [readThumbnail] + * @apiDescription Load Thubnail of specific Video + * @apiName readThumbnail + * @apiGroup video + * + * @apiParam {int} Movieid id of video to load thumbnail + * + * @apiSuccess {string} . Base64 encoded Thubnail + */ + AddHandler("readThumbnail", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + Movieid int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + var pic []byte - query := fmt.Sprintf("SELECT thumbnail FROM videos WHERE movie_id=%d", rtn.Movieid) + query := fmt.Sprintf("SELECT thumbnail FROM videos WHERE movie_id=%d", args.Movieid) err := database.QueryRow(query).Scan(&pic) if err != nil { - fmt.Printf("the thumbnail of movie id %d couldn't be found", rtn.Movieid) + fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Movieid) return nil } return pic }) - var grm struct { - Number int - } - AddHandler("getRandomMovies", VideoNode, &grm, func() []byte { + /** + * @api {post} /api/video [getRandomMovies] + * @apiDescription Load random videos + * @apiName getRandomMovies + * @apiGroup video + * + * @apiParam {int} Number number of random videos to load + * + * @apiSuccess {Object[]} Tags Array of tags occuring in selection + * @apiSuccess {string} Tags.TagName Tagname + * @apiSuccess {uint32} Tags.TagId Tag ID + * + * @apiSuccess {Object[]} Videos Array of the videos + * @apiSuccess {string} Videos.MovieName Video Name + * @apiSuccess {int} Videos.MovieId Video ID + */ + AddHandler("getRandomMovies", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + Number int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + var result struct { Tags []types.Tag Videos []types.VideoUnloadedType } - query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", grm.Number) + query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", args.Number) result.Videos = readVideosFromResultset(database.Query(query)) var ids string @@ -99,13 +152,30 @@ func getVideoHandlers() { return str }) - var gsk struct { - KeyWord string - } - AddHandler("getSearchKeyWord", VideoNode, &gsk, func() []byte { + /** + * @api {post} /api/video [getSearchKeyWord] + * @apiDescription Get videos for search keyword + * @apiName getSearchKeyWord + * @apiGroup video + * + * @apiParam {string} KeyWord Keyword to search for + * + * @apiSuccess {Object[]} . List of Videos + * @apiSuccess {number} .MovieId Id of Video + * @apiSuccess {String} .MovieName Name of video + */ + AddHandler("getSearchKeyWord", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + KeyWord string + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := fmt.Sprintf(`SELECT movie_id,movie_name FROM videos WHERE movie_name LIKE '%%%s%%' - ORDER BY likes DESC, create_date DESC, movie_name`, gsk.KeyWord) + ORDER BY likes DESC, create_date DESC, movie_name`, args.KeyWord) result := readVideosFromResultset(database.Query(query)) // jsonify results @@ -116,12 +186,47 @@ func getVideoHandlers() { // function to handle stuff for loading specific videos and startdata func loadVideosHandlers() { - var lv struct { - MovieId int - } - AddHandler("loadVideo", VideoNode, &lv, func() []byte { + /** + * @api {post} /api/video [loadVideo] + * @apiDescription Load all data for a specific video + * @apiName loadVideo + * @apiGroup video + * + * @apiParam {int} MovieId ID of video + * + * @apiSuccess {string} MovieName Videoname + * @apiSuccess {uint32} MovieId Video ID + * @apiSuccess {string} MovieUrl Url to video file + * @apiSuccess {string} Poster Base64 encoded Poster + * @apiSuccess {uint64} Likes Number of likes + * @apiSuccess {uint16} Quality Video FrameWidth + * @apiSuccess {uint16} Length Video Length in seconds + * + * + * @apiSuccess {Object[]} Tags Array of tags of video + * @apiSuccess {string} Tags.TagName Tagname + * @apiSuccess {uint32} Tags.TagId Tag ID + * + * @apiSuccess {Object[]} SuggestedTag Array of tags for quick add suggestions + * @apiSuccess {string} SuggestedTag.TagName Tagname + * @apiSuccess {uint32} SuggestedTag.TagId Tag ID + * + * @apiSuccess {Object[]} Actors Array of Actors playing in this video + * @apiSuccess {uint32} Actors.ActorId Actor Id + * @apiSuccess {string} Actors.Name Actor Name + * @apiSuccess {string} Actors.Thumbnail Portrait Thumbnail + */ + AddHandler("loadVideo", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + MovieId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + query := fmt.Sprintf(`SELECT movie_name,movie_url,movie_id,thumbnail,poster,likes,quality,length - FROM videos WHERE movie_id=%d`, lv.MovieId) + FROM videos WHERE movie_id=%d`, args.MovieId) var res types.FullVideoType var poster []byte @@ -129,7 +234,7 @@ func loadVideosHandlers() { err := database.QueryRow(query).Scan(&res.MovieName, &res.MovieUrl, &res.MovieId, &thumbnail, &poster, &res.Likes, &res.Quality, &res.Length) if err != nil { - fmt.Printf("error getting full data list of videoid - %d", lv.MovieId) + fmt.Printf("error getting full data list of videoid - %d", args.MovieId) fmt.Println(err.Error()) return nil } @@ -149,7 +254,7 @@ func loadVideosHandlers() { query = fmt.Sprintf(`SELECT t.tag_id, t.tag_name FROM video_tags INNER JOIN tags t on video_tags.tag_id = t.tag_id WHERE video_tags.video_id=%d - GROUP BY t.tag_id`, lv.MovieId) + GROUP BY t.tag_id`, args.MovieId) res.Tags = readTagsFromResultset(database.Query(query)) @@ -158,14 +263,14 @@ func loadVideosHandlers() { SELECT video_tags.tag_id FROM video_tags WHERE video_id=%d) ORDER BY rand() - LIMIT 5`, lv.MovieId) + LIMIT 5`, args.MovieId) res.SuggestedTag = readTagsFromResultset(database.Query(query)) // query the actors corresponding to video query = fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos JOIN actors a on actors_videos.actor_id = a.actor_id - WHERE actors_videos.video_id=%d`, lv.MovieId) + WHERE actors_videos.video_id=%d`, args.MovieId) res.Actors = readActorsFromResultset(database.Query(query)) @@ -174,7 +279,20 @@ func loadVideosHandlers() { return str }) - AddHandler("getStartData", VideoNode, nil, func() []byte { + /** + * @api {post} /api/video [getStartData] + * @apiDescription Get general video informations at start + * @apiName getStartData + * @apiGroup video + * + * @apiSuccess {uint32} VideoNr Total nr of videos + * @apiSuccess {uint32} FullHdNr number of FullHD videos + * @apiSuccess {uint32} HDNr number of HD videos + * @apiSuccess {uint32} SDNr number of SD videos + * @apiSuccess {uint32} DifferentTags number of different Tags available + * @apiSuccess {uint32} Tagged number of different Tags assigned + */ + AddHandler("getStartData", VideoNode, func(info *HandlerInfo) []byte { var result types.StartData // query settings and infotile values query := ` @@ -215,24 +333,54 @@ func loadVideosHandlers() { } func addToVideoHandlers() { - var al struct { - MovieId int - } - AddHandler("addLike", VideoNode, &al, func() []byte { - query := fmt.Sprintf("update videos set likes = likes + 1 where movie_id = %d", al.MovieId) + /** + * @api {post} /api/video [addLike] + * @apiDescription Add a like to a video + * @apiName addLike + * @apiGroup video + * + * @apiParam {int} MovieId ID of video + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ + AddHandler("addLike", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + MovieId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + + query := fmt.Sprintf("update videos set likes = likes + 1 where movie_id = %d", args.MovieId) return database.SuccessQuery(query) }) - var dv struct { - MovieId int - } - AddHandler("deleteVideo", VideoNode, &dv, func() []byte { + /** + * @api {post} /api/video [deleteVideo] + * @apiDescription Delete a specific video from database + * @apiName deleteVideo + * @apiGroup video + * + * @apiParam {int} MovieId ID of video + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ + AddHandler("deleteVideo", VideoNode, func(info *HandlerInfo) []byte { + var args struct { + MovieId int + } + if err := FillStruct(&args, info.Data); err != nil { + fmt.Println(err.Error()) + return nil + } + // delete tag constraints - query := fmt.Sprintf("DELETE FROM video_tags WHERE video_id=%d", dv.MovieId) + query := fmt.Sprintf("DELETE FROM video_tags WHERE video_id=%d", args.MovieId) err := database.Edit(query) // delete actor constraints - query = fmt.Sprintf("DELETE FROM actors_videos WHERE video_id=%d", dv.MovieId) + query = fmt.Sprintf("DELETE FROM actors_videos WHERE video_id=%d", args.MovieId) err = database.Edit(query) // respond only if result not successful @@ -240,7 +388,7 @@ func addToVideoHandlers() { return database.ManualSuccessResponse(err) } - query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", dv.MovieId) + query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", args.MovieId) return database.SuccessQuery(query) }) } diff --git a/apiGo/api/oauth/Oauth.go b/apiGo/api/oauth/Oauth.go index 0d98e25..024b962 100644 --- a/apiGo/api/oauth/Oauth.go +++ b/apiGo/api/oauth/Oauth.go @@ -1,6 +1,7 @@ package oauth import ( + "gopkg.in/oauth2.v3" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/server" @@ -48,14 +49,14 @@ func InitOAuth() { }) } -func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int), node int) http.HandlerFunc { +func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo), node int) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - _, err := srv.ValidationBearerToken(r) + tokeninfo, err := srv.ValidationBearerToken(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - f(w, r, node) + f(w, r, node, &tokeninfo) } } diff --git a/package.json b/package.json index 4058a23..11f3e16 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "start": "react-scripts start", "build": "CI=false react-scripts build", "test": "CI=true react-scripts test --reporters=jest-junit --verbose --silent --coverage --reporters=default", - "lint": "eslint --format gitlab src/" + "lint": "eslint --format gitlab src/", + "apidoc": "apidoc -i apiGo/ -o doc/" }, "jest": { "collectCoverageFrom": [ @@ -76,6 +77,7 @@ "jest-junit": "^12.0.0", "prettier": "^2.2.1", "prettier-config": "^1.0.0", - "react-scripts": "4.0.3" + "react-scripts": "4.0.3", + "apidoc": "^0.28.1" } } diff --git a/src/elements/VideoContainer/VideoContainer.tsx b/src/elements/VideoContainer/VideoContainer.tsx index e2804f5..53d3e59 100644 --- a/src/elements/VideoContainer/VideoContainer.tsx +++ b/src/elements/VideoContainer/VideoContainer.tsx @@ -20,7 +20,7 @@ const VideoContainer = (props: Props): JSX.Element => { APINode.Video, { action: 'readThumbnail', - movieid: el.MovieId + Movieid: el.MovieId }, (result) => callback(result) ); diff --git a/src/pages/CategoryPage/CategoryView.tsx b/src/pages/CategoryPage/CategoryView.tsx index 03e8013..16cd655 100644 --- a/src/pages/CategoryPage/CategoryView.tsx +++ b/src/pages/CategoryPage/CategoryView.tsx @@ -105,7 +105,7 @@ export class CategoryView extends React.Component(APINode.Video, {action: 'getMovies', tag: id}, (result) => { + callAPI(APINode.Video, {action: 'getMovies', Tag: id}, (result) => { this.videodata = result; this.setState({loaded: true}); }); diff --git a/src/pages/HomePage/HomePage.tsx b/src/pages/HomePage/HomePage.tsx index dd6b102..c191725 100644 --- a/src/pages/HomePage/HomePage.tsx +++ b/src/pages/HomePage/HomePage.tsx @@ -59,7 +59,7 @@ export class HomePage extends React.Component { * @param tag tag to fetch videos */ fetchVideoData(tag: number): void { - callAPI(APINode.Video, {action: 'getMovies', tag: tag}, (result: VideoTypes.VideoUnloadedType[]) => { + callAPI(APINode.Video, {action: 'getMovies', Tag: tag}, (result: VideoTypes.VideoUnloadedType[]) => { this.setState({ data: [] }); diff --git a/src/pages/RandomPage/RandomPage.tsx b/src/pages/RandomPage/RandomPage.tsx index c3468be..baa7b0a 100644 --- a/src/pages/RandomPage/RandomPage.tsx +++ b/src/pages/RandomPage/RandomPage.tsx @@ -85,8 +85,7 @@ class RandomPage extends React.Component<{}, state> { * @param nr number of videos to load */ loadShuffledvideos(nr: number): void { - callAPI(APINode.Video, {action: 'getRandomMovies', number: nr}, (result) => { - console.log(result); + callAPI(APINode.Video, {action: 'getRandomMovies', Number: nr}, (result) => { this.setState({videos: []}); // needed to trigger rerender of main videoview this.setState({ videos: result.Videos, diff --git a/yarn.lock b/yarn.lock index de35c11..4d19670 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1174,6 +1174,15 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== +"@dabh/diagnostics@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31" + integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + "@eslint/eslintrc@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547" @@ -1528,6 +1537,11 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "@sinonjs/commons@^1.7.0": version "1.8.2" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" @@ -1653,6 +1667,13 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + "@testing-library/dom@^7.28.1": version "7.29.6" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.29.6.tgz#eb37844fb431186db7960a7ff6749ea65a19617c" @@ -2314,6 +2335,11 @@ abab@^2.0.3: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -2421,6 +2447,13 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" @@ -2488,6 +2521,32 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +apidoc-core@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/apidoc-core/-/apidoc-core-0.15.0.tgz#4dfcc76cc76694bd4457ccbd8655c03a87a2e2a5" + integrity sha512-CJNjRs6R8nc774vUtbv9Uakos5/JbEFpBXgE6oiWUX7OpjI1s04xPuULEoQQJyQM427r5hr55GSHAm5/LRc5TQ== + dependencies: + fs-extra "^9.0.1" + glob "^7.1.6" + iconv-lite "^0.6.2" + klaw-sync "^6.0.0" + lodash "^4.17.20" + semver "~7.3.2" + +apidoc@^0.28.1: + version "0.28.1" + resolved "https://registry.yarnpkg.com/apidoc/-/apidoc-0.28.1.tgz#5fcf2027f7fca13817332be9eaa04c2e2bd765a4" + integrity sha512-vJbRtNnxWqUUfbY4NJwq9vRB8+Fh43nccckhG9nC4nQBxrMDaBYHhwMbls3OZ9Nv36jWN4KexpLrZ5Ivph8GYg== + dependencies: + apidoc-core "^0.15.0" + commander "^2.20.0" + fs-extra "^9.0.1" + handlebars "^4.7.7" + lodash "^4.17.20" + markdown-it "^11.0.0" + nodemon "^2.0.4" + winston "^3.3.3" + aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -2680,6 +2739,11 @@ async@^2.6.2: dependencies: lodash "^4.17.14" +async@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" + integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -3036,6 +3100,20 @@ bootstrap@^4.5.3: resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7" integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw== +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -3269,6 +3347,19 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -3429,7 +3520,7 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.1: +chokidar@^3.2.2, chokidar@^3.4.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -3506,6 +3597,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3524,6 +3620,13 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3575,7 +3678,7 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.4: +color-string@^1.5.2, color-string@^1.5.4: version "1.5.5" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== @@ -3583,6 +3686,14 @@ color-string@^1.5.4: color-name "^1.0.0" simple-swizzle "^0.2.2" +color@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" + integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + color@^3.0.0: version "3.1.3" resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" @@ -3596,6 +3707,19 @@ colorette@^1.2.1, colorette@^1.2.2: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +colors@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +colorspace@1.1.x: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5" + integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ== + dependencies: + color "3.0.x" + text-hex "1.0.x" + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -3670,6 +3794,18 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + confusing-browser-globals@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" @@ -3879,6 +4015,11 @@ crypto-random-string@^1.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + css-blank-pseudo@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" @@ -4195,6 +4336,13 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -4212,6 +4360,11 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -4230,6 +4383,11 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -4496,6 +4654,11 @@ dotenv@8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -4577,6 +4740,11 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -4615,6 +4783,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" @@ -4767,6 +4940,11 @@ escalade@^3.0.2, escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -5326,6 +5504,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-safe-stringify@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" + integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== + fastq@^1.6.0: version "1.11.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.0.tgz#bb9fb955a07130a918eb63c1f5161cc32a5d0858" @@ -5347,6 +5530,11 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fecha@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce" + integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q== + figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" @@ -5473,6 +5661,11 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + follow-redirects@^1.0.0: version "1.13.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" @@ -5652,14 +5845,14 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-stream@^4.0.0: +get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" -get-stream@^5.0.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -5705,6 +5898,13 @@ glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" + integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== + dependencies: + ini "1.3.7" + global-modules@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" @@ -5775,6 +5975,23 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" @@ -5798,6 +6015,18 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== +handlebars@^4.7.7: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -5867,6 +6096,11 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -6039,6 +6273,11 @@ htmlparser2@^6.0.0: domutils "^2.4.4" entities "^2.0.0" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -6126,6 +6365,13 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" @@ -6150,6 +6396,11 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -6195,6 +6446,11 @@ import-from@^2.1.0: dependencies: resolve-from "^3.0.0" +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -6254,7 +6510,12 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.5: +ini@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + +ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -6494,6 +6755,14 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + is-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" @@ -6504,6 +6773,11 @@ is-negative-zero@^2.0.1: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + is-number-object@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" @@ -6550,6 +6824,11 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" +is-path-inside@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -6646,6 +6925,11 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -7231,6 +7515,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -7319,6 +7608,13 @@ jsprim@^1.2.2: array-includes "^3.1.2" object.assign "^4.1.2" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -7348,6 +7644,13 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -7358,6 +7661,11 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -7378,6 +7686,13 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7404,6 +7719,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +linkify-it@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" + integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== + dependencies: + uc.micro "^1.0.1" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -7539,6 +7861,17 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +logform@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2" + integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg== + dependencies: + colors "^1.2.1" + fast-safe-stringify "^2.0.4" + fecha "^4.2.0" + ms "^2.1.1" + triple-beam "^1.3.0" + loglevel@^1.6.8: version "1.7.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" @@ -7558,6 +7891,16 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7618,6 +7961,17 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it@^11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-11.0.1.tgz#b54f15ec2a2193efa66dda1eb4173baea08993d6" + integrity sha512-aU1TzmBKcWNNYvH9pjq6u92BML+Hz3h5S/QpfTFwiQF852pLT+9qHsrhM9JYipkOXZxGn+sGH8oyJE9FD9WezQ== + dependencies: + argparse "^1.0.7" + entities "~2.0.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -7637,6 +7991,11 @@ mdn-data@2.0.4: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -7745,6 +8104,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -7966,7 +8330,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -8050,6 +8414,29 @@ node-releases@^1.1.61, node-releases@^1.1.70: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== +nodemon@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32" + integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA== + dependencies: + chokidar "^3.2.2" + debug "^3.2.6" + ignore-by-default "^1.0.1" + minimatch "^3.0.4" + pstree.remy "^1.1.7" + semver "^5.7.1" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.3" + update-notifier "^4.1.0" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -8092,6 +8479,11 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -8254,6 +8646,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -8320,6 +8719,11 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-each-series@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" @@ -8401,6 +8805,16 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -9373,6 +9787,11 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + prettier-config@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-config/-/prettier-config-1.0.0.tgz#f8eed3916369b81678acaa33dc0298147d1958c8" @@ -9492,6 +9911,11 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +pstree.remy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -9544,6 +9968,13 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pupa@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -9647,6 +10078,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-app-polyfill@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz#a0bea50f078b8a082970a9d853dc34b6dcc6a3cf" @@ -9920,7 +10361,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -9933,7 +10374,7 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -10045,6 +10486,20 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + regjsgen@^0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" @@ -10221,6 +10676,13 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.1 is-core-module "^2.2.0" path-parse "^1.0.6" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -10360,7 +10822,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -10463,6 +10925,13 @@ selfsigned@^1.10.8: dependencies: node-forge "^0.10.0" +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -10478,7 +10947,7 @@ semver@7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -10490,6 +10959,13 @@ semver@^7.2.1, semver@^7.3.2: dependencies: lru-cache "^6.0.0" +semver@~7.3.2: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -10868,6 +11344,11 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= + stack-utils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" @@ -10957,7 +11438,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== @@ -11088,6 +11569,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + style-loader@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" @@ -11105,7 +11591,7 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -11204,6 +11690,11 @@ tempy@^0.3.0: type-fest "^0.3.1" unique-string "^1.0.0" +term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -11269,6 +11760,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + text-table@0.2.0, text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -11336,6 +11832,11 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -11366,6 +11867,13 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -11390,6 +11898,11 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +triple-beam@^1.2.0, triple-beam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" + integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -11523,6 +12036,16 @@ typescript@^4.1.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3" integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw== +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-js@^3.1.4: + version "3.13.7" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.7.tgz#25468a3b39b1c875df03f0937b2b7036a93f3fee" + integrity sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA== + unbox-primitive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" @@ -11543,6 +12066,13 @@ uncontrollable@^7.0.0: invariant "^2.2.4" react-lifecycles-compat "^3.0.4" +undefsafe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" + integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== + dependencies: + debug "^2.2.0" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -11607,6 +12137,13 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -11640,6 +12177,25 @@ upath@^1.1.1, upath@^1.1.2, upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-notifier@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -11661,6 +12217,13 @@ url-loader@4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + url-parse@^1.4.3, url-parse@^1.4.7: version "1.5.1" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" @@ -12033,11 +12596,46 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +winston-transport@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59" + integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw== + dependencies: + readable-stream "^2.3.7" + triple-beam "^1.2.0" + +winston@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170" + integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw== + dependencies: + "@dabh/diagnostics" "^2.0.2" + async "^3.1.0" + is-stream "^2.0.0" + logform "^2.2.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.4.0" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + workbox-background-sync@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-5.1.4.tgz#5ae0bbd455f4e9c319e8d827c055bb86c894fd12" @@ -12250,6 +12848,11 @@ ws@^7.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd" integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA== +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" From b59b6a17f4fa44df09a02efc899439e258ad11f7 Mon Sep 17 00:00:00 2001 From: lukas Date: Sun, 23 May 2021 14:21:44 +0200 Subject: [PATCH 2/3] add missing apidoc, dont show sendrequest form on docpage fix unit tests --- apiGo/api/ApiBase_test.go | 36 +++++++++++--------- apiGo/api/Settings.go | 70 +++++++++++++++++++++++++++++++++++++++ apiGo/api/TVShows.go | 48 +++++++++++++++++++++++++++ apiGo/api/Tags.go | 44 +++++++++++++++++++++++- package.json | 6 ++++ 5 files changed, 188 insertions(+), 16 deletions(-) diff --git a/apiGo/api/ApiBase_test.go b/apiGo/api/ApiBase_test.go index 9893c29..d692f01 100644 --- a/apiGo/api/ApiBase_test.go +++ b/apiGo/api/ApiBase_test.go @@ -5,13 +5,13 @@ import ( ) func cleanUp() { - handlers = nil + handlers = make(map[string]Handler) } func TestAddHandler(t *testing.T) { cleanUp() - AddHandler("test", ActorNode, nil, func() []byte { + AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { return nil }) if len(handlers) != 1 { @@ -23,13 +23,13 @@ func TestCallOfHandler(t *testing.T) { cleanUp() i := 0 - AddHandler("test", ActorNode, nil, func() []byte { + AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { i++ return nil }) // simulate the call of the api - handleAPICall("test", "", ActorNode) + handleAPICall("test", "", ActorNode, nil) if i != 1 { t.Errorf("Unexpected number of Lambda calls : %d/1", i) @@ -39,26 +39,32 @@ func TestCallOfHandler(t *testing.T) { func TestDecodingOfArguments(t *testing.T) { cleanUp() - var myvar struct { - Test string - TestInt int - } - AddHandler("test", ActorNode, &myvar, func() []byte { + AddHandler("test", ActorNode, func(info *HandlerInfo) []byte { + var args struct { + Test string + TestInt int + } + err := FillStruct(&args, info.Data) + if err != nil { + t.Errorf("Error parsing args: %s", err.Error()) + return nil + } + + if args.TestInt != 42 || args.Test != "myString" { + t.Errorf("Wrong parsing of argument parameters : %d/42 - %s/myString", args.TestInt, args.Test) + } + return nil }) // simulate the call of the api - handleAPICall("test", `{"Test":"myString","TestInt":42}`, ActorNode) - - if myvar.TestInt != 42 || myvar.Test != "myString" { - t.Errorf("Wrong parsing of argument parameters : %d/42 - %s/myString", myvar.TestInt, myvar.Test) - } + handleAPICall("test", `{"Test":"myString","TestInt":42}`, ActorNode, nil) } func TestNoHandlerCovers(t *testing.T) { cleanUp() - ret := handleAPICall("test", "", ActorNode) + ret := handleAPICall("test", "", ActorNode, nil) if ret != nil { t.Error("Expect nil return within unhandled api action") diff --git a/apiGo/api/Settings.go b/apiGo/api/Settings.go index ddb8c13..59a1fd7 100644 --- a/apiGo/api/Settings.go +++ b/apiGo/api/Settings.go @@ -18,11 +18,42 @@ func AddSettingsHandlers() { } func getSettingsFromDB() { + /** + * @api {post} /api/settings [loadGeneralSettings] + * @apiDescription Get the settings object + * @apiName loadGeneralSettings + * @apiGroup Settings + * + * @apiSuccess {Object} Settings Settings object + * @apiSuccess {string} Settings.VideoPath webserver path to the videos + * @apiSuccess {string} Settings.EpisodePath webserver path to the tvshows + * @apiSuccess {string} Settings.MediacenterName overall name of the mediacenter + * @apiSuccess {string} Settings.Password new server password (-1 if no password set) + * @apiSuccess {bool} Settings.TMDBGrabbing TMDB grabbing support to grab tag info and thumbnails + * @apiSuccess {bool} Settings.DarkMode Darkmode enabled? + * @apiSuccess {uint32} Settings.VideoNr total number of videos + * @apiSuccess {float32} Settings.DBSize total size of database + * @apiSuccess {uint32} Settings.DifferentTags number of different tags available + * @apiSuccess {uint32} Settings.TagsAdded number of different tags added to videos + * @apiSuccess {string} Settings.PathPrefix + */ AddHandler("loadGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { result := database.GetSettings() return jsonify(result) }) + /** + * @api {post} /api/settings [loadInitialData] + * @apiDescription load startdata to display on homepage + * @apiName loadInitialData + * @apiGroup Settings + * + * @apiSuccess {string} VideoPath webserver path to the videos + * @apiSuccess {string} EpisodePath webserver path to the tvshows + * @apiSuccess {string} MediacenterName overall name of the mediacenter + * @apiSuccess {string} Pasword new server password (-1 if no password set) + * @apiSuccess {bool} DarkMode Darkmode enabled? + */ AddHandler("loadInitialData", SettingsNode, func(info *HandlerInfo) []byte { sett := settings.LoadSettings() @@ -54,7 +85,24 @@ func getSettingsFromDB() { } func saveSettingsToDB() { + /** + * @api {post} /api/settings [saveGeneralSettings] + * @apiDescription Save the global settings provided + * @apiName saveGeneralSettings + * @apiGroup Settings + * + * @apiParam {Object} Settings Settings object + * @apiParam {string} Settings.VideoPath webserver path to the videos + * @apiParam {string} Settings.EpisodePath webserver path to the tvshows + * @apiParam {string} Settings.MediacenterName overall name of the mediacenter + * @apiParam {string} Settings.Password new server password (-1 if no password set) + * @apiParam {bool} Settings.TMDBGrabbing TMDB grabbing support to grab tag info and thumbnails + * @apiParam {bool} Settings.DarkMode Darkmode enabled? + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("saveGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte { + // todo correct type here! var args struct { Settings types.SettingsType } @@ -80,16 +128,38 @@ func saveSettingsToDB() { // methods for handling reindexing and cleanup of db gravity func reIndexHandling() { + /** + * @api {post} /api/settings [startReindex] + * @apiDescription Start Database video reindex Job + * @apiName startReindex + * @apiGroup Settings + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("startReindex", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartReindex() return database.ManualSuccessResponse(nil) }) + /** + * @api {post} /api/settings [startTVShowReindex] + * @apiDescription Start Database TVShow reindex job + * @apiName startTVShowReindex + * @apiGroup Settings + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("startTVShowReindex", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartTVShowReindex() return database.ManualSuccessResponse(nil) }) + /** + * @api {post} /api/settings [cleanupGravity] + * @apiDescription Start Database cleanup job + * @apiName cleanupGravity + * @apiGroup Settings + */ AddHandler("cleanupGravity", SettingsNode, func(info *HandlerInfo) []byte { videoparser.StartCleanup() return nil diff --git a/apiGo/api/TVShows.go b/apiGo/api/TVShows.go index 99fea75..20dae62 100644 --- a/apiGo/api/TVShows.go +++ b/apiGo/api/TVShows.go @@ -6,12 +6,36 @@ import ( ) func AddTvshowHandlers() { + /** + * @api {post} /api/tvshow [getTVShows] + * @apiDescription get all available tv shows + * @apiName getTVShows + * @apiGroup TVshow + * + * @apiSuccess {Object[]} . + * @apiSuccess {uint32} .Id tvshow id + * @apiSuccess {string} .Name tvshow name + */ AddHandler("getTVShows", TVShowNode, func(info *HandlerInfo) []byte { query := "SELECT id, name FROM tvshow" rows := database.Query(query) return jsonify(readTVshowsFromResultset(rows)) }) + /** + * @api {post} /api/tvshow [getEpisodes] + * @apiDescription get all Episodes of a TVShow + * @apiName getEpisodes + * @apiGroup TVshow + * + * @apiParam {uint32} ShowID id of tvshow to get episodes from + * + * @apiSuccess {Object[]} . + * @apiSuccess {uint32} .ID episode id + * @apiSuccess {string} .Name episode name + * @apiSuccess {uint8} .Season Season number + * @apiSuccess {uint8} .Episode Episode number + */ AddHandler("getEpisodes", TVShowNode, func(info *HandlerInfo) []byte { var args struct { ShowID uint32 @@ -46,6 +70,20 @@ func AddTvshowHandlers() { return jsonify(episodes) }) + /** + * @api {post} /api/tvshow [loadEpisode] + * @apiDescription load all info of episode + * @apiName loadEpisode + * @apiGroup TVshow + * + * @apiParam {uint32} ID id of episode + * + * @apiSuccess {uint32} TVShowID episode id + * @apiSuccess {string} Name episode name + * @apiSuccess {uint8} Season Season number + * @apiSuccess {uint8} Episode Episode number + * @apiSuccess {string} Path webserver path of video file + */ AddHandler("loadEpisode", TVShowNode, func(info *HandlerInfo) []byte { var args struct { ID uint32 @@ -83,6 +121,16 @@ WHERE tvshow_episodes.id=%d`, args.ID) return jsonify(ret) }) + /** + * @api {post} /api/tvshow [readThumbnail] + * @apiDescription Load Thubnail of specific episode + * @apiName readThumbnail + * @apiGroup TVshow + * + * @apiParam {int} Id id of episode to load thumbnail + * + * @apiSuccess {string} . Base64 encoded Thubnail + */ AddHandler("readThumbnail", TVShowNode, func(info *HandlerInfo) []byte { var args struct { Id int diff --git a/apiGo/api/Tags.go b/apiGo/api/Tags.go index 71bc977..13a6a54 100644 --- a/apiGo/api/Tags.go +++ b/apiGo/api/Tags.go @@ -13,6 +13,17 @@ func AddTagHandlers() { } func deleteFromDB() { + /** + * @api {post} /api/tags [deleteTag] + * @apiDescription Start Database video reindex Job + * @apiName deleteTag + * @apiGroup Tags + * + * @apiParam {bool} [Force] force delete tag with its constraints + * @apiParam {int} TagId id of tag to delete + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("deleteTag", TagNode, func(info *HandlerInfo) []byte { var args struct { TagId int @@ -44,7 +55,7 @@ func deleteFromDB() { // check with regex if its the key constraint error r := regexp.MustCompile("^.*a foreign key constraint fails.*$") if r.MatchString(err.Error()) { - return []byte(`{"result":"not empty tag"}`) + return database.ManualSuccessResponse(fmt.Errorf("not empty tag")) } else { return database.ManualSuccessResponse(err) } @@ -53,6 +64,16 @@ func deleteFromDB() { } func getFromDB() { + /** + * @api {post} /api/tags [getAllTags] + * @apiDescription get all available Tags + * @apiName getAllTags + * @apiGroup Tags + * + * @apiSuccess {Object[]} array of tag objects + * @apiSuccess {uint32} TagId + * @apiSuccess {string} TagName name of the Tag + */ AddHandler("getAllTags", TagNode, func(info *HandlerInfo) []byte { query := "SELECT tag_id,tag_name from tags" return jsonify(readTagsFromResultset(database.Query(query))) @@ -60,6 +81,16 @@ func getFromDB() { } func addToDB() { + /** + * @api {post} /api/tags [createTag] + * @apiDescription create a new tag + * @apiName createTag + * @apiGroup Tags + * + * @apiParam {string} TagName name of the tag + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("createTag", TagNode, func(info *HandlerInfo) []byte { var args struct { TagName string @@ -73,6 +104,17 @@ func addToDB() { return database.SuccessQuery(query, args.TagName) }) + /** + * @api {post} /api/tags [addTag] + * @apiDescription Add new tag to video + * @apiName addTag + * @apiGroup Tags + * + * @apiParam {int} TagId Tag id to add to video + * @apiParam {int} MovieId Video Id of video to add tag to + * + * @apiSuccess {string} result 'success' if successfully or error message if not + */ AddHandler("addTag", TagNode, func(info *HandlerInfo) []byte { var args struct { MovieId int diff --git a/package.json b/package.json index 11f3e16..23e5ca0 100644 --- a/package.json +++ b/package.json @@ -79,5 +79,11 @@ "prettier-config": "^1.0.0", "react-scripts": "4.0.3", "apidoc": "^0.28.1" + }, + "apidoc":{ + "name": "OpenMediaCenter", + "description": "API Documentation of OpenMediaCenter", + "title": "OpenMediaCenter Doc", + "sampleUrl": null } } From e47b3eecf25aacf2f5a36f81530bb3ed2eca792c Mon Sep 17 00:00:00 2001 From: lukas Date: Tue, 25 May 2021 22:34:29 +0200 Subject: [PATCH 3/3] fix api typo --- src/pages/HomePage/SearchHandling.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/HomePage/SearchHandling.tsx b/src/pages/HomePage/SearchHandling.tsx index 7064c23..75b114c 100644 --- a/src/pages/HomePage/SearchHandling.tsx +++ b/src/pages/HomePage/SearchHandling.tsx @@ -57,7 +57,7 @@ export class SearchHandling extends React.Component { * @param keyword The keyword to search for */ searchVideos(keyword: string): void { - callAPI(APINode.Video, {action: 'getSearchKeyWord', keyword: keyword}, (result: VideoTypes.VideoUnloadedType[]) => { + callAPI(APINode.Video, {action: 'getSearchKeyWord', KeyWord: keyword}, (result: VideoTypes.VideoUnloadedType[]) => { this.setState({ data: result });