From cbb804e67173df93f3604db76547503c0832ba44 Mon Sep 17 00:00:00 2001
From: Nityanand Rai <107465508+Nityanand13@users.noreply.github.com>
Date: Tue, 31 Jan 2023 15:02:00 +0530
Subject: [PATCH 01/18] [MI-2502]:Added custom type for webhook post in order
to comment, edit and close issues (#13)
* [MI-2502]:Added custom type for webhook post in order to comment, edit and close issues
* [MI-2502]: Added EOF
* [MI-2502]: Fixed lint errors
* [MI-2502]: Review fixes done
1. Improved code quality
2. Made few contants
* [MI-2502]: Review fixes done
1. Changed few files to .tsx
2. Improved code quality
* [MI-2502]: Review fixes done
1. Improved code quality
2. Made a constant
* [MI-2502]: Review fixes done
1. Improved code readability
* [MI-2502]: Review fixes done
1. Made a package dor constants
2. Made a package for struct
3. Improved code redability
* [MI-2502]: Review fixes done
1. Improved code quality
2. Fixed the issue that I was facing while creating issue or attaching a comment to the issue.
3. Changed few file names
* [MI-2502]: Review fixes done
1. Changed the names of few functions
2. Improved code quality
* [MI-2502]: Review fixes done
1.Improved code readability
* [MI-2502]: Review fixes done
1. Improved code readability
* [MI-2502]: Review done
1. Improved code quality
* [MI-2502]: Review fixes done
1. Improved code quality
---
go.mod | 2 +-
go.sum | 6 +-
server/client/client.go | 2 +-
server/constants/constants.go | 46 ++
server/plugin/api.go | 689 +++++++++++-------
server/plugin/api_test.go | 6 +-
server/plugin/cluster.go | 2 +-
server/plugin/command.go | 40 +-
server/plugin/flows.go | 2 +-
server/plugin/mm_34646_token_refresh.go | 11 +-
server/plugin/permalinks.go | 2 +-
server/plugin/permalinks_test.go | 2 +-
server/plugin/plugin.go | 55 +-
server/plugin/subscriptions.go | 2 +-
server/plugin/template_test.go | 2 +-
server/plugin/utils.go | 141 ++++
server/plugin/webhook.go | 114 +--
server/serializer/error.go | 11 +
server/serializer/issue.go | 52 ++
server/serializer/notification.go | 8 +
server/serializer/pr.go | 12 +
server/serializer/repo.go | 8 +
server/serializer/user.go | 62 ++
webapp/src/action_types/index.js | 8 +-
webapp/src/actions/index.js | 129 +++-
webapp/src/client/client.js | 20 +
webapp/src/components/github_issue/index.tsx | 118 +++
.../attach_comment_to_issue.jsx | 48 +-
.../modals/attach_comment_to_issue/index.js | 6 +-
.../modals/close_reopen_issue/index.tsx | 181 +++++
.../components/modals/create_issue/index.js | 30 -
.../create_update_issue.jsx} | 131 +++-
.../modals/create_update_issue/index.js | 31 +
.../post_menu_action/create_issue/index.js | 4 +-
.../sidebar_buttons/sidebar_buttons.jsx | 48 +-
.../components/sidebar_right/github_items.tsx | 102 ++-
webapp/src/index.js | 15 +-
webapp/src/reducers/index.js | 56 +-
webapp/src/selectors.js | 13 +
webapp/src/websocket/index.js | 26 +-
40 files changed, 1691 insertions(+), 552 deletions(-)
create mode 100644 server/constants/constants.go
create mode 100644 server/serializer/error.go
create mode 100644 server/serializer/issue.go
create mode 100644 server/serializer/notification.go
create mode 100644 server/serializer/pr.go
create mode 100644 server/serializer/repo.go
create mode 100644 server/serializer/user.go
create mode 100644 webapp/src/components/github_issue/index.tsx
create mode 100644 webapp/src/components/modals/close_reopen_issue/index.tsx
delete mode 100644 webapp/src/components/modals/create_issue/index.js
rename webapp/src/components/modals/{create_issue/create_issue.jsx => create_update_issue/create_update_issue.jsx} (63%)
create mode 100644 webapp/src/components/modals/create_update_issue/index.js
diff --git a/go.mod b/go.mod
index 148a14880..156a66cac 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.16
require (
github.com/Masterminds/sprig/v3 v3.2.2
- github.com/google/go-github/v41 v41.0.0
+ github.com/google/go-github/v48 v48.2.0
github.com/gorilla/mux v1.8.0
github.com/mattermost/mattermost-plugin-api v0.0.27
github.com/mattermost/mattermost-server/v6 v6.5.2
diff --git a/go.sum b/go.sum
index b69878ae2..76bea24aa 100644
--- a/go.sum
+++ b/go.sum
@@ -635,13 +635,16 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v35 v35.2.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs=
github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg=
github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg=
+github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE=
+github.com/google/go-github/v48 v48.2.0/go.mod h1:dDlehKBDo850ZPvCTK0sEqTCVWcrGl2LcDiajkYi89Y=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
@@ -1941,7 +1944,6 @@ golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
diff --git a/server/client/client.go b/server/client/client.go
index 4320c6542..e79e046fa 100644
--- a/server/client/client.go
+++ b/server/client/client.go
@@ -7,7 +7,7 @@ import (
"net/url"
"strings"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/pkg/errors"
"golang.org/x/oauth2"
diff --git a/server/constants/constants.go b/server/constants/constants.go
new file mode 100644
index 000000000..6e832b9be
--- /dev/null
+++ b/server/constants/constants.go
@@ -0,0 +1,46 @@
+package constants
+
+import "time"
+
+const (
+ APIErrorIDNotConnected = "not_connected"
+ // TokenTTL is the OAuth token expiry duration in seconds
+ TokenTTL = 600
+
+ RequestTimeout = 30 * time.Second
+ OauthCompleteTimeout = 2 * time.Minute
+ HeaderMattermostUserID = "Mattermost-User-ID"
+ OwnerQueryParam = "owner"
+ RepoQueryParam = "repo"
+ NumberQueryParam = "number"
+ PostIdQueryParam = "postId"
+
+ IssueStatus = "status"
+ AssigneesForProps = "assignees"
+ LabelsForProps = "labels"
+ DescriptionForProps = "description"
+ TitleForProps = "title"
+ IssueNumberForProps = "issue_number"
+ IssueUrlForProps = "issue_url"
+ RepoOwnerForProps = "repo_owner"
+ RepoNameForProps = "repo_name"
+
+ Close = "Close"
+ Reopen = "Reopen"
+
+ IssueCompleted = "completed"
+ IssueNotPlanned = "not_planned"
+ IssueClose = "closed"
+ IssueOpen = "open"
+
+ //Actions of webhook events
+ ActionOpened = "opened"
+ ActionClosed = "closed"
+ ActionReopened = "reopened"
+ ActionSubmitted = "submitted"
+ ActionLabeled = "labeled"
+ ActionAssigned = "assigned"
+ ActionCreated = "created"
+ ActionDeleted = "deleted"
+ ActionEdited = "edited"
+)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 3ef3eda4f..4a73520c7 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -11,67 +11,24 @@ import (
"sync"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"golang.org/x/oauth2"
"github.com/mattermost/mattermost-plugin-api/experimental/bot/logger"
"github.com/mattermost/mattermost-plugin-api/experimental/flow"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
)
-const (
- apiErrorIDNotConnected = "not_connected"
- // TokenTTL is the OAuth token expiry duration in seconds
- TokenTTL = 10 * 60
-
- requestTimeout = 30 * time.Second
- oauthCompleteTimeout = 2 * time.Minute
-)
-
-type OAuthState struct {
- UserID string `json:"user_id"`
- Token string `json:"token"`
- PrivateAllowed bool `json:"private_allowed"`
-}
-
-type APIErrorResponse struct {
- ID string `json:"id"`
- Message string `json:"message"`
- StatusCode int `json:"status_code"`
-}
-
-func (e *APIErrorResponse) Error() string {
- return e.Message
-}
-
-type PRDetails struct {
- URL string `json:"url"`
- Number int `json:"number"`
- Status string `json:"status"`
- Mergeable bool `json:"mergeable"`
- RequestedReviewers []*string `json:"requestedReviewers"`
- Reviews []*github.PullRequestReview `json:"reviews"`
-}
-
-type Context struct {
- Ctx context.Context
- UserID string
- Log logger.Logger
-}
-
-// HTTPHandlerFuncWithContext is http.HandleFunc but with a Context attached
-type HTTPHandlerFuncWithContext func(c *Context, w http.ResponseWriter, r *http.Request)
-
-type UserContext struct {
- Context
- GHInfo *GitHubUserInfo
-}
-
// HTTPHandlerFuncWithUserContext is http.HandleFunc but with a UserContext attached
-type HTTPHandlerFuncWithUserContext func(c *UserContext, w http.ResponseWriter, r *http.Request)
+type HTTPHandlerFuncWithUserContext func(c *serializer.UserContext, w http.ResponseWriter, r *http.Request)
+
+// HTTPHandlerFuncWithContext is http.HandleFunc but with a .ontext attached
+type HTTPHandlerFuncWithContext func(c *serializer.Context, w http.ResponseWriter, r *http.Request)
// ResponseType indicates type of response returned by api
type ResponseType string
@@ -90,15 +47,14 @@ func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
w.WriteHeader(http.StatusInternalServerError)
return
}
- _, err = w.Write(b)
- if err != nil {
+ if _, err = w.Write(b); err != nil {
p.API.LogWarn("Failed to write JSON response", "error", err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
}
}
-func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *APIErrorResponse) {
+func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *serializer.APIErrorResponse) {
b, err := json.Marshal(apiErr)
if err != nil {
p.API.LogWarn("Failed to marshal API error", "error", err.Error())
@@ -108,8 +64,7 @@ func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *APIErrorResponse)
w.WriteHeader(apiErr.StatusCode)
- _, err = w.Write(b)
- if err != nil {
+ if _, err = w.Write(b); err != nil {
p.API.LogWarn("Failed to write JSON response", "error", err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
@@ -139,6 +94,11 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc("/searchissues", p.checkAuth(p.attachUserContext(p.searchIssues), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/yourassignments", p.checkAuth(p.attachUserContext(p.getYourAssignments), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/createissue", p.checkAuth(p.attachUserContext(p.createIssue), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc("/closeorreopenissue", p.checkAuth(p.attachUserContext(p.closeOrReopenIssue), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc("/updateissue", p.checkAuth(p.attachUserContext(p.updateIssue), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc("/editissuemodal", p.checkAuth(p.attachUserContext(p.openIssueEditModal), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc("/closereopenissuemodal", p.checkAuth(p.attachUserContext(p.openCloseOrReopenIssueModal), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc("/attachcommentissuemodal", p.checkAuth(p.attachUserContext(p.openAttachCommentIssueModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/createissuecomment", p.checkAuth(p.attachUserContext(p.createIssueComment), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/mentions", p.checkAuth(p.attachUserContext(p.getMentions), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/unreads", p.checkAuth(p.attachUserContext(p.getUnreads), ResponseTypePlain)).Methods(http.MethodGet)
@@ -184,11 +144,11 @@ func (p *Plugin) checkConfigured(next http.Handler) http.Handler {
func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- userID := r.Header.Get("Mattermost-User-ID")
+ userID := r.Header.Get(constants.HeaderMattermostUserID)
if userID == "" {
switch responseType {
case ResponseTypeJSON:
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized})
case ResponseTypePlain:
http.Error(w, "Not authorized", http.StatusUnauthorized)
default:
@@ -201,16 +161,16 @@ func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType)
}
}
-func (p *Plugin) createContext(_ http.ResponseWriter, r *http.Request) (*Context, context.CancelFunc) {
- userID := r.Header.Get("Mattermost-User-ID")
+func (p *Plugin) createContext(_ http.ResponseWriter, r *http.Request) (*serializer.Context, context.CancelFunc) {
+ userID := r.Header.Get(constants.HeaderMattermostUserID)
logger := logger.New(p.API).With(logger.LogContext{
"userid": userID,
})
- ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
- context := &Context{
+ context := &serializer.Context{
Ctx: ctx,
UserID: userID,
Log: logger,
@@ -243,7 +203,7 @@ func (p *Plugin) attachUserContext(handler HTTPHandlerFuncWithUserContext) http.
"github username": info.GitHubUsername,
})
- userContext := &UserContext{
+ userContext := &serializer.UserContext{
Context: *context,
GHInfo: info,
}
@@ -271,7 +231,7 @@ func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Req
p.router.ServeHTTP(w, r)
}
-func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) connectUserToGitHub(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
privateAllowed := false
pValBool, _ := strconv.ParseBool(r.URL.Query().Get("private"))
if pValBool {
@@ -280,7 +240,7 @@ func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http.
conf := p.getOAuthConfig(privateAllowed)
- state := OAuthState{
+ state := serializer.OAuthState{
UserID: c.UserID,
Token: model.NewId()[:15],
PrivateAllowed: privateAllowed,
@@ -292,7 +252,7 @@ func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http.
return
}
- appErr := p.API.KVSetWithExpiry(githubOauthKey+state.Token, stateBytes, TokenTTL)
+ appErr := p.API.KVSetWithExpiry(fmt.Sprintf("%s%s", githubOauthKey, state.Token), stateBytes, constants.TokenTTL)
if appErr != nil {
http.Error(w, "error setting stored state", http.StatusBadRequest)
return
@@ -332,7 +292,7 @@ func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http.
http.Redirect(w, r, url, http.StatusFound)
}
-func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
var rErr error
defer func() {
p.oauthBroker.publishOAuthComplete(c.UserID, rErr, false)
@@ -347,7 +307,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
stateToken := r.URL.Query().Get("state")
- storedState, appErr := p.API.KVGet(githubOauthKey + stateToken)
+ storedState, appErr := p.API.KVGet(fmt.Sprintf("%s%s", githubOauthKey, stateToken))
if appErr != nil {
c.Log.Warnf("Failed to get state token", "error", appErr.Error())
@@ -355,7 +315,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
http.Error(w, rErr.Error(), http.StatusBadRequest)
return
}
- var state OAuthState
+ var state serializer.OAuthState
if err := json.Unmarshal(storedState, &state); err != nil {
rErr = errors.Wrap(err, "json unmarshal failed")
@@ -363,10 +323,8 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
return
}
- appErr = p.API.KVDelete(githubOauthKey + stateToken)
- if appErr != nil {
+ if appErr = p.API.KVDelete(fmt.Sprintf("%s%s", githubOauthKey, stateToken)); appErr != nil {
c.Log.WithError(appErr).Warnf("Failed to delete state token")
-
rErr = errors.Wrap(appErr, "error deleting stored state")
http.Error(w, rErr.Error(), http.StatusBadRequest)
return
@@ -386,7 +344,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
conf := p.getOAuthConfig(state.PrivateAllowed)
- ctx, cancel := context.WithTimeout(context.Background(), oauthCompleteTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), constants.OauthCompleteTimeout)
defer cancel()
tok, err := conf.Exchange(ctx, code)
@@ -408,12 +366,12 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
return
}
- userInfo := &GitHubUserInfo{
+ userInfo := &serializer.GitHubUserInfo{
UserID: state.UserID,
Token: tok,
GitHubUsername: gitUser.GetLogin(),
LastToDoPostAt: model.GetMillis(),
- Settings: &UserSettings{
+ Settings: &serializer.UserSettings{
SidebarButtons: settingButtonsTeam,
DailyReminder: true,
Notifications: true,
@@ -442,8 +400,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
}
if stepName == stepOAuthConnect {
- err = flow.Go(stepWebhookQuestion)
- if err != nil {
+ if err = flow.Go(stepWebhookQuestion); err != nil {
c.Log.WithError(err).Warnf("Failed go to next step")
}
} else {
@@ -508,35 +465,30 @@ func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter,
`
w.Header().Set("Content-Type", "text/html")
- _, err = w.Write([]byte(html))
- if err != nil {
+ if _, err = w.Write([]byte(html)); err != nil {
c.Log.WithError(err).Warnf("Failed to write HTML response")
w.WriteHeader(http.StatusInternalServerError)
return
}
}
-func (p *Plugin) getGitHubUser(c *Context, w http.ResponseWriter, r *http.Request) {
- type GitHubUserRequest struct {
- UserID string `json:"user_id"`
- }
-
- req := &GitHubUserRequest{}
+func (p *Plugin) getGitHubUser(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.GitHubUserRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding GitHubUserRequest from JSON body")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if req.UserID == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object with a non-blank user_id field.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a JSON object with a non-blank user_id field.", StatusCode: http.StatusBadRequest})
return
}
userInfo, apiErr := p.getGitHubUserInfo(req.UserID)
if apiErr != nil {
- if apiErr.ID == apiErrorIDNotConnected {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
+ if apiErr.ID == constants.APIErrorIDNotConnected {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
} else {
p.writeAPIError(w, apiErr)
}
@@ -544,32 +496,17 @@ func (p *Plugin) getGitHubUser(c *Context, w http.ResponseWriter, r *http.Reques
}
if userInfo == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
return
}
- type GitHubUserResponse struct {
- Username string `json:"username"`
- }
-
- resp := &GitHubUserResponse{Username: userInfo.GitHubUsername}
+ resp := &serializer.GitHubUserResponse{Username: userInfo.GitHubUsername}
p.writeJSON(w, resp)
}
-func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getConnected(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
-
- type ConnectedResponse struct {
- Connected bool `json:"connected"`
- GitHubUsername string `json:"github_username"`
- GitHubClientID string `json:"github_client_id"`
- EnterpriseBaseURL string `json:"enterprise_base_url,omitempty"`
- Organization string `json:"organization"`
- UserSettings *UserSettings `json:"user_settings"`
- ClientConfiguration map[string]interface{} `json:"configuration"`
- }
-
- resp := &ConnectedResponse{
+ resp := &serializer.ConnectedResponse{
Connected: false,
EnterpriseBaseURL: config.EnterpriseBaseURL,
Organization: config.GitHubOrg,
@@ -616,7 +553,7 @@ func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request
}
}
- privateRepoStoreKey := info.UserID + githubPrivateRepoKey
+ privateRepoStoreKey := fmt.Sprintf("%s%s", info.UserID, githubPrivateRepoKey)
if config.EnablePrivateRepo && !info.AllowedPrivateRepos {
val, err := p.API.KVGet(privateRepoStoreKey)
if err != nil {
@@ -632,8 +569,7 @@ func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request
} else {
p.CreateBotDMPost(info.UserID, fmt.Sprintf(message, "`/github connect private`."), "")
}
- err := p.API.KVSet(privateRepoStoreKey, []byte("1"))
- if err != nil {
+ if err := p.API.KVSet(privateRepoStoreKey, []byte("1")); err != nil {
c.Log.WithError(err).Warnf("Unable to set private repo key value")
}
}
@@ -642,7 +578,7 @@ func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request
p.writeJSON(w, resp)
}
-func (p *Plugin) getMentions(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getMentions(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -658,7 +594,7 @@ func (p *Plugin) getMentions(c *UserContext, w http.ResponseWriter, r *http.Requ
p.writeJSON(w, result.Issues)
}
-func (p *Plugin) getUnreads(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getUnreads(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
notifications, _, err := githubClient.Activity.ListNotifications(c.Ctx, &github.NotificationListOptions{})
@@ -667,13 +603,7 @@ func (p *Plugin) getUnreads(c *UserContext, w http.ResponseWriter, r *http.Reque
return
}
- type filteredNotification struct {
- github.Notification
-
- HTMLUrl string `json:"html_url"`
- }
-
- filteredNotifications := []*filteredNotification{}
+ filteredNotifications := []*serializer.FilteredNotification{}
for _, n := range notifications {
if n.GetReason() == notificationReasonSubscribed {
continue
@@ -691,7 +621,7 @@ func (p *Plugin) getUnreads(c *UserContext, w http.ResponseWriter, r *http.Reque
subjectURL = n.GetSubject().GetLatestCommentURL()
}
- filteredNotifications = append(filteredNotifications, &filteredNotification{
+ filteredNotifications = append(filteredNotifications, &serializer.FilteredNotification{
Notification: *n,
HTMLUrl: fixGithubNotificationSubjectURL(subjectURL, issueNum),
})
@@ -700,7 +630,7 @@ func (p *Plugin) getUnreads(c *UserContext, w http.ResponseWriter, r *http.Reque
p.writeJSON(w, filteredNotifications)
}
-func (p *Plugin) getReviews(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getReviews(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -716,7 +646,7 @@ func (p *Plugin) getReviews(c *UserContext, w http.ResponseWriter, r *http.Reque
p.writeJSON(w, result.Issues)
}
-func (p *Plugin) getYourPrs(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getYourPrs(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -732,17 +662,17 @@ func (p *Plugin) getYourPrs(c *UserContext, w http.ResponseWriter, r *http.Reque
p.writeJSON(w, result.Issues)
}
-func (p *Plugin) getPrsDetails(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getPrsDetails(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- var prList []*PRDetails
+ var prList []*serializer.PRDetails
if err := json.NewDecoder(r.Body).Decode(&prList); err != nil {
c.Log.WithError(err).Warnf("Error decoding PRDetails JSON body")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
- prDetails := make([]*PRDetails, len(prList))
+ prDetails := make([]*serializer.PRDetails, len(prList))
var wg sync.WaitGroup
for i, pr := range prList {
i := i
@@ -760,7 +690,7 @@ func (p *Plugin) getPrsDetails(c *UserContext, w http.ResponseWriter, r *http.Re
p.writeJSON(w, prDetails)
}
-func (p *Plugin) fetchPRDetails(c *UserContext, client *github.Client, prURL string, prNumber int) *PRDetails {
+func (p *Plugin) fetchPRDetails(c *serializer.UserContext, client *github.Client, prURL string, prNumber int) *serializer.PRDetails {
var status string
var mergeable bool
// Initialize to a non-nil slice to simplify JSON handling semantics
@@ -807,7 +737,7 @@ func (p *Plugin) fetchPRDetails(c *UserContext, client *github.Client, prURL str
}()
wg.Wait()
- return &PRDetails{
+ return &serializer.PRDetails{
URL: prURL,
Number: prNumber,
Status: status,
@@ -817,7 +747,7 @@ func (p *Plugin) fetchPRDetails(c *UserContext, client *github.Client, prURL str
}
}
-func fetchReviews(c *UserContext, client *github.Client, repoOwner string, repoName string, number int) ([]*github.PullRequestReview, error) {
+func fetchReviews(c *serializer.UserContext, client *github.Client, repoOwner string, repoName string, number int) ([]*github.PullRequestReview, error) {
reviewsList, _, err := client.PullRequests.ListReviews(c.Ctx, repoOwner, repoName, number, nil)
if err != nil {
@@ -832,7 +762,7 @@ func getRepoOwnerAndNameFromURL(url string) (string, string) {
return splitted[len(splitted)-2], splitted[len(splitted)-1]
}
-func (p *Plugin) searchIssues(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) searchIssues(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -873,44 +803,36 @@ func getFailReason(code int, repo string, username string) string {
return cause
}
-func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *http.Request) {
- type CreateIssueCommentRequest struct {
- PostID string `json:"post_id"`
- Owner string `json:"owner"`
- Repo string `json:"repo"`
- Number int `json:"number"`
- Comment string `json:"comment"`
- }
-
- req := &CreateIssueCommentRequest{}
+func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.CreateIssueCommentRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding CreateIssueCommentRequest JSON body")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if req.PostID == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid post id", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid post id", StatusCode: http.StatusBadRequest})
return
}
if req.Owner == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repo owner.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository owner.", StatusCode: http.StatusBadRequest})
return
}
if req.Repo == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repo.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository.", StatusCode: http.StatusBadRequest})
return
}
if req.Number == 0 {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue number.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue number.", StatusCode: http.StatusBadRequest})
return
}
if req.Comment == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid non empty comment.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid non empty comment.", StatusCode: http.StatusBadRequest})
return
}
@@ -918,17 +840,17 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
post, appErr := p.API.GetPost(req.PostID)
if appErr != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + req.PostID, StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + req.PostID + ": not found", StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
return
}
commentUsername, err := p.getUsername(post.UserId)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
@@ -936,18 +858,20 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
permalink := p.getPermaLink(req.PostID)
permalinkMessage := fmt.Sprintf("*@%s attached a* [message](%s) *from %s*\n\n", currentUsername, permalink, commentUsername)
- req.Comment = permalinkMessage + req.Comment
+ if req.ShowAttachedMessage {
+ req.Comment = fmt.Sprintf("%s%s", permalinkMessage, req.Comment)
+ }
comment := &github.IssueComment{
Body: &req.Comment,
}
result, rawResponse, err := githubClient.Issues.CreateComment(c.Ctx, req.Owner, req.Repo, req.Number, comment)
if err != nil {
- statusCode := 500
+ statusCode := http.StatusInternalServerError
if rawResponse != nil {
statusCode = rawResponse.StatusCode
}
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create an issue comment: " + getFailReason(statusCode, req.Repo, currentUsername), StatusCode: statusCode})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, req.Repo, currentUsername)), StatusCode: statusCode})
return
}
@@ -965,16 +889,15 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
UserId: c.UserID,
}
- _, appErr = p.API.CreatePost(reply)
- if appErr != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create notification post " + req.PostID, StatusCode: http.StatusInternalServerError})
+ if _, appErr = p.API.CreatePost(reply); appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
p.writeJSON(w, result)
}
-func (p *Plugin) getYourAssignments(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getYourAssignments(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -990,14 +913,14 @@ func (p *Plugin) getYourAssignments(c *UserContext, w http.ResponseWriter, r *ht
p.writeJSON(w, result.Issues)
}
-func (p *Plugin) postToDo(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) postToDo(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
username := c.GHInfo.GitHubUsername
text, err := p.GetToDo(c.Ctx, username, githubClient)
if err != nil {
c.Log.WithError(err).Warnf("Failed to get Todos")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Encountered an error getting the to do items.", StatusCode: http.StatusUnauthorized})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Encountered an error getting the to do items.", StatusCode: http.StatusUnauthorized})
return
}
@@ -1010,8 +933,8 @@ func (p *Plugin) postToDo(c *UserContext, w http.ResponseWriter, r *http.Request
p.writeJSON(w, resp)
}
-func (p *Plugin) updateSettings(c *UserContext, w http.ResponseWriter, r *http.Request) {
- var settings *UserSettings
+func (p *Plugin) updateSettings(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ var settings *serializer.UserSettings
if err := json.NewDecoder(r.Body).Decode(&settings); err != nil {
c.Log.WithError(err).Warnf("Error decoding settings from JSON body")
http.Error(w, "Invalid request body", http.StatusBadRequest)
@@ -1035,29 +958,181 @@ func (p *Plugin) updateSettings(c *UserContext, w http.ResponseWriter, r *http.R
p.writeJSON(w, info.Settings)
}
-func (p *Plugin) getIssueByNumber(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue("owner")
- repo := r.FormValue("repo")
- number := r.FormValue("number")
- numberInt, err := strconv.Atoi(number)
+func (p *Plugin) openAttachCommentIssueModal(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.OpenCreateCommentOrEditIssueModalRequestBody{}
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ userID := r.Header.Get(constants.HeaderMattermostUserID)
+ post, appErr := p.API.GetPost(req.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+
+ p.API.PublishWebSocketEvent(
+ wsEventAttachCommentToIssue,
+ map[string]interface{}{
+ "postId": post.Id,
+ "owner": req.RepoOwner,
+ "repo": req.RepoName,
+ "number": req.IssueNumber,
+ },
+ &model.WebsocketBroadcast{UserId: userID},
+ )
+}
+
+func (p *Plugin) openCloseOrReopenIssueModal(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.OpenCreateCommentOrEditIssueModalRequestBody{}
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ userID := r.Header.Get(constants.HeaderMattermostUserID)
+
+ post, appErr := p.API.GetPost(req.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+
+ p.API.PublishWebSocketEvent(
+ wsEventCloseOrReopenIssue,
+ map[string]interface{}{
+ "channel_id": post.ChannelId,
+ "owner": req.RepoOwner,
+ "repo": req.RepoName,
+ "number": req.IssueNumber,
+ "status": req.Status,
+ "postId": req.PostID,
+ },
+ &model.WebsocketBroadcast{UserId: userID},
+ )
+}
+
+func (p *Plugin) openIssueEditModal(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.OpenCreateCommentOrEditIssueModalRequestBody{}
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+ issue, _, err := githubClient.Issues.Get(c.Ctx, req.RepoOwner, req.RepoName, req.IssueNumber)
+ if err != nil {
+ // If the issue is not found, it probably belongs to a private repo.
+ // Return an empty response in that case.
+ var gerr *github.ErrorResponse
+ if errors.As(err, &gerr) && gerr.Response.StatusCode == http.StatusNotFound {
+ c.Log.WithError(err).With(logger.LogContext{
+ "owner": req.RepoOwner,
+ "repo": req.RepoName,
+ "number": req.IssueNumber,
+ }).Debugf("Issue not found")
+ p.writeJSON(w, nil)
+ return
+ }
+
+ c.Log.WithError(err).With(logger.LogContext{
+ "owner": req.RepoOwner,
+ "repo": req.RepoName,
+ "number": req.IssueNumber,
+ }).Debugf("Could not get the issue")
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ description := ""
+ if issue.Body != nil {
+ *issue.Body = mdCommentRegex.ReplaceAllString(issue.GetBody(), "")
+ description = *issue.Body
+ }
+
+ assignees := make([]string, len(issue.Assignees))
+ for index, user := range issue.Assignees {
+ assignees[index] = user.GetLogin()
+ }
+
+ labels := make([]string, len(issue.Labels))
+ for index, label := range issue.Labels {
+ labels[index] = label.GetName()
+ }
+
+ milestoneTitle := ""
+ var milestoneNumber int
+ if issue.Milestone != nil && issue.Milestone.Title != nil {
+ milestoneTitle = *issue.Milestone.Title
+ milestoneNumber = *issue.Milestone.Number
+ }
+
+ userID := r.Header.Get(constants.HeaderMattermostUserID)
+ post, appErr := p.API.GetPost(req.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+
+ p.API.PublishWebSocketEvent(
+ wsEventCreateOrUpdateIssue,
+ map[string]interface{}{
+ "title": *issue.Title,
+ "channel_id": post.ChannelId,
+ "postId": req.PostID,
+ "milestone_title": milestoneTitle,
+ "milestone_number": milestoneNumber,
+ "assignees": assignees,
+ "labels": labels,
+ "description": description,
+ "repo_full_name": fmt.Sprintf("%s/%s", req.RepoOwner, req.RepoName),
+ "issue_number": *issue.Number,
+ },
+ &model.WebsocketBroadcast{UserId: userID},
+ )
+
+ p.writeJSON(w, issue)
+}
+
+func (p *Plugin) getIssueByNumber(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(constants.OwnerQueryParam)
+ repo := r.FormValue(constants.RepoQueryParam)
+ number := r.FormValue(constants.NumberQueryParam)
+ issueNumber, err := strconv.Atoi(number)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- result, _, err := githubClient.Issues.Get(c.Ctx, owner, repo, numberInt)
+ result, _, err := githubClient.Issues.Get(c.Ctx, owner, repo, issueNumber)
if err != nil {
- // If the issue is not found, it's probably behind a private repo.
- // Return an empty repose in this case.
+ // If the issue is not found, it probably belongs to a private repo.
+ // Return an empty response in that case.
var gerr *github.ErrorResponse
if errors.As(err, &gerr) && gerr.Response.StatusCode == http.StatusNotFound {
c.Log.WithError(err).With(logger.LogContext{
"owner": owner,
"repo": repo,
- "number": numberInt,
- }).Debugf("Issue not found")
+ "number": issueNumber,
+ }).Debugf("Issue not found")
p.writeJSON(w, nil)
return
}
@@ -1065,40 +1140,41 @@ func (p *Plugin) getIssueByNumber(c *UserContext, w http.ResponseWriter, r *http
c.Log.WithError(err).With(logger.LogContext{
"owner": owner,
"repo": repo,
- "number": numberInt,
- }).Debugf("Could not get issue")
- p.writeAPIError(w, &APIErrorResponse{Message: "Could not get issue", StatusCode: http.StatusInternalServerError})
+ "number": issueNumber,
+ }).Debugf("Could not get the issue")
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
return
}
+
if result.Body != nil {
*result.Body = mdCommentRegex.ReplaceAllString(result.GetBody(), "")
}
p.writeJSON(w, result)
}
-func (p *Plugin) getPrByNumber(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue("owner")
- repo := r.FormValue("repo")
- number := r.FormValue("number")
+func (p *Plugin) getPrByNumber(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(constants.OwnerQueryParam)
+ repo := r.FormValue(constants.RepoQueryParam)
+ number := r.FormValue(constants.NumberQueryParam)
- numberInt, err := strconv.Atoi(number)
+ prNumber, err := strconv.Atoi(number)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- result, _, err := githubClient.PullRequests.Get(c.Ctx, owner, repo, numberInt)
+ result, _, err := githubClient.PullRequests.Get(c.Ctx, owner, repo, prNumber)
if err != nil {
// If the pull request is not found, it's probably behind a private repo.
- // Return an empty repose in this case.
+ // Return an empty response in that case.
var gerr *github.ErrorResponse
if errors.As(err, &gerr) && gerr.Response.StatusCode == http.StatusNotFound {
c.Log.With(logger.LogContext{
"owner": owner,
"repo": repo,
- "number": numberInt,
+ "number": prNumber,
}).Debugf("Pull request not found")
p.writeJSON(w, nil)
@@ -1108,9 +1184,9 @@ func (p *Plugin) getPrByNumber(c *UserContext, w http.ResponseWriter, r *http.Re
c.Log.WithError(err).With(logger.LogContext{
"owner": owner,
"repo": repo,
- "number": numberInt,
+ "number": prNumber,
}).Debugf("Could not get pull request")
- p.writeAPIError(w, &APIErrorResponse{Message: "Could not get pull request", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get pull request", StatusCode: http.StatusInternalServerError})
return
}
if result.Body != nil {
@@ -1119,10 +1195,10 @@ func (p *Plugin) getPrByNumber(c *UserContext, w http.ResponseWriter, r *http.Re
p.writeJSON(w, result)
}
-func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getLabels(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1134,7 +1210,7 @@ func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Reques
labels, resp, err := githubClient.Issues.ListLabels(c.Ctx, owner, repo, &opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list labels")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
return
}
allLabels = append(allLabels, labels...)
@@ -1147,10 +1223,10 @@ func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Reques
p.writeJSON(w, allLabels)
}
-func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getAssignees(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1162,7 +1238,7 @@ func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Req
assignees, resp, err := githubClient.Issues.ListAssignees(c.Ctx, owner, repo, &opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list assignees")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
return
}
allAssignees = append(allAssignees, assignees...)
@@ -1175,10 +1251,10 @@ func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Req
p.writeJSON(w, allAssignees)
}
-func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getMilestones(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1190,7 +1266,7 @@ func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Re
milestones, resp, err := githubClient.Issues.ListMilestones(c.Ctx, owner, repo, &github.MilestoneListOptions{ListOptions: opt})
if err != nil {
c.Log.WithError(err).Warnf("Failed to list milestones")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
return
}
allMilestones = append(allMilestones, milestones...)
@@ -1203,7 +1279,7 @@ func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Re
p.writeJSON(w, allMilestones)
}
-func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getRepositories(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
org := p.getConfiguration().GitHubOrg
@@ -1216,7 +1292,7 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
repos, resp, err := githubClient.Repositories.List(c.Ctx, "", &github.RepositoryListOptions{ListOptions: opt})
if err != nil {
c.Log.WithError(err).Warnf("Failed to list repositories")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
return
}
allRepos = append(allRepos, repos...)
@@ -1230,7 +1306,7 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
repos, resp, err := githubClient.Repositories.ListByOrg(c.Ctx, org, &github.RepositoryListByOrgOptions{Sort: "full_name", ListOptions: opt})
if err != nil {
c.Log.WithError(err).Warnf("Failed to list repositories by org")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
return
}
allRepos = append(allRepos, repos...)
@@ -1240,15 +1316,7 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
opt.Page = resp.NextPage
}
}
-
- // Only send down fields to client that are needed
- type RepositoryResponse struct {
- Name string `json:"name,omitempty"`
- FullName string `json:"full_name,omitempty"`
- Permissions map[string]bool `json:"permissions,omitempty"`
- }
-
- resp := make([]RepositoryResponse, len(allRepos))
+ resp := make([]serializer.RepositoryResponse, len(allRepos))
for i, r := range allRepos {
resp[i].Name = r.GetName()
resp[i].FullName = r.GetFullName()
@@ -1258,38 +1326,168 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
p.writeJSON(w, resp)
}
-func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
- type IssueRequest struct {
- Title string `json:"title"`
- Body string `json:"body"`
- Repo string `json:"repo"`
- PostID string `json:"post_id"`
- ChannelID string `json:"channel_id"`
- Labels []string `json:"labels"`
- Assignees []string `json:"assignees"`
- Milestone int `json:"milestone"`
+func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ // get data for the issue from the request body and fill UpdateIssueRequest to update the issue
+ issue := &serializer.UpdateIssueRequest{}
+ if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ if !p.validateIssueRequestForUpdation(issue, w) {
+ return
}
- // get data for the issue from the request body and fill IssueRequest object
- issue := &IssueRequest{}
+ var post *model.Post
+ permalink := ""
+ if issue.PostID != "" {
+ var appErr *model.AppError
+ post, appErr = p.API.GetPost(issue.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+ permalink = p.getPermaLink(issue.PostID)
+ }
+
+ githubIssue := &github.IssueRequest{
+ Title: &issue.Title,
+ Body: &issue.Body,
+ Labels: &issue.Labels,
+ Assignees: &issue.Assignees,
+ }
+
+ // submitting the request with an invalid milestone ID results in a 422 error
+ // we should make sure it's not zero here because the webapp client might have left this field empty
+ if issue.Milestone > 0 {
+ githubIssue.Milestone = &issue.Milestone
+ }
+
+ currentUser, appErr := p.API.GetUser(c.UserID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ splittedRepo := strings.Split(issue.Repo, "/")
+ if len(splittedRepo) < 2 {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository", StatusCode: http.StatusBadRequest})
+ }
+
+ owner, repoName := splittedRepo[0], splittedRepo[1]
+ githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+
+ result, resp, err := githubClient.Issues.Edit(c.Ctx, owner, repoName, issue.IssueNumber, githubIssue)
+ if err != nil {
+ if resp != nil && resp.Response.StatusCode == http.StatusGone {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ return
+ }
+
+ c.Log.WithError(err).Warnf("Failed to update the issue")
+ p.writeAPIError(w, &serializer.APIErrorResponse{
+ ID: "",
+ Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode,
+ issue.Repo,
+ currentUser.Username,
+ )),
+ StatusCode: resp.StatusCode,
+ })
+ return
+ }
+
+ rootID := issue.PostID
+ channelID := issue.ChannelID
+ message := fmt.Sprintf("Updated GitHub issue [#%v](%v)", result.GetNumber(), result.GetHTMLURL())
+ if post != nil {
+ if post.RootId != "" {
+ rootID = post.RootId
+ }
+ channelID = post.ChannelId
+ message += fmt.Sprintf(" from a [message](%s)", permalink)
+ }
+
+ reply := &model.Post{
+ Message: message,
+ ChannelId: channelID,
+ RootId: rootID,
+ UserId: c.UserID,
+ }
+
+ if post != nil {
+ _, appErr = p.API.CreatePost(reply)
+ } else {
+ _ = p.API.SendEphemeralPost(c.UserID, reply)
+ }
+ if appErr != nil {
+ c.Log.WithError(appErr).Warnf("failed to create the notification post")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ p.updatePost(post, issue, w)
+ p.writeJSON(w, result)
+}
+
+func (p *Plugin) closeOrReopenIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ req := &serializer.CommentAndCloseRequest{}
+ if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ post, appErr := p.API.GetPost(req.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+
+ if _, err := p.getUsername(post.UserId); err != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if req.IssueComment != "" {
+ p.CreateCommentToIssue(c, w, req.IssueComment, req.Owner, req.Repository, post, req.Number)
+ }
+
+ if req.Status == constants.Close {
+ p.CloseOrReopenIssue(c, w, constants.IssueClose, req.StatusReason, req.Owner, req.Repository, post, req.Number)
+ } else {
+ p.CloseOrReopenIssue(c, w, constants.IssueOpen, req.StatusReason, req.Owner, req.Repository, post, req.Number)
+ }
+}
+
+func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+ // get data for the issue from the request body and fill CreateIssueRequest object to create the issue
+ issue := &serializer.CreateIssueRequest{}
if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
- c.Log.WithError(err).Warnf("Error decoding JSON body")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object.", StatusCode: http.StatusBadRequest})
+ c.Log.WithError(err).Warnf("Error decoding the JSON body")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if issue.Title == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
return
}
if issue.Repo == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repo name.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository name.", StatusCode: http.StatusBadRequest})
return
}
if issue.PostID == "" && issue.ChannelID == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
return
}
@@ -1300,17 +1498,17 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
var appErr *model.AppError
post, appErr = p.API.GetPost(issue.PostID)
if appErr != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + issue.PostID, StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load post " + issue.PostID + ": not found", StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
return
}
username, err := p.getUsername(post.UserId)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
@@ -1319,7 +1517,7 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
mmMessage = fmt.Sprintf("_Issue created from a [Mattermost message](%v) *by %s*._", permalink, username)
}
- ghIssue := &github.IssueRequest{
+ githubIssue := &github.IssueRequest{
Title: &issue.Title,
Body: &issue.Body,
Labels: &issue.Labels,
@@ -1327,44 +1525,39 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
}
// submitting the request with an invalid milestone ID results in a 422 error
- // we make sure it's not zero here, because the webapp client might have left this field empty
+ // we should make sure it's not zero here because the webapp client might have left this field empty
if issue.Milestone > 0 {
- ghIssue.Milestone = &issue.Milestone
+ githubIssue.Milestone = &issue.Milestone
}
- if ghIssue.GetBody() != "" && mmMessage != "" {
+ if githubIssue.GetBody() != "" && mmMessage != "" {
mmMessage = "\n\n" + mmMessage
}
- *ghIssue.Body = ghIssue.GetBody() + mmMessage
+ *githubIssue.Body = fmt.Sprintf("%s%s", githubIssue.GetBody(), mmMessage)
currentUser, appErr := p.API.GetUser(c.UserID)
if appErr != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
return
}
splittedRepo := strings.Split(issue.Repo, "/")
- owner := splittedRepo[0]
- repoName := splittedRepo[1]
+ owner, repoName := splittedRepo[0], splittedRepo[1]
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- result, resp, err := githubClient.Issues.Create(c.Ctx, owner, repoName, ghIssue)
+ result, resp, err := githubClient.Issues.Create(c.Ctx, owner, repoName, githubIssue)
if err != nil {
if resp != nil && resp.Response.StatusCode == http.StatusGone {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
return
}
c.Log.WithError(err).Warnf("Failed to create issue")
- p.writeAPIError(w,
- &APIErrorResponse{
- ID: "",
- Message: "failed to create issue: " + getFailReason(resp.StatusCode,
- issue.Repo,
- currentUser.Username,
- ),
- StatusCode: resp.StatusCode,
- })
+ p.writeAPIError(w, &serializer.APIErrorResponse{
+ ID: "",
+ Message: fmt.Sprintf("failed to create issue: %s", getFailReason(resp.StatusCode, issue.Repo, currentUser.Username)),
+ StatusCode: resp.StatusCode,
+ })
return
}
@@ -1389,11 +1582,11 @@ func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
if post != nil {
_, appErr = p.API.CreatePost(reply)
} else {
- p.API.SendEphemeralPost(c.UserID, reply)
+ _ = p.API.SendEphemeralPost(c.UserID, reply)
}
if appErr != nil {
- c.Log.WithError(appErr).Warnf("failed to create notification post")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create notification post, postID: " + issue.PostID + ", channelID: " + channelID, StatusCode: http.StatusInternalServerError})
+ c.Log.WithError(appErr).Warnf("failed to create the notification post")
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID), StatusCode: http.StatusInternalServerError})
return
}
diff --git a/server/plugin/api_test.go b/server/plugin/api_test.go
index 8aaa5bd89..0db23f92a 100644
--- a/server/plugin/api_test.go
+++ b/server/plugin/api_test.go
@@ -11,6 +11,8 @@ import (
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-plugin-github/server/testutils"
)
@@ -79,7 +81,7 @@ func TestPlugin_ServeHTTP(t *testing.T) {
expectedResponse: testutils.ExpectedResponse{
StatusCode: http.StatusUnauthorized,
ResponseType: testutils.ContentTypeJSON,
- Body: APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized},
+ Body: serializer.APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized},
},
userID: "",
}, "unauthorized test http": {
@@ -115,7 +117,7 @@ func TestPlugin_ServeHTTP(t *testing.T) {
p.SetAPI(&plugintest.API{})
req := test.httpTest.CreateHTTPRequest(test.request)
- req.Header.Add("Mattermost-User-ID", test.userID)
+ req.Header.Add(constants.HeaderMattermostUserID, test.userID)
rr := httptest.NewRecorder()
p.ServeHTTP(&plugin.Context{}, rr, req)
test.httpTest.CompareHTTPResponse(rr, test.expectedResponse)
diff --git a/server/plugin/cluster.go b/server/plugin/cluster.go
index 87b992c40..f78325647 100644
--- a/server/plugin/cluster.go
+++ b/server/plugin/cluster.go
@@ -3,7 +3,7 @@ package plugin
import (
"encoding/json"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/mattermost/mattermost-server/v6/model"
)
diff --git a/server/plugin/command.go b/server/plugin/command.go
index af1412697..e0e38de75 100644
--- a/server/plugin/command.go
+++ b/server/plugin/command.go
@@ -7,6 +7,8 @@ import (
"unicode"
"github.com/mattermost/mattermost-plugin-api/experimental/command"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/pkg/errors"
@@ -93,7 +95,7 @@ func (p *Plugin) postCommandResponse(args *model.CommandArgs, text string) {
_ = p.API.SendEphemeralPost(args.UserId, post)
}
-func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) []string {
+func (p *Plugin) getMutedUsernames(userInfo *serializer.GitHubUserInfo) []string {
mutedUsernameBytes, err := p.API.KVGet(userInfo.UserID + "-muted-users")
if err != nil {
return nil
@@ -107,7 +109,7 @@ func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) []string {
return mutedUsers
}
-func (p *Plugin) handleMuteList(args *model.CommandArgs, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleMuteList(args *model.CommandArgs, userInfo *serializer.GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
var mutedUsers string
for _, user := range mutedUsernames {
@@ -128,7 +130,7 @@ func contains(s []string, e string) bool {
return false
}
-func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInfo *serializer.GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
if contains(mutedUsernames, username) {
return username + " is already muted"
@@ -151,7 +153,7 @@ func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInf
return fmt.Sprintf("`%v`", username) + " is now muted. You'll no longer receive notifications for comments in your PRs and issues."
}
-func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo *serializer.GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
userToMute := []string{username}
newMutedList := arrayDifference(mutedUsernames, userToMute)
@@ -161,14 +163,14 @@ func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo
return fmt.Sprintf("`%v`", username) + " is no longer muted"
}
-func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *serializer.GitHubUserInfo) string {
if err := p.API.KVSet(userInfo.UserID+"-muted-users", []byte("")); err != nil {
return "Error occurred unmuting users"
}
return "Unmuted all users"
}
-func (p *Plugin) handleMuteCommand(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleMuteCommand(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid mute command. Available commands are 'list', 'add' and 'delete'."
}
@@ -210,7 +212,7 @@ func arrayDifference(a, b []string) []string {
return diff
}
-func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
switch {
case len(parameters) == 0:
return "Please specify a repository or 'list' command."
@@ -221,7 +223,7 @@ func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, par
}
}
-func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid subscribe command. Available commands are 'list', 'add' and 'delete'."
}
@@ -241,7 +243,7 @@ func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs,
}
}
-func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
+func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *serializer.GitHubUserInfo) string {
txt := ""
subs, err := p.GetSubscriptionsByChannel(args.ChannelId)
if err != nil {
@@ -265,7 +267,7 @@ func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandA
return txt
}
-func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
if len(parameters) == 0 {
return "Please specify a repository."
}
@@ -345,7 +347,7 @@ func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs,
return msg
}
-func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
+func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *serializer.GitHubUserInfo) string {
if len(parameters) == 0 {
return "Please specify a repository."
}
@@ -360,12 +362,12 @@ func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, p
return fmt.Sprintf("Successfully unsubscribed from %s.", repo)
}
-func (p *Plugin) handleDisconnect(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
+func (p *Plugin) handleDisconnect(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *serializer.GitHubUserInfo) string {
p.disconnectGitHubAccount(args.UserId)
return "Disconnected your GitHub account."
}
-func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *serializer.GitHubUserInfo) string {
githubClient := p.githubConnectUser(context.Background(), userInfo)
text, err := p.GetToDo(context.Background(), userInfo.GitHubUsername, githubClient)
@@ -377,7 +379,7 @@ func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string,
return text
}
-func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *serializer.GitHubUserInfo) string {
githubClient := p.githubConnectUser(context.Background(), userInfo)
gitUser, _, err := githubClient.Users.Get(context.Background(), "")
if err != nil {
@@ -388,7 +390,7 @@ func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, u
return text
}
-func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
+func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *serializer.GitHubUserInfo) string {
message, err := renderTemplate("helpText", p.getConfiguration())
if err != nil {
p.API.LogWarn("Failed to render help template", "error", err.Error())
@@ -398,7 +400,7 @@ func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string,
return "###### Mattermost GitHub Plugin - Slash Command Help\n" + message
}
-func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
if len(parameters) < 2 {
return "Please specify both a setting and value. Use `/github help` for more usage information."
}
@@ -463,7 +465,7 @@ func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, paramet
return "Settings updated."
}
-func (p *Plugin) handleIssue(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
+func (p *Plugin) handleIssue(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid issue command. Available command is 'create'."
}
@@ -517,7 +519,7 @@ func (p *Plugin) handleSetup(c *plugin.Context, args *model.CommandArgs, paramet
return ""
}
-type CommandHandleFunc func(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string
+type CommandHandleFunc func(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string
func (p *Plugin) isAuthorizedSysAdmin(userID string) (bool, error) {
user, appErr := p.API.GetUser(userID)
@@ -603,7 +605,7 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
info, apiErr := p.getGitHubUserInfo(args.UserId)
if apiErr != nil {
text := "Unknown error."
- if apiErr.ID == apiErrorIDNotConnected {
+ if apiErr.ID == constants.APIErrorIDNotConnected {
text = "You must connect your account to GitHub first. Either click on the GitHub logo in the bottom left of the screen or enter `/github connect`."
}
p.postCommandResponse(args, text)
diff --git a/server/plugin/flows.go b/server/plugin/flows.go
index d5c74549d..c8e459a6f 100644
--- a/server/plugin/flows.go
+++ b/server/plugin/flows.go
@@ -7,7 +7,7 @@ import (
"strings"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/gorilla/mux"
pluginapi "github.com/mattermost/mattermost-plugin-api"
"github.com/mattermost/mattermost-plugin-api/experimental/flow"
diff --git a/server/plugin/mm_34646_token_refresh.go b/server/plugin/mm_34646_token_refresh.go
index 62c7ccb72..fd9c63c1b 100644
--- a/server/plugin/mm_34646_token_refresh.go
+++ b/server/plugin/mm_34646_token_refresh.go
@@ -5,10 +5,11 @@ import (
"encoding/json"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-plugin-api/cluster"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
)
const pageSize = 100
@@ -49,7 +50,7 @@ func (p *Plugin) forceResetAllMM34646() error {
appErr.Error())
continue
}
- tryInfo := GitHubUserInfo{}
+ tryInfo := serializer.GitHubUserInfo{}
err := json.Unmarshal(data, &tryInfo)
if err != nil {
// too noisy to report
@@ -65,7 +66,7 @@ func (p *Plugin) forceResetAllMM34646() error {
info, errResp := p.getGitHubUserInfo(tryInfo.UserID)
if errResp != nil {
- p.API.LogError("failed to retrieve GitHubUserInfo", "key", key, "user_id", tryInfo.UserID,
+ p.API.LogError("failed to retrieve serializer.GitHubUserInfo", "key", key, "user_id", tryInfo.UserID,
"error", errResp.Error())
continue
}
@@ -89,7 +90,7 @@ func (p *Plugin) forceResetAllMM34646() error {
return nil
}
-func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configuration, info *GitHubUserInfo) (string, error) {
+func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configuration, info *serializer.GitHubUserInfo) (string, error) {
if info.MM34646ResetTokenDone {
return info.Token.AccessToken, nil
}
@@ -111,7 +112,7 @@ func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configu
info.MM34646ResetTokenDone = true
err = p.storeGitHubUserInfo(info)
if err != nil {
- return "", errors.Wrap(err, "failed to store updated GitHubUserInfo")
+ return "", errors.Wrap(err, "failed to store updated serializer.GitHubUserInfo")
}
p.API.LogDebug("Updated user access token for MM-34646", "user_id", info.UserID)
diff --git a/server/plugin/permalinks.go b/server/plugin/permalinks.go
index 22d1bd6a8..4f1c27353 100644
--- a/server/plugin/permalinks.go
+++ b/server/plugin/permalinks.go
@@ -6,7 +6,7 @@ import (
"strings"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
)
// maxPermalinkReplacements sets the maximum limit to the number of
diff --git a/server/plugin/permalinks_test.go b/server/plugin/permalinks_test.go
index cbc48cdd0..82d4d3b27 100644
--- a/server/plugin/permalinks_test.go
+++ b/server/plugin/permalinks_test.go
@@ -7,7 +7,7 @@ import (
"net/url"
"testing"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/mattermost/mattermost-server/v6/plugin/plugintest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go
index 5dc367947..ac8a7baca 100644
--- a/server/plugin/plugin.go
+++ b/server/plugin/plugin.go
@@ -12,11 +12,13 @@ import (
"strings"
"sync"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/gorilla/mux"
pluginapi "github.com/mattermost/mattermost-plugin-api"
"github.com/mattermost/mattermost-plugin-api/experimental/bot/poster"
"github.com/mattermost/mattermost-plugin-api/experimental/telemetry"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/pkg/errors"
@@ -37,9 +39,11 @@ const (
wsEventConnect = "connect"
wsEventDisconnect = "disconnect"
// WSEventConfigUpdate is the WebSocket event to update the configurations on webapp.
- WSEventConfigUpdate = "config_update"
- wsEventRefresh = "refresh"
- wsEventCreateIssue = "createIssue"
+ WSEventConfigUpdate = "config_update"
+ wsEventRefresh = "refresh"
+ wsEventCreateOrUpdateIssue = "createOrUpdateIssue"
+ wsEventCloseOrReopenIssue = "closeOrReopenIssue"
+ wsEventAttachCommentToIssue = "attachCommentToIssue"
WSEventRefresh = "refresh"
@@ -123,7 +127,7 @@ func (p *Plugin) GetGitHubClient(ctx context.Context, userID string) (*github.Cl
return p.githubConnectUser(ctx, userInfo), nil
}
-func (p *Plugin) githubConnectUser(ctx context.Context, info *GitHubUserInfo) *github.Client {
+func (p *Plugin) githubConnectUser(ctx context.Context, info *serializer.GitHubUserInfo) *github.Client {
tok := *info.Token
return p.githubConnectToken(tok)
}
@@ -301,7 +305,7 @@ func (p *Plugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode
msg := post.Message
info, appErr := p.getGitHubUserInfo(post.UserId)
if appErr != nil {
- if appErr.ID != apiErrorIDNotConnected {
+ if appErr.ID != constants.APIErrorIDNotConnected {
p.API.LogError("Error in getting user info", "error", appErr.Message)
}
return nil, ""
@@ -371,26 +375,7 @@ func (p *Plugin) getOAuthConfigForChimeraApp(scopes []string) *oauth2.Config {
}
}
-type GitHubUserInfo struct {
- UserID string
- Token *oauth2.Token
- GitHubUsername string
- LastToDoPostAt int64
- Settings *UserSettings
- AllowedPrivateRepos bool
-
- // MM34646ResetTokenDone is set for a user whose token has been reset for MM-34646.
- MM34646ResetTokenDone bool
-}
-
-type UserSettings struct {
- SidebarButtons string `json:"sidebar_buttons"`
- DailyReminder bool `json:"daily_reminder"`
- DailyReminderOnChange bool `json:"daily_reminder_on_change"`
- Notifications bool `json:"notifications"`
-}
-
-func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error {
+func (p *Plugin) storeGitHubUserInfo(info *serializer.GitHubUserInfo) error {
config := p.getConfiguration()
encryptedToken, err := encrypt([]byte(config.EncryptionKey), info.Token.AccessToken)
@@ -412,24 +397,24 @@ func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error {
return nil
}
-func (p *Plugin) getGitHubUserInfo(userID string) (*GitHubUserInfo, *APIErrorResponse) {
+func (p *Plugin) getGitHubUserInfo(userID string) (*serializer.GitHubUserInfo, *serializer.APIErrorResponse) {
config := p.getConfiguration()
- var userInfo GitHubUserInfo
+ var userInfo serializer.GitHubUserInfo
infoBytes, appErr := p.API.KVGet(userID + githubTokenKey)
if appErr != nil || infoBytes == nil {
- return nil, &APIErrorResponse{ID: apiErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest}
+ return nil, &serializer.APIErrorResponse{ID: constants.APIErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest}
}
if err := json.Unmarshal(infoBytes, &userInfo); err != nil {
- return nil, &APIErrorResponse{ID: "", Message: "Unable to parse token.", StatusCode: http.StatusInternalServerError}
+ return nil, &serializer.APIErrorResponse{ID: "", Message: "Unable to parse token.", StatusCode: http.StatusInternalServerError}
}
unencryptedToken, err := decrypt([]byte(config.EncryptionKey), userInfo.Token.AccessToken)
if err != nil {
p.API.LogWarn("Failed to decrypt access token", "error", err.Error())
- return nil, &APIErrorResponse{ID: "", Message: "Unable to decrypt access token.", StatusCode: http.StatusInternalServerError}
+ return nil, &serializer.APIErrorResponse{ID: "", Message: "Unable to decrypt access token.", StatusCode: http.StatusInternalServerError}
}
userInfo.Token.AccessToken = unencryptedToken
@@ -496,7 +481,7 @@ func (p *Plugin) disconnectGitHubAccount(userID string) {
func (p *Plugin) openIssueCreateModal(userID string, channelID string, title string) {
p.API.PublishWebSocketEvent(
- wsEventCreateIssue,
+ wsEventCreateOrUpdateIssue,
map[string]interface{}{
"title": title,
"channel_id": channelID,
@@ -556,7 +541,7 @@ func (p *Plugin) GetDailySummaryText(userID string) (string, error) {
return string(summaryByte), nil
}
-func (p *Plugin) PostToDo(info *GitHubUserInfo, userID string) error {
+func (p *Plugin) PostToDo(info *serializer.GitHubUserInfo, userID string) error {
ctx := context.Background()
text, err := p.GetToDo(ctx, info.GitHubUsername, p.githubConnectUser(ctx, info))
if err != nil {
@@ -691,7 +676,7 @@ func (p *Plugin) GetToDo(ctx context.Context, username string, githubClient *git
return text, nil
}
-func (p *Plugin) HasUnreads(info *GitHubUserInfo) bool {
+func (p *Plugin) HasUnreads(info *serializer.GitHubUserInfo) bool {
username := info.GitHubUsername
ctx := context.Background()
githubClient := p.githubConnectUser(ctx, info)
@@ -796,7 +781,7 @@ func (p *Plugin) sendRefreshEvent(userID string) {
func (p *Plugin) getUsername(mmUserID string) (string, error) {
info, apiEr := p.getGitHubUserInfo(mmUserID)
if apiEr != nil {
- if apiEr.ID != apiErrorIDNotConnected {
+ if apiEr.ID != constants.APIErrorIDNotConnected {
return "", apiEr
}
diff --git a/server/plugin/subscriptions.go b/server/plugin/subscriptions.go
index d5067fe65..517fe488c 100644
--- a/server/plugin/subscriptions.go
+++ b/server/plugin/subscriptions.go
@@ -9,7 +9,7 @@ import (
"strconv"
"strings"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/pkg/errors"
)
diff --git a/server/plugin/template_test.go b/server/plugin/template_test.go
index 6b31a508d..b52f00c77 100644
--- a/server/plugin/template_test.go
+++ b/server/plugin/template_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
"github.com/stretchr/testify/require"
)
diff --git a/server/plugin/utils.go b/server/plugin/utils.go
index 91ccc94c2..a7628cb4b 100644
--- a/server/plugin/utils.go
+++ b/server/plugin/utils.go
@@ -9,12 +9,17 @@ import (
"encoding/base64"
"fmt"
"io"
+ "net/http"
"net/url"
"path"
"strconv"
"strings"
"unicode"
+ "github.com/google/go-github/v48/github"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
+ "github.com/mattermost/mattermost-server/v6/model"
"github.com/pkg/errors"
)
@@ -351,3 +356,139 @@ func isValidURL(rawURL string) error {
return nil
}
+
+func (p *Plugin) validateIssueRequestForUpdation(issue *serializer.UpdateIssueRequest, w http.ResponseWriter) bool {
+ if issue.Title == "" {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
+ return false
+ }
+ if issue.PostID == "" && issue.ChannelID == "" {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
+ return false
+ }
+
+ return true
+}
+
+func (p *Plugin) updatePost(post *model.Post, issue *serializer.UpdateIssueRequest, w http.ResponseWriter) {
+ post, appErr := p.API.GetPost(issue.PostID)
+ if appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if post == nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
+ return
+ }
+
+ post.Props[constants.AssigneesForProps] = issue.Assignees
+ post.Props[constants.LabelsForProps] = issue.Labels
+ post.Props[constants.DescriptionForProps] = issue.Body
+ post.Props[constants.TitleForProps] = issue.Title
+ if _, appErr = p.API.UpdatePost(post); appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ }
+}
+
+func (p *Plugin) CreateCommentToIssue(c *serializer.UserContext, w http.ResponseWriter, comment, owner, repo string, post *model.Post, issueNumber int) {
+ currentUsername := c.GHInfo.GitHubUsername
+ permalink := p.getPermaLink(post.Id)
+ issueComment := &github.IssueComment{
+ Body: &comment,
+ }
+ githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+
+ result, rawResponse, err := githubClient.Issues.CreateComment(c.Ctx, owner, repo, issueNumber, issueComment)
+ if err != nil {
+ statusCode := http.StatusInternalServerError
+ if rawResponse != nil {
+ statusCode = rawResponse.StatusCode
+ }
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, repo, currentUsername)), StatusCode: statusCode})
+ return
+ }
+
+ rootID := post.Id
+ if post.RootId != "" {
+ // the original post was a reply
+ rootID = post.RootId
+ }
+
+ permalinkReplyMessage := fmt.Sprintf("[Comment](%v) attached to GitHub issue [#%v](%v)", permalink, issueNumber, result.GetHTMLURL())
+ reply := &model.Post{
+ Message: permalinkReplyMessage,
+ ChannelId: post.ChannelId,
+ RootId: rootID,
+ UserId: c.UserID,
+ }
+
+ if _, appErr := p.API.CreatePost(reply); appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ return
+ }
+}
+
+func (p *Plugin) CloseOrReopenIssue(c *serializer.UserContext, w http.ResponseWriter, status, statusReason, owner, repo string, post *model.Post, issueNumber int) {
+ currentUsername := c.GHInfo.GitHubUsername
+ githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+ githubIssue := &github.IssueRequest{
+ State: &(status),
+ StateReason: &(statusReason),
+ }
+
+ issue, resp, err := githubClient.Issues.Edit(c.Ctx, owner, repo, issueNumber, githubIssue)
+ if err != nil {
+ if resp != nil && resp.Response.StatusCode == http.StatusGone {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ return
+ }
+
+ c.Log.WithError(err).Warnf("Failed to update the issue")
+ p.writeAPIError(w, &serializer.APIErrorResponse{
+ ID: "",
+ Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode,
+ repo,
+ currentUsername,
+ )),
+ StatusCode: resp.StatusCode,
+ })
+ return
+ }
+
+ var permalinkReplyMessage string
+ switch statusReason {
+ case constants.IssueCompleted:
+ permalinkReplyMessage = fmt.Sprintf("Issue closed as completed [#%v](%v)", issueNumber, issue.GetHTMLURL())
+ case constants.IssueNotPlanned:
+ permalinkReplyMessage = fmt.Sprintf("Issue closed as not planned [#%v](%v)", issueNumber, issue.GetHTMLURL())
+ default:
+ permalinkReplyMessage = fmt.Sprintf("Issue reopend [#%v](%v)", issueNumber, issue.GetHTMLURL())
+ }
+
+ rootID := post.Id
+ if post.RootId != "" {
+ // the original post was a reply
+ rootID = post.RootId
+ }
+
+ reply := &model.Post{
+ Message: permalinkReplyMessage,
+ ChannelId: post.ChannelId,
+ RootId: rootID,
+ UserId: c.UserID,
+ }
+
+ if _, appErr := p.API.CreatePost(reply); appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ if status == constants.IssueClose {
+ post.Props[constants.IssueStatus] = constants.Reopen
+ } else {
+ post.Props[constants.IssueStatus] = constants.Close
+ }
+ if _, appErr := p.API.UpdatePost(post); appErr != nil {
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ }
+ p.writeJSON(w, issue)
+}
diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go
index 39d967c82..ed9196556 100644
--- a/server/plugin/webhook.go
+++ b/server/plugin/webhook.go
@@ -6,30 +6,19 @@ import (
"crypto/sha1" //nolint:gosec // GitHub webhooks are signed using sha1 https://developer.github.com/webhooks/.
"encoding/hex"
"encoding/json"
+ "fmt"
"io"
"net/http"
"strings"
"sync"
"time"
- "github.com/google/go-github/v41/github"
+ "github.com/google/go-github/v48/github"
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/microcosm-cc/bluemonday"
)
-const (
- actionOpened = "opened"
- actionClosed = "closed"
- actionReopened = "reopened"
- actionSubmitted = "submitted"
- actionLabeled = "labeled"
- actionAssigned = "assigned"
-
- actionCreated = "created"
- actionDeleted = "deleted"
- actionEdited = "edited"
-)
-
// RenderConfig holds various configuration options to be used in a template
// for redering an event.
type RenderConfig struct {
@@ -343,15 +332,15 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
}
action := event.GetAction()
- if action != actionOpened && action != actionLabeled && action != actionClosed {
+ if action != constants.ActionOpened && action != constants.ActionLabeled && action != constants.ActionClosed {
return
}
pr := event.GetPullRequest()
eventLabel := event.GetLabel().GetName()
labels := make([]string, len(pr.Labels))
- for i, v := range pr.Labels {
- labels[i] = v.GetName()
+ for index, label := range pr.Labels {
+ labels[index] = label.GetName()
}
closedPRMessage, err := renderTemplate("closedPR", event)
@@ -370,7 +359,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
continue
}
- if sub.PullsMerged() && action != actionClosed {
+ if sub.PullsMerged() && action != constants.ActionClosed {
continue
}
@@ -391,7 +380,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
continue
}
- if action == actionLabeled {
+ if action == constants.ActionLabeled {
if label != "" && label == eventLabel {
pullRequestLabelledMessage, err := renderTemplate("pullRequestLabelled", event)
if err != nil {
@@ -405,7 +394,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
}
}
- if action == actionOpened {
+ if action == constants.ActionOpened {
newPRMessage, err := renderTemplate("newPR", GetEventWithRenderConfig(event, sub))
if err != nil {
p.API.LogWarn("Failed to render template", "error", err.Error())
@@ -415,7 +404,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
post.Message = p.sanitizeDescription(newPRMessage)
}
- if action == actionClosed {
+ if action == constants.ActionClosed {
post.Message = closedPRMessage
}
@@ -434,7 +423,7 @@ func (p *Plugin) sanitizeDescription(description string) string {
func (p *Plugin) handlePRDescriptionMentionNotification(event *github.PullRequestEvent) {
action := event.GetAction()
- if action != actionOpened {
+ if action != constants.ActionOpened {
return
}
@@ -496,7 +485,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
// This condition is made to check if the message doesn't get automatically labeled to prevent duplicated issue messages
timeDiff := time.Until(issue.GetCreatedAt()) * -1
- if action == actionLabeled && timeDiff.Seconds() < 4.00 {
+ if action == constants.ActionLabeled && timeDiff.Seconds() < 4.00 {
return
}
@@ -507,16 +496,16 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
issueTemplate := ""
switch action {
- case actionOpened:
+ case constants.ActionOpened:
issueTemplate = "newIssue"
- case actionClosed:
+ case constants.ActionClosed:
issueTemplate = "closedIssue"
- case actionReopened:
+ case constants.ActionReopened:
issueTemplate = "reopenedIssue"
- case actionLabeled:
+ case constants.ActionLabeled:
issueTemplate = "issueLabelled"
default:
@@ -525,8 +514,8 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
eventLabel := event.GetLabel().GetName()
labels := make([]string, len(issue.Labels))
- for i, v := range issue.Labels {
- labels[i] = v.GetName()
+ for index, label := range issue.Labels {
+ labels[index] = label.GetName()
}
for _, sub := range subscribedChannels {
@@ -534,7 +523,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
continue
}
- if sub.IssueCreations() && action != actionOpened {
+ if sub.IssueCreations() && action != constants.ActionOpened {
continue
}
@@ -549,12 +538,35 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
}
renderedMessage = p.sanitizeDescription(renderedMessage)
+ assignees := make([]string, len(issue.Assignees))
+ for index, user := range issue.Assignees {
+ assignees[index] = user.GetLogin()
+ }
+ description := ""
+ if issue.Body != nil {
+ description = *issue.Body
+ }
+
post := &model.Post{
UserId: p.BotUserID,
- Type: "custom_git_issue",
Message: renderedMessage,
}
+ if action == constants.ActionOpened {
+ post.Type = "custom_git_issue"
+ post.Props = map[string]interface{}{
+ constants.TitleForProps: *issue.Title,
+ constants.IssueUrlForProps: *issue.HTMLURL,
+ constants.IssueNumberForProps: *issue.Number,
+ constants.DescriptionForProps: description,
+ constants.AssigneesForProps: assignees,
+ constants.LabelsForProps: labels,
+ constants.RepoOwnerForProps: *repo.Owner.Login,
+ constants.RepoNameForProps: *repo.Name,
+ constants.IssueStatus: constants.Close,
+ }
+ }
+
label := sub.Label()
contained := false
@@ -568,7 +580,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
continue
}
- if action == actionLabeled {
+ if action == constants.ActionLabeled {
if label == "" || label != eventLabel {
continue
}
@@ -716,7 +728,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
return
}
- if event.GetAction() != actionCreated {
+ if event.GetAction() != constants.ActionCreated {
return
}
@@ -732,8 +744,8 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
}
labels := make([]string, len(event.GetIssue().Labels))
- for i, v := range event.GetIssue().Labels {
- labels[i] = v.GetName()
+ for index, label := range event.GetIssue().Labels {
+ labels[index] = label.GetName()
}
for _, sub := range subs {
@@ -758,7 +770,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
continue
}
- if event.GetAction() == actionCreated {
+ if event.GetAction() == constants.ActionCreated {
post.Message = message
}
@@ -771,7 +783,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
}
func (p *Plugin) senderMutedByReceiver(userID string, sender string) bool {
- mutedUsernameBytes, _ := p.API.KVGet(userID + "-muted-users")
+ mutedUsernameBytes, _ := p.API.KVGet(fmt.Sprintf("%s-muted-users", userID))
mutedUsernames := string(mutedUsernameBytes)
return strings.Contains(mutedUsernames, sender)
}
@@ -785,7 +797,7 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent
}
action := event.GetAction()
- if action != actionSubmitted {
+ if action != constants.ActionSubmitted {
return
}
@@ -811,8 +823,8 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent
}
labels := make([]string, len(event.GetPullRequest().Labels))
- for i, v := range event.GetPullRequest().Labels {
- labels[i] = v.GetName()
+ for index, label := range event.GetPullRequest().Labels {
+ labels[index] = label.GetName()
}
for _, sub := range subs {
@@ -865,8 +877,8 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
}
labels := make([]string, len(event.GetPullRequest().Labels))
- for i, v := range event.GetPullRequest().Labels {
- labels[i] = v.GetName()
+ for index, label := range event.GetPullRequest().Labels {
+ labels[index] = label.GetName()
}
for _, sub := range subs {
@@ -900,7 +912,7 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
func (p *Plugin) handleCommentMentionNotification(event *github.IssueCommentEvent) {
action := event.GetAction()
- if action == actionEdited || action == actionDeleted {
+ if action == constants.ActionEdited || action == constants.ActionDeleted {
return
}
@@ -966,7 +978,7 @@ func (p *Plugin) handleCommentAuthorNotification(event *github.IssueCommentEvent
}
action := event.GetAction()
- if action == actionEdited || action == actionDeleted {
+ if action == constants.ActionEdited || action == constants.ActionDeleted {
return
}
@@ -1088,7 +1100,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(requestedUserID, repoName) {
requestedUserID = ""
}
- case actionClosed:
+ case constants.ActionClosed:
if author == sender {
return
}
@@ -1096,7 +1108,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case actionReopened:
+ case constants.ActionReopened:
if author == sender {
return
}
@@ -1104,7 +1116,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case actionAssigned:
+ case constants.ActionAssigned:
assignee := event.GetPullRequest().GetAssignee().GetLogin()
if assignee == sender {
return
@@ -1146,17 +1158,17 @@ func (p *Plugin) handleIssueNotification(event *github.IssuesEvent) {
assigneeUserID := ""
switch event.GetAction() {
- case actionClosed:
+ case constants.ActionClosed:
authorUserID = p.getGitHubToUserIDMapping(author)
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case actionReopened:
+ case constants.ActionReopened:
authorUserID = p.getGitHubToUserIDMapping(author)
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case actionAssigned:
+ case constants.ActionAssigned:
assignee := event.GetAssignee().GetLogin()
if assignee == sender {
return
@@ -1197,7 +1209,7 @@ func (p *Plugin) handlePullRequestReviewNotification(event *github.PullRequestRe
return
}
- if event.GetAction() != actionSubmitted {
+ if event.GetAction() != constants.ActionSubmitted {
return
}
diff --git a/server/serializer/error.go b/server/serializer/error.go
new file mode 100644
index 000000000..1e2974f51
--- /dev/null
+++ b/server/serializer/error.go
@@ -0,0 +1,11 @@
+package serializer
+
+type APIErrorResponse struct {
+ ID string `json:"id"`
+ Message string `json:"message"`
+ StatusCode int `json:"status_code"`
+}
+
+func (e *APIErrorResponse) Error() string {
+ return e.Message
+}
diff --git a/server/serializer/issue.go b/server/serializer/issue.go
new file mode 100644
index 000000000..e21432423
--- /dev/null
+++ b/server/serializer/issue.go
@@ -0,0 +1,52 @@
+package serializer
+
+type CreateIssueRequest struct {
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Repo string `json:"repo"`
+ PostID string `json:"post_id"`
+ ChannelID string `json:"channel_id"`
+ Labels []string `json:"labels"`
+ Assignees []string `json:"assignees"`
+ Milestone int `json:"milestone"`
+}
+
+type CreateIssueCommentRequest struct {
+ PostID string `json:"post_id"`
+ Owner string `json:"owner"`
+ Repo string `json:"repo"`
+ Number int `json:"number"`
+ Comment string `json:"comment"`
+ ShowAttachedMessage bool `json:"show_attached_message"`
+}
+
+type UpdateIssueRequest struct {
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Repo string `json:"repo"`
+ PostID string `json:"post_id"`
+ ChannelID string `json:"channel_id"`
+ Labels []string `json:"labels"`
+ Assignees []string `json:"assignees"`
+ Milestone int `json:"milestone"`
+ IssueNumber int `json:"issue_number"`
+}
+
+type CommentAndCloseRequest struct {
+ ChannelID string `json:"channel_id"`
+ IssueComment string `json:"issue_comment"`
+ StatusReason string `json:"status_reason"`
+ Number int `json:"number"`
+ Owner string `json:"owner"`
+ Repository string `json:"repo"`
+ Status string `json:"status"`
+ PostID string `json:"postId"`
+}
+
+type OpenCreateCommentOrEditIssueModalRequestBody struct {
+ RepoOwner string `json:"repo_owner"`
+ RepoName string `json:"repo_name"`
+ IssueNumber int `json:"issue_number"`
+ PostID string `json:"postId"`
+ Status string `json:"status"`
+}
diff --git a/server/serializer/notification.go b/server/serializer/notification.go
new file mode 100644
index 000000000..236e6da56
--- /dev/null
+++ b/server/serializer/notification.go
@@ -0,0 +1,8 @@
+package serializer
+
+import "github.com/google/go-github/v48/github"
+
+type FilteredNotification struct {
+ github.Notification
+ HTMLUrl string `json:"html_url"`
+}
diff --git a/server/serializer/pr.go b/server/serializer/pr.go
new file mode 100644
index 000000000..01f9f0c37
--- /dev/null
+++ b/server/serializer/pr.go
@@ -0,0 +1,12 @@
+package serializer
+
+import "github.com/google/go-github/v48/github"
+
+type PRDetails struct {
+ URL string `json:"url"`
+ Number int `json:"number"`
+ Status string `json:"status"`
+ Mergeable bool `json:"mergeable"`
+ RequestedReviewers []*string `json:"requestedReviewers"`
+ Reviews []*github.PullRequestReview `json:"reviews"`
+}
diff --git a/server/serializer/repo.go b/server/serializer/repo.go
new file mode 100644
index 000000000..a7d3eaf7e
--- /dev/null
+++ b/server/serializer/repo.go
@@ -0,0 +1,8 @@
+package serializer
+
+// Only send down fields to the client that are needed
+type RepositoryResponse struct {
+ Name string `json:"name,omitempty"`
+ FullName string `json:"full_name,omitempty"`
+ Permissions map[string]bool `json:"permissions,omitempty"`
+}
diff --git a/server/serializer/user.go b/server/serializer/user.go
new file mode 100644
index 000000000..9c1342e4a
--- /dev/null
+++ b/server/serializer/user.go
@@ -0,0 +1,62 @@
+package serializer
+
+import (
+ "context"
+
+ "github.com/mattermost/mattermost-plugin-api/experimental/bot/logger"
+ "golang.org/x/oauth2"
+)
+
+type Context struct {
+ Ctx context.Context
+ UserID string
+ Log logger.Logger
+}
+
+type GitHubUserRequest struct {
+ UserID string `json:"user_id"`
+}
+
+type GitHubUserResponse struct {
+ Username string `json:"username"`
+}
+
+type ConnectedResponse struct {
+ Connected bool `json:"connected"`
+ GitHubUsername string `json:"github_username"`
+ GitHubClientID string `json:"github_client_id"`
+ EnterpriseBaseURL string `json:"enterprise_base_url,omitempty"`
+ Organization string `json:"organization"`
+ UserSettings *UserSettings `json:"user_settings"`
+ ClientConfiguration map[string]interface{} `json:"configuration"`
+}
+
+type UserSettings struct {
+ SidebarButtons string `json:"sidebar_buttons"`
+ DailyReminder bool `json:"daily_reminder"`
+ DailyReminderOnChange bool `json:"daily_reminder_on_change"`
+ Notifications bool `json:"notifications"`
+}
+
+type GitHubUserInfo struct {
+ UserID string
+ Token *oauth2.Token
+ GitHubUsername string
+ LastToDoPostAt int64
+ Settings *UserSettings
+ AllowedPrivateRepos bool
+
+ // MM34646ResetTokenDone is set for a user whose token has been reset for MM-34646.
+ MM34646ResetTokenDone bool
+}
+
+type UserContext struct {
+ Context
+ GHInfo *GitHubUserInfo
+}
+
+type OAuthState struct {
+ UserID string `json:"user_id"`
+ Token string `json:"token"`
+ PrivateAllowed bool `json:"private_allowed"`
+}
diff --git a/webapp/src/action_types/index.js b/webapp/src/action_types/index.js
index 88da0997b..f46990850 100644
--- a/webapp/src/action_types/index.js
+++ b/webapp/src/action_types/index.js
@@ -17,9 +17,11 @@ export default {
RECEIVED_GITHUB_USER: pluginId + '_received_github_user',
RECEIVED_SHOW_RHS_ACTION: pluginId + '_received_rhs_action',
UPDATE_RHS_STATE: pluginId + '_update_rhs_state',
- CLOSE_CREATE_ISSUE_MODAL: pluginId + '_close_create_modal',
- OPEN_CREATE_ISSUE_MODAL: pluginId + '_open_create_modal',
- OPEN_CREATE_ISSUE_MODAL_WITHOUT_POST: pluginId + '_open_create_modal_without_post',
+ CLOSE_CREATE_OR_UPDATE_ISSUE_MODAL: pluginId + '_close_create_or_update_issue_modal',
+ CLOSE_CLOSE_OR_REOPEN_ISSUE_MODAL: pluginId + '_close_close_or_reopen_issue_modal',
+ OPEN_CREATE_ISSUE_MODAL_WITH_POST: pluginId + '_open_create_issue_modal_with_post',
+ OPEN_CLOSE_OR_REOPEN_ISSUE_MODAL: pluginId + '_open_close_or_reopen_issue_modal',
+ OPEN_CREATE_OR_UPDATE_ISSUE_MODAL: pluginId + '_open_create_or_update_issue_modal',
CLOSE_ATTACH_COMMENT_TO_ISSUE_MODAL: pluginId + '_close_attach_modal',
OPEN_ATTACH_COMMENT_TO_ISSUE_MODAL: pluginId + '_open_attach_modal',
RECEIVED_ATTACH_COMMENT_RESULT: pluginId + '_received_attach_comment',
diff --git a/webapp/src/actions/index.js b/webapp/src/actions/index.js
index 1788ae959..17935a1e9 100644
--- a/webapp/src/actions/index.js
+++ b/webapp/src/actions/index.js
@@ -211,6 +211,60 @@ export function getMilestoneOptions(repo) {
};
}
+export function attachCommentIssueModal(payload) {
+ return async (dispatch, getState) => {
+ let data;
+ try {
+ data = await Client.attachCommentIssueModal(payload);
+ } catch (error) {
+ return {error};
+ }
+
+ const connected = await checkAndHandleNotConnected(data)(dispatch, getState);
+ if (!connected) {
+ return {error: data};
+ }
+
+ return {data};
+ };
+}
+
+export function editIssueModal(payload) {
+ return async (dispatch, getState) => {
+ let data;
+ try {
+ data = await Client.editIssueModal(payload);
+ } catch (error) {
+ return {error};
+ }
+
+ const connected = await checkAndHandleNotConnected(data)(dispatch, getState);
+ if (!connected) {
+ return {error: data};
+ }
+
+ return {data};
+ };
+}
+
+export function closeOrReopenIssueModal(payload) {
+ return async (dispatch, getState) => {
+ let data;
+ try {
+ data = await Client.closeOrReopenIssueModal(payload);
+ } catch (error) {
+ return {error};
+ }
+
+ const connected = await checkAndHandleNotConnected(data)(dispatch, getState);
+ if (!connected) {
+ return {error: data};
+ }
+
+ return {data};
+ };
+}
+
export function getYourAssignments() {
return async (dispatch, getState) => {
let data;
@@ -339,28 +393,51 @@ export function updateRhsState(rhsState) {
};
}
-export function openCreateIssueModal(postId) {
+export function openCreateIssueModalWithPost(postId) {
return {
- type: ActionTypes.OPEN_CREATE_ISSUE_MODAL,
+ type: ActionTypes.OPEN_CREATE_ISSUE_MODAL_WITH_POST,
data: {
postId,
},
};
}
-export function openCreateIssueModalWithoutPost(title, channelId) {
+export function openCreateOrUpdateIssueModal(messageData) {
return {
- type: ActionTypes.OPEN_CREATE_ISSUE_MODAL_WITHOUT_POST,
+ type: ActionTypes.OPEN_CREATE_OR_UPDATE_ISSUE_MODAL,
data: {
- title,
- channelId,
+ messageData,
},
};
}
-export function closeCreateIssueModal() {
+export function openCloseOrReopenIssueModal(messageData) {
return {
- type: ActionTypes.CLOSE_CREATE_ISSUE_MODAL,
+ type: ActionTypes.OPEN_CLOSE_OR_REOPEN_ISSUE_MODAL,
+ data: {
+ messageData,
+ },
+ };
+}
+
+export function openCreateCommentOnIssueModal(messageData) {
+ return {
+ type: ActionTypes.OPEN_ATTACH_COMMENT_TO_ISSUE_MODAL,
+ data: {
+ messageData,
+ },
+ };
+}
+
+export function closeCreateOrUpdateIssueModal() {
+ return {
+ type: ActionTypes.CLOSE_CREATE_OR_UPDATE_ISSUE_MODAL,
+ };
+}
+
+export function closeCloseOrReOpenIssueModal() {
+ return {
+ type: ActionTypes.CLOSE_CLOSE_OR_REOPEN_ISSUE_MODAL,
};
}
@@ -382,6 +459,42 @@ export function createIssue(payload) {
};
}
+export function closeOrReopenIssue(payload) {
+ return async (dispatch) => {
+ let data;
+ try {
+ data = await Client.closeOrReopenIssue(payload);
+ } catch (error) {
+ return {error};
+ }
+
+ const connected = await dispatch(checkAndHandleNotConnected(data));
+ if (!connected) {
+ return {error: data};
+ }
+
+ return {data};
+ };
+}
+
+export function updateIssue(payload) {
+ return async (dispatch) => {
+ let data;
+ try {
+ data = await Client.updateIssue(payload);
+ } catch (error) {
+ return {error};
+ }
+
+ const connected = await dispatch(checkAndHandleNotConnected(data));
+ if (!connected) {
+ return {error: data};
+ }
+
+ return {data};
+ };
+}
+
export function openAttachCommentToIssueModal(postId) {
return {
type: ActionTypes.OPEN_ATTACH_COMMENT_TO_ISSUE_MODAL,
diff --git a/webapp/src/client/client.js b/webapp/src/client/client.js
index 25d6f3f9c..5ebcdb510 100644
--- a/webapp/src/client/client.js
+++ b/webapp/src/client/client.js
@@ -7,6 +7,18 @@ import {ClientError} from 'mattermost-redux/client/client4';
import {id as pluginId} from '../manifest';
export default class Client {
+ editIssueModal = async (payload) => {
+ return this.doPost(`${this.url}/editissuemodal`, payload);
+ }
+
+ closeOrReopenIssueModal = async (payload) => {
+ return this.doPost(`${this.url}/closereopenissuemodal`, payload);
+ }
+
+ attachCommentIssueModal = async (payload) => {
+ return this.doPost(`${this.url}/attachcommentissuemodal`, payload);
+ }
+
setServerRoute(url) {
this.url = url + `/plugins/${pluginId}/api/v1`;
}
@@ -63,6 +75,14 @@ export default class Client {
return this.doPost(`${this.url}/createissue`, payload);
}
+ closeOrReopenIssue = async (payload) => {
+ return this.doPost(`${this.url}/closeorreopenissue`, payload);
+ }
+
+ updateIssue = async (payload) => {
+ return this.doPost(`${this.url}/updateissue`, payload);
+ }
+
searchIssues = async (searchTerm) => {
return this.doGet(`${this.url}/searchissues?term=${searchTerm}`);
}
diff --git a/webapp/src/components/github_issue/index.tsx b/webapp/src/components/github_issue/index.tsx
new file mode 100644
index 000000000..9edeee267
--- /dev/null
+++ b/webapp/src/components/github_issue/index.tsx
@@ -0,0 +1,118 @@
+import * as React from 'react';
+import {makeStyleFromTheme} from 'mattermost-redux/utils/theme_utils';
+import {Theme} from 'mattermost-redux/types/preferences';
+import {Post} from 'mattermost-redux/types/posts';
+import {useDispatch} from 'react-redux';
+
+import {attachCommentIssueModal, editIssueModal, closeOrReopenIssueModal} from '../../actions';
+
+type GithubIssueProps = {
+ theme: Theme,
+ post: Post,
+}
+
+const GithubIssue = ({theme, post}: GithubIssueProps) => {
+ const style = getStyle(theme);
+ const postProps = post.props || {};
+ let assignees;
+ let labels;
+ const dispatch = useDispatch();
+
+ const issue = {
+ repo_owner: postProps.repo_owner,
+ repo_name: postProps.repo_name,
+ issue_number: postProps.issue_number,
+ postId: post.id,
+ status: postProps.status,
+ };
+
+ const content = (
+
+
+
+
+
+ );
+
+ if (postProps.assignees?.length) {
+ assignees = (
+
+
{'Assignees'}
+
+ {postProps.assignees.map((assignee: string, index: number) => (
+ {(index ? ', ' : '') + assignee}
+ ))}
+
+
+ );
+ }
+
+ if (postProps.labels?.length) {
+ labels = (
+
+
{'Labels'}
+
+ {postProps.labels.map((label: string, index: number) => (
+ {(index ? ', ' : '') + label}
+ ))}
+
+
+ );
+ }
+
+ return (
+
+
+
{postProps.description}
+ {assignees}
+ {labels}
+ {content}
+
+ );
+};
+
+const getStyle = makeStyleFromTheme((theme) => ({
+ button: {
+ fontFamily: 'Open Sans',
+ fontSize: '12px',
+ fontWeight: 'bold',
+ letterSpacing: '1px',
+ lineHeight: '19px',
+ margin: '12px 12px 8px 0px',
+ borderRadius: '4px',
+ color: theme.buttonColor,
+ },
+ close_or_reopen_button: {
+ backgroundColor: theme.errorTextColor,
+ },
+ other_buttons: {
+ backgroundColor: theme.buttonBg,
+ },
+ assignees_and_labels: {
+ display: 'inline-block',
+ verticalAlign: 'top',
+ width: '30%',
+ },
+}));
+
+export default GithubIssue;
diff --git a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
index 703adc28f..f959f884a 100644
--- a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
+++ b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
@@ -12,6 +12,7 @@ import GithubIssueSelector from 'components/github_issue_selector';
import {getErrorMessage} from 'utils/user_utils';
const initialState = {
+ comment: '',
submitting: false,
issueValue: null,
textSearchTerms: '',
@@ -25,6 +26,7 @@ export default class AttachIssueModal extends PureComponent {
post: PropTypes.object,
theme: PropTypes.object.isRequired,
visible: PropTypes.bool.isRequired,
+ messageData: PropTypes.object,
};
constructor(props) {
@@ -38,6 +40,25 @@ export default class AttachIssueModal extends PureComponent {
}
if (!this.state.issueValue) {
+ const {owner, repo, number} = this.props.messageData ?? {};
+ const issue = {
+ owner,
+ repo,
+ number,
+ comment: this.state.comment,
+ post_id: this.props.post.id,
+ show_attached_message: false,
+ };
+ this.setState({submitting: true});
+
+ this.props.create(issue).then((created) => {
+ if (created.error) {
+ const errMessage = getErrorMessage(created.error.message);
+ this.setState({error: errMessage, submitting: false});
+ return;
+ }
+ this.handleClose(e);
+ });
return;
}
@@ -53,6 +74,7 @@ export default class AttachIssueModal extends PureComponent {
number,
comment: this.props.post.message,
post_id: this.props.post.id,
+ show_attached_message: true,
};
this.setState({submitting: true});
@@ -68,6 +90,8 @@ export default class AttachIssueModal extends PureComponent {
});
};
+ handleIssueCommentChange = (comment) => this.setState({comment});
+
handleClose = (e) => {
if (e && e.preventDefault) {
e.preventDefault();
@@ -83,15 +107,25 @@ export default class AttachIssueModal extends PureComponent {
};
render() {
- const {visible, theme} = this.props;
- const {error, submitting} = this.state;
+ const {error, submitting, comment, issueValue} = this.state;
+ const {visible, theme, messageData, post} = this.props;
const style = getStyle(theme);
-
if (!visible) {
return null;
}
- const component = (
+ const {number} = messageData ?? {};
+ const modalTitle = number ? 'Create a comment to GitHub Issue' : 'Attach Message to GitHub Issue';
+ const component = number ? (
+
+
+
+ ) : (
);
diff --git a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
index f959f884a..a674b6cac 100644
--- a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
+++ b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
@@ -40,11 +40,11 @@ export default class AttachIssueModal extends PureComponent {
}
if (!this.state.issueValue) {
- const {owner, repo, number} = this.props.messageData ?? {};
+ const {repo_owner, repo_name, issue_number} = this.props.messageData ?? {};
const issue = {
- owner,
- repo,
- number,
+ owner: repo_owner,
+ repo: repo_name,
+ number: issue_number,
comment: this.state.comment,
post_id: this.props.post.id,
show_attached_message: false,
@@ -72,7 +72,7 @@ export default class AttachIssueModal extends PureComponent {
owner,
repo,
number,
- comment: this.props.post.message,
+ comment: this.state.comment,
post_id: this.props.post.id,
show_attached_message: true,
};
@@ -106,17 +106,23 @@ export default class AttachIssueModal extends PureComponent {
});
};
+ componentDidUpdate(prevProps) {
+ if (this.props.post && !this.props.messageData && !prevProps.post) {
+ this.setState({comment: this.props.post.message}); // eslint-disable-line react/no-did-update-set-state
+ }
+ }
+
render() {
const {error, submitting, comment, issueValue} = this.state;
- const {visible, theme, messageData, post} = this.props;
+ const {visible, theme, messageData} = this.props;
const style = getStyle(theme);
if (!visible) {
return null;
}
- const {number} = messageData ?? {};
- const modalTitle = number ? 'Create a comment to GitHub Issue' : 'Attach Message to GitHub Issue';
- const component = number ? (
+ const {issue_number} = messageData ?? {};
+ const modalTitle = issue_number ? 'Create a comment to GitHub Issue' : 'Attach Message to GitHub Issue';
+ const component = issue_number ? (
);
diff --git a/webapp/src/components/modals/close_reopen_issue/index.tsx b/webapp/src/components/modals/close_reopen_issue/index.tsx
index 5e793a19a..a78c4cb25 100644
--- a/webapp/src/components/modals/close_reopen_issue/index.tsx
+++ b/webapp/src/components/modals/close_reopen_issue/index.tsx
@@ -36,9 +36,9 @@ const CloseOrReopenIssueModal = ({theme}: {theme: Theme}) => {
channel_id: messageData.channel_id,
issue_comment: comment,
status_reason: currentStatus,
- repo: messageData.repo,
- number: messageData.number,
- owner: messageData.owner,
+ repo: messageData.repo_name,
+ number: messageData.issue_number,
+ owner: messageData.repo_owner,
status: messageData.status,
postId: messageData.postId,
};
diff --git a/webapp/src/components/modals/create_update_issue/create_update_issue.jsx b/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
index 2a8bbab83..7ad0983f1 100644
--- a/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
+++ b/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
@@ -22,6 +22,7 @@ const initialState = {
repo: null,
issueTitle: '',
issueDescription: '',
+ channelId: '',
labels: [],
assignees: [],
milestone: null,
@@ -34,6 +35,7 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
update: PropTypes.func.isRequired,
close: PropTypes.func.isRequired,
create: PropTypes.func.isRequired,
+ getIssueInfo: PropTypes.func.isRequired,
post: PropTypes.object,
theme: PropTypes.object.isRequired,
visible: PropTypes.bool.isRequired,
@@ -46,36 +48,50 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
this.validator = new Validator();
}
+ getIssueInfo = async () => {
+ const {repo_owner, repo_name, issue_number, postId} = this.props.messageData;
+ const issueInfo = await this.props.getIssueInfo(repo_owner, repo_name, issue_number, postId);
+ return issueInfo;
+ }
+
+ updateState(issueInfo) {
+ const {channel_id, title, description, milestone_title, milestone_number, repo_full_name} = issueInfo ?? {};
+ const assignees = issueInfo?.assignees ?? [];
+ const labels = issueInfo?.labels ?? [];
+
+ this.setState({milestone: {
+ value: milestone_number,
+ label: milestone_title,
+ },
+ repo: {
+ name: repo_full_name,
+ },
+ assignees,
+ labels,
+ channelId: channel_id,
+ issueDescription: description,
+ issueTitle: title.substring(0, MAX_TITLE_LENGTH)});
+ }
+
/* eslint-disable react/no-did-update-set-state*/
componentDidUpdate(prevProps) {
- if (this.props.post && !this.props.messageData) {
+ if (this.props.post && !this.props.messageData && !prevProps.post) {
this.setState({issueDescription: this.props.post.message});
}
- const {channel_id, title, description, assignees, labels, milestone_title, milestone_number, repo_full_name} = this.props.messageData ?? {};
- if (channel_id && (channel_id !== prevProps.messageData?.channel_id || title !== prevProps.messageData?.title || description !== prevProps.messageData?.description || assignees !== prevProps.messageData?.assignees || labels !== prevProps.messageData?.labels || milestone_title !== prevProps.messageData?.milestone_title || milestone_number !== prevProps.messageData?.milestone_number)) {
- if (assignees) {
- this.setState({assignees});
- }
- if (labels) {
- this.setState({labels});
- }
- this.setState({milestone: {
- value: milestone_number,
- label: milestone_title,
- },
- repo: {
- name: repo_full_name,
- },
- issueDescription: description,
- issueTitle: title.substring(0, MAX_TITLE_LENGTH)});
+ if (this.props.messageData?.repo_owner && !prevProps.visible && this.props.visible) {
+ this.getIssueInfo().then((issueInfo) => {
+ this.updateState(issueInfo.data);
+ });
+ } else if (this.props.messageData?.channel_id && (this.props.messageData?.channel_id !== prevProps.messageData?.channel_id || this.props.messageData?.title !== prevProps.messageData?.title)) {
+ this.updateState(this.props.messageData);
}
}
/* eslint-enable */
// handle issue creation or updation after form is populated
handleCreateOrUpdate = async (e) => {
- const {channel_id, issue_number, repo_full_name} = this.props.messageData ?? {};
+ const {issue_number} = this.props.messageData ?? {};
if (e && e.preventDefault) {
e.preventDefault();
}
@@ -99,7 +115,7 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
assignees: this.state.assignees,
milestone: this.state.milestone && this.state.milestone.value,
post_id: postId,
- channel_id,
+ channel_id: this.state.channelId,
issue_number,
};
@@ -107,7 +123,7 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
issue.repo = this.state.repo;
}
this.setState({submitting: true});
- if (repo_full_name) {
+ if (issue_number) {
const updated = await this.props.update(issue);
if (updated?.error) {
const errMessage = getErrorMessage(updated.error.message);
@@ -233,6 +249,7 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
onChange={this.handleIssueTitleChange}
/>
{issueTitleValidationError}
+
{this.renderIssueAttributeSelectors()}
bindActionCreators({
close: closeCreateOrUpdateIssueModal,
create: createIssue,
update: updateIssue,
+ getIssueInfo,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(CreateOrUpdateIssueModal);
diff --git a/webapp/src/index.js b/webapp/src/index.js
index 0a7a18a42..9b79a57da 100644
--- a/webapp/src/index.js
+++ b/webapp/src/index.js
@@ -15,7 +15,7 @@ import GithubIssue from './components/github_issue';
import Reducer from './reducers';
import Client from './client';
import {getConnected, setShowRHSAction} from './actions';
-import {handleConnect, handleDisconnect, handleConfigurationUpdate, handleOpenCreateOrUpdateIssueModal, handleOpenCreateCommentOnIssueModal, handleOpenCloseOrReopenIssueModal, handleReconnect, handleRefresh} from './websocket';
+import {handleConnect, handleDisconnect, handleConfigurationUpdate, handleOpenCreateOrUpdateIssueModal, handleReconnect, handleRefresh} from './websocket';
import {getServerRoute} from './selectors';
import {id as pluginId} from './manifest';
@@ -47,9 +47,7 @@ class PluginClass {
registry.registerWebSocketEventHandler(`custom_${pluginId}_disconnect`, handleDisconnect(store));
registry.registerWebSocketEventHandler(`custom_${pluginId}_config_update`, handleConfigurationUpdate(store));
registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, handleRefresh(store));
- registry.registerWebSocketEventHandler(`custom_${pluginId}_createOrUpdateIssue`, handleOpenCreateOrUpdateIssueModal(store));
- registry.registerWebSocketEventHandler(`custom_${pluginId}_attachCommentToIssue`, handleOpenCreateCommentOnIssueModal(store));
- registry.registerWebSocketEventHandler(`custom_${pluginId}_closeOrReopenIssue`, handleOpenCloseOrReopenIssueModal(store));
+ registry.registerWebSocketEventHandler(`custom_${pluginId}_createIssue`, handleOpenCreateOrUpdateIssueModal(store));
registry.registerPostTypeComponent('custom_git_issue', GithubIssue);
registry.registerReconnectHandler(handleReconnect(store));
diff --git a/webapp/src/websocket/index.js b/webapp/src/websocket/index.js
index 88690dc55..3a91692cf 100644
--- a/webapp/src/websocket/index.js
+++ b/webapp/src/websocket/index.js
@@ -10,8 +10,6 @@ import {
getYourAssignments,
getYourPrs,
openCreateOrUpdateIssueModal,
- openCloseOrReopenIssueModal,
- openCreateCommentOnIssueModal,
} from '../actions';
import {id as pluginId} from '../manifest';
@@ -95,21 +93,3 @@ export function handleOpenCreateOrUpdateIssueModal(store) {
store.dispatch(openCreateOrUpdateIssueModal(msg.data));
};
}
-
-export function handleOpenCloseOrReopenIssueModal(store) {
- return (msg) => {
- if (!msg.data) {
- return;
- }
- store.dispatch(openCloseOrReopenIssueModal(msg.data));
- };
-}
-
-export function handleOpenCreateCommentOnIssueModal(store) {
- return (msg) => {
- if (!msg.data) {
- return;
- }
- store.dispatch(openCreateCommentOnIssueModal(msg.data));
- };
-}
From 0f40aba448ee44aeef6614a87f63b496d1fa5673 Mon Sep 17 00:00:00 2001
From: ayusht2810
Date: Wed, 10 Apr 2024 17:29:59 +0530
Subject: [PATCH 05/18] [MM-618] Update validations, modal title, styling, post
messages, conflicts error and lint errors
---
server/constants/constants.go | 18 +++++------
server/plugin/api.go | 16 +++++++---
server/plugin/api_test.go | 2 +-
server/plugin/command.go | 6 ++--
server/plugin/mm_34646_token_refresh.go | 1 +
server/plugin/utils.go | 9 +++---
server/plugin/webhook.go | 4 +--
server/serializer/user.go | 2 +-
webapp/src/components/input.jsx | 5 +--
.../attach_comment_to_issue.jsx | 9 +++++-
.../components/modals/create_issue/index.js | 31 -------------------
.../create_update_issue.jsx | 19 +++++++-----
webapp/src/selectors.js | 6 ++--
13 files changed, 60 insertions(+), 68 deletions(-)
delete mode 100644 webapp/src/components/modals/create_issue/index.js
diff --git a/server/constants/constants.go b/server/constants/constants.go
index 88c0fdc42..985f81ae9 100644
--- a/server/constants/constants.go
+++ b/server/constants/constants.go
@@ -34,15 +34,15 @@ const (
IssueOpen = "open"
// Actions of webhook events
- ActionOpened = "opened"
- ActionClosed = "closed"
- ActionReopened = "reopened"
- ActionSubmitted = "submitted"
- ActionLabeled = "labeled"
- ActionAssigned = "assigned"
- ActionCreated = "created"
- ActionDeleted = "deleted"
- ActionEdited = "edited"
+ ActionOpened = "opened"
+ ActionClosed = "closed"
+ ActionReopened = "reopened"
+ ActionSubmitted = "submitted"
+ ActionLabeled = "labeled"
+ ActionAssigned = "assigned"
+ ActionCreated = "created"
+ ActionDeleted = "deleted"
+ ActionEdited = "edited"
ActionMarkedReadyForReview = "ready_for_review"
PostPropGithubRepo = "gh_repo"
diff --git a/server/plugin/api.go b/server/plugin/api.go
index bd89e0c7e..dae066aa4 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -836,7 +836,11 @@ func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWr
rootID = post.RootId
}
- permalinkReplyMessage := fmt.Sprintf("[Message](%v) attached to GitHub issue [#%v](%v)", permalink, req.Number, result.GetHTMLURL())
+ permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v) from a [Message](%v)", req.Number, result.GetHTMLURL(), permalink)
+ if req.ShowAttachedMessage {
+ permalinkReplyMessage = fmt.Sprintf("[Message](%v) attached to GitHub issue [#%v](%v)", permalink, req.Number, result.GetHTMLURL())
+ }
+
reply := &model.Post{
Message: permalinkReplyMessage,
ChannelId: post.ChannelId,
@@ -972,8 +976,7 @@ func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter,
description := ""
if issue.Body != nil {
- *issue.Body = mdCommentRegex.ReplaceAllString(issue.GetBody(), "")
- description = *issue.Body
+ description = mdCommentRegex.ReplaceAllString(issue.GetBody(), "")
}
assignees := make([]string, len(issue.Assignees))
@@ -995,6 +998,7 @@ func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter,
post, appErr := p.API.GetPost(postID)
if appErr != nil {
+ p.client.Log.Error("Unable to get the post", "PostID", postID, "Error", appErr.Error())
p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", postID), StatusCode: http.StatusInternalServerError})
return
}
@@ -1288,6 +1292,7 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
var appErr *model.AppError
post, appErr = p.API.GetPost(issue.PostID)
if appErr != nil {
+ p.client.Log.Error("Unable to get the post", "PostID", issue.PostID, "Error", appErr.Error())
p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
@@ -1313,6 +1318,7 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
currentUser, appErr := p.API.GetUser(c.UserID)
if appErr != nil {
+ p.client.Log.Error("Unable to get the user", "UserID", c.UserID, "Error", appErr.Error())
p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
return
}
@@ -1387,6 +1393,7 @@ func (p *Plugin) closeOrReopenIssue(c *serializer.UserContext, w http.ResponseWr
post, appErr := p.API.GetPost(req.PostID)
if appErr != nil {
+ p.client.Log.Error("Unable to get the post", "PostID", req.PostID, "Error", appErr.Error())
p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
@@ -1396,6 +1403,7 @@ func (p *Plugin) closeOrReopenIssue(c *serializer.UserContext, w http.ResponseWr
}
if _, err := p.getUsername(post.UserId); err != nil {
+ p.client.Log.Error("Unable to get the username", "UserID", post.UserId, "Error", err.Error())
p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
@@ -1441,7 +1449,7 @@ func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r
var err error
post, err = p.client.Post.GetPost(issue.PostID)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
diff --git a/server/plugin/api_test.go b/server/plugin/api_test.go
index 40931a0d7..fe013ec55 100644
--- a/server/plugin/api_test.go
+++ b/server/plugin/api_test.go
@@ -12,7 +12,7 @@ import (
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/plugin/plugintest"
"github.com/mattermost/mattermost/server/public/pluginapi"
-
+
"github.com/mattermost/mattermost-plugin-github/server/constants"
"github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-plugin-github/server/testutils"
diff --git a/server/plugin/command.go b/server/plugin/command.go
index e06dfc33c..55572c83a 100644
--- a/server/plugin/command.go
+++ b/server/plugin/command.go
@@ -7,14 +7,14 @@ import (
"unicode"
"github.com/google/go-github/v48/github"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
-
"github.com/pkg/errors"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/command"
+
+ "github.com/mattermost/mattermost-plugin-github/server/constants"
+ "github.com/mattermost/mattermost-plugin-github/server/serializer"
)
const (
diff --git a/server/plugin/mm_34646_token_refresh.go b/server/plugin/mm_34646_token_refresh.go
index 0b5064950..e1dd0a3fa 100644
--- a/server/plugin/mm_34646_token_refresh.go
+++ b/server/plugin/mm_34646_token_refresh.go
@@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/mattermost/mattermost-plugin-github/server/serializer"
+
"github.com/mattermost/mattermost/server/public/pluginapi/cluster"
)
diff --git a/server/plugin/utils.go b/server/plugin/utils.go
index 05358aab2..9d161254d 100644
--- a/server/plugin/utils.go
+++ b/server/plugin/utils.go
@@ -16,12 +16,13 @@ import (
"strings"
"unicode"
+ "github.com/google/go-github/v48/github"
+ "github.com/pkg/errors"
+
"github.com/mattermost/mattermost-plugin-github/server/constants"
"github.com/mattermost/mattermost-plugin-github/server/serializer"
- "github.com/mattermost/mattermost/server/public/model"
- "github.com/google/go-github/v48/github"
- "github.com/pkg/errors"
+ "github.com/mattermost/mattermost/server/public/model"
)
func getMentionSearchQuery(username, org string) string {
@@ -427,7 +428,7 @@ func (p *Plugin) CreateCommentToIssue(c *serializer.UserContext, w http.Response
rootID = post.RootId
}
- permalinkReplyMessage := fmt.Sprintf("[Comment](%v) attached to GitHub issue [#%v](%v)", permalink, issueNumber, result.GetHTMLURL())
+ permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v) from a [message](%v)", issueNumber, result.GetHTMLURL(), permalink)
reply := &model.Post{
Message: permalinkReplyMessage,
ChannelId: post.ChannelId,
diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go
index 98dbc916d..e5bfe6ed6 100644
--- a/server/plugin/webhook.go
+++ b/server/plugin/webhook.go
@@ -337,8 +337,8 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
action := event.GetAction()
switch action {
case constants.ActionOpened,
- constants.ActionReopened,
- constants.ActionMarkedReadyForReview,
+ constants.ActionReopened,
+ constants.ActionMarkedReadyForReview,
constants.ActionLabeled,
constants.ActionClosed:
default:
diff --git a/server/serializer/user.go b/server/serializer/user.go
index 1927e7018..e37f4e410 100644
--- a/server/serializer/user.go
+++ b/server/serializer/user.go
@@ -3,8 +3,8 @@ package serializer
import (
"context"
- "golang.org/x/oauth2"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger"
+ "golang.org/x/oauth2"
)
type Context struct {
diff --git a/webapp/src/components/input.jsx b/webapp/src/components/input.jsx
index 324cbdcd3..c9392c3f3 100644
--- a/webapp/src/components/input.jsx
+++ b/webapp/src/components/input.jsx
@@ -16,6 +16,7 @@ export default class Input extends PureComponent {
PropTypes.string,
PropTypes.number,
]),
+ error: PropTypes.string,
addValidate: PropTypes.func,
removeValidate: PropTypes.func,
maxLength: PropTypes.number,
@@ -84,10 +85,10 @@ export default class Input extends PureComponent {
const value = this.props.value || '';
let validationError = null;
- if (this.props.required && this.state.invalid) {
+ if ((this.props.required && this.state.invalid) || this.props.error) {
validationError = (
- {requiredMsg}
+ {requiredMsg || this.props.error}
);
}
diff --git a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
index a674b6cac..2096f60e8 100644
--- a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
+++ b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
@@ -40,6 +40,11 @@ export default class AttachIssueModal extends PureComponent {
}
if (!this.state.issueValue) {
+ if (!this.state.comment.trim()) {
+ this.setState({error: 'This field is required.', submitting: false});
+ return;
+ }
+
const {repo_owner, repo_name, issue_number} = this.props.messageData ?? {};
const issue = {
owner: repo_owner,
@@ -90,7 +95,7 @@ export default class AttachIssueModal extends PureComponent {
});
};
- handleIssueCommentChange = (comment) => this.setState({comment});
+ handleIssueCommentChange = (comment) => this.setState({comment, error: ''});
handleClose = (e) => {
if (e && e.preventDefault) {
@@ -127,7 +132,9 @@ export default class AttachIssueModal extends PureComponent {
diff --git a/webapp/src/components/modals/create_issue/index.js b/webapp/src/components/modals/create_issue/index.js
deleted file mode 100644
index e75562886..000000000
--- a/webapp/src/components/modals/create_issue/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import {connect} from 'react-redux';
-import {bindActionCreators} from 'redux';
-import {getPost} from 'mattermost-redux/selectors/entities/posts';
-
-import manifest from 'manifest';
-import {closeCreateIssueModal, createIssue} from 'actions';
-
-import CreateIssueModal from './create_issue';
-
-const mapStateToProps = (state) => {
- const {id: pluginId} = manifest;
- const {postId, title, channelId} = state[`plugins-${pluginId}`].createIssueModal;
- const post = (postId) ? getPost(state, postId) : null;
-
- return {
- visible: state[`plugins-${pluginId}`].isCreateIssueModalVisible,
- post,
- title,
- channelId,
- };
-};
-
-const mapDispatchToProps = (dispatch) => bindActionCreators({
- close: closeCreateIssueModal,
- create: createIssue,
-}, dispatch);
-
-export default connect(mapStateToProps, mapDispatchToProps)(CreateIssueModal);
diff --git a/webapp/src/components/modals/create_update_issue/create_update_issue.jsx b/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
index 7ad0983f1..0240b5063 100644
--- a/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
+++ b/webapp/src/components/modals/create_update_issue/create_update_issue.jsx
@@ -205,16 +205,21 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
}
const theme = this.props.theme;
- const {error, submitting, showErrors, issueTitleValid, issueTitle, issueDescription, repo} = this.state;
+ const {error, submitting, showErrors, issueTitle, issueDescription, repo} = this.state;
const style = getStyle(theme);
- const {repo_full_name} = this.props.messageData ?? {};
- const modalTitle = repo_full_name ? 'Update GitHub Issue' : 'Create GitHub Issue';
+ const {repo_name, repo_owner} = this.props.messageData ?? {};
+ const modalTitle = repo_name ? 'Update GitHub Issue' : 'Create GitHub Issue';
const requiredMsg = 'This field is required.';
let issueTitleValidationError = null;
- if (showErrors && !issueTitleValid) {
+ if (showErrors && !issueTitle) {
issueTitleValidationError = (
-
+
{requiredMsg}
);
@@ -229,14 +234,14 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
);
}
- const component = repo_full_name ? (
+ const component = repo_name ? (
Date: Wed, 1 May 2024 17:37:14 +0530
Subject: [PATCH 06/18] [MM-618] Remove constants and serializers package
---
server/constants/constants.go | 55 ----
server/plugin/api.go | 318 +++++++++++++----------
server/plugin/api_test.go | 6 +-
server/plugin/command.go | 41 ++-
server/{serializer => plugin}/error.go | 2 +-
server/plugin/mm_34646_token_refresh.go | 6 +-
server/plugin/oauth.go | 58 +++++
server/plugin/plugin.go | 117 ++++++---
server/{serializer => plugin}/sidebar.go | 7 +-
server/plugin/utils.go | 51 ++--
server/plugin/webhook.go | 110 ++++----
server/serializer/issue.go | 44 ----
server/serializer/notification.go | 8 -
server/serializer/pr.go | 12 -
server/serializer/repo.go | 8 -
server/serializer/user.go | 62 -----
16 files changed, 436 insertions(+), 469 deletions(-)
delete mode 100644 server/constants/constants.go
rename server/{serializer => plugin}/error.go (91%)
rename server/{serializer => plugin}/sidebar.go (84%)
delete mode 100644 server/serializer/issue.go
delete mode 100644 server/serializer/notification.go
delete mode 100644 server/serializer/pr.go
delete mode 100644 server/serializer/repo.go
delete mode 100644 server/serializer/user.go
diff --git a/server/constants/constants.go b/server/constants/constants.go
deleted file mode 100644
index 985f81ae9..000000000
--- a/server/constants/constants.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package constants
-
-import "time"
-
-const (
- APIErrorIDNotConnected = "not_connected"
- // TokenTTL is the OAuth token expiry duration in seconds
- TokenTTL = 600
-
- RequestTimeout = 30 * time.Second
- OauthCompleteTimeout = 2 * time.Minute
- HeaderMattermostUserID = "Mattermost-User-ID"
- OwnerQueryParam = "owner"
- RepoQueryParam = "repo"
- NumberQueryParam = "number"
- PostIDQueryParam = "postId"
-
- IssueStatus = "status"
- AssigneesForProps = "assignees"
- LabelsForProps = "labels"
- DescriptionForProps = "description"
- TitleForProps = "title"
- IssueNumberForProps = "issue_number"
- IssueURLForProps = "issue_url"
- RepoOwnerForProps = "repo_owner"
- RepoNameForProps = "repo_name"
-
- Close = "Close"
- Reopen = "Reopen"
-
- IssueCompleted = "completed"
- IssueNotPlanned = "not_planned"
- IssueClose = "closed"
- IssueOpen = "open"
-
- // Actions of webhook events
- ActionOpened = "opened"
- ActionClosed = "closed"
- ActionReopened = "reopened"
- ActionSubmitted = "submitted"
- ActionLabeled = "labeled"
- ActionAssigned = "assigned"
- ActionCreated = "created"
- ActionDeleted = "deleted"
- ActionEdited = "edited"
- ActionMarkedReadyForReview = "ready_for_review"
-
- PostPropGithubRepo = "gh_repo"
- PostPropGithubObjectID = "gh_object_id"
- PostPropGithubObjectType = "gh_object_type"
-
- GithubObjectTypeIssue = "issue"
- GithubObjectTypeIssueComment = "issue_comment"
- GithubObjectTypePRReviewComment = "pr_review_comment"
-)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 23706c81d..106031a5e 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -16,9 +16,6 @@ import (
"github.com/pkg/errors"
"golang.org/x/oauth2"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
-
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/pluginapi"
@@ -27,14 +24,35 @@ import (
)
// HTTPHandlerFuncWithUserContext is http.HandleFunc but with a UserContext attached
-type HTTPHandlerFuncWithUserContext func(c *serializer.UserContext, w http.ResponseWriter, r *http.Request)
+type HTTPHandlerFuncWithUserContext func(c *UserContext, w http.ResponseWriter, r *http.Request)
// HTTPHandlerFuncWithContext is http.HandleFunc but with a .ontext attached
-type HTTPHandlerFuncWithContext func(c *serializer.Context, w http.ResponseWriter, r *http.Request)
+type HTTPHandlerFuncWithContext func(c *Context, w http.ResponseWriter, r *http.Request)
// ResponseType indicates type of response returned by api
type ResponseType string
+type UpdateIssueRequest struct {
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Repo string `json:"repo"`
+ PostID string `json:"post_id"`
+ ChannelID string `json:"channel_id"`
+ Labels []string `json:"labels"`
+ Assignees []string `json:"assignees"`
+ Milestone int `json:"milestone"`
+ IssueNumber int `json:"issue_number"`
+}
+
+type PRDetails struct {
+ URL string `json:"url"`
+ Number int `json:"number"`
+ Status string `json:"status"`
+ Mergeable bool `json:"mergeable"`
+ RequestedReviewers []*string `json:"requestedReviewers"`
+ Reviews []*github.PullRequestReview `json:"reviews"`
+}
+
const (
// ResponseTypeJSON indicates that response type is json
ResponseTypeJSON ResponseType = "JSON_RESPONSE"
@@ -56,7 +74,7 @@ func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
}
}
-func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *serializer.APIErrorResponse) {
+func (p *Plugin) writeAPIError(w http.ResponseWriter, apiErr *APIErrorResponse) {
b, err := json.Marshal(apiErr)
if err != nil {
p.client.Log.Warn("Failed to marshal API error", "error", err.Error())
@@ -141,11 +159,11 @@ func (p *Plugin) checkConfigured(next http.Handler) http.Handler {
func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- userID := r.Header.Get(constants.HeaderMattermostUserID)
+ userID := r.Header.Get(headerMattermostUserID)
if userID == "" {
switch responseType {
case ResponseTypeJSON:
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized})
case ResponseTypePlain:
http.Error(w, "Not authorized", http.StatusUnauthorized)
default:
@@ -158,16 +176,16 @@ func (p *Plugin) checkAuth(handler http.HandlerFunc, responseType ResponseType)
}
}
-func (p *Plugin) createContext(_ http.ResponseWriter, r *http.Request) (*serializer.Context, context.CancelFunc) {
- userID := r.Header.Get(constants.HeaderMattermostUserID)
+func (p *Plugin) createContext(_ http.ResponseWriter, r *http.Request) (*Context, context.CancelFunc) {
+ userID := r.Header.Get(headerMattermostUserID)
logger := logger.New(p.API).With(logger.LogContext{
"userid": userID,
})
- ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
- context := &serializer.Context{
+ context := &Context{
Ctx: ctx,
UserID: userID,
Log: logger,
@@ -200,7 +218,7 @@ func (p *Plugin) attachUserContext(handler HTTPHandlerFuncWithUserContext) http.
"github username": info.GitHubUsername,
})
- userContext := &serializer.UserContext{
+ userContext := &UserContext{
Context: *context,
GHInfo: info,
}
@@ -228,7 +246,7 @@ func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Req
p.router.ServeHTTP(w, r)
}
-func (p *Plugin) connectUserToGitHub(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) connectUserToGitHub(c *Context, w http.ResponseWriter, r *http.Request) {
privateAllowed := false
pValBool, _ := strconv.ParseBool(r.URL.Query().Get("private"))
if pValBool {
@@ -237,13 +255,13 @@ func (p *Plugin) connectUserToGitHub(c *serializer.Context, w http.ResponseWrite
conf := p.getOAuthConfig(privateAllowed)
- state := serializer.OAuthState{
+ state := OAuthState{
UserID: c.UserID,
Token: model.NewId()[:15],
PrivateAllowed: privateAllowed,
}
- _, err := p.store.Set(githubOauthKey+state.Token, state, pluginapi.SetExpiry(constants.TokenTTL))
+ _, err := p.store.Set(githubOauthKey+state.Token, state, pluginapi.SetExpiry(tokenTTL))
if err != nil {
http.Error(w, "error setting stored state", http.StatusBadRequest)
return
@@ -283,7 +301,7 @@ func (p *Plugin) connectUserToGitHub(c *serializer.Context, w http.ResponseWrite
http.Redirect(w, r, url, http.StatusFound)
}
-func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) completeConnectUserToGitHub(c *Context, w http.ResponseWriter, r *http.Request) {
var rErr error
defer func() {
p.oauthBroker.publishOAuthComplete(c.UserID, rErr, false)
@@ -298,7 +316,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.Respo
stateToken := r.URL.Query().Get("state")
- var state serializer.OAuthState
+ var state OAuthState
if err := p.store.Get(fmt.Sprintf("%s%s", githubOauthKey, stateToken), &state); err != nil {
c.Log.Warnf("Failed to get state token", "error", err.Error())
rErr = errors.Wrap(err, "missing stored state")
@@ -327,7 +345,7 @@ func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.Respo
conf := p.getOAuthConfig(state.PrivateAllowed)
- ctx, cancel := context.WithTimeout(context.Background(), constants.OauthCompleteTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), oauthCompleteTimeout)
defer cancel()
tok, err := conf.Exchange(ctx, code)
@@ -352,12 +370,12 @@ func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.Respo
// track the successful connection
p.TrackUserEvent("account_connected", c.UserID, nil)
- userInfo := &serializer.GitHubUserInfo{
+ userInfo := &GitHubUserInfo{
UserID: state.UserID,
Token: tok,
GitHubUsername: gitUser.GetLogin(),
LastToDoPostAt: model.GetMillis(),
- Settings: &serializer.UserSettings{
+ Settings: &UserSettings{
SidebarButtons: settingButtonsTeam,
DailyReminder: true,
Notifications: true,
@@ -458,23 +476,23 @@ func (p *Plugin) completeConnectUserToGitHub(c *serializer.Context, w http.Respo
}
}
-func (p *Plugin) getGitHubUser(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
- req := &serializer.GitHubUserRequest{}
+func (p *Plugin) getGitHubUser(c *Context, w http.ResponseWriter, r *http.Request) {
+ req := &GitHubUserRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding GitHubUserRequest from JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if req.UserID == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a JSON object with a non-blank user_id field.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a JSON object with a non-blank user_id field.", StatusCode: http.StatusBadRequest})
return
}
userInfo, apiErr := p.getGitHubUserInfo(req.UserID)
if apiErr != nil {
- if apiErr.ID == constants.APIErrorIDNotConnected {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
+ if apiErr.ID == apiErrorIDNotConnected {
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
} else {
p.writeAPIError(w, apiErr)
}
@@ -482,17 +500,17 @@ func (p *Plugin) getGitHubUser(c *serializer.Context, w http.ResponseWriter, r *
}
if userInfo == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "User is not connected to a GitHub account.", StatusCode: http.StatusNotFound})
return
}
- resp := &serializer.GitHubUserResponse{Username: userInfo.GitHubUsername}
+ resp := &GitHubUserResponse{Username: userInfo.GitHubUsername}
p.writeJSON(w, resp)
}
-func (p *Plugin) getConnected(c *serializer.Context, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getConnected(c *Context, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
- resp := &serializer.ConnectedResponse{
+ resp := &ConnectedResponse{
Connected: false,
EnterpriseBaseURL: config.EnterpriseBaseURL,
Organization: config.GitHubOrg,
@@ -565,7 +583,7 @@ func (p *Plugin) getConnected(c *serializer.Context, w http.ResponseWriter, r *h
p.writeJSON(w, resp)
}
-func (p *Plugin) getMentions(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getMentions(c *UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -581,7 +599,7 @@ func (p *Plugin) getMentions(c *serializer.UserContext, w http.ResponseWriter, r
p.writeJSON(w, result.Issues)
}
-func (p *Plugin) getUnreadsData(c *serializer.UserContext) []*serializer.FilteredNotification {
+func (p *Plugin) getUnreadsData(c *UserContext) []*FilteredNotification {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
notifications, _, err := githubClient.Activity.ListNotifications(c.Ctx, &github.NotificationListOptions{})
@@ -590,7 +608,7 @@ func (p *Plugin) getUnreadsData(c *serializer.UserContext) []*serializer.Filtere
return nil
}
- filteredNotifications := []*serializer.FilteredNotification{}
+ filteredNotifications := []*FilteredNotification{}
for _, n := range notifications {
if n.GetReason() == notificationReasonSubscribed {
continue
@@ -608,7 +626,7 @@ func (p *Plugin) getUnreadsData(c *serializer.UserContext) []*serializer.Filtere
subjectURL = n.GetSubject().GetLatestCommentURL()
}
- filteredNotifications = append(filteredNotifications, &serializer.FilteredNotification{
+ filteredNotifications = append(filteredNotifications, &FilteredNotification{
Notification: *n,
HTMLURL: fixGithubNotificationSubjectURL(subjectURL, issueNum),
})
@@ -617,17 +635,17 @@ func (p *Plugin) getUnreadsData(c *serializer.UserContext) []*serializer.Filtere
return filteredNotifications
}
-func (p *Plugin) getPrsDetails(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getPrsDetails(c *UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- var prList []*serializer.PRDetails
+ var prList []*PRDetails
if err := json.NewDecoder(r.Body).Decode(&prList); err != nil {
c.Log.WithError(err).Warnf("Error decoding PRDetails JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
- prDetails := make([]*serializer.PRDetails, len(prList))
+ prDetails := make([]*PRDetails, len(prList))
var wg sync.WaitGroup
for i, pr := range prList {
i := i
@@ -645,7 +663,7 @@ func (p *Plugin) getPrsDetails(c *serializer.UserContext, w http.ResponseWriter,
p.writeJSON(w, prDetails)
}
-func (p *Plugin) fetchPRDetails(c *serializer.UserContext, client *github.Client, prURL string, prNumber int) *serializer.PRDetails {
+func (p *Plugin) fetchPRDetails(c *UserContext, client *github.Client, prURL string, prNumber int) *PRDetails {
var status string
var mergeable bool
// Initialize to a non-nil slice to simplify JSON handling semantics
@@ -692,7 +710,7 @@ func (p *Plugin) fetchPRDetails(c *serializer.UserContext, client *github.Client
}()
wg.Wait()
- return &serializer.PRDetails{
+ return &PRDetails{
URL: prURL,
Number: prNumber,
Status: status,
@@ -702,7 +720,7 @@ func (p *Plugin) fetchPRDetails(c *serializer.UserContext, client *github.Client
}
}
-func fetchReviews(c *serializer.UserContext, client *github.Client, repoOwner string, repoName string, number int) ([]*github.PullRequestReview, error) {
+func fetchReviews(c *UserContext, client *github.Client, repoOwner string, repoName string, number int) ([]*github.PullRequestReview, error) {
reviewsList, _, err := client.PullRequests.ListReviews(c.Ctx, repoOwner, repoName, number, nil)
if err != nil {
@@ -717,7 +735,7 @@ func getRepoOwnerAndNameFromURL(url string) (string, string) {
return splitted[len(splitted)-2], splitted[len(splitted)-1]
}
-func (p *Plugin) searchIssues(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) searchIssues(c *UserContext, w http.ResponseWriter, r *http.Request) {
config := p.getConfiguration()
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
@@ -758,36 +776,45 @@ func getFailReason(code int, repo string, username string) string {
return cause
}
-func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- req := &serializer.CreateIssueCommentRequest{}
+func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ type CreateIssueCommentRequest struct {
+ PostID string `json:"post_id"`
+ Owner string `json:"owner"`
+ Repo string `json:"repo"`
+ Number int `json:"number"`
+ Comment string `json:"comment"`
+ ShowAttachedMessage bool `json:"show_attached_message"`
+ }
+
+ req := &CreateIssueCommentRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding CreateIssueCommentRequest JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if req.PostID == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid post id", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid post id", StatusCode: http.StatusBadRequest})
return
}
if req.Owner == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository owner.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository owner.", StatusCode: http.StatusBadRequest})
return
}
if req.Repo == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository.", StatusCode: http.StatusBadRequest})
return
}
if req.Number == 0 {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue number.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue number.", StatusCode: http.StatusBadRequest})
return
}
if req.Comment == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid non empty comment.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid non empty comment.", StatusCode: http.StatusBadRequest})
return
}
@@ -795,17 +822,17 @@ func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWr
post, err := p.client.Post.GetPost(req.PostID)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
return
}
commentUsername, err := p.getUsername(post.UserId)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
@@ -826,7 +853,7 @@ func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWr
if rawResponse != nil {
statusCode = rawResponse.StatusCode
}
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, req.Repo, currentUsername)), StatusCode: statusCode})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, req.Repo, currentUsername)), StatusCode: statusCode})
return
}
@@ -850,14 +877,14 @@ func (p *Plugin) createIssueComment(c *serializer.UserContext, w http.ResponseWr
err = p.client.Post.CreatePost(reply)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
p.writeJSON(w, result)
}
-func (p *Plugin) getLHSData(c *serializer.UserContext) (reviewResp []*github.Issue, assignmentResp []*github.Issue, openPRResp []*github.Issue, err error) {
+func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*github.Issue, assignmentResp []*github.Issue, openPRResp []*github.Issue, err error) {
graphQLClient := p.graphQLConnect(c.GHInfo)
reviewResp, assignmentResp, openPRResp, err = graphQLClient.GetLHSData(c.Context.Ctx)
@@ -868,13 +895,13 @@ func (p *Plugin) getLHSData(c *serializer.UserContext) (reviewResp []*github.Iss
return reviewResp, assignmentResp, openPRResp, nil
}
-func (p *Plugin) getSidebarData(c *serializer.UserContext) (*serializer.SidebarContent, error) {
+func (p *Plugin) getSidebarData(c *UserContext) (*SidebarContent, error) {
reviewResp, assignmentResp, openPRResp, err := p.getLHSData(c)
if err != nil {
return nil, err
}
- return &serializer.SidebarContent{
+ return &SidebarContent{
PRs: openPRResp,
Assignments: assignmentResp,
Reviews: reviewResp,
@@ -882,7 +909,7 @@ func (p *Plugin) getSidebarData(c *serializer.UserContext) (*serializer.SidebarC
}, nil
}
-func (p *Plugin) getSidebarContent(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getSidebarContent(c *UserContext, w http.ResponseWriter, r *http.Request) {
sidebarContent, err := p.getSidebarData(c)
if err != nil {
c.Log.WithError(err).Warnf("Failed to search for the sidebar data")
@@ -892,14 +919,14 @@ func (p *Plugin) getSidebarContent(c *serializer.UserContext, w http.ResponseWri
p.writeJSON(w, sidebarContent)
}
-func (p *Plugin) postToDo(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) postToDo(c *UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
username := c.GHInfo.GitHubUsername
text, err := p.GetToDo(c.Ctx, username, githubClient)
if err != nil {
c.Log.WithError(err).Warnf("Failed to get Todos")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Encountered an error getting the to do items.", StatusCode: http.StatusUnauthorized})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Encountered an error getting the to do items.", StatusCode: http.StatusUnauthorized})
return
}
@@ -912,8 +939,8 @@ func (p *Plugin) postToDo(c *serializer.UserContext, w http.ResponseWriter, r *h
p.writeJSON(w, resp)
}
-func (p *Plugin) updateSettings(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- var settings *serializer.UserSettings
+func (p *Plugin) updateSettings(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ var settings *UserSettings
if err := json.NewDecoder(r.Body).Decode(&settings); err != nil {
c.Log.WithError(err).Warnf("Error decoding settings from JSON body")
http.Error(w, "Invalid request body", http.StatusBadRequest)
@@ -937,15 +964,15 @@ func (p *Plugin) updateSettings(c *serializer.UserContext, w http.ResponseWriter
p.writeJSON(w, info.Settings)
}
-func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue(constants.OwnerQueryParam)
- repo := r.FormValue(constants.RepoQueryParam)
- number := r.FormValue(constants.NumberQueryParam)
- postID := r.FormValue(constants.PostIDQueryParam)
+func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(ownerQueryParam)
+ repo := r.FormValue(repoQueryParam)
+ number := r.FormValue(numberQueryParam)
+ postID := r.FormValue(postIDQueryParam)
issueNumber, err := strconv.Atoi(number)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
@@ -970,7 +997,7 @@ func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter,
"repo": repo,
"number": issueNumber,
}).Debugf("Could not get the issue")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
return
}
@@ -999,11 +1026,11 @@ func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter,
post, appErr := p.API.GetPost(postID)
if appErr != nil {
p.client.Log.Error("Unable to get the post", "PostID", postID, "Error", appErr.Error())
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", postID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", postID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", postID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", postID), StatusCode: http.StatusNotFound})
return
}
@@ -1023,13 +1050,13 @@ func (p *Plugin) getIssueInfo(c *serializer.UserContext, w http.ResponseWriter,
p.writeJSON(w, issueInfo)
}
-func (p *Plugin) getIssueByNumber(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue(constants.OwnerQueryParam)
- repo := r.FormValue(constants.RepoQueryParam)
- number := r.FormValue(constants.NumberQueryParam)
+func (p *Plugin) getIssueByNumber(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(ownerQueryParam)
+ repo := r.FormValue(repoQueryParam)
+ number := r.FormValue(numberQueryParam)
issueNumber, err := strconv.Atoi(number)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
@@ -1055,7 +1082,7 @@ func (p *Plugin) getIssueByNumber(c *serializer.UserContext, w http.ResponseWrit
"repo": repo,
"number": issueNumber,
}).Debugf("Could not get the issue")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
return
}
@@ -1065,14 +1092,14 @@ func (p *Plugin) getIssueByNumber(c *serializer.UserContext, w http.ResponseWrit
p.writeJSON(w, result)
}
-func (p *Plugin) getPrByNumber(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue(constants.OwnerQueryParam)
- repo := r.FormValue(constants.RepoQueryParam)
- number := r.FormValue(constants.NumberQueryParam)
+func (p *Plugin) getPrByNumber(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(ownerQueryParam)
+ repo := r.FormValue(repoQueryParam)
+ number := r.FormValue(numberQueryParam)
prNumber, err := strconv.Atoi(number)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
@@ -1099,7 +1126,7 @@ func (p *Plugin) getPrByNumber(c *serializer.UserContext, w http.ResponseWriter,
"repo": repo,
"number": prNumber,
}).Debugf("Could not get pull request")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Could not get pull request", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Could not get pull request", StatusCode: http.StatusInternalServerError})
return
}
if result.Body != nil {
@@ -1108,10 +1135,10 @@ func (p *Plugin) getPrByNumber(c *serializer.UserContext, w http.ResponseWriter,
p.writeJSON(w, result)
}
-func (p *Plugin) getLabels(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1123,7 +1150,7 @@ func (p *Plugin) getLabels(c *serializer.UserContext, w http.ResponseWriter, r *
labels, resp, err := githubClient.Issues.ListLabels(c.Ctx, owner, repo, &opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list labels")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
return
}
allLabels = append(allLabels, labels...)
@@ -1136,10 +1163,10 @@ func (p *Plugin) getLabels(c *serializer.UserContext, w http.ResponseWriter, r *
p.writeJSON(w, allLabels)
}
-func (p *Plugin) getAssignees(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1151,7 +1178,7 @@ func (p *Plugin) getAssignees(c *serializer.UserContext, w http.ResponseWriter,
assignees, resp, err := githubClient.Issues.ListAssignees(c.Ctx, owner, repo, &opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list assignees")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
return
}
allAssignees = append(allAssignees, assignees...)
@@ -1164,10 +1191,10 @@ func (p *Plugin) getAssignees(c *serializer.UserContext, w http.ResponseWriter,
p.writeJSON(w, allAssignees)
}
-func (p *Plugin) getMilestones(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Request) {
owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
return
}
@@ -1179,7 +1206,7 @@ func (p *Plugin) getMilestones(c *serializer.UserContext, w http.ResponseWriter,
milestones, resp, err := githubClient.Issues.ListMilestones(c.Ctx, owner, repo, &github.MilestoneListOptions{ListOptions: opt})
if err != nil {
c.Log.WithError(err).Warnf("Failed to list milestones")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
return
}
allMilestones = append(allMilestones, milestones...)
@@ -1229,7 +1256,7 @@ func getRepositoryListByOrg(c context.Context, org string, githubClient *github.
return allRepos, http.StatusOK, nil
}
-func (p *Plugin) getRepositories(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.Request) {
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
org := p.getConfiguration().GitHubOrg
@@ -1243,7 +1270,7 @@ func (p *Plugin) getRepositories(c *serializer.UserContext, w http.ResponseWrite
allRepos, err = getRepositoryList(c.Ctx, "", githubClient, opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list repositories")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
return
}
} else {
@@ -1253,17 +1280,24 @@ func (p *Plugin) getRepositories(c *serializer.UserContext, w http.ResponseWrite
allRepos, err = getRepositoryList(c.Ctx, org, githubClient, opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list repositories")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
return
}
} else {
c.Log.WithError(err).Warnf("Failed to list repositories")
- p.writeAPIError(w, &serializer.APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
return
}
}
}
- resp := make([]serializer.RepositoryResponse, len(allRepos))
+
+ type RepositoryResponse struct {
+ Name string `json:"name,omitempty"`
+ FullName string `json:"full_name,omitempty"`
+ Permissions map[string]bool `json:"permissions,omitempty"`
+ }
+
+ resp := make([]RepositoryResponse, len(allRepos))
for i, r := range allRepos {
resp[i].Name = r.GetName()
resp[i].FullName = r.GetFullName()
@@ -1273,12 +1307,12 @@ func (p *Plugin) getRepositories(c *serializer.UserContext, w http.ResponseWrite
p.writeJSON(w, resp)
}
-func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
// get data for the issue from the request body and fill UpdateIssueRequest to update the issue
- issue := &serializer.UpdateIssueRequest{}
+ issue := &UpdateIssueRequest{}
if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
c.Log.WithError(err).Warnf("Error decoding the JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
@@ -1293,11 +1327,11 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
post, appErr = p.API.GetPost(issue.PostID)
if appErr != nil {
p.client.Log.Error("Unable to get the post", "PostID", issue.PostID, "Error", appErr.Error())
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
return
}
permalink = p.getPermaLink(issue.PostID)
@@ -1319,13 +1353,13 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
currentUser, appErr := p.API.GetUser(c.UserID)
if appErr != nil {
p.client.Log.Error("Unable to get the user", "UserID", c.UserID, "Error", appErr.Error())
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
return
}
splittedRepo := strings.Split(issue.Repo, "/")
if len(splittedRepo) < 2 {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository", StatusCode: http.StatusBadRequest})
}
owner, repoName := splittedRepo[0], splittedRepo[1]
@@ -1334,12 +1368,12 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
result, resp, err := githubClient.Issues.Edit(c.Ctx, owner, repoName, issue.IssueNumber, githubIssue)
if err != nil {
if resp != nil && resp.Response.StatusCode == http.StatusGone {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
return
}
c.Log.WithError(err).Warnf("Failed to update the issue")
- p.writeAPIError(w, &serializer.APIErrorResponse{
+ p.writeAPIError(w, &APIErrorResponse{
ID: "",
Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode,
issue.Repo,
@@ -1375,7 +1409,7 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
}
if appErr != nil {
c.Log.WithError(appErr).Warnf("failed to create the notification post")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID), StatusCode: http.StatusInternalServerError})
return
}
@@ -1383,62 +1417,84 @@ func (p *Plugin) updateIssue(c *serializer.UserContext, w http.ResponseWriter, r
p.writeJSON(w, result)
}
-func (p *Plugin) closeOrReopenIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
- req := &serializer.CommentAndCloseRequest{}
+func (p *Plugin) closeOrReopenIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ type CommentAndCloseRequest struct {
+ ChannelID string `json:"channel_id"`
+ IssueComment string `json:"issue_comment"`
+ StatusReason string `json:"status_reason"`
+ Number int `json:"number"`
+ Owner string `json:"owner"`
+ Repository string `json:"repo"`
+ Status string `json:"status"`
+ PostID string `json:"postId"`
+ }
+
+ req := &CommentAndCloseRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding the JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
post, appErr := p.API.GetPost(req.PostID)
if appErr != nil {
p.client.Log.Error("Unable to get the post", "PostID", req.PostID, "Error", appErr.Error())
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
return
}
if _, err := p.getUsername(post.UserId); err != nil {
p.client.Log.Error("Unable to get the username", "UserID", post.UserId, "Error", err.Error())
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
if req.IssueComment != "" {
p.CreateCommentToIssue(c, w, req.IssueComment, req.Owner, req.Repository, post, req.Number)
}
- if req.Status == constants.Close {
- p.CloseOrReopenIssue(c, w, constants.IssueClose, req.StatusReason, req.Owner, req.Repository, post, req.Number)
+ if req.Status == statusClose {
+ p.CloseOrReopenIssue(c, w, issueClose, req.StatusReason, req.Owner, req.Repository, post, req.Number)
} else {
- p.CloseOrReopenIssue(c, w, constants.IssueOpen, req.StatusReason, req.Owner, req.Repository, post, req.Number)
+ p.CloseOrReopenIssue(c, w, issueOpen, req.StatusReason, req.Owner, req.Repository, post, req.Number)
}
}
-func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r *http.Request) {
+func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ type CreateIssueRequest struct {
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Repo string `json:"repo"`
+ PostID string `json:"post_id"`
+ ChannelID string `json:"channel_id"`
+ Labels []string `json:"labels"`
+ Assignees []string `json:"assignees"`
+ Milestone int `json:"milestone"`
+ }
+
// get data for the issue from the request body and fill CreateIssueRequest object to create the issue
- issue := &serializer.CreateIssueRequest{}
+ issue := &CreateIssueRequest{}
if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
c.Log.WithError(err).Warnf("Error decoding the JSON body")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
if issue.Title == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
return
}
if issue.Repo == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid repository name.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository name.", StatusCode: http.StatusBadRequest})
return
}
if issue.PostID == "" && issue.ChannelID == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
return
}
@@ -1449,17 +1505,17 @@ func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r
var err error
post, err = p.client.Post.GetPost(issue.PostID)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
return
}
username, err := p.getUsername(post.UserId)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
@@ -1488,7 +1544,7 @@ func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r
currentUser, err := p.client.User.Get(c.UserID)
if err != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
return
}
@@ -1499,12 +1555,12 @@ func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r
result, resp, err := githubClient.Issues.Create(c.Ctx, owner, repoName, githubIssue)
if err != nil {
if resp != nil && resp.Response.StatusCode == http.StatusGone {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
return
}
c.Log.WithError(err).Warnf("Failed to create issue")
- p.writeAPIError(w, &serializer.APIErrorResponse{
+ p.writeAPIError(w, &APIErrorResponse{
ID: "",
Message: fmt.Sprintf("failed to create issue: %s", getFailReason(resp.StatusCode, issue.Repo, currentUser.Username)),
StatusCode: resp.StatusCode,
@@ -1537,7 +1593,7 @@ func (p *Plugin) createIssue(c *serializer.UserContext, w http.ResponseWriter, r
}
if err != nil {
c.Log.WithError(err).Warnf("failed to create notification post")
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "failed to create notification post, postID: " + issue.PostID + ", channelID: " + channelID, StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create notification post, postID: " + issue.PostID + ", channelID: " + channelID, StatusCode: http.StatusInternalServerError})
return
}
diff --git a/server/plugin/api_test.go b/server/plugin/api_test.go
index fe013ec55..7a3a560de 100644
--- a/server/plugin/api_test.go
+++ b/server/plugin/api_test.go
@@ -13,8 +13,6 @@ import (
"github.com/mattermost/mattermost/server/public/plugin/plugintest"
"github.com/mattermost/mattermost/server/public/pluginapi"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
"github.com/mattermost/mattermost-plugin-github/server/testutils"
)
@@ -84,7 +82,7 @@ func TestPlugin_ServeHTTP(t *testing.T) {
expectedResponse: testutils.ExpectedResponse{
StatusCode: http.StatusUnauthorized,
ResponseType: testutils.ContentTypeJSON,
- Body: serializer.APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized},
+ Body: APIErrorResponse{ID: "", Message: "Not authorized.", StatusCode: http.StatusUnauthorized},
},
userID: "",
}, "unauthorized test http": {
@@ -120,7 +118,7 @@ func TestPlugin_ServeHTTP(t *testing.T) {
p.SetAPI(&plugintest.API{})
req := test.httpTest.CreateHTTPRequest(test.request)
- req.Header.Add(constants.HeaderMattermostUserID, test.userID)
+ req.Header.Add(headerMattermostUserID, test.userID)
rr := httptest.NewRecorder()
p.ServeHTTP(&plugin.Context{}, rr, req)
test.httpTest.CompareHTTPResponse(rr, test.expectedResponse)
diff --git a/server/plugin/command.go b/server/plugin/command.go
index 2e247b125..a14970c5c 100644
--- a/server/plugin/command.go
+++ b/server/plugin/command.go
@@ -12,9 +12,6 @@ import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/command"
-
- "github.com/mattermost/mattermost-plugin-github/server/constants"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
)
const (
@@ -133,7 +130,7 @@ func (p *Plugin) postCommandResponse(args *model.CommandArgs, text string) {
p.client.Post.SendEphemeralPost(args.UserId, post)
}
-func (p *Plugin) getMutedUsernames(userInfo *serializer.GitHubUserInfo) []string {
+func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) []string {
var mutedUsernameBytes []byte
err := p.store.Get(userInfo.UserID+"-muted-users", &mutedUsernameBytes)
if err != nil {
@@ -148,7 +145,7 @@ func (p *Plugin) getMutedUsernames(userInfo *serializer.GitHubUserInfo) []string
return mutedUsers
}
-func (p *Plugin) handleMuteList(args *model.CommandArgs, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleMuteList(args *model.CommandArgs, userInfo *GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
var mutedUsers string
for _, user := range mutedUsernames {
@@ -169,7 +166,7 @@ func contains(s []string, e string) bool {
return false
}
-func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
if contains(mutedUsernames, username) {
return username + " is already muted"
@@ -195,7 +192,7 @@ func (p *Plugin) handleMuteAdd(args *model.CommandArgs, username string, userInf
return fmt.Sprintf("`%v`", username) + " is now muted. You'll no longer receive notifications for comments in your PRs and issues."
}
-func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
mutedUsernames := p.getMutedUsernames(userInfo)
userToMute := []string{username}
newMutedList := arrayDifference(mutedUsernames, userToMute)
@@ -208,7 +205,7 @@ func (p *Plugin) handleUnmute(args *model.CommandArgs, username string, userInfo
return fmt.Sprintf("`%v`", username) + " is no longer muted"
}
-func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *GitHubUserInfo) string {
_, err := p.store.Set(userInfo.UserID+"-muted-users", []byte(""))
if err != nil {
return "Error occurred unmuting users"
@@ -217,7 +214,7 @@ func (p *Plugin) handleUnmuteAll(args *model.CommandArgs, userInfo *serializer.G
return "Unmuted all users"
}
-func (p *Plugin) handleMuteCommand(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleMuteCommand(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid mute command. Available commands are 'list', 'add' and 'delete'."
}
@@ -259,7 +256,7 @@ func arrayDifference(a, b []string) []string {
return diff
}
-func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
switch {
case len(parameters) == 0:
return "Please specify a repository or 'list' command."
@@ -270,7 +267,7 @@ func (p *Plugin) handleSubscribe(c *plugin.Context, args *model.CommandArgs, par
}
}
-func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid subscribe command. Available commands are 'list', 'add' and 'delete'."
}
@@ -290,7 +287,7 @@ func (p *Plugin) handleSubscriptions(c *plugin.Context, args *model.CommandArgs,
}
}
-func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
txt := ""
subs, err := p.GetSubscriptionsByChannel(args.ChannelId)
if err != nil {
@@ -368,7 +365,7 @@ func (p *Plugin) checkIfConfiguredWebhookExists(ctx context.Context, githubClien
return found, nil
}
-func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
const errorNoWebhookFound = "\nNo webhook was found for this repository or organization. To create one, enter the following slash command `/github setup webhook`"
const errorWebhookToUser = "\nNot able to get the list of webhooks. This feature is not available for subscription to a user."
subscriptionEvents := Features("pulls,issues,creates,deletes")
@@ -534,7 +531,7 @@ func (p *Plugin) getSubscribedFeatures(channelID, owner, repo string) (Features,
return previousFeatures, nil
}
-func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Please specify a repository."
}
@@ -582,12 +579,12 @@ func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, p
return ""
}
-func (p *Plugin) handleDisconnect(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleDisconnect(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
p.disconnectGitHubAccount(args.UserId)
return "Disconnected your GitHub account."
}
-func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *GitHubUserInfo) string {
githubClient := p.githubConnectUser(context.Background(), userInfo)
text, err := p.GetToDo(context.Background(), userInfo.GitHubUsername, githubClient)
@@ -599,7 +596,7 @@ func (p *Plugin) handleTodo(_ *plugin.Context, _ *model.CommandArgs, _ []string,
return text
}
-func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, userInfo *GitHubUserInfo) string {
githubClient := p.githubConnectUser(context.Background(), userInfo)
gitUser, _, err := githubClient.Users.Get(context.Background(), "")
if err != nil {
@@ -610,7 +607,7 @@ func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, u
return text
}
-func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
message, err := renderTemplate("helpText", p.getConfiguration())
if err != nil {
p.client.Log.Warn("Failed to render help template", "error", err.Error())
@@ -620,7 +617,7 @@ func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string,
return "###### Mattermost GitHub Plugin - Slash Command Help\n" + message
}
-func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
if len(parameters) < 2 {
return "Please specify both a setting and value. Use `/github help` for more usage information."
}
@@ -685,7 +682,7 @@ func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, paramet
return "Settings updated."
}
-func (p *Plugin) handleIssue(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string {
+func (p *Plugin) handleIssue(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Invalid issue command. Available command is 'create'."
}
@@ -739,7 +736,7 @@ func (p *Plugin) handleSetup(c *plugin.Context, args *model.CommandArgs, paramet
return ""
}
-type CommandHandleFunc func(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *serializer.GitHubUserInfo) string
+type CommandHandleFunc func(c *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string
func (p *Plugin) isAuthorizedSysAdmin(userID string) (bool, error) {
user, err := p.client.User.Get(userID)
@@ -838,7 +835,7 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
info, apiErr := p.getGitHubUserInfo(args.UserId)
if apiErr != nil {
text := "Unknown error."
- if apiErr.ID == constants.APIErrorIDNotConnected {
+ if apiErr.ID == apiErrorIDNotConnected {
text = "You must connect your account to GitHub first. Either click on the GitHub logo in the bottom left of the screen or enter `/github connect`."
}
p.postCommandResponse(args, text)
diff --git a/server/serializer/error.go b/server/plugin/error.go
similarity index 91%
rename from server/serializer/error.go
rename to server/plugin/error.go
index 1e2974f51..3919c2cff 100644
--- a/server/serializer/error.go
+++ b/server/plugin/error.go
@@ -1,4 +1,4 @@
-package serializer
+package plugin
type APIErrorResponse struct {
ID string `json:"id"`
diff --git a/server/plugin/mm_34646_token_refresh.go b/server/plugin/mm_34646_token_refresh.go
index b4d38c9a2..60eb6f4fe 100644
--- a/server/plugin/mm_34646_token_refresh.go
+++ b/server/plugin/mm_34646_token_refresh.go
@@ -7,8 +7,6 @@ import (
"github.com/google/go-github/v54/github"
"github.com/pkg/errors"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
-
"github.com/mattermost/mattermost/server/public/pluginapi/cluster"
)
@@ -46,7 +44,7 @@ func (p *Plugin) forceResetAllMM34646() error {
}
for _, key := range keys {
- var tryInfo serializer.GitHubUserInfo
+ var tryInfo GitHubUserInfo
err = p.store.Get(key, &tryInfo)
if err != nil {
p.client.Log.Warn("failed to inspect key", "key", key, "error",
@@ -92,7 +90,7 @@ func (p *Plugin) forceResetAllMM34646() error {
return nil
}
-func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configuration, info *serializer.GitHubUserInfo) (string, error) {
+func (p *Plugin) forceResetUserTokenMM34646(ctx context.Context, config *Configuration, info *GitHubUserInfo) (string, error) {
if info.MM34646ResetTokenDone {
return info.Token.AccessToken, nil
}
diff --git a/server/plugin/oauth.go b/server/plugin/oauth.go
index 294727fce..7036cc712 100644
--- a/server/plugin/oauth.go
+++ b/server/plugin/oauth.go
@@ -1,14 +1,72 @@
package plugin
import (
+ "context"
"sync"
+
+ "github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger"
+ "golang.org/x/oauth2"
)
+type Context struct {
+ Ctx context.Context
+ UserID string
+ Log logger.Logger
+}
+
+type GitHubUserRequest struct {
+ UserID string `json:"user_id"`
+}
+
+type GitHubUserResponse struct {
+ Username string `json:"username"`
+}
+
+type ConnectedResponse struct {
+ Connected bool `json:"connected"`
+ GitHubUsername string `json:"github_username"`
+ GitHubClientID string `json:"github_client_id"`
+ EnterpriseBaseURL string `json:"enterprise_base_url,omitempty"`
+ Organization string `json:"organization"`
+ UserSettings *UserSettings `json:"user_settings"`
+ ClientConfiguration map[string]interface{} `json:"configuration"`
+}
+
+type UserSettings struct {
+ SidebarButtons string `json:"sidebar_buttons"`
+ DailyReminder bool `json:"daily_reminder"`
+ DailyReminderOnChange bool `json:"daily_reminder_on_change"`
+ Notifications bool `json:"notifications"`
+}
+
+type GitHubUserInfo struct {
+ UserID string
+ Token *oauth2.Token
+ GitHubUsername string
+ LastToDoPostAt int64
+ Settings *UserSettings
+ AllowedPrivateRepos bool
+
+ // MM34646ResetTokenDone is set for a user whose token has been reset for MM-34646.
+ MM34646ResetTokenDone bool
+}
+
type OAuthCompleteEvent struct {
UserID string
Err error
}
+type UserContext struct {
+ Context
+ GHInfo *GitHubUserInfo
+}
+
+type OAuthState struct {
+ UserID string `json:"user_id"`
+ Token string `json:"token"`
+ PrivateAllowed bool `json:"private_allowed"`
+}
+
type OAuthBroker struct {
sendOAuthCompleteEvent func(event OAuthCompleteEvent)
diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go
index ee1af71d1..1da17175e 100644
--- a/server/plugin/plugin.go
+++ b/server/plugin/plugin.go
@@ -10,6 +10,7 @@ import (
"regexp"
"strings"
"sync"
+ "time"
"github.com/google/go-github/v54/github"
"github.com/gorilla/mux"
@@ -23,16 +24,17 @@ import (
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/poster"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/telemetry"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
"github.com/mattermost/mattermost-plugin-github/server/plugin/graphql"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
)
const (
- githubTokenKey = "_githubtoken"
- githubOauthKey = "githuboauthkey_"
- githubUsernameKey = "_githubusername"
- githubPrivateRepoKey = "_githubprivate"
+ githubTokenKey = "_githubtoken"
+ githubOauthKey = "githuboauthkey_"
+ githubUsernameKey = "_githubusername"
+ githubPrivateRepoKey = "_githubprivate"
+ githubObjectTypeIssue = "issue"
+ githubObjectTypeIssueComment = "issue_comment"
+ githubObjectTypePRReviewComment = "pr_review_comment"
mm34646MutexKey = "mm34646_token_reset_mutex"
mm34646DoneKey = "mm34646_token_reset_done"
@@ -57,6 +59,53 @@ const (
dailySummary = "_dailySummary"
chimeraGitHubAppIdentifier = "plugin-github"
+
+ apiErrorIDNotConnected = "not_connected"
+
+ // TokenTTL is the OAuth token expiry duration in seconds
+ tokenTTL = 600
+
+ requestTimeout = 30 * time.Second
+ oauthCompleteTimeout = 2 * time.Minute
+ headerMattermostUserID = "Mattermost-User-ID"
+ ownerQueryParam = "owner"
+ repoQueryParam = "repo"
+ numberQueryParam = "number"
+ postIDQueryParam = "postId"
+
+ issueStatus = "status"
+ assigneesForProps = "assignees"
+ labelsForProps = "labels"
+ descriptionForProps = "description"
+ titleForProps = "title"
+ issueNumberForProps = "issue_number"
+ issueURLForProps = "issue_url"
+ repoOwnerForProps = "repo_owner"
+ repoNameForProps = "repo_name"
+
+ statusClose = "Close"
+ statusReopen = "Reopen"
+
+ issueCompleted = "completed"
+ issueNotPlanned = "not_planned"
+ issueClose = "closed"
+ issueOpen = "open"
+
+ // Actions of webhook events
+ actionOpened = "opened"
+ actionClosed = "closed"
+ actionReopened = "reopened"
+ actionSubmitted = "submitted"
+ actionLabeled = "labeled"
+ actionAssigned = "assigned"
+ actionCreated = "created"
+ actionDeleted = "deleted"
+ actionEdited = "edited"
+ actionMarkedReadyForReview = "ready_for_review"
+
+ postPropGithubRepo = "gh_repo"
+ postPropGithubObjectID = "gh_object_id"
+ postPropGithubObjectType = "gh_object_type"
)
var (
@@ -171,12 +220,12 @@ func (p *Plugin) GetGitHubClient(ctx context.Context, userID string) (*github.Cl
return p.githubConnectUser(ctx, userInfo), nil
}
-func (p *Plugin) githubConnectUser(ctx context.Context, info *serializer.GitHubUserInfo) *github.Client {
+func (p *Plugin) githubConnectUser(ctx context.Context, info *GitHubUserInfo) *github.Client {
tok := *info.Token
return p.githubConnectToken(tok)
}
-func (p *Plugin) graphQLConnect(info *serializer.GitHubUserInfo) *graphql.Client {
+func (p *Plugin) graphQLConnect(info *GitHubUserInfo) *graphql.Client {
conf := p.getConfiguration()
return graphql.NewClient(p.client.Log, *info.Token, info.GitHubUsername, conf.GitHubOrg, conf.EnterpriseBaseURL)
}
@@ -310,7 +359,7 @@ func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo st
}
// Getting the Github repository from notification post props
- repo, ok = post.GetProp(constants.PostPropGithubRepo).(string)
+ repo, ok = post.GetProp(postPropGithubRepo).(string)
if !ok || repo == "" {
return org, repo, id, objectType, false
}
@@ -324,13 +373,13 @@ func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo st
org, repo = orgRepo[0], orgRepo[1]
// Getting the Github object id from notification post props
- id, ok = post.GetProp(constants.PostPropGithubObjectID).(float64)
+ id, ok = post.GetProp(postPropGithubObjectID).(float64)
if !ok || id == 0 {
return org, repo, id, objectType, false
}
// Getting the Github object type from notification post props
- objectType, ok = post.GetProp(constants.PostPropGithubObjectType).(string)
+ objectType, ok = post.GetProp(postPropGithubObjectType).(string)
if !ok || objectType == "" {
return org, repo, id, objectType, false
}
@@ -352,27 +401,27 @@ func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reactio
info, appErr := p.getGitHubUserInfo(reaction.UserId)
if appErr != nil {
- if appErr.ID != constants.APIErrorIDNotConnected {
+ if appErr.ID != apiErrorIDNotConnected {
p.client.Log.Debug("Error in getting user info", "error", appErr.Error())
}
return
}
- ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
ghClient := p.githubConnectUser(ctx, info)
switch objectType {
- case constants.GithubObjectTypeIssueComment:
+ case githubObjectTypeIssueComment:
if _, _, err := ghClient.Reactions.CreateIssueCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil {
p.client.Log.Debug("Error occurred while creating issue comment reaction", "error", err.Error())
return
}
- case constants.GithubObjectTypeIssue:
+ case githubObjectTypeIssue:
if _, _, err := ghClient.Reactions.CreateIssueReaction(context.Background(), owner, repo, int(id), githubEmoji); err != nil {
p.client.Log.Debug("Error occurred while creating issue reaction", "error", err.Error())
return
}
- case constants.GithubObjectTypePRReviewComment:
+ case githubObjectTypePRReviewComment:
if _, _, err := ghClient.Reactions.CreatePullRequestCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil {
p.client.Log.Debug("Error occurred while creating PR review comment reaction", "error", err.Error())
return
@@ -396,17 +445,17 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React
info, appErr := p.getGitHubUserInfo(reaction.UserId)
if appErr != nil {
- if appErr.ID != constants.APIErrorIDNotConnected {
+ if appErr.ID != apiErrorIDNotConnected {
p.client.Log.Debug("Error in getting user info", "error", appErr.Error())
}
return
}
- ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
ghClient := p.githubConnectUser(ctx, info)
switch objectType {
- case constants.GithubObjectTypeIssueComment:
+ case githubObjectTypeIssueComment:
reactions, _, err := ghClient.Reactions.ListIssueCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{})
if err != nil {
p.client.Log.Debug("Error getting issue comment reaction list", "error", err.Error())
@@ -421,7 +470,7 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React
return
}
}
- case constants.GithubObjectTypeIssue:
+ case githubObjectTypeIssue:
reactions, _, err := ghClient.Reactions.ListIssueReactions(context.Background(), owner, repo, int(id), &github.ListOptions{})
if err != nil {
p.client.Log.Debug("Error getting issue reaction list", "error", err.Error())
@@ -436,7 +485,7 @@ func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.React
return
}
}
- case constants.GithubObjectTypePRReviewComment:
+ case githubObjectTypePRReviewComment:
reactions, _, err := ghClient.Reactions.ListPullRequestCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{})
if err != nil {
p.client.Log.Debug("Error getting PR review comment reaction list", "error", err.Error())
@@ -511,7 +560,7 @@ func (p *Plugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode
msg := post.Message
info, appErr := p.getGitHubUserInfo(post.UserId)
if appErr != nil {
- if appErr.ID != constants.APIErrorIDNotConnected {
+ if appErr.ID != apiErrorIDNotConnected {
p.client.Log.Warn("Error in getting user info", "error", appErr.Message)
}
return nil, ""
@@ -585,7 +634,7 @@ func (p *Plugin) getOAuthConfigForChimeraApp(scopes []string) *oauth2.Config {
}
}
-func (p *Plugin) storeGitHubUserInfo(info *serializer.GitHubUserInfo) error {
+func (p *Plugin) storeGitHubUserInfo(info *GitHubUserInfo) error {
config := p.getConfiguration()
encryptedToken, err := encrypt([]byte(config.EncryptionKey), info.Token.AccessToken)
@@ -602,22 +651,22 @@ func (p *Plugin) storeGitHubUserInfo(info *serializer.GitHubUserInfo) error {
return nil
}
-func (p *Plugin) getGitHubUserInfo(userID string) (*serializer.GitHubUserInfo, *serializer.APIErrorResponse) {
+func (p *Plugin) getGitHubUserInfo(userID string) (*GitHubUserInfo, *APIErrorResponse) {
config := p.getConfiguration()
- var userInfo *serializer.GitHubUserInfo
+ var userInfo *GitHubUserInfo
err := p.store.Get(userID+githubTokenKey, &userInfo)
if err != nil {
- return nil, &serializer.APIErrorResponse{ID: "", Message: "Unable to get user info.", StatusCode: http.StatusInternalServerError}
+ return nil, &APIErrorResponse{ID: "", Message: "Unable to get user info.", StatusCode: http.StatusInternalServerError}
}
if userInfo == nil {
- return nil, &serializer.APIErrorResponse{ID: constants.APIErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest}
+ return nil, &APIErrorResponse{ID: apiErrorIDNotConnected, Message: "Must connect user account to GitHub first.", StatusCode: http.StatusBadRequest}
}
unencryptedToken, err := decrypt([]byte(config.EncryptionKey), userInfo.Token.AccessToken)
if err != nil {
p.client.Log.Warn("Failed to decrypt access token", "error", err.Error())
- return nil, &serializer.APIErrorResponse{ID: "", Message: "Unable to decrypt access token.", StatusCode: http.StatusInternalServerError}
+ return nil, &APIErrorResponse{ID: "", Message: "Unable to decrypt access token.", StatusCode: http.StatusInternalServerError}
}
userInfo.Token.AccessToken = unencryptedToken
@@ -754,7 +803,7 @@ func (p *Plugin) GetDailySummaryText(userID string) (string, error) {
return string(summaryByte), nil
}
-func (p *Plugin) PostToDo(info *serializer.GitHubUserInfo, userID string) error {
+func (p *Plugin) PostToDo(info *GitHubUserInfo, userID string) error {
ctx := context.Background()
text, err := p.GetToDo(ctx, info.GitHubUsername, p.githubConnectUser(ctx, info))
if err != nil {
@@ -889,7 +938,7 @@ func (p *Plugin) GetToDo(ctx context.Context, username string, githubClient *git
return text, nil
}
-func (p *Plugin) HasUnreads(info *serializer.GitHubUserInfo) bool {
+func (p *Plugin) HasUnreads(info *GitHubUserInfo) bool {
username := info.GitHubUsername
ctx := context.Background()
githubClient := p.githubConnectUser(ctx, info)
@@ -985,9 +1034,9 @@ func (p *Plugin) sendRefreshEvent(userID string) {
"userid": userID,
})
- ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
- context := &serializer.Context{
+ context := &Context{
Ctx: ctx,
UserID: userID,
Log: eventLogger,
@@ -1001,7 +1050,7 @@ func (p *Plugin) sendRefreshEvent(userID string) {
return
}
- userContext := &serializer.UserContext{
+ userContext := &UserContext{
Context: *context,
GHInfo: info,
}
@@ -1031,7 +1080,7 @@ func (p *Plugin) sendRefreshEvent(userID string) {
func (p *Plugin) getUsername(mmUserID string) (string, error) {
info, apiEr := p.getGitHubUserInfo(mmUserID)
if apiEr != nil {
- if apiEr.ID != constants.APIErrorIDNotConnected {
+ if apiEr.ID != apiErrorIDNotConnected {
return "", apiEr
}
diff --git a/server/serializer/sidebar.go b/server/plugin/sidebar.go
similarity index 84%
rename from server/serializer/sidebar.go
rename to server/plugin/sidebar.go
index 80d76cdf9..c58b3c46c 100644
--- a/server/serializer/sidebar.go
+++ b/server/plugin/sidebar.go
@@ -1,4 +1,4 @@
-package serializer
+package plugin
import (
"encoding/json"
@@ -6,6 +6,11 @@ import (
"github.com/google/go-github/v54/github"
)
+type FilteredNotification struct {
+ github.Notification
+ HTMLURL string `json:"html_url"`
+}
+
type SidebarContent struct {
PRs []*github.Issue `json:"prs"`
Reviews []*github.Issue `json:"reviews"`
diff --git a/server/plugin/utils.go b/server/plugin/utils.go
index e7e391244..baedcf91f 100644
--- a/server/plugin/utils.go
+++ b/server/plugin/utils.go
@@ -19,9 +19,6 @@ import (
"github.com/google/go-github/v54/github"
"github.com/pkg/errors"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
- "github.com/mattermost/mattermost-plugin-github/server/serializer"
-
"github.com/mattermost/mattermost/server/public/model"
)
@@ -371,40 +368,40 @@ func isValidURL(rawURL string) error {
return nil
}
-func (p *Plugin) validateIssueRequestForUpdation(issue *serializer.UpdateIssueRequest, w http.ResponseWriter) bool {
+func (p *Plugin) validateIssueRequestForUpdation(issue *UpdateIssueRequest, w http.ResponseWriter) bool {
if issue.Title == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue title.", StatusCode: http.StatusBadRequest})
return false
}
if issue.PostID == "" && issue.ChannelID == "" {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide either a postID or a channelID", StatusCode: http.StatusBadRequest})
return false
}
return true
}
-func (p *Plugin) updatePost(issue *serializer.UpdateIssueRequest, w http.ResponseWriter) {
+func (p *Plugin) updatePost(issue *UpdateIssueRequest, w http.ResponseWriter) {
post, appErr := p.API.GetPost(issue.PostID)
if appErr != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
return
}
if post == nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
return
}
- post.Props[constants.AssigneesForProps] = issue.Assignees
- post.Props[constants.LabelsForProps] = issue.Labels
- post.Props[constants.DescriptionForProps] = issue.Body
- post.Props[constants.TitleForProps] = issue.Title
+ post.Props[assigneesForProps] = issue.Assignees
+ post.Props[labelsForProps] = issue.Labels
+ post.Props[descriptionForProps] = issue.Body
+ post.Props[titleForProps] = issue.Title
if _, appErr = p.API.UpdatePost(post); appErr != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
}
}
-func (p *Plugin) CreateCommentToIssue(c *serializer.UserContext, w http.ResponseWriter, comment, owner, repo string, post *model.Post, issueNumber int) {
+func (p *Plugin) CreateCommentToIssue(c *UserContext, w http.ResponseWriter, comment, owner, repo string, post *model.Post, issueNumber int) {
currentUsername := c.GHInfo.GitHubUsername
permalink := p.getPermaLink(post.Id)
issueComment := &github.IssueComment{
@@ -418,7 +415,7 @@ func (p *Plugin) CreateCommentToIssue(c *serializer.UserContext, w http.Response
if rawResponse != nil {
statusCode = rawResponse.StatusCode
}
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, repo, currentUsername)), StatusCode: statusCode})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create an issue comment: %s", getFailReason(statusCode, repo, currentUsername)), StatusCode: statusCode})
return
}
@@ -437,12 +434,12 @@ func (p *Plugin) CreateCommentToIssue(c *serializer.UserContext, w http.Response
}
if _, appErr := p.API.CreatePost(reply); appErr != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
return
}
}
-func (p *Plugin) CloseOrReopenIssue(c *serializer.UserContext, w http.ResponseWriter, status, statusReason, owner, repo string, post *model.Post, issueNumber int) {
+func (p *Plugin) CloseOrReopenIssue(c *UserContext, w http.ResponseWriter, status, statusReason, owner, repo string, post *model.Post, issueNumber int) {
currentUsername := c.GHInfo.GitHubUsername
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
githubIssue := &github.IssueRequest{
@@ -453,12 +450,12 @@ func (p *Plugin) CloseOrReopenIssue(c *serializer.UserContext, w http.ResponseWr
issue, resp, err := githubClient.Issues.Edit(c.Ctx, owner, repo, issueNumber, githubIssue)
if err != nil {
if resp != nil && resp.Response.StatusCode == http.StatusGone {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
return
}
c.Log.WithError(err).Warnf("Failed to update the issue")
- p.writeAPIError(w, &serializer.APIErrorResponse{
+ p.writeAPIError(w, &APIErrorResponse{
ID: "",
Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode,
repo,
@@ -471,9 +468,9 @@ func (p *Plugin) CloseOrReopenIssue(c *serializer.UserContext, w http.ResponseWr
var permalinkReplyMessage string
switch statusReason {
- case constants.IssueCompleted:
+ case issueCompleted:
permalinkReplyMessage = fmt.Sprintf("Issue closed as completed [#%v](%v)", issueNumber, issue.GetHTMLURL())
- case constants.IssueNotPlanned:
+ case issueNotPlanned:
permalinkReplyMessage = fmt.Sprintf("Issue closed as not planned [#%v](%v)", issueNumber, issue.GetHTMLURL())
default:
permalinkReplyMessage = fmt.Sprintf("Issue reopend [#%v](%v)", issueNumber, issue.GetHTMLURL())
@@ -493,16 +490,16 @@ func (p *Plugin) CloseOrReopenIssue(c *serializer.UserContext, w http.ResponseWr
}
if _, appErr := p.API.CreatePost(reply); appErr != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
return
}
- if status == constants.IssueClose {
- post.Props[constants.IssueStatus] = constants.Reopen
+ if status == issueClose {
+ post.Props[issueStatus] = statusReopen
} else {
- post.Props[constants.IssueStatus] = constants.Close
+ post.Props[issueStatus] = statusClose
}
if _, appErr := p.API.UpdatePost(post); appErr != nil {
- p.writeAPIError(w, &serializer.APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", post.Id), StatusCode: http.StatusInternalServerError})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", post.Id), StatusCode: http.StatusInternalServerError})
}
p.writeJSON(w, issue)
}
diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go
index 99f8e787b..bb0dd442b 100644
--- a/server/plugin/webhook.go
+++ b/server/plugin/webhook.go
@@ -14,8 +14,6 @@ import (
"sync"
"time"
- "github.com/mattermost/mattermost-plugin-github/server/constants"
-
"github.com/google/go-github/v54/github"
"github.com/microcosm-cc/bluemonday"
@@ -336,11 +334,11 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
action := event.GetAction()
switch action {
- case constants.ActionOpened,
- constants.ActionReopened,
- constants.ActionMarkedReadyForReview,
- constants.ActionLabeled,
- constants.ActionClosed:
+ case actionOpened,
+ actionReopened,
+ actionMarkedReadyForReview,
+ actionLabeled,
+ actionClosed:
default:
return
}
@@ -369,11 +367,11 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
continue
}
- if sub.PullsMerged() && action != constants.ActionClosed {
+ if sub.PullsMerged() && action != actionClosed {
continue
}
- if sub.PullsCreated() && action != constants.ActionOpened {
+ if sub.PullsCreated() && action != actionOpened {
continue
}
@@ -393,15 +391,15 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
repoName := strings.ToLower(repo.GetFullName())
prNumber := event.GetPullRequest().Number
- post.AddProp(constants.PostPropGithubRepo, repoName)
- post.AddProp(constants.PostPropGithubObjectID, prNumber)
- post.AddProp(constants.PostPropGithubObjectType, constants.GithubObjectTypeIssue)
+ post.AddProp(postPropGithubRepo, repoName)
+ post.AddProp(postPropGithubObjectID, prNumber)
+ post.AddProp(postPropGithubObjectType, githubObjectTypeIssue)
if !contained && label != "" {
continue
}
- if action == constants.ActionLabeled {
+ if action == actionLabeled {
if label != "" && label == eventLabel {
pullRequestLabelledMessage, err := renderTemplate("pullRequestLabelled", event)
if err != nil {
@@ -415,7 +413,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
}
}
- if action == constants.ActionOpened {
+ if action == actionOpened {
prNotificationType := "newPR"
if isPRInDraftState {
prNotificationType = "newDraftPR"
@@ -429,7 +427,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
post.Message = p.sanitizeDescription(newPRMessage)
}
- if action == constants.ActionReopened {
+ if action == actionReopened {
reopenedPRMessage, err := renderTemplate("reopenedPR", event)
if err != nil {
p.client.Log.Warn("Failed to render template", "error", err.Error())
@@ -439,7 +437,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
post.Message = p.sanitizeDescription(reopenedPRMessage)
}
- if action == constants.ActionMarkedReadyForReview {
+ if action == actionMarkedReadyForReview {
markedReadyToReviewPRMessage, err := renderTemplate("markedReadyToReviewPR", GetEventWithRenderConfig(event, sub))
if err != nil {
p.client.Log.Warn("Failed to render template", "error", err.Error())
@@ -449,7 +447,7 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
post.Message = p.sanitizeDescription(markedReadyToReviewPRMessage)
}
- if action == constants.ActionClosed {
+ if action == actionClosed {
post.Message = closedPRMessage
}
@@ -471,7 +469,7 @@ func (p *Plugin) sanitizeDescription(description string) string {
func (p *Plugin) handlePRDescriptionMentionNotification(event *github.PullRequestEvent) {
action := event.GetAction()
- if action != constants.ActionOpened {
+ if action != actionOpened {
return
}
@@ -533,7 +531,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
// This condition is made to check if the message doesn't get automatically labeled to prevent duplicated issue messages
timeDiff := time.Until(issue.GetCreatedAt().Time) * -1
- if action == constants.ActionLabeled && timeDiff.Seconds() < 4.00 {
+ if action == actionLabeled && timeDiff.Seconds() < 4.00 {
return
}
@@ -544,16 +542,16 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
issueTemplate := ""
switch action {
- case constants.ActionOpened:
+ case actionOpened:
issueTemplate = "newIssue"
- case constants.ActionClosed:
+ case actionClosed:
issueTemplate = "closedIssue"
- case constants.ActionReopened:
+ case actionReopened:
issueTemplate = "reopenedIssue"
- case constants.ActionLabeled:
+ case actionLabeled:
issueTemplate = "issueLabelled"
default:
@@ -571,7 +569,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
continue
}
- if sub.IssueCreations() && action != constants.ActionOpened && action != constants.ActionReopened && action != constants.ActionLabeled {
+ if sub.IssueCreations() && action != actionOpened && action != actionReopened && action != actionLabeled {
continue
}
@@ -600,26 +598,26 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
Message: renderedMessage,
}
- if action == constants.ActionOpened {
+ if action == actionOpened {
post.Type = "custom_git_issue"
post.Props = map[string]interface{}{
- constants.TitleForProps: *issue.Title,
- constants.IssueURLForProps: *issue.HTMLURL,
- constants.IssueNumberForProps: *issue.Number,
- constants.DescriptionForProps: description,
- constants.AssigneesForProps: assignees,
- constants.LabelsForProps: labels,
- constants.RepoOwnerForProps: *repo.Owner.Login,
- constants.RepoNameForProps: *repo.Name,
- constants.IssueStatus: constants.Close,
+ titleForProps: *issue.Title,
+ issueURLForProps: *issue.HTMLURL,
+ issueNumberForProps: *issue.Number,
+ descriptionForProps: description,
+ assigneesForProps: assignees,
+ labelsForProps: labels,
+ repoOwnerForProps: *repo.Owner.Login,
+ repoNameForProps: *repo.Name,
+ issueStatus: statusClose,
}
}
repoName := strings.ToLower(repo.GetFullName())
issueNumber := issue.Number
- post.AddProp(constants.PostPropGithubRepo, repoName)
- post.AddProp(constants.PostPropGithubObjectID, issueNumber)
- post.AddProp(constants.PostPropGithubObjectType, constants.GithubObjectTypeIssue)
+ post.AddProp(postPropGithubRepo, repoName)
+ post.AddProp(postPropGithubObjectID, issueNumber)
+ post.AddProp(postPropGithubObjectType, githubObjectTypeIssue)
label := sub.Label()
@@ -634,7 +632,7 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
continue
}
- if action == constants.ActionLabeled {
+ if action == actionLabeled {
if label == "" || label != eventLabel {
continue
}
@@ -783,7 +781,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
return
}
- if event.GetAction() != constants.ActionCreated {
+ if event.GetAction() != actionCreated {
return
}
@@ -801,9 +799,9 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
repoName := strings.ToLower(repo.GetFullName())
commentID := event.GetComment().GetID()
- post.AddProp(constants.PostPropGithubRepo, repoName)
- post.AddProp(constants.PostPropGithubObjectID, commentID)
- post.AddProp(constants.PostPropGithubObjectType, constants.GithubObjectTypeIssueComment)
+ post.AddProp(postPropGithubRepo, repoName)
+ post.AddProp(postPropGithubObjectID, commentID)
+ post.AddProp(postPropGithubObjectType, githubObjectTypeIssueComment)
labels := make([]string, len(event.GetIssue().Labels))
for index, label := range event.GetIssue().Labels {
@@ -832,7 +830,7 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
continue
}
- if event.GetAction() == constants.ActionCreated {
+ if event.GetAction() == actionCreated {
post.Message = message
}
@@ -864,7 +862,7 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent
}
action := event.GetAction()
- if action != constants.ActionSubmitted {
+ if action != actionSubmitted {
return
}
@@ -946,9 +944,9 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
repoName := strings.ToLower(repo.GetFullName())
commentID := event.GetComment().GetID()
- post.AddProp(constants.PostPropGithubRepo, repoName)
- post.AddProp(constants.PostPropGithubObjectID, commentID)
- post.AddProp(constants.PostPropGithubObjectType, constants.GithubObjectTypePRReviewComment)
+ post.AddProp(postPropGithubRepo, repoName)
+ post.AddProp(postPropGithubObjectID, commentID)
+ post.AddProp(postPropGithubObjectType, githubObjectTypePRReviewComment)
labels := make([]string, len(event.GetPullRequest().Labels))
for index, label := range event.GetPullRequest().Labels {
@@ -986,7 +984,7 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
func (p *Plugin) handleCommentMentionNotification(event *github.IssueCommentEvent) {
action := event.GetAction()
- if action == constants.ActionEdited || action == constants.ActionDeleted {
+ if action == actionEdited || action == actionDeleted {
return
}
@@ -1067,7 +1065,7 @@ func (p *Plugin) handleCommentAuthorNotification(event *github.IssueCommentEvent
}
action := event.GetAction()
- if action == constants.ActionEdited || action == constants.ActionDeleted {
+ if action == actionEdited || action == actionDeleted {
return
}
@@ -1211,7 +1209,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(requestedUserID, repoName) {
requestedUserID = ""
}
- case constants.ActionClosed:
+ case actionClosed:
if author == sender {
return
}
@@ -1219,7 +1217,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case constants.ActionReopened:
+ case actionReopened:
if author == sender {
return
}
@@ -1227,7 +1225,7 @@ func (p *Plugin) handlePullRequestNotification(event *github.PullRequestEvent) {
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case constants.ActionAssigned:
+ case actionAssigned:
assignee := event.GetPullRequest().GetAssignee().GetLogin()
if assignee == sender {
return
@@ -1269,17 +1267,17 @@ func (p *Plugin) handleIssueNotification(event *github.IssuesEvent) {
assigneeUserID := ""
switch event.GetAction() {
- case constants.ActionClosed:
+ case actionClosed:
authorUserID = p.getGitHubToUserIDMapping(author)
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case constants.ActionReopened:
+ case actionReopened:
authorUserID = p.getGitHubToUserIDMapping(author)
if isPrivate && !p.permissionToRepo(authorUserID, repoName) {
authorUserID = ""
}
- case constants.ActionAssigned:
+ case actionAssigned:
assignee := event.GetAssignee().GetLogin()
if assignee == sender {
return
@@ -1320,7 +1318,7 @@ func (p *Plugin) handlePullRequestReviewNotification(event *github.PullRequestRe
return
}
- if event.GetAction() != constants.ActionSubmitted {
+ if event.GetAction() != actionSubmitted {
return
}
diff --git a/server/serializer/issue.go b/server/serializer/issue.go
deleted file mode 100644
index a5d400a79..000000000
--- a/server/serializer/issue.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package serializer
-
-type CreateIssueRequest struct {
- Title string `json:"title"`
- Body string `json:"body"`
- Repo string `json:"repo"`
- PostID string `json:"post_id"`
- ChannelID string `json:"channel_id"`
- Labels []string `json:"labels"`
- Assignees []string `json:"assignees"`
- Milestone int `json:"milestone"`
-}
-
-type CreateIssueCommentRequest struct {
- PostID string `json:"post_id"`
- Owner string `json:"owner"`
- Repo string `json:"repo"`
- Number int `json:"number"`
- Comment string `json:"comment"`
- ShowAttachedMessage bool `json:"show_attached_message"`
-}
-
-type UpdateIssueRequest struct {
- Title string `json:"title"`
- Body string `json:"body"`
- Repo string `json:"repo"`
- PostID string `json:"post_id"`
- ChannelID string `json:"channel_id"`
- Labels []string `json:"labels"`
- Assignees []string `json:"assignees"`
- Milestone int `json:"milestone"`
- IssueNumber int `json:"issue_number"`
-}
-
-type CommentAndCloseRequest struct {
- ChannelID string `json:"channel_id"`
- IssueComment string `json:"issue_comment"`
- StatusReason string `json:"status_reason"`
- Number int `json:"number"`
- Owner string `json:"owner"`
- Repository string `json:"repo"`
- Status string `json:"status"`
- PostID string `json:"postId"`
-}
diff --git a/server/serializer/notification.go b/server/serializer/notification.go
deleted file mode 100644
index 0b3e1c03f..000000000
--- a/server/serializer/notification.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package serializer
-
-import "github.com/google/go-github/v54/github"
-
-type FilteredNotification struct {
- github.Notification
- HTMLURL string `json:"html_url"`
-}
diff --git a/server/serializer/pr.go b/server/serializer/pr.go
deleted file mode 100644
index 5cdb3b1ef..000000000
--- a/server/serializer/pr.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package serializer
-
-import "github.com/google/go-github/v54/github"
-
-type PRDetails struct {
- URL string `json:"url"`
- Number int `json:"number"`
- Status string `json:"status"`
- Mergeable bool `json:"mergeable"`
- RequestedReviewers []*string `json:"requestedReviewers"`
- Reviews []*github.PullRequestReview `json:"reviews"`
-}
diff --git a/server/serializer/repo.go b/server/serializer/repo.go
deleted file mode 100644
index a7d3eaf7e..000000000
--- a/server/serializer/repo.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package serializer
-
-// Only send down fields to the client that are needed
-type RepositoryResponse struct {
- Name string `json:"name,omitempty"`
- FullName string `json:"full_name,omitempty"`
- Permissions map[string]bool `json:"permissions,omitempty"`
-}
diff --git a/server/serializer/user.go b/server/serializer/user.go
deleted file mode 100644
index e37f4e410..000000000
--- a/server/serializer/user.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package serializer
-
-import (
- "context"
-
- "github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger"
- "golang.org/x/oauth2"
-)
-
-type Context struct {
- Ctx context.Context
- UserID string
- Log logger.Logger
-}
-
-type GitHubUserRequest struct {
- UserID string `json:"user_id"`
-}
-
-type GitHubUserResponse struct {
- Username string `json:"username"`
-}
-
-type ConnectedResponse struct {
- Connected bool `json:"connected"`
- GitHubUsername string `json:"github_username"`
- GitHubClientID string `json:"github_client_id"`
- EnterpriseBaseURL string `json:"enterprise_base_url,omitempty"`
- Organization string `json:"organization"`
- UserSettings *UserSettings `json:"user_settings"`
- ClientConfiguration map[string]interface{} `json:"configuration"`
-}
-
-type UserSettings struct {
- SidebarButtons string `json:"sidebar_buttons"`
- DailyReminder bool `json:"daily_reminder"`
- DailyReminderOnChange bool `json:"daily_reminder_on_change"`
- Notifications bool `json:"notifications"`
-}
-
-type GitHubUserInfo struct {
- UserID string
- Token *oauth2.Token
- GitHubUsername string
- LastToDoPostAt int64
- Settings *UserSettings
- AllowedPrivateRepos bool
-
- // MM34646ResetTokenDone is set for a user whose token has been reset for MM-34646.
- MM34646ResetTokenDone bool
-}
-
-type UserContext struct {
- Context
- GHInfo *GitHubUserInfo
-}
-
-type OAuthState struct {
- UserID string `json:"user_id"`
- Token string `json:"token"`
- PrivateAllowed bool `json:"private_allowed"`
-}
From 136221f5b067e00b5d20182b55ba256c62235c0f Mon Sep 17 00:00:00 2001
From: raghavaggarwal2308
Date: Fri, 5 Jul 2024 15:24:23 +0530
Subject: [PATCH 07/18] [MM-556] Review fixes
---
webapp/package-lock.json | 27 +++++++----
webapp/src/components/github_issue/index.tsx | 49 +++++++++-----------
2 files changed, 41 insertions(+), 35 deletions(-)
diff --git a/webapp/package-lock.json b/webapp/package-lock.json
index 91b58967d..571d900b9 100644
--- a/webapp/package-lock.json
+++ b/webapp/package-lock.json
@@ -20209,17 +20209,20 @@
"@primer/octicons-react": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-10.1.0.tgz",
- "integrity": "sha512-WjIaetTaf4x66xxaG/gxwsWRL2JYG33n8CfeR/L134YcX2zl9TPps9crLzI2f3rxjOdKZgVFBoUh94Cim4Fflw=="
+ "integrity": "sha512-WjIaetTaf4x66xxaG/gxwsWRL2JYG33n8CfeR/L134YcX2zl9TPps9crLzI2f3rxjOdKZgVFBoUh94Cim4Fflw==",
+ "requires": {}
},
"@react-native-community/netinfo": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz",
- "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA=="
+ "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==",
+ "requires": {}
},
"@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
- "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
+ "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==",
+ "requires": {}
},
"@restart/hooks": {
"version": "0.3.27",
@@ -20876,7 +20879,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"acorn-walk": {
"version": "7.2.0",
@@ -20931,13 +20935,15 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"ansi-colors": {
"version": "4.1.3",
@@ -23211,7 +23217,8 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.2.tgz",
"integrity": "sha512-ykUeqkGyUGgwTtk78C0o8UG2fzwmgJ0qxBGPp2WqRKsTwcLuVf01kTDRAtOsd4u6whX2XOC8749n2vPydP82fg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-scope": {
"version": "5.1.1",
@@ -25794,7 +25801,8 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"jest-regex-util": {
"version": "26.0.0",
@@ -31955,7 +31963,8 @@
"ws": {
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
- "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "requires": {}
},
"xml": {
"version": "1.0.1",
diff --git a/webapp/src/components/github_issue/index.tsx b/webapp/src/components/github_issue/index.tsx
index 75eb03873..1b13fd5b5 100644
--- a/webapp/src/components/github_issue/index.tsx
+++ b/webapp/src/components/github_issue/index.tsx
@@ -28,20 +28,17 @@ const GithubIssue = ({theme, post}: GithubIssueProps) => {
};
const content = (
-
+
@@ -49,7 +46,7 @@ const GithubIssue = ({theme, post}: GithubIssueProps) => {
if (postProps.assignees?.length) {
assignees = (
-
+
{'Assignees'}
{postProps.assignees.map((assignee: string, index: number) => (
@@ -62,7 +59,7 @@ const GithubIssue = ({theme, post}: GithubIssueProps) => {
if (postProps.labels?.length) {
labels = (
-
+
{'Labels'}
{postProps.labels.map((label: string, index: number) => (
@@ -75,39 +72,39 @@ const GithubIssue = ({theme, post}: GithubIssueProps) => {
return (
-
-
{postProps.description}
- {assignees}
- {labels}
+
+
{postProps.description}
+
+ {assignees}
+ {labels}
+
{content}
);
};
const getStyle = makeStyleFromTheme((theme) => ({
- button: {
- fontFamily: 'Open Sans',
- fontSize: '12px',
- fontWeight: 'bold',
- letterSpacing: '1px',
- lineHeight: '19px',
- margin: '12px 12px 8px 0px',
- borderRadius: '4px',
- color: theme.buttonColor,
+ button_container: {
+ margin: '16px 0 8px 0',
+ },
+ issue_description: {
+ marginBottom: '10px',
},
- close_or_reopen_button: {
- backgroundColor: theme.errorTextColor,
+ assignee: {
+ marginRight: '20px',
},
- other_buttons: {
- backgroundColor: theme.buttonBg,
+ issue_title: {
+ fontFamily: 'Metropolis',
+ fontWeight: 600,
},
assignees_and_labels: {
display: 'inline-block',
From 482fcf9a39dec85c31c6160b28ac051ece213a08 Mon Sep 17 00:00:00 2001
From: kshitij katiyar <90389917+Kshitij-Katiyar@users.noreply.github.com>
Date: Tue, 6 Aug 2024 15:15:50 +0530
Subject: [PATCH 08/18] [MM-617]: converted the custom post to slack attachment
for issue creation event on Github (#37)
* [MM-617]: converted the custom post to slack attachment for issue creation
* [MM-617]: fixed lint and testcases
* [MM-617]: removed unused variables
* [MM-617]: Fixed the title of the issue slackAttachment
* [MM-617]: review fixes
* [MM-617]: fixed lint
* [MM-617]: Review fixes and code clean up
* [MM-617]: removed the custom post file
* [MM-617]: review fixes
* [MM-617]: review fixes
* [MM-617]: Fixed lint
* [MM-617]: improved the error logging
---
server/plugin/api.go | 110 +++++++++-
server/plugin/plugin.go | 5 +
server/plugin/template.go | 16 +-
server/plugin/template_test.go | 192 +++---------------
server/plugin/utils.go | 87 +++++++-
server/plugin/webhook.go | 68 +++++--
webapp/src/components/github_issue/index.tsx | 116 -----------
.../attach_comment_to_issue.jsx | 6 +-
.../modals/close_reopen_issue/index.tsx | 18 +-
.../create_update_issue.jsx | 5 +-
webapp/src/index.js | 7 +-
webapp/src/types/common/index.d.ts | 4 +
webapp/src/websocket/index.js | 53 +++++
13 files changed, 346 insertions(+), 341 deletions(-)
delete mode 100644 webapp/src/components/github_issue/index.tsx
create mode 100644 webapp/src/types/common/index.d.ts
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 106031a5e..72464952b 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -58,6 +58,22 @@ const (
ResponseTypeJSON ResponseType = "JSON_RESPONSE"
// ResponseTypePlain indicates that response type is text plain
ResponseTypePlain ResponseType = "TEXT_RESPONSE"
+
+ KeyRepoName string = "repo_name"
+ KeyRepoOwner string = "repo_owner"
+ KeyIssueNumber string = "issue_number"
+ KeyIssueID string = "issue_id"
+ KeyStatus string = "status"
+ KeyChannelID string = "channel_id"
+ KeyPostID string = "postId"
+
+ WebsocketEventOpenCommentModal string = "open_comment_modal"
+ WebsocketEventOpenStatusModal string = "open_status_modal"
+ WebsocketEventOpenEditModal string = "open_edit_modal"
+
+ PathOpenIssueCommentModal string = "/open-comment-modal"
+ PathOpenIssueEditModal string = "/open-edit-modal"
+ PathOpenIssueStatusModal string = "/open-status-modal"
)
func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
@@ -124,6 +140,9 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc("/issue", p.checkAuth(p.attachUserContext(p.getIssueByNumber), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/pr", p.checkAuth(p.attachUserContext(p.getPrByNumber), ResponseTypePlain)).Methods(http.MethodGet)
apiRouter.HandleFunc("/lhs-content", p.checkAuth(p.attachUserContext(p.getSidebarContent), ResponseTypePlain)).Methods(http.MethodGet)
+ apiRouter.HandleFunc(PathOpenIssueCommentModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueCommentModal), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc(PathOpenIssueEditModal, p.checkAuth(p.attachUserContext(p.handleOpenEditIssueModal), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc(PathOpenIssueStatusModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueStatusModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/config", checkPluginRequest(p.getConfig)).Methods(http.MethodGet)
apiRouter.HandleFunc("/token", checkPluginRequest(p.getToken)).Methods(http.MethodGet)
@@ -863,7 +882,7 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
rootID = post.RootId
}
- permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v) from a [Message](%v)", req.Number, result.GetHTMLURL(), permalink)
+ permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v)", req.Number, result.GetHTMLURL())
if req.ShowAttachedMessage {
permalinkReplyMessage = fmt.Sprintf("[Message](%v) attached to GitHub issue [#%v](%v)", permalink, req.Number, result.GetHTMLURL())
}
@@ -1321,7 +1340,6 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
}
var post *model.Post
- permalink := ""
if issue.PostID != "" {
var appErr *model.AppError
post, appErr = p.API.GetPost(issue.PostID)
@@ -1334,7 +1352,6 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
return
}
- permalink = p.getPermaLink(issue.PostID)
}
githubIssue := &github.IssueRequest{
@@ -1392,7 +1409,6 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
rootID = post.RootId
}
channelID = post.ChannelId
- message += fmt.Sprintf(" from a [message](%s)", permalink)
}
reply := &model.Post{
@@ -1622,6 +1638,92 @@ func (p *Plugin) getToken(w http.ResponseWriter, r *http.Request) {
p.writeJSON(w, info.Token)
}
+func (p *Plugin) handleOpenEditIssueModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ response := &model.PostActionIntegrationResponse{}
+ decoder := json.NewDecoder(r.Body)
+ postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
+ if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
+ p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, response)
+ return
+ }
+
+ p.client.Frontend.PublishWebSocketEvent(
+ WebsocketEventOpenEditModal,
+ map[string]interface{}{
+ KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
+ KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
+ KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
+ KeyPostID: postActionIntegrationRequest.PostId,
+ KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
+ KeyChannelID: postActionIntegrationRequest.ChannelId,
+ },
+ &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
+ )
+
+ p.returnPostActionIntegrationResponse(w, response)
+}
+
+func (p *Plugin) returnPostActionIntegrationResponse(w http.ResponseWriter, res *model.PostActionIntegrationResponse) {
+ w.Header().Set("Content-Type", "application/json")
+
+ if err := json.NewEncoder(w).Encode(res); err != nil {
+ p.API.LogWarn("Failed to write PostActionIntegrationResponse", "Error", err.Error())
+ }
+}
+
+func (p *Plugin) handleOpenIssueStatusModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ response := &model.PostActionIntegrationResponse{}
+ decoder := json.NewDecoder(r.Body)
+ postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
+ if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
+ p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, response)
+ return
+ }
+
+ p.client.Frontend.PublishWebSocketEvent(
+ WebsocketEventOpenStatusModal,
+ map[string]interface{}{
+ KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
+ KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
+ KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
+ KeyPostID: postActionIntegrationRequest.PostId,
+ KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
+ KeyChannelID: postActionIntegrationRequest.ChannelId,
+ },
+ &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
+ )
+
+ p.returnPostActionIntegrationResponse(w, response)
+}
+
+func (p *Plugin) handleOpenIssueCommentModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ response := &model.PostActionIntegrationResponse{}
+ decoder := json.NewDecoder(r.Body)
+ postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
+ if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
+ p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, response)
+ return
+ }
+
+ p.client.Frontend.PublishWebSocketEvent(
+ WebsocketEventOpenCommentModal,
+ map[string]interface{}{
+ KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
+ KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
+ KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
+ KeyPostID: postActionIntegrationRequest.PostId,
+ KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
+ KeyChannelID: postActionIntegrationRequest.ChannelId,
+ },
+ &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
+ )
+
+ p.returnPostActionIntegrationResponse(w, response)
+}
+
// parseRepo parses the owner & repository name from the repo query parameter
func parseRepo(repoParam string) (owner, repo string, err error) {
if repoParam == "" {
diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go
index 1da17175e..f89430b04 100644
--- a/server/plugin/plugin.go
+++ b/server/plugin/plugin.go
@@ -78,6 +78,7 @@ const (
labelsForProps = "labels"
descriptionForProps = "description"
titleForProps = "title"
+ attachmentsForProps = "attachments"
issueNumberForProps = "issue_number"
issueURLForProps = "issue_url"
repoOwnerForProps = "repo_owner"
@@ -1094,3 +1095,7 @@ func (p *Plugin) getUsername(mmUserID string) (string, error) {
return "@" + info.GitHubUsername, nil
}
+
+func (p *Plugin) GetPluginAPIPath() string {
+ return fmt.Sprintf("%s/plugins/%s/api/v1", *p.client.Configuration.GetConfig().ServiceSettings.SiteURL, Manifest.Id)
+}
diff --git a/server/plugin/template.go b/server/plugin/template.go
index 753abc183..160a59367 100644
--- a/server/plugin/template.go
+++ b/server/plugin/template.go
@@ -126,7 +126,7 @@ func init() {
// The repo template links to the corresponding repository.
template.Must(masterTemplate.New("repo").Parse(
- `[\[{{.GetFullName}}\]]({{.GetHTMLURL}})`,
+ `[{{.GetFullName}}]({{.GetHTMLURL}})`,
))
// The eventRepoPullRequest links to the corresponding pull request, anchored at the repo.
@@ -256,19 +256,7 @@ Assignees: {{range $i, $el := .Assignees -}} {{- if $i}}, {{end}}{{template "use
{{.GetPullRequest.GetBody | trimBody | quote | replaceAllGitHubUsernames}}`))
template.Must(masterTemplate.New("newIssue").Funcs(funcMap).Parse(`
-{{ if eq .Config.Style "collapsed" -}}
-{{template "repo" .Event.GetRepo}} New issue {{template "issue" .Event.GetIssue}} opened by {{template "user" .Event.GetSender}}.
-{{- else -}}
-#### {{.Event.GetIssue.GetTitle}}
-##### {{template "eventRepoIssue" .Event}}
-#new-issue by {{template "user" .Event.GetSender}}
-{{- if ne .Config.Style "skip-body" -}}
-{{- template "labels" dict "Labels" .Event.GetIssue.Labels "RepositoryURL" .Event.GetRepo.GetHTMLURL }}
-{{- template "assignee" .Event.GetIssue }}
-
-{{.Event.GetIssue.GetBody | removeComments | replaceAllGitHubUsernames}}
-{{- end -}}
-{{- end }}
+{{template "user" .Event.GetSender}} created a new issue in {{template "repo" .Event.GetRepo}}
`))
template.Must(masterTemplate.New("closedIssue").Funcs(funcMap).Parse(`
diff --git a/server/plugin/template_test.go b/server/plugin/template_test.go
index e66947ea3..aa651c418 100644
--- a/server/plugin/template_test.go
+++ b/server/plugin/template_test.go
@@ -115,39 +115,6 @@ var issue = github.Issue{
Body: sToP(`git-get-head sounds like a great feature we should support`),
}
-var issueWithMentions = github.Issue{
- Number: iToP(1),
- HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
- Title: sToP("Implement git-get-head"),
- CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
- UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
- Body: sToP(`git-get-head sounds like a great feature we should support
-` + gitHubMentions),
-}
-
-var issueWithLabelAndAssignee = github.Issue{
- Number: iToP(1),
- HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
- Title: sToP("Implement git-get-head"),
- CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
- UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
- Body: sToP(`git-get-head sounds like a great feature we should support`),
- Labels: singleLabel,
- Assignee: &user,
- Assignees: []*github.User{&user},
-}
-
-var issueWithMultipleLabelsAndAssignee = github.Issue{
- Number: iToP(1),
- HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
- Title: sToP("Implement git-get-head"),
- CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
- UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
- Body: sToP(`git-get-head sounds like a great feature we should support`),
- Labels: labels,
- Assignees: []*github.User{&user, &user},
-}
-
var user = github.User{
Login: sToP("panda"),
HTMLURL: sToP("https://github.com/panda"),
@@ -324,7 +291,7 @@ git-get-head gets the non-sent upstream heads inside the stashed non-cleaned app
t.Run("with collapsed render style", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was opened by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was opened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("newPR", &EventWithRenderConfig{
@@ -366,7 +333,7 @@ git-get-head gets the non-sent upstream heads inside the stashed non-cleaned app
func TestClosedPRMessageTemplate(t *testing.T) {
t.Run("merged", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was merged by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was merged by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedPR", &github.PullRequestEvent{
@@ -380,7 +347,7 @@ func TestClosedPRMessageTemplate(t *testing.T) {
t.Run("closed", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was closed by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was closed by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedPR", &github.PullRequestEvent{
@@ -396,7 +363,7 @@ func TestClosedPRMessageTemplate(t *testing.T) {
func TestReopenedPRMessageTemplate(t *testing.T) {
t.Run("reopened", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was reopened by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was reopened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("reopenedPR", &github.PullRequestEvent{
@@ -429,15 +396,10 @@ func TestPullRequestLabelledTemplate(t *testing.T) {
}
func TestNewIssueTemplate(t *testing.T) {
- t.Run("without mentions", func(t *testing.T) {
+ t.Run("new issue", func(t *testing.T) {
expected := `
-#### Implement git-get-head
-##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
-#new-issue by [panda](https://github.com/panda)
-
-git-get-head sounds like a great feature we should support
+[panda](https://github.com/panda) created a new issue in [mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github)
`
-
actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
&github.IssuesEvent{
Repo: &repo,
@@ -449,119 +411,11 @@ git-get-head sounds like a great feature we should support
require.NoError(t, err)
require.Equal(t, expected, actual)
})
-
- t.Run("with mentions", withGitHubUserNameMapping(func(t *testing.T) {
- expected := `
-#### Implement git-get-head
-##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
-#new-issue by @pandabot
-
-git-get-head sounds like a great feature we should support
-` + usernameMentions + `
-`
-
- actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
- &github.IssuesEvent{
- Repo: &repo,
- Issue: &issueWithMentions,
- Sender: &user,
- },
- nil,
- ))
- require.NoError(t, err)
- require.Equal(t, expected, actual)
- }))
-
- t.Run("with single label and assignee", func(t *testing.T) {
- expected := `
-#### Implement git-get-head
-##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
-#new-issue by [panda](https://github.com/panda)
-Labels: ` + "[`Help Wanted`](https://github.com/mattermost/mattermost-plugin-github/labels/Help%20Wanted)" + `
-Assignees: [panda](https://github.com/panda)
-
-git-get-head sounds like a great feature we should support
-`
-
- actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
- &github.IssuesEvent{
- Repo: &repo,
- Issue: &issueWithLabelAndAssignee,
- Sender: &user,
- },
- nil,
- ))
- require.NoError(t, err)
- require.Equal(t, expected, actual)
- })
-
- t.Run("with multiple labels and assignees", func(t *testing.T) {
- expected := `
-#### Implement git-get-head
-##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
-#new-issue by [panda](https://github.com/panda)
-Labels: ` + "[`Help Wanted`](https://github.com/mattermost/mattermost-plugin-github/labels/Help%20Wanted), [`Tech/Go`](https://github.com/mattermost/mattermost-plugin-github/labels/Tech%2FGo)" + `
-Assignees: [panda](https://github.com/panda), [panda](https://github.com/panda)
-
-git-get-head sounds like a great feature we should support
-`
-
- actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
- &github.IssuesEvent{
- Repo: &repo,
- Issue: &issueWithMultipleLabelsAndAssignee,
- Sender: &user,
- },
- nil,
- ))
- require.NoError(t, err)
- require.Equal(t, expected, actual)
- })
-
- t.Run("with collapsed render style", func(t *testing.T) {
- expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) opened by [panda](https://github.com/panda).
-`
-
- actual, err := renderTemplate("newIssue", &EventWithRenderConfig{
- Event: &github.IssuesEvent{
- Repo: &repo,
- Issue: &issue,
- Sender: &user,
- },
- Config: RenderConfig{
- Style: "collapsed",
- },
- })
- require.NoError(t, err)
- require.Equal(t, expected, actual)
- })
-
- t.Run("with skip-body render style", func(t *testing.T) {
- expected := `
-#### Implement git-get-head
-##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
-#new-issue by [panda](https://github.com/panda)
-`
-
- actual, err := renderTemplate("newIssue", &EventWithRenderConfig{
- Event: &github.IssuesEvent{
- Repo: &repo,
- Issue: &issue,
- Sender: &user,
- },
- Config: RenderConfig{
- Style: "skip-body",
- },
- })
- require.NoError(t, err)
- require.Equal(t, expected, actual)
- })
}
func TestClosedIssueTemplate(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) closed by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) closed by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedIssue", GetEventWithRenderConfig(
@@ -578,7 +432,7 @@ func TestClosedIssueTemplate(t *testing.T) {
func TestReopenedIssueTemplate(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) reopened by [panda](https://github.com/panda).
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) reopened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("reopenedIssue", GetEventWithRenderConfig(
@@ -789,7 +643,7 @@ func TestPushedCommitsTemplate(t *testing.T) {
func TestCreateMessageTemplate(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) branch [branchname](https://github.com/mattermost/mattermost-plugin-github/tree/branchname) created by [panda](https://github.com/panda)
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) branch [branchname](https://github.com/mattermost/mattermost-plugin-github/tree/branchname) created by [panda](https://github.com/panda)
`
actual, err := renderTemplate("newCreateMessage", &github.CreateEvent{
@@ -804,7 +658,7 @@ func TestCreateMessageTemplate(t *testing.T) {
func TestDeletedMessageTemplate(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) branch branchname deleted by [panda](https://github.com/panda)
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) branch branchname deleted by [panda](https://github.com/panda)
`
actual, err := renderTemplate("newDeleteMessage", &github.DeleteEvent{
@@ -819,7 +673,7 @@ func TestDeletedMessageTemplate(t *testing.T) {
func TestRepoStarTemplate(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) starred by [panda](https://github.com/panda)
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) starred by [panda](https://github.com/panda)
It now has **1** stars.`
actual, err := renderTemplate("newRepoStar", &github.StarEvent{
@@ -834,7 +688,7 @@ It now has **1** stars.`
func TestIssueCommentTemplate(t *testing.T) {
t.Run("non-email body without mentions", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
`
@@ -853,7 +707,7 @@ git-get-head sounds like a great feature we should support
t.Run("email body without mentions", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
`
@@ -872,7 +726,7 @@ git-get-head sounds like a great feature we should support
t.Run("non-email body with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
` + usernameMentions + `
@@ -892,7 +746,7 @@ git-get-head sounds like a great feature we should support
t.Run("email body with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
` + usernameMentions + `
@@ -914,7 +768,7 @@ git-get-head sounds like a great feature we should support
func TestPullRequestReviewEventTemplate(t *testing.T) {
t.Run("approved", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -934,7 +788,7 @@ Excited to see git-get-head land!
t.Run("commented", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) commented on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) commented on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -954,7 +808,7 @@ Excited to see git-get-head land!
t.Run("requested changes", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) requested changes on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) requested changes on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -974,7 +828,7 @@ Excited to see git-get-head land!
t.Run("approved with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) @pandabot approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) @pandabot approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
` + usernameMentions + `
@@ -997,7 +851,7 @@ Excited to see git-get-head land!
func TestPullRequestReviewCommentEventTemplate(t *testing.T) {
t.Run("without mentions", func(*testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New review comment by [panda](https://github.com/panda) on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New review comment by [panda](https://github.com/panda) on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Should this be here?
`
@@ -1016,7 +870,7 @@ Should this be here?
t.Run("with mentions", withGitHubUserNameMapping(func(*testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New review comment by @pandabot on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New review comment by @pandabot on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Should this be here?
` + usernameMentions + `
@@ -1406,7 +1260,7 @@ func TestPullRequestReviewNotification(t *testing.T) {
func TestReleaseNotification(t *testing.T) {
t.Run("created", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) created a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) created a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
actual, err := renderTemplate("newReleaseEvent", &github.ReleaseEvent{
Repo: &repo,
@@ -1423,7 +1277,7 @@ func TestReleaseNotification(t *testing.T) {
t.Run("deleted", func(t *testing.T) {
expected := `
-[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) deleted a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
+[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) deleted a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
actual, err := renderTemplate("newReleaseEvent", &github.ReleaseEvent{
Repo: &repo,
diff --git a/server/plugin/utils.go b/server/plugin/utils.go
index baedcf91f..dd618db08 100644
--- a/server/plugin/utils.go
+++ b/server/plugin/utils.go
@@ -7,6 +7,7 @@ import (
"crypto/cipher"
"crypto/rand"
"encoding/base64"
+ "encoding/json"
"fmt"
"io"
"net/http"
@@ -392,18 +393,46 @@ func (p *Plugin) updatePost(issue *UpdateIssueRequest, w http.ResponseWriter) {
return
}
- post.Props[assigneesForProps] = issue.Assignees
- post.Props[labelsForProps] = issue.Labels
- post.Props[descriptionForProps] = issue.Body
- post.Props[titleForProps] = issue.Title
+ attachments, err := getAttachmentsFromProps(post.Props)
+ if err != nil {
+ p.client.Log.Warn("Error occurred while getting attachments from props", "PostID", post.Id, "error", err.Error())
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("existing attachments format error: %v", err), StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ attachments[0].Fields = p.CreateFieldsForIssuePost(issue.Assignees, issue.Labels)
+ attachments[0].Title = fmt.Sprintf("%s #%d", issue.Title, issue.IssueNumber)
+ attachments[0].Text = issue.Body
+
+ post.Props[attachmentsForProps] = attachments
+
if _, appErr = p.API.UpdatePost(post); appErr != nil {
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
}
}
+func getAttachmentsFromProps(props map[string]interface{}) ([]*model.SlackAttachment, error) {
+ attachments, ok := props["attachments"]
+ if !ok {
+ return nil, fmt.Errorf("no attachments found in props")
+ }
+
+ attachmentsData, err := json.Marshal(attachments)
+ if err != nil {
+ return nil, fmt.Errorf("failed to marshal attachments: %v", err)
+ }
+
+ var slackAttachments []*model.SlackAttachment
+ err = json.Unmarshal(attachmentsData, &slackAttachments)
+ if err != nil {
+ return nil, fmt.Errorf("failed to unmarshal attachments: %v", err)
+ }
+
+ return slackAttachments, nil
+}
+
func (p *Plugin) CreateCommentToIssue(c *UserContext, w http.ResponseWriter, comment, owner, repo string, post *model.Post, issueNumber int) {
currentUsername := c.GHInfo.GitHubUsername
- permalink := p.getPermaLink(post.Id)
issueComment := &github.IssueComment{
Body: &comment,
}
@@ -425,7 +454,7 @@ func (p *Plugin) CreateCommentToIssue(c *UserContext, w http.ResponseWriter, com
rootID = post.RootId
}
- permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v) from a [message](%v)", issueNumber, result.GetHTMLURL(), permalink)
+ permalinkReplyMessage := fmt.Sprintf("Comment attached to GitHub issue [#%v](%v)", issueNumber, result.GetHTMLURL())
reply := &model.Post{
Message: permalinkReplyMessage,
ChannelId: post.ChannelId,
@@ -493,11 +522,36 @@ func (p *Plugin) CloseOrReopenIssue(c *UserContext, w http.ResponseWriter, statu
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", post.Id), StatusCode: http.StatusInternalServerError})
return
}
+
+ var actionButtonTitle string
if status == issueClose {
post.Props[issueStatus] = statusReopen
+ actionButtonTitle = statusReopen
} else {
post.Props[issueStatus] = statusClose
+ actionButtonTitle = statusClose
}
+
+ attachment, err := getAttachmentsFromProps(post.Props)
+ if err != nil {
+ p.client.Log.Error("Error occurred while getting attachments from props", "PostID", post.Id, "Error", err.Error())
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("existing attachments format error: %v", err), StatusCode: http.StatusInternalServerError})
+ return
+ }
+ actions := attachment[0].Actions
+ for _, action := range actions {
+ if action.Name == statusClose || action.Name == statusReopen {
+ action.Name = actionButtonTitle
+ if status == issueClose {
+ action.Integration.Context["status"] = "close"
+ } else {
+ action.Integration.Context["status"] = "open"
+ }
+ }
+ }
+ attachment[0].Actions = actions
+ post.Props[attachmentsForProps] = attachment
+
if _, appErr := p.API.UpdatePost(post); appErr != nil {
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to update the post %s", post.Id), StatusCode: http.StatusInternalServerError})
}
@@ -523,3 +577,24 @@ func lastN(s string, n int) string {
return string(out)
}
+
+func (p *Plugin) CreateFieldsForIssuePost(assignees []string, labels []string) []*model.SlackAttachmentField {
+ fields := []*model.SlackAttachmentField{}
+ if len(assignees) > 0 {
+ fields = append(fields, &model.SlackAttachmentField{
+ Title: "Assignees",
+ Value: strings.Join(assignees, ", "),
+ Short: true,
+ })
+ }
+
+ if len(labels) > 0 {
+ fields = append(fields, &model.SlackAttachmentField{
+ Title: "Labels",
+ Value: strings.Join(labels, ", "),
+ Short: true,
+ })
+ }
+
+ return fields
+}
diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go
index 622f38296..4535dc4ac 100644
--- a/server/plugin/webhook.go
+++ b/server/plugin/webhook.go
@@ -590,20 +590,64 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
description = *issue.Body
}
- post := p.makeBotPost(renderedMessage, "")
+ post := &model.Post{
+ UserId: p.BotUserID,
+ Type: "custom_git_release",
+ }
if action == actionOpened {
- post.Type = "custom_git_issue"
- post.Props = map[string]interface{}{
- titleForProps: *issue.Title,
- issueURLForProps: *issue.HTMLURL,
- issueNumberForProps: *issue.Number,
- descriptionForProps: description,
- assigneesForProps: assignees,
- labelsForProps: labels,
- repoOwnerForProps: *repo.Owner.Login,
- repoNameForProps: *repo.Name,
- issueStatus: statusClose,
+ post.Props = model.StringInterface{
+ "attachments": []*model.SlackAttachment{
+ {
+ Pretext: renderedMessage,
+ Title: fmt.Sprintf("%s #%d", *issue.Title, *issue.Number),
+ TitleLink: *issue.HTMLURL,
+ Text: description,
+ Actions: []*model.PostAction{
+ {
+ Name: "Comment",
+ Integration: &model.PostActionIntegration{
+ Context: map[string]interface{}{
+ KeyRepoOwner: repo.GetOwner().GetLogin(),
+ KeyRepoName: repo.GetName(),
+ KeyIssueNumber: issue.GetNumber(),
+ KeyIssueID: issue.GetID(),
+ KeyStatus: *issue.State,
+ },
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathOpenIssueCommentModal),
+ },
+ Style: "primary",
+ },
+ {
+ Name: "Edit",
+ Integration: &model.PostActionIntegration{
+ Context: map[string]interface{}{
+ KeyRepoOwner: repo.GetOwner().GetLogin(),
+ KeyRepoName: repo.GetName(),
+ KeyIssueNumber: issue.GetNumber(),
+ KeyIssueID: issue.GetID(),
+ KeyStatus: *issue.State,
+ },
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathOpenIssueEditModal),
+ },
+ },
+ {
+ Name: "Close",
+ Integration: &model.PostActionIntegration{
+ Context: map[string]interface{}{
+ KeyRepoOwner: repo.GetOwner().GetLogin(),
+ KeyRepoName: repo.GetName(),
+ KeyIssueNumber: issue.GetNumber(),
+ KeyIssueID: issue.GetID(),
+ KeyStatus: *issue.State,
+ },
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathOpenIssueStatusModal),
+ },
+ },
+ },
+ Fields: p.CreateFieldsForIssuePost(assignees, labels),
+ },
+ },
}
}
repoName := strings.ToLower(repo.GetFullName())
diff --git a/webapp/src/components/github_issue/index.tsx b/webapp/src/components/github_issue/index.tsx
deleted file mode 100644
index 1b13fd5b5..000000000
--- a/webapp/src/components/github_issue/index.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import * as React from 'react';
-import {makeStyleFromTheme} from 'mattermost-redux/utils/theme_utils';
-import {Theme} from 'mattermost-redux/types/preferences';
-import {Post} from 'mattermost-redux/types/posts';
-import {useDispatch} from 'react-redux';
-
-import {openCreateCommentOnIssueModal, openCreateOrUpdateIssueModal, openCloseOrReopenIssueModal} from '../../actions';
-
-type GithubIssueProps = {
- theme: Theme,
- post: Post,
-}
-
-const GithubIssue = ({theme, post}: GithubIssueProps) => {
- const style = getStyle(theme);
- const postProps = post.props || {};
- let assignees;
- let labels;
- const dispatch = useDispatch();
-
- const issue = {
- repo_owner: postProps.repo_owner,
- repo_name: postProps.repo_name,
- issue_number: postProps.issue_number,
- postId: post.id,
- status: postProps.status,
- channel_id: post.channel_id,
- };
-
- const content = (
-
-
-
-
-
- );
-
- if (postProps.assignees?.length) {
- assignees = (
-
-
{'Assignees'}
-
- {postProps.assignees.map((assignee: string, index: number) => (
- {(index ? ', ' : '') + assignee}
- ))}
-
-
- );
- }
-
- if (postProps.labels?.length) {
- labels = (
-
-
{'Labels'}
-
- {postProps.labels.map((label: string, index: number) => (
- {(index ? ', ' : '') + label}
- ))}
-
-
- );
- }
-
- return (
-
- );
-};
-
-const getStyle = makeStyleFromTheme((theme) => ({
- button_container: {
- margin: '16px 0 8px 0',
- },
- issue_description: {
- marginBottom: '10px',
- },
- assignee: {
- marginRight: '20px',
- },
- issue_title: {
- fontFamily: 'Metropolis',
- fontWeight: 600,
- },
- assignees_and_labels: {
- display: 'inline-block',
- verticalAlign: 'top',
- width: '30%',
- },
-}));
-
-export default GithubIssue;
diff --git a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
index 2096f60e8..adbb80c4b 100644
--- a/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
+++ b/webapp/src/components/modals/attach_comment_to_issue/attach_comment_to_issue.jsx
@@ -45,13 +45,13 @@ export default class AttachIssueModal extends PureComponent {
return;
}
- const {repo_owner, repo_name, issue_number} = this.props.messageData ?? {};
+ const {repo_owner, repo_name, issue_number, postId} = this.props.messageData ?? {};
const issue = {
owner: repo_owner,
repo: repo_name,
number: issue_number,
comment: this.state.comment,
- post_id: this.props.post.id,
+ post_id: postId,
show_attached_message: false,
};
this.setState({submitting: true});
@@ -78,7 +78,7 @@ export default class AttachIssueModal extends PureComponent {
repo,
number,
comment: this.state.comment,
- post_id: this.props.post.id,
+ post_id: this.props.messageData?.postId,
show_attached_message: true,
};
diff --git a/webapp/src/components/modals/close_reopen_issue/index.tsx b/webapp/src/components/modals/close_reopen_issue/index.tsx
index a78c4cb25..f40833453 100644
--- a/webapp/src/components/modals/close_reopen_issue/index.tsx
+++ b/webapp/src/components/modals/close_reopen_issue/index.tsx
@@ -17,8 +17,7 @@ import Input from '../../input';
const CloseOrReopenIssueModal = ({theme}: {theme: Theme}) => {
const dispatch = useDispatch();
- const closeOrReopenIssueModalData = useSelector(getCloseOrReopenIssueModalData);
- const {messageData, visible} = closeOrReopenIssueModalData;
+ const {messageData, visible} = useSelector(getCloseOrReopenIssueModalData);
const [statusReason, setStatusReason] = useState('completed');
const [submitting, setSubmitting] = useState(false);
const [comment, setComment] = useState('');
@@ -31,18 +30,16 @@ const CloseOrReopenIssueModal = ({theme}: {theme: Theme}) => {
e.preventDefault();
}
- const currentStatus = messageData?.status === 'Close' ? statusReason : 'reopened';
const issue = {
channel_id: messageData.channel_id,
issue_comment: comment,
- status_reason: currentStatus,
+ status_reason: messageData?.status === 'open' ? statusReason : 'reopened', // Sending the reason for the issue edit API call
repo: messageData.repo_name,
number: messageData.issue_number,
owner: messageData.repo_owner,
- status: messageData.status,
+ status: messageData.status === 'open' ? 'Close' : 'Reopen', // Sending the state of the issue which we want it to be after the edit API call
postId: messageData.postId,
};
-
setSubmitting(true);
await dispatch(closeOrReopenIssue(issue));
setSubmitting(false);
@@ -61,12 +58,13 @@ const CloseOrReopenIssueModal = ({theme}: {theme: Theme}) => {
const handleIssueCommentChange = (updatedComment: string) => setComment(updatedComment);
const style = getStyle(theme);
- const modalTitle = messageData.status + ' Issue';
- const savingMessage = messageData.status === 'Close' ? 'Closing' : 'Reopening';
- const status = messageData.status + ' Issue';
+ const issueAction = messageData.status === 'open' ? 'Close Issue' : 'Open Issue';
+ const modalTitle = issueAction;
+ const status = issueAction;
+ const savingMessage = messageData.status === 'open' ? 'Closing' : 'Reopening';
const submitError = null;
- const component = (messageData.status === 'Close') ? (
+ const component = (messageData.status === 'open') ? (
{
- const {issue_number} = this.props.messageData ?? {};
+ const {issue_number, postId} = this.props.messageData ?? {};
if (e && e.preventDefault) {
e.preventDefault();
}
@@ -105,9 +105,6 @@ export default class CreateOrUpdateIssueModal extends PureComponent {
return;
}
- const {post} = this.props;
- const postId = (post) ? post.id : '';
-
const issue = {
title: this.state.issueTitle,
body: this.state.issueDescription,
diff --git a/webapp/src/index.js b/webapp/src/index.js
index 886db3b91..34101eb08 100644
--- a/webapp/src/index.js
+++ b/webapp/src/index.js
@@ -11,11 +11,10 @@ import TeamSidebar from './components/team_sidebar';
import UserAttribute from './components/user_attribute';
import SidebarRight from './components/sidebar_right';
import LinkTooltip from './components/link_tooltip';
-import GithubIssue from './components/github_issue';
import Reducer from './reducers';
import Client from './client';
import {getConnected, setShowRHSAction} from './actions';
-import {handleConnect, handleDisconnect, handleConfigurationUpdate, handleOpenCreateOrUpdateIssueModal, handleReconnect, handleRefresh} from './websocket';
+import {handleConnect, handleDisconnect, handleConfigurationUpdate, handleOpenCreateOrUpdateIssueModal, handleOpenCreateCommentOnIssueModal, handleOpenCloseOrReopenIssueModal, handleReconnect, handleRefresh, handleOpenEditIssueModal} from './websocket';
import {getServerRoute} from './selectors';
import manifest from './manifest';
@@ -49,7 +48,9 @@ class PluginClass {
registry.registerWebSocketEventHandler(`custom_${pluginId}_config_update`, handleConfigurationUpdate(store));
registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, handleRefresh(store));
registry.registerWebSocketEventHandler(`custom_${pluginId}_createIssue`, handleOpenCreateOrUpdateIssueModal(store));
- registry.registerPostTypeComponent('custom_git_issue', GithubIssue);
+ registry.registerWebSocketEventHandler(`custom_${pluginId}_open_comment_modal`, handleOpenCreateCommentOnIssueModal(store));
+ registry.registerWebSocketEventHandler(`custom_${pluginId}_open_edit_modal`, handleOpenEditIssueModal(store));
+ registry.registerWebSocketEventHandler(`custom_${pluginId}_open_status_modal`, handleOpenCloseOrReopenIssueModal(store));
registry.registerReconnectHandler(handleReconnect(store));
diff --git a/webapp/src/types/common/index.d.ts b/webapp/src/types/common/index.d.ts
new file mode 100644
index 000000000..3b6ea1f0f
--- /dev/null
+++ b/webapp/src/types/common/index.d.ts
@@ -0,0 +1,4 @@
+type WebsocketEventParams = {
+ event: string,
+ data: Record
,
+}
diff --git a/webapp/src/websocket/index.js b/webapp/src/websocket/index.js
index a969b5b88..24fbba271 100644
--- a/webapp/src/websocket/index.js
+++ b/webapp/src/websocket/index.js
@@ -6,6 +6,8 @@ import Constants from '../constants';
import {
getConnected,
openCreateOrUpdateIssueModal,
+ openCreateCommentOnIssueModal,
+ openCloseOrReopenIssueModal,
getSidebarContent,
} from '../actions';
@@ -99,3 +101,54 @@ export function handleOpenCreateOrUpdateIssueModal(store) {
store.dispatch(openCreateOrUpdateIssueModal(msg.data));
};
}
+
+export function handleOpenEditIssueModal(store) {
+ return (msg) => {
+ if (!msg.data) {
+ return;
+ }
+ const editIssueModalData = {
+ repo_owner: msg.data.repo_owner,
+ repo_name: msg.data.repo_name,
+ issue_number: msg.data.issue_number,
+ postId: msg.data.postId,
+ status: msg.data.status,
+ channel_id: msg.data.channel_id,
+ };
+ store.dispatch(openCreateOrUpdateIssueModal(editIssueModalData));
+ };
+}
+
+export function handleOpenCreateCommentOnIssueModal(store) {
+ return (msg) => {
+ if (!msg.data) {
+ return;
+ }
+ const commmentModalData = {
+ repo_owner: msg.data.repo_owner,
+ repo_name: msg.data.repo_name,
+ issue_number: msg.data.issue_number,
+ postId: msg.data.postId,
+ status: msg.data.status,
+ channel_id: msg.data.channel_id,
+ };
+ store.dispatch(openCreateCommentOnIssueModal(commmentModalData));
+ };
+}
+
+export function handleOpenCloseOrReopenIssueModal(store) {
+ return (msg) => {
+ if (!msg.data) {
+ return;
+ }
+ const statusModalData = {
+ repo_owner: msg.data.repo_owner,
+ repo_name: msg.data.repo_name,
+ issue_number: msg.data.issue_number,
+ postId: msg.data.postId,
+ status: msg.data.status,
+ channel_id: msg.data.channel_id,
+ };
+ store.dispatch(openCloseOrReopenIssueModal(statusModalData));
+ };
+}
From b413828e5b154d16bf2412da6228c3cede7d1316 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Fri, 30 Aug 2024 13:22:58 +0530
Subject: [PATCH 09/18] [MM-618]: Fixed the lint
---
server/plugin/plugin.go | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go
index 05d416070..c09ed2164 100644
--- a/server/plugin/plugin.go
+++ b/server/plugin/plugin.go
@@ -28,13 +28,13 @@ import (
)
const (
- githubTokenKey = "_githubtoken"
- githubOauthKey = "githuboauthkey_"
- githubUsernameKey = "_githubusername"
- githubPrivateRepoKey = "_githubprivate"
- githubObjectTypeIssue = "issue"
- githubObjectTypeIssueComment = "issue_comment"
- githubObjectTypePRReviewComment = "pr_review_comment"
+ githubTokenKey = "_githubtoken"
+ githubOauthKey = "githuboauthkey_"
+ githubUsernameKey = "_githubusername"
+ githubPrivateRepoKey = "_githubprivate"
+ githubObjectTypeIssue = "issue"
+ githubObjectTypeIssueComment = "issue_comment"
+ githubObjectTypePRReviewComment = "pr_review_comment"
githubObjectTypeDiscussionComment = "discussion_comment"
mm34646MutexKey = "mm34646_token_reset_mutex"
From 9ad7d481bb46939035b100ee37ff3597f4e01f0c Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Tue, 21 Jan 2025 20:04:31 +0530
Subject: [PATCH 10/18] fxed testcases
---
server/plugin/template.go | 2 +-
server/plugin/template_test.go | 192 +++++++++++++++++++++++++++++----
2 files changed, 170 insertions(+), 24 deletions(-)
diff --git a/server/plugin/template.go b/server/plugin/template.go
index 16d3bee20..7878c4e64 100644
--- a/server/plugin/template.go
+++ b/server/plugin/template.go
@@ -136,7 +136,7 @@ func init() {
// The repo template links to the corresponding repository.
template.Must(masterTemplate.New("repo").Parse(
- `[{{.GetFullName}}]({{.GetHTMLURL}})`,
+ `[\[{{.GetFullName}}\]]({{.GetHTMLURL}})`,
))
// The eventRepoPullRequest links to the corresponding pull request, anchored at the repo.
diff --git a/server/plugin/template_test.go b/server/plugin/template_test.go
index 323603ad7..cc8e59bf0 100644
--- a/server/plugin/template_test.go
+++ b/server/plugin/template_test.go
@@ -115,6 +115,39 @@ var issue = github.Issue{
Body: sToP(`git-get-head sounds like a great feature we should support`),
}
+var issueWithMentions = github.Issue{
+ Number: iToP(1),
+ HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
+ Title: sToP("Implement git-get-head"),
+ CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
+ UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
+ Body: sToP(`git-get-head sounds like a great feature we should support
+` + gitHubMentions),
+}
+
+var issueWithLabelAndAssignee = github.Issue{
+ Number: iToP(1),
+ HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
+ Title: sToP("Implement git-get-head"),
+ CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
+ UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
+ Body: sToP(`git-get-head sounds like a great feature we should support`),
+ Labels: singleLabel,
+ Assignee: &user,
+ Assignees: []*github.User{&user},
+}
+
+var issueWithMultipleLabelsAndAssignee = github.Issue{
+ Number: iToP(1),
+ HTMLURL: sToP("https://github.com/mattermost/mattermost-plugin-github/issues/1"),
+ Title: sToP("Implement git-get-head"),
+ CreatedAt: tToP(time.Date(2019, 04, 01, 02, 03, 04, 0, time.UTC)),
+ UpdatedAt: tToP(time.Date(2019, 05, 01, 02, 03, 04, 0, time.UTC)),
+ Body: sToP(`git-get-head sounds like a great feature we should support`),
+ Labels: labels,
+ Assignees: []*github.User{&user, &user},
+}
+
var user = github.User{
Login: sToP("panda"),
HTMLURL: sToP("https://github.com/panda"),
@@ -291,7 +324,7 @@ git-get-head gets the non-sent upstream heads inside the stashed non-cleaned app
t.Run("with collapsed render style", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was opened by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was opened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("newPR", &EventWithRenderConfig{
@@ -333,7 +366,7 @@ git-get-head gets the non-sent upstream heads inside the stashed non-cleaned app
func TestClosedPRMessageTemplate(t *testing.T) {
t.Run("merged", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was merged by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was merged by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedPR", &github.PullRequestEvent{
@@ -347,7 +380,7 @@ func TestClosedPRMessageTemplate(t *testing.T) {
t.Run("closed", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was closed by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was closed by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedPR", &github.PullRequestEvent{
@@ -363,7 +396,7 @@ func TestClosedPRMessageTemplate(t *testing.T) {
func TestReopenedPRMessageTemplate(t *testing.T) {
t.Run("reopened", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was reopened by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Pull request [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42) was reopened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("reopenedPR", &github.PullRequestEvent{
@@ -396,10 +429,15 @@ func TestPullRequestLabelledTemplate(t *testing.T) {
}
func TestNewIssueTemplate(t *testing.T) {
- t.Run("new issue", func(t *testing.T) {
+ t.Run("without mentions", func(t *testing.T) {
expected := `
-[panda](https://github.com/panda) created a new issue in [mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github)
+#### Implement git-get-head
+##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
+#new-issue by [panda](https://github.com/panda)
+
+git-get-head sounds like a great feature we should support
`
+
actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
&github.IssuesEvent{
Repo: &repo,
@@ -411,11 +449,119 @@ func TestNewIssueTemplate(t *testing.T) {
require.NoError(t, err)
require.Equal(t, expected, actual)
})
+
+ t.Run("with mentions", withGitHubUserNameMapping(func(t *testing.T) {
+ expected := `
+#### Implement git-get-head
+##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
+#new-issue by @pandabot
+
+git-get-head sounds like a great feature we should support
+` + usernameMentions + `
+`
+
+ actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
+ &github.IssuesEvent{
+ Repo: &repo,
+ Issue: &issueWithMentions,
+ Sender: &user,
+ },
+ nil,
+ ))
+ require.NoError(t, err)
+ require.Equal(t, expected, actual)
+ }))
+
+ t.Run("with single label and assignee", func(t *testing.T) {
+ expected := `
+#### Implement git-get-head
+##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
+#new-issue by [panda](https://github.com/panda)
+Labels: ` + "[`Help Wanted`](https://github.com/mattermost/mattermost-plugin-github/labels/Help%20Wanted)" + `
+Assignees: [panda](https://github.com/panda)
+
+git-get-head sounds like a great feature we should support
+`
+
+ actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
+ &github.IssuesEvent{
+ Repo: &repo,
+ Issue: &issueWithLabelAndAssignee,
+ Sender: &user,
+ },
+ nil,
+ ))
+ require.NoError(t, err)
+ require.Equal(t, expected, actual)
+ })
+
+ t.Run("with multiple labels and assignees", func(t *testing.T) {
+ expected := `
+#### Implement git-get-head
+##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
+#new-issue by [panda](https://github.com/panda)
+Labels: ` + "[`Help Wanted`](https://github.com/mattermost/mattermost-plugin-github/labels/Help%20Wanted), [`Tech/Go`](https://github.com/mattermost/mattermost-plugin-github/labels/Tech%2FGo)" + `
+Assignees: [panda](https://github.com/panda), [panda](https://github.com/panda)
+
+git-get-head sounds like a great feature we should support
+`
+
+ actual, err := renderTemplate("newIssue", GetEventWithRenderConfig(
+ &github.IssuesEvent{
+ Repo: &repo,
+ Issue: &issueWithMultipleLabelsAndAssignee,
+ Sender: &user,
+ },
+ nil,
+ ))
+ require.NoError(t, err)
+ require.Equal(t, expected, actual)
+ })
+
+ t.Run("with collapsed render style", func(t *testing.T) {
+ expected := `
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) opened by [panda](https://github.com/panda).
+`
+
+ actual, err := renderTemplate("newIssue", &EventWithRenderConfig{
+ Event: &github.IssuesEvent{
+ Repo: &repo,
+ Issue: &issue,
+ Sender: &user,
+ },
+ Config: RenderConfig{
+ Style: "collapsed",
+ },
+ })
+ require.NoError(t, err)
+ require.Equal(t, expected, actual)
+ })
+
+ t.Run("with skip-body render style", func(t *testing.T) {
+ expected := `
+#### Implement git-get-head
+##### [mattermost-plugin-github#1](https://github.com/mattermost/mattermost-plugin-github/issues/1)
+#new-issue by [panda](https://github.com/panda)
+`
+
+ actual, err := renderTemplate("newIssue", &EventWithRenderConfig{
+ Event: &github.IssuesEvent{
+ Repo: &repo,
+ Issue: &issue,
+ Sender: &user,
+ },
+ Config: RenderConfig{
+ Style: "skip-body",
+ },
+ })
+ require.NoError(t, err)
+ require.Equal(t, expected, actual)
+ })
}
func TestClosedIssueTemplate(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) closed by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) closed by [panda](https://github.com/panda).
`
actual, err := renderTemplate("closedIssue", GetEventWithRenderConfig(
@@ -432,7 +578,7 @@ func TestClosedIssueTemplate(t *testing.T) {
func TestReopenedIssueTemplate(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) reopened by [panda](https://github.com/panda).
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) Issue [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1) reopened by [panda](https://github.com/panda).
`
actual, err := renderTemplate("reopenedIssue", GetEventWithRenderConfig(
@@ -643,7 +789,7 @@ func TestPushedCommitsTemplate(t *testing.T) {
func TestCreateMessageTemplate(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) branch [branchname](https://github.com/mattermost/mattermost-plugin-github/tree/branchname) created by [panda](https://github.com/panda)
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) branch [branchname](https://github.com/mattermost/mattermost-plugin-github/tree/branchname) created by [panda](https://github.com/panda)
`
actual, err := renderTemplate("newCreateMessage", &github.CreateEvent{
@@ -658,7 +804,7 @@ func TestCreateMessageTemplate(t *testing.T) {
func TestDeletedMessageTemplate(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) branch branchname deleted by [panda](https://github.com/panda)
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) branch branchname deleted by [panda](https://github.com/panda)
`
actual, err := renderTemplate("newDeleteMessage", &github.DeleteEvent{
@@ -673,7 +819,7 @@ func TestDeletedMessageTemplate(t *testing.T) {
func TestRepoStarTemplate(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) starred by [panda](https://github.com/panda)
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) starred by [panda](https://github.com/panda)
It now has **1** stars.`
actual, err := renderTemplate("newRepoStar", &github.StarEvent{
@@ -688,7 +834,7 @@ It now has **1** stars.`
func TestIssueCommentTemplate(t *testing.T) {
t.Run("non-email body without mentions", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
`
@@ -707,7 +853,7 @@ git-get-head sounds like a great feature we should support
t.Run("email body without mentions", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by [panda](https://github.com/panda) on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
`
@@ -726,7 +872,7 @@ git-get-head sounds like a great feature we should support
t.Run("non-email body with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
` + usernameMentions + `
@@ -746,7 +892,7 @@ git-get-head sounds like a great feature we should support
t.Run("email body with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New comment by @pandabot on [#1 Implement git-get-head](https://github.com/mattermost/mattermost-plugin-github/issues/1):
git-get-head sounds like a great feature we should support
` + usernameMentions + `
@@ -768,7 +914,7 @@ git-get-head sounds like a great feature we should support
func TestPullRequestReviewEventTemplate(t *testing.T) {
t.Run("approved", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -788,7 +934,7 @@ Excited to see git-get-head land!
t.Run("commented", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) commented on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) commented on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -808,7 +954,7 @@ Excited to see git-get-head land!
t.Run("requested changes", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) requested changes on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) requested changes on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
`
@@ -828,7 +974,7 @@ Excited to see git-get-head land!
t.Run("approved with mentions", withGitHubUserNameMapping(func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) @pandabot approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) @pandabot approved [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Excited to see git-get-head land!
` + usernameMentions + `
@@ -851,7 +997,7 @@ Excited to see git-get-head land!
func TestPullRequestReviewCommentEventTemplate(t *testing.T) {
t.Run("without mentions", func(*testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New review comment by [panda](https://github.com/panda) on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New review comment by [panda](https://github.com/panda) on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Should this be here?
`
@@ -870,7 +1016,7 @@ Should this be here?
t.Run("with mentions", withGitHubUserNameMapping(func(*testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) New review comment by @pandabot on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) New review comment by @pandabot on [#42 Leverage git-get-head](https://github.com/mattermost/mattermost-plugin-github/pull/42):
Should this be here?
` + usernameMentions + `
@@ -1260,7 +1406,7 @@ func TestPullRequestReviewNotification(t *testing.T) {
func TestReleaseNotification(t *testing.T) {
t.Run("created", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) created a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) created a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
actual, err := renderTemplate("newReleaseEvent", &github.ReleaseEvent{
Repo: &repo,
@@ -1277,7 +1423,7 @@ func TestReleaseNotification(t *testing.T) {
t.Run("deleted", func(t *testing.T) {
expected := `
-[mattermost-plugin-github](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) deleted a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
+[\[mattermost-plugin-github\]](https://github.com/mattermost/mattermost-plugin-github) [panda](https://github.com/panda) deleted a release [v0.0.1](https://github.com/mattermost/mattermost-plugin-github/releases/tag/v0.0.1)`
actual, err := renderTemplate("newReleaseEvent", &github.ReleaseEvent{
Repo: &repo,
From 25c1a3e0dab51e7f34e89662082d96c60897d0c8 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Fri, 31 Jan 2025 18:33:25 +0530
Subject: [PATCH 11/18] fixed lint
---
server/plugin/plugin.go | 2 +-
webapp/src/components/modals/close_reopen_issue/index.tsx | 2 +-
webapp/src/types/common/index.d.ts | 3 +++
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/server/plugin/plugin.go b/server/plugin/plugin.go
index 45ebcdb63..6a3f8a623 100644
--- a/server/plugin/plugin.go
+++ b/server/plugin/plugin.go
@@ -76,7 +76,7 @@ const (
repoQueryParam = "repo"
numberQueryParam = "number"
postIDQueryParam = "postId"
- channelIDParam = "channelId"
+ channelIDParam = "channelId"
issueStatus = "status"
assigneesForProps = "assignees"
diff --git a/webapp/src/components/modals/close_reopen_issue/index.tsx b/webapp/src/components/modals/close_reopen_issue/index.tsx
index f40833453..e488473ca 100644
--- a/webapp/src/components/modals/close_reopen_issue/index.tsx
+++ b/webapp/src/components/modals/close_reopen_issue/index.tsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useState} from 'react';
diff --git a/webapp/src/types/common/index.d.ts b/webapp/src/types/common/index.d.ts
index 3b6ea1f0f..4b7a51a52 100644
--- a/webapp/src/types/common/index.d.ts
+++ b/webapp/src/types/common/index.d.ts
@@ -1,3 +1,6 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
type WebsocketEventParams = {
event: string,
data: Record,
From f225e3ac7d625ad17545a0635aff4cddefdc92f4 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Mon, 21 Apr 2025 15:08:40 +0530
Subject: [PATCH 12/18] merge master to bs/MM-618
---
e2e/playwright/package-lock.json | 51 +-
e2e/playwright/package.json | 2 +-
server/mocks/logger_mock.go | 159 +
server/plugin/api.go | 29 +-
server/plugin/api_test.go | 385 +-
server/plugin/command.go | 44 +-
server/plugin/command_test.go | 1555 ++-
server/plugin/flows.go | 2 +-
server/plugin/subscriptions.go | 37 +-
server/plugin/subscriptions_test.go | 102 +
server/plugin/template.go | 16 +-
server/plugin/test_utils.go | 80 +
server/plugin/utils.go | 15 +-
server/plugin/webhook.go | 61 +-
server/plugin/webhook_test.go | 130 +
webapp/package-lock.json | 10186 +++++++++++++---
webapp/package.json | 6 +
.../github_repo_selector.jsx | 2 +-
.../create_update_issue.test.jsx.snap | 105 +
.../create_update_issue.test.jsx | 116 +
webapp/tests/setup.tsx | 7 +
21 files changed, 11286 insertions(+), 1804 deletions(-)
create mode 100644 server/mocks/logger_mock.go
create mode 100644 server/plugin/test_utils.go
create mode 100644 server/plugin/webhook_test.go
create mode 100644 webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
create mode 100644 webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
create mode 100644 webapp/tests/setup.tsx
diff --git a/e2e/playwright/package-lock.json b/e2e/playwright/package-lock.json
index 5efb68f8f..901edf335 100644
--- a/e2e/playwright/package-lock.json
+++ b/e2e/playwright/package-lock.json
@@ -613,11 +613,6 @@
}
}
},
- "buffer-writer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
- "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
- },
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -2236,11 +2231,6 @@
"integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
"dev": true
},
- "packet-reader": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
- "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
- },
"parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -2303,23 +2293,28 @@
}
},
"pg": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.10.0.tgz",
- "integrity": "sha512-ke7o7qSTMb47iwzOSaZMfeR7xToFdkE71ifIipOAAaLIM0DYzfOAXlgFFmYUIE2BcJtvnVlGCID84ZzCegE8CQ==",
- "requires": {
- "buffer-writer": "2.0.0",
- "packet-reader": "1.0.0",
- "pg-connection-string": "^2.5.0",
- "pg-pool": "^3.6.0",
- "pg-protocol": "^1.6.0",
+ "version": "8.13.1",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz",
+ "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==",
+ "requires": {
+ "pg-cloudflare": "^1.1.1",
+ "pg-connection-string": "^2.7.0",
+ "pg-pool": "^3.7.0",
+ "pg-protocol": "^1.7.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
}
},
+ "pg-cloudflare": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
+ "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
+ "optional": true
+ },
"pg-connection-string": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
- "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz",
+ "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA=="
},
"pg-int8": {
"version": "1.0.1",
@@ -2327,14 +2322,14 @@
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
},
"pg-pool": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
- "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ=="
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.1.tgz",
+ "integrity": "sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw=="
},
"pg-protocol": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
- "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.1.tgz",
+ "integrity": "sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ=="
},
"pg-types": {
"version": "2.2.0",
diff --git a/e2e/playwright/package.json b/e2e/playwright/package.json
index 07b14421d..a80401b0a 100644
--- a/e2e/playwright/package.json
+++ b/e2e/playwright/package.json
@@ -25,6 +25,6 @@
},
"dependencies": {
"express": "^4.21.2",
- "pg": "^8.10.0"
+ "pg": "^8.13.1"
}
}
diff --git a/server/mocks/logger_mock.go b/server/mocks/logger_mock.go
new file mode 100644
index 000000000..8c3d2ea75
--- /dev/null
+++ b/server/mocks/logger_mock.go
@@ -0,0 +1,159 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger (interfaces: Logger)
+
+// Package mocks is a generated GoMock package.
+package mocks
+
+import (
+ reflect "reflect"
+
+ gomock "github.com/golang/mock/gomock"
+ logger "github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger"
+)
+
+// MockLogger is a mock of Logger interface.
+type MockLogger struct {
+ ctrl *gomock.Controller
+ recorder *MockLoggerMockRecorder
+}
+
+// MockLoggerMockRecorder is the mock recorder for MockLogger.
+type MockLoggerMockRecorder struct {
+ mock *MockLogger
+}
+
+// NewMockLogger creates a new mock instance.
+func NewMockLogger(ctrl *gomock.Controller) *MockLogger {
+ mock := &MockLogger{ctrl: ctrl}
+ mock.recorder = &MockLoggerMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockLogger) EXPECT() *MockLoggerMockRecorder {
+ return m.recorder
+}
+
+// Context mocks base method.
+func (m *MockLogger) Context() logger.LogContext {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Context")
+ ret0, _ := ret[0].(logger.LogContext)
+ return ret0
+}
+
+// Context indicates an expected call of Context.
+func (mr *MockLoggerMockRecorder) Context() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockLogger)(nil).Context))
+}
+
+// Debugf mocks base method.
+func (m *MockLogger) Debugf(arg0 string, arg1 ...interface{}) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{arg0}
+ for _, a := range arg1 {
+ varargs = append(varargs, a)
+ }
+ m.ctrl.Call(m, "Debugf", varargs...)
+}
+
+// Debugf indicates an expected call of Debugf.
+func (mr *MockLoggerMockRecorder) Debugf(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{arg0}, arg1...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debugf", reflect.TypeOf((*MockLogger)(nil).Debugf), varargs...)
+}
+
+// Errorf mocks base method.
+func (m *MockLogger) Errorf(arg0 string, arg1 ...interface{}) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{arg0}
+ for _, a := range arg1 {
+ varargs = append(varargs, a)
+ }
+ m.ctrl.Call(m, "Errorf", varargs...)
+}
+
+// Errorf indicates an expected call of Errorf.
+func (mr *MockLoggerMockRecorder) Errorf(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{arg0}, arg1...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Errorf", reflect.TypeOf((*MockLogger)(nil).Errorf), varargs...)
+}
+
+// Infof mocks base method.
+func (m *MockLogger) Infof(arg0 string, arg1 ...interface{}) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{arg0}
+ for _, a := range arg1 {
+ varargs = append(varargs, a)
+ }
+ m.ctrl.Call(m, "Infof", varargs...)
+}
+
+// Infof indicates an expected call of Infof.
+func (mr *MockLoggerMockRecorder) Infof(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{arg0}, arg1...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Infof", reflect.TypeOf((*MockLogger)(nil).Infof), varargs...)
+}
+
+// Timed mocks base method.
+func (m *MockLogger) Timed() logger.Logger {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Timed")
+ ret0, _ := ret[0].(logger.Logger)
+ return ret0
+}
+
+// Timed indicates an expected call of Timed.
+func (mr *MockLoggerMockRecorder) Timed() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Timed", reflect.TypeOf((*MockLogger)(nil).Timed))
+}
+
+// Warnf mocks base method.
+func (m *MockLogger) Warnf(arg0 string, arg1 ...interface{}) {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{arg0}
+ for _, a := range arg1 {
+ varargs = append(varargs, a)
+ }
+ m.ctrl.Call(m, "Warnf", varargs...)
+}
+
+// Warnf indicates an expected call of Warnf.
+func (mr *MockLoggerMockRecorder) Warnf(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ varargs := append([]interface{}{arg0}, arg1...)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warnf", reflect.TypeOf((*MockLogger)(nil).Warnf), varargs...)
+}
+
+// With mocks base method.
+func (m *MockLogger) With(arg0 logger.LogContext) logger.Logger {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "With", arg0)
+ ret0, _ := ret[0].(logger.Logger)
+ return ret0
+}
+
+// With indicates an expected call of With.
+func (mr *MockLoggerMockRecorder) With(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "With", reflect.TypeOf((*MockLogger)(nil).With), arg0)
+}
+
+// WithError mocks base method.
+func (m *MockLogger) WithError(arg0 error) logger.Logger {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "WithError", arg0)
+ ret0, _ := ret[0].(logger.Logger)
+ return ret0
+}
+
+// WithError indicates an expected call of WithError.
+func (mr *MockLoggerMockRecorder) WithError(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithError", reflect.TypeOf((*MockLogger)(nil).WithError), arg0)
+}
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 55c78d18f..394afd3ec 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -840,6 +840,12 @@ func (p *Plugin) searchIssues(c *UserContext, w http.ResponseWriter, r *http.Req
searchTerm := r.FormValue("term")
orgsList := p.configuration.getOrganizations()
allIssues := []*github.Issue{}
+
+ if len(orgsList) == 0 {
+ orgsList = []string{""}
+ }
+
+ hasFetchedIssues := false
for _, org := range orgsList {
query := getIssuesSearchQuery(org, searchTerm)
var result *github.IssuesSearchResult
@@ -853,11 +859,17 @@ func (p *Plugin) searchIssues(c *UserContext, w http.ResponseWriter, r *http.Req
})
if cErr != nil {
c.Log.WithError(cErr).With(logger.LogContext{"query": query}).Warnf("Failed to search for issues")
- p.writeJSON(w, make([]*github.Issue, 0))
- return
}
- allIssues = append(allIssues, result.Issues...)
+ if result != nil && len(result.Issues) > 0 {
+ allIssues = append(allIssues, result.Issues...)
+ hasFetchedIssues = true
+ }
+ }
+
+ if !hasFetchedIssues {
+ p.writeJSON(w, make([]*github.Issue, 0))
+ return
}
p.writeJSON(w, allIssues)
@@ -1486,6 +1498,7 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
}
} else {
orgsList := p.configuration.getOrganizations()
+ hasFetchedRepos := false
for _, org := range orgsList {
orgRepos, statusCode, err := p.getRepositoryListByOrg(c.Ctx, c.GHInfo, org, githubClient, opt)
if err != nil {
@@ -1493,20 +1506,22 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
orgRepos, err = p.getRepositoryList(c.Ctx, c.GHInfo, org, githubClient, opt)
if err != nil {
c.Log.WithError(err).Warnf("Failed to list repositories", "Organization", org)
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
- return
}
} else {
c.Log.WithError(err).Warnf("Failed to list repositories", "Organization", org)
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
- return
}
}
if len(orgRepos) > 0 {
allRepos = append(allRepos, orgRepos...)
+ hasFetchedRepos = true
}
}
+
+ if !hasFetchedRepos {
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch repositories", StatusCode: http.StatusInternalServerError})
+ return
+ }
}
repoResp := make([]RepoResponse, len(allRepos))
diff --git a/server/plugin/api_test.go b/server/plugin/api_test.go
index 17fceda4c..232e0ee0f 100644
--- a/server/plugin/api_test.go
+++ b/server/plugin/api_test.go
@@ -4,13 +4,19 @@
package plugin
import (
+ "encoding/json"
"io"
"net/http"
"net/http/httptest"
+ "strings"
"testing"
+ "github.com/golang/mock/gomock"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
+ "golang.org/x/oauth2"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/plugin/plugintest"
@@ -129,52 +135,129 @@ func TestPlugin_ServeHTTP(t *testing.T) {
}
}
-func TestGetToken(t *testing.T) {
- httpTestString := testutils.HTTPTest{
- T: t,
- Encoder: testutils.EncodeString,
+func TestCheckPluginRequest(t *testing.T) {
+ tests := []struct {
+ name string
+ headers map[string]string
+ setup func()
+ assertions func(t *testing.T, rec *httptest.ResponseRecorder)
+ }{
+ {
+ name: "Missing Mattermost-Plugin-ID header",
+ headers: map[string]string{},
+ setup: func() {},
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusUnauthorized, rec.Result().StatusCode)
+ body, _ := io.ReadAll(rec.Body)
+ assert.Equal(t, "Not authorized\n", string(body))
+ },
+ },
+ {
+ name: "Valid Mattermost-Plugin-ID header",
+ headers: map[string]string{
+ "Mattermost-Plugin-ID": "validPluginID",
+ },
+ setup: func() {},
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
+ body, _ := io.ReadAll(rec.Body)
+ assert.Equal(t, "Success\n", string(body))
+ },
+ },
}
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
- for name, test := range map[string]struct {
- httpTest testutils.HTTPTest
- request testutils.Request
- context *plugin.Context
- expectedResponse testutils.ExpectedResponse
+ nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ _, err := w.Write([]byte("Success\n"))
+ assert.NoError(t, err)
+ })
+
+ handler := checkPluginRequest(nextHandler)
+
+ req := httptest.NewRequest(http.MethodGet, "/test", nil)
+ for key, value := range tc.headers {
+ req.Header.Set(key, value)
+ }
+ rec := httptest.NewRecorder()
+
+ handler(rec, req)
+
+ tc.assertions(t, rec)
+ })
+ }
+}
+
+func TestGetToken(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+
+ tests := []struct {
+ name string
+ userID string
+ setup func()
+ assertions func(t *testing.T, rec *httptest.ResponseRecorder)
}{
- "not authorized": {
- httpTest: httpTestString,
- request: testutils.Request{
- Method: http.MethodGet,
- URL: "/api/v1/token",
- Body: nil,
+ {
+ name: "Missing userID",
+ userID: "",
+ setup: func() {
+ mockAPI.On("LogError", "UserID not found.")
},
- context: &plugin.Context{},
- expectedResponse: testutils.ExpectedResponse{
- StatusCode: http.StatusUnauthorized,
- ResponseType: testutils.ContentTypePlain,
- Body: "Not authorized\n",
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusBadRequest, rec.Result().StatusCode)
+ body, _ := io.ReadAll(rec.Body)
+ assert.Contains(t, string(body), "please provide a userID")
},
},
- } {
- t.Run(name, func(t *testing.T) {
- p := NewPlugin()
- p.setConfiguration(
- &Configuration{
- GitHubOrg: "mockOrg",
- GitHubOAuthClientID: "mockID",
- GitHubOAuthClientSecret: "mockSecret",
- EncryptionKey: "mockKey",
- })
- p.initializeAPI()
-
- p.SetAPI(&plugintest.API{})
+ {
+ name: "User info not found in store",
+ userID: "mockUserID",
+ setup: func() {
+ mockAPI.On("LogError", "error occurred while getting the github user info", "UserID", MockUserID, "error", &APIErrorResponse{Message: "Unable to get user info.", StatusCode: http.StatusInternalServerError})
+ mockKvStore.EXPECT().Get("mockUserID"+githubTokenKey, gomock.Any()).Return(errors.New("not found")).Times(1)
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusInternalServerError, rec.Result().StatusCode)
+ body, _ := io.ReadAll(rec.Body)
+ assert.Contains(t, string(body), "Unable to get user info.")
+ },
+ },
+ {
+ name: "Successful token retrieval",
+ userID: "mockUserID",
+ setup: func() {
+ encryptedToken, err := encrypt([]byte("dummyEncryptKey1"), MockAccessToken)
+ assert.NoError(t, err)
+ mockKvStore.EXPECT().Get("mockUserID"+githubTokenKey, gomock.Any()).DoAndReturn(func(key string, value **GitHubUserInfo) error {
+ *value = &GitHubUserInfo{
+ Token: &oauth2.Token{
+ AccessToken: encryptedToken,
+ },
+ }
+ return nil
+ }).Times(1)
+ p.setConfiguration(&Configuration{EncryptionKey: "dummyEncryptKey1"})
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
+ body, _ := io.ReadAll(rec.Body)
+ assert.Contains(t, string(body), MockAccessToken)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
- req := test.httpTest.CreateHTTPRequest(test.request)
- rr := httptest.NewRecorder()
+ req := httptest.NewRequest(http.MethodGet, "/get/token?userID="+tc.userID, nil)
+ rec := httptest.NewRecorder()
- p.ServeHTTP(test.context, rr, req)
+ p.getToken(rec, req)
- test.httpTest.CompareHTTPResponse(rr, test.expectedResponse)
+ tc.assertions(t, rec)
})
}
}
@@ -249,3 +332,231 @@ func TestGetConfig(t *testing.T) {
})
}
}
+
+func TestGetGitHubUser(t *testing.T) {
+ mockKvStore, mockAPI, mockLogger, mockLoggerWith, mockContext := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+
+ tests := []struct {
+ name string
+ requestBody string
+ setup func()
+ expectedStatusCode int
+ assertions func(t *testing.T, rec *httptest.ResponseRecorder)
+ }{
+ {
+ name: "Invalid JSON Request Body",
+ requestBody: "invalid-json",
+ setup: func() {
+ mockLogger.EXPECT().WithError(gomock.Any()).Return(mockLoggerWith).Times(1)
+ mockLoggerWith.EXPECT().Warnf("Error decoding GitHubUserRequest from JSON body").Times(1)
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusBadRequest, rec.Result().StatusCode)
+
+ var response APIErrorResponse
+ _ = json.NewDecoder(rec.Body).Decode(&response)
+ assert.Contains(t, response.Message, "Please provide a valid JSON object.")
+ },
+ },
+ {
+ name: "Blank user_id field",
+ requestBody: `{"user_id": ""}`,
+ setup: func() {},
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusBadRequest, rec.Result().StatusCode)
+ var response APIErrorResponse
+ _ = json.NewDecoder(rec.Body).Decode(&response)
+ assert.Contains(t, response.Message, "non-blank user_id field")
+ },
+ },
+ {
+ name: "Error to getting user info",
+ requestBody: `{"user_id": "mockUserID"}`,
+ setup: func() {
+ mockKvStore.EXPECT().Get(gomock.Any(), gomock.Any()).Return(errors.New("Error getting user details")).Times(1)
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusInternalServerError, rec.Result().StatusCode)
+ var response APIErrorResponse
+ _ = json.NewDecoder(rec.Body).Decode(&response)
+ assert.Contains(t, response.Message, "Unable to get user info")
+ },
+ },
+ {
+ name: "User is not connected to a GitHub account.",
+ requestBody: `{"user_id": "mockUserID"}`,
+ setup: func() {
+ mockKvStore.EXPECT().Get(gomock.Any(), gomock.Any()).Return(nil).Times(1)
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusNotFound, rec.Result().StatusCode)
+
+ var response APIErrorResponse
+ _ = json.NewDecoder(rec.Body).Decode(&response)
+ assert.Contains(t, response.Message, "User is not connected to a GitHub account.")
+ },
+ },
+ {
+ name: "Successfully get github user",
+ requestBody: `{"user_id": "mockUserID"}`,
+ setup: func() {
+ dummyUserInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+ mockKvStore.EXPECT().Get("mockUserID"+githubTokenKey, gomock.Any()).DoAndReturn(func(key string, value **GitHubUserInfo) error {
+ *value = dummyUserInfo
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
+ var response GitHubUserResponse
+ err := json.NewDecoder(rec.Body).Decode(&response)
+ assert.NoError(t, err)
+ assert.Equal(t, MockUsername, response.Username)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ req := httptest.NewRequest(http.MethodPost, "/github/user", strings.NewReader(tc.requestBody))
+ rec := httptest.NewRecorder()
+
+ p.getGitHubUser(mockContext, rec, req)
+
+ tc.assertions(t, rec)
+ })
+ }
+}
+
+func TestParseRepo(t *testing.T) {
+ tests := []struct {
+ name string
+ repoParam string
+ setup func()
+ assertions func(t *testing.T, owner, repo string, err error)
+ }{
+ {
+ name: "Empty repository parameter",
+ repoParam: "",
+ setup: func() {},
+ assertions: func(t *testing.T, owner, repo string, err error) {
+ assert.Equal(t, "", owner)
+ assert.Equal(t, "", repo)
+ assert.EqualError(t, err, "repository cannot be blank")
+ },
+ },
+ {
+ name: "Invalid repository format",
+ repoParam: "owner",
+ setup: func() {},
+ assertions: func(t *testing.T, owner, repo string, err error) {
+ assert.Equal(t, "", owner)
+ assert.Equal(t, "", repo)
+ assert.EqualError(t, err, "invalid repository")
+ },
+ },
+ {
+ name: "Valid repository format",
+ repoParam: "owner/repo",
+ setup: func() {},
+ assertions: func(t *testing.T, owner, repo string, err error) {
+ assert.NoError(t, err)
+ assert.Equal(t, "owner", owner)
+ assert.Equal(t, "repo", repo)
+ },
+ },
+ {
+ name: "Extra slashes in repository parameter",
+ repoParam: "owner/repo/",
+ setup: func() {},
+ assertions: func(t *testing.T, owner, repo string, err error) {
+ assert.Equal(t, "", owner)
+ assert.Equal(t, "", repo)
+ assert.EqualError(t, err, "invalid repository")
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ owner, repo, err := parseRepo(tc.repoParam)
+
+ tc.assertions(t, owner, repo, err)
+ })
+ }
+}
+
+func TestUpdateSettings(t *testing.T) {
+ mockKvStore, mockAPI, mockLogger, mockLoggerWith, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ mockGHContext, err := GetMockUserContext(p, mockLogger)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ requestBody string
+ setup func()
+ expectedStatusCode int
+ assertions func(t *testing.T, rec *httptest.ResponseRecorder)
+ }{
+ {
+ name: "Invalid JSON Request Body",
+ requestBody: "invalid-json",
+ setup: func() {
+ mockLogger.EXPECT().WithError(gomock.Any()).Return(mockLoggerWith).Times(1)
+ mockLoggerWith.EXPECT().Warnf("Error decoding settings from JSON body").Times(1)
+ },
+ expectedStatusCode: http.StatusBadRequest,
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusBadRequest, rec.Result().StatusCode)
+ },
+ },
+ {
+ name: "Error Storing User Info",
+ requestBody: `{"access_token": "mockAccessToken"}`,
+ setup: func() {
+ p.setConfiguration(&Configuration{
+ EncryptionKey: "dummyEncryptKey1",
+ })
+ mockKvStore.EXPECT().Set(gomock.Any(), gomock.Any()).Return(false, errors.New("store error")).Times(1)
+ mockLogger.EXPECT().WithError(gomock.Any()).Return(mockLoggerWith).Times(1)
+ mockLoggerWith.EXPECT().Warnf("Failed to store GitHub user info").Times(1)
+ },
+ expectedStatusCode: http.StatusInternalServerError,
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusInternalServerError, rec.Result().StatusCode)
+ },
+ },
+ {
+ name: "Successful Update",
+ requestBody: `{"access_token": "mockAccessToken"}`,
+ setup: func() {
+ mockKvStore.EXPECT().Set(gomock.Any(), gomock.Any()).Return(true, nil).Times(1)
+ },
+ expectedStatusCode: http.StatusOK,
+ assertions: func(t *testing.T, rec *httptest.ResponseRecorder) {
+ assert.Equal(t, http.StatusOK, rec.Result().StatusCode)
+ var settings UserSettings
+ err := json.NewDecoder(rec.Body).Decode(&settings)
+ assert.NoError(t, err)
+ assert.Equal(t, mockGHContext.GHInfo.Settings, &settings)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ req := httptest.NewRequest(http.MethodPost, "/update/settings", strings.NewReader(tc.requestBody))
+ rec := httptest.NewRecorder()
+
+ p.updateSettings(mockGHContext, rec, req)
+
+ tc.assertions(t, rec)
+ })
+ }
+}
diff --git a/server/plugin/command.go b/server/plugin/command.go
index cd3d020f4..455422912 100644
--- a/server/plugin/command.go
+++ b/server/plugin/command.go
@@ -146,23 +146,28 @@ func (p *Plugin) postCommandResponse(args *model.CommandArgs, text string) {
p.client.Post.SendEphemeralPost(args.UserId, post)
}
-func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) []string {
+func (p *Plugin) getMutedUsernames(userInfo *GitHubUserInfo) ([]string, error) {
var mutedUsernameBytes []byte
err := p.store.Get(userInfo.UserID+"-muted-users", &mutedUsernameBytes)
if err != nil {
- return nil
+ return nil, err
}
mutedUsernames := string(mutedUsernameBytes)
var mutedUsers []string
if len(mutedUsernames) == 0 {
- return mutedUsers
+ return mutedUsers, nil
}
mutedUsers = strings.Split(mutedUsernames, ",")
- return mutedUsers
+ return mutedUsers, nil
}
func (p *Plugin) handleMuteList(_ *model.CommandArgs, userInfo *GitHubUserInfo) string {
- mutedUsernames := p.getMutedUsernames(userInfo)
+ mutedUsernames, err := p.getMutedUsernames(userInfo)
+ if err != nil {
+ p.client.Log.Error("error occurred getting muted users.", "UserID", userInfo.UserID, "Error", err)
+ return "An error occurred getting muted users. Please try again later"
+ }
+
var mutedUsers string
for _, user := range mutedUsernames {
mutedUsers += fmt.Sprintf("- %v\n", user)
@@ -183,7 +188,12 @@ func contains(s []string, e string) bool {
}
func (p *Plugin) handleMuteAdd(_ *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
- mutedUsernames := p.getMutedUsernames(userInfo)
+ mutedUsernames, err := p.getMutedUsernames(userInfo)
+ if err != nil {
+ p.client.Log.Error("error occurred getting muted users.", "UserID", userInfo.UserID, "Error", err)
+ return "An error occurred getting muted users. Please try again later"
+ }
+
if contains(mutedUsernames, username) {
return username + " is already muted"
}
@@ -200,7 +210,7 @@ func (p *Plugin) handleMuteAdd(_ *model.CommandArgs, username string, userInfo *
mutedUsers = username
}
- _, err := p.store.Set(userInfo.UserID+"-muted-users", []byte(mutedUsers))
+ _, err = p.store.Set(userInfo.UserID+"-muted-users", []byte(mutedUsers))
if err != nil {
return "Error occurred saving list of muted users"
}
@@ -209,11 +219,16 @@ func (p *Plugin) handleMuteAdd(_ *model.CommandArgs, username string, userInfo *
}
func (p *Plugin) handleUnmute(_ *model.CommandArgs, username string, userInfo *GitHubUserInfo) string {
- mutedUsernames := p.getMutedUsernames(userInfo)
+ mutedUsernames, err := p.getMutedUsernames(userInfo)
+ if err != nil {
+ p.client.Log.Error("error occurred getting muted users.", "UserID", userInfo.UserID, "Error", err)
+ return "An error occurred getting muted users. Please try again later"
+ }
+
userToMute := []string{username}
newMutedList := arrayDifference(mutedUsernames, userToMute)
- _, err := p.store.Set(userInfo.UserID+"-muted-users", []byte(strings.Join(newMutedList, ",")))
+ _, err = p.store.Set(userInfo.UserID+"-muted-users", []byte(strings.Join(newMutedList, ",")))
if err != nil {
return "Error occurred unmuting users"
}
@@ -569,6 +584,7 @@ func (p *Plugin) getSubscribedFeatures(channelID, owner, repo string) (Features,
return previousFeatures, nil
}
+
func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Please specify a repository."
@@ -1058,6 +1074,16 @@ func getAutocompleteData(config *Configuration) *model.AutocompleteData {
HelpText: "Include posts from members of the configured organization",
},
})
+ subscriptionsAdd.AddNamedStaticListArgument("include-only-org-members", "Events triggered only by organization members will be delivered (the organization config should be set, otherwise this flag has not effect)", false, []model.AutocompleteListItem{
+ {
+ Item: "true",
+ HelpText: "Include posts only from members of the configured organization",
+ },
+ {
+ Item: "false",
+ HelpText: "Include posts from members and collaborators of the configured organization",
+ },
+ })
}
subscriptionsAdd.AddNamedStaticListArgument("render-style", "Determine the rendering style of various notifications.", false, []model.AutocompleteListItem{
diff --git a/server/plugin/command_test.go b/server/plugin/command_test.go
index f9ee3544c..555081033 100644
--- a/server/plugin/command_test.go
+++ b/server/plugin/command_test.go
@@ -5,6 +5,8 @@ package plugin
import (
"fmt"
+ "os"
+ "path/filepath"
"testing"
"github.com/golang/mock/gomock"
@@ -12,6 +14,7 @@ import (
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/plugin/plugintest"
"github.com/mattermost/mattermost/server/public/pluginapi"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
@@ -31,11 +34,8 @@ func getPluginTest(api *plugintest.API, mockKvStore *mocks.MockKvStore) *Plugin
EncryptionKey: "mockKey123456789",
})
p.initializeAPI()
-
p.store = mockKvStore
-
- p.BotUserID = "mockBotID"
-
+ p.BotUserID = MockBotID
p.SetAPI(api)
p.client = pluginapi.NewClient(api, p.Driver)
@@ -336,3 +336,1550 @@ func TestExecuteCommand(t *testing.T) {
})
}
}
+
+func TestGetMutedUsernames(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(t *testing.T, result []string, err error)
+ }{
+ {
+ name: "Error retrieving muted usernames",
+ setup: func() {
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).Return(errors.New("error retrieving muted users")).Times(1)
+ },
+ assertions: func(t *testing.T, result []string, err error) {
+ assert.Nil(t, result)
+ assert.ErrorContains(t, err, "error retrieving muted users")
+ },
+ },
+ {
+ name: "No muted usernames set for user",
+ setup: func() {
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("")
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result []string, _ error) {
+ assert.Equal(t, []string(nil), result)
+ },
+ },
+ {
+ name: "Successfully retrieves muted usernames",
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result []string, _ error) {
+ assert.Equal(t, []string{"user1", "user2", "user3"}, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ mutedUsernames, err := p.getMutedUsernames(userInfo)
+
+ tc.assertions(t, mutedUsernames, err)
+ })
+ }
+}
+
+func TestHandleMuteList(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(t *testing.T, result string)
+ }{
+ {
+ name: "Error retrieving muted usernames",
+ setup: func() {
+ mockAPI.On("LogError", "error occurred getting muted users.", "UserID", userInfo.UserID, "Error", mock.Anything)
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).Return(errors.New("error retrieving muted users")).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "An error occurred getting muted users. Please try again later", result)
+ },
+ },
+ {
+ name: "No muted usernames set for user",
+ setup: func() {
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("")
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "You have no muted users", result)
+ },
+ },
+ {
+ name: "Successfully retrieves and formats muted usernames",
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ expectedOutput := "Your muted users:\n- user1\n- user2\n- user3\n"
+ assert.Equal(t, expectedOutput, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ result := p.handleMuteList(nil, userInfo)
+
+ tc.assertions(t, result)
+ })
+ }
+}
+
+func TestContains(t *testing.T) {
+ tests := []struct {
+ name string
+ slice []string
+ element string
+ assertions func(t *testing.T, result bool)
+ }{
+ {
+ name: "Element is present in slice",
+ slice: []string{"expectedElement1", "expectedElement2", "expectedElement3"},
+ element: "expectedElement2",
+ assertions: func(t *testing.T, result bool) {
+ assert.True(t, result)
+ },
+ },
+ {
+ name: "Element is not present in slice",
+ slice: []string{"expectedElement1", "expectedElement2", "expectedElement3"},
+ element: "expectedElement4",
+ assertions: func(t *testing.T, result bool) {
+ assert.False(t, result)
+ },
+ },
+ {
+ name: "Empty slice",
+ slice: []string{},
+ element: "expectedElement1",
+ assertions: func(t *testing.T, result bool) {
+ assert.False(t, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := contains(tc.slice, tc.element)
+ tc.assertions(t, result)
+ })
+ }
+}
+
+func TestHandleMuteAdd(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ username string
+ setup func()
+ assertions func(t *testing.T, result string)
+ }{
+ {
+ name: "Error retrieving muted usernames",
+ setup: func() {
+ mockAPI.On("LogError", "error occurred getting muted users.", "UserID", userInfo.UserID, "Error", mock.Anything)
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).Return(errors.New("error retrieving muted users")).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "An error occurred getting muted users. Please try again later", result)
+ },
+ },
+ {
+ name: "Error saving the new muted username",
+ username: "errorUser",
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("existingUser")
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("existingUser,errorUser")).Return(false, errors.New("store error")).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "Error occurred saving list of muted users", result)
+ },
+ },
+ {
+ name: "Username is already muted",
+ username: "alreadyMutedUser",
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("alreadyMutedUser")
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "alreadyMutedUser is already muted", result)
+ },
+ },
+ {
+ name: "Invalid username with comma",
+ username: "invalid,user",
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("")
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "Invalid username provided", result)
+ },
+ },
+ {
+ name: "Successfully adds first muted username",
+ username: "firstUser",
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("")
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("firstUser")).Return(true, nil).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ expectedMessage := "`firstUser` is now muted. You'll no longer receive notifications for comments in your PRs and issues."
+ assert.Equal(t, expectedMessage, result)
+ },
+ },
+ {
+ name: "Successfully adds new muted username",
+ username: "newUser",
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("existingUser")
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("existingUser,newUser")).Return(true, nil).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ expectedMessage := "`newUser` is now muted. You'll no longer receive notifications for comments in your PRs and issues."
+ assert.Equal(t, expectedMessage, result)
+ },
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ result := p.handleMuteAdd(nil, tc.username, userInfo)
+ tc.assertions(t, result)
+ })
+ }
+}
+
+func TestHandleUnmute(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ username string
+ setup func()
+ expectedResult string
+ }{
+ {
+ name: "Error retrieving muted usernames",
+ setup: func() {
+ mockAPI.On("LogError", "error occurred getting muted users.", "UserID", userInfo.UserID, "Error", mock.Anything)
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).Return(errors.New("error retrieving muted users")).Times(1)
+ },
+ expectedResult: "An error occurred getting muted users. Please try again later",
+ },
+ {
+ name: "Error occurred while unmuting the user",
+ username: "user1",
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", gomock.Any()).Return(false, errors.New("error saving muted users")).Times(1)
+ },
+ expectedResult: "Error occurred unmuting users",
+ },
+ {
+ name: "Successfully unmute a user",
+ username: "user1",
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", gomock.Any()).Return(true, nil).Times(1)
+ },
+ expectedResult: "`user1` is no longer muted",
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ result := p.handleUnmute(nil, tc.username, userInfo)
+ assert.Equal(t, tc.expectedResult, result)
+ })
+ }
+}
+
+func TestHandleUnmuteAll(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(string)
+ expectedResult string
+ }{
+ {
+ name: "Error occurred while unmuting all users",
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("")).Return(false, errors.New("error saving muted users")).Times(1)
+ },
+ assertions: func(expectedResult string) {
+ assert.Equal(t, expectedResult, "Error occurred unmuting users")
+ },
+ },
+ {
+ name: "Successfully unmute all users",
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("")).Return(true, nil).Times(1)
+ },
+ assertions: func(expectedResult string) {
+ assert.Equal(t, expectedResult, "Unmuted all users")
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ result := p.handleUnmuteAll(nil, userInfo)
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestHandleMuteCommand(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(*testing.T, string)
+ }{
+ {
+ name: "Success - list muted users",
+ parameters: []string{"list"},
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Your muted users:\n- user1\n- user2\n- user3\n", response)
+ },
+ },
+ {
+ name: "Success - add new muted user",
+ parameters: []string{"add", "newUser"},
+ setup: func() {
+ mockKvStore.EXPECT().Get(userInfo.UserID+"-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = []byte("existingUser")
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("existingUser,newUser")).Return(true, nil).Times(1)
+ },
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "`newUser` is now muted. You'll no longer receive notifications for comments in your PRs and issues.", response)
+ },
+ },
+ {
+ name: "Error - invalid number of parameters for add",
+ parameters: []string{"add"},
+ setup: func() {},
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Invalid number of parameters supplied to add", response)
+ },
+ },
+ {
+ name: "Success - delete muted user",
+ parameters: []string{"delete", "user1"},
+ setup: func() {
+ mutedUsernames := []byte("user1,user2,user3")
+ mockKvStore.EXPECT().Get("mockUserID-muted-users", gomock.Any()).DoAndReturn(func(key string, value *[]byte) error {
+ *value = mutedUsernames
+ return nil
+ }).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "`user1` is no longer muted", response)
+ },
+ },
+ {
+ name: "Error - invalid number of parameters for delete",
+ parameters: []string{"delete"},
+ setup: func() {},
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Invalid number of parameters supplied to delete", response)
+ },
+ },
+ {
+ name: "Success - delete all muted users",
+ parameters: []string{"delete-all"},
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+"-muted-users", []byte("")).Return(true, nil).Times(1)
+ },
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Unmuted all users", response)
+ },
+ },
+ {
+ name: "Error - unknown subcommand",
+ parameters: []string{"unknown"},
+ setup: func() {},
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Unknown subcommand unknown", response)
+ },
+ },
+ {
+ name: "Error - no parameters provided",
+ parameters: []string{},
+ setup: func() {},
+ assertions: func(t *testing.T, response string) {
+ assert.Equal(t, "Invalid mute command. Available commands are 'list', 'add' and 'delete'.", response)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ result := p.handleMuteCommand(nil, nil, tc.parameters, userInfo)
+ tc.assertions(t, result)
+ })
+ }
+}
+
+func TestArrayDifference(t *testing.T) {
+ tests := []struct {
+ name string
+ arr1 []string
+ arr2 []string
+ expected []string
+ }{
+ {
+ name: "No difference - all elements in a are in b",
+ arr1: []string{"apple", "banana", "cherry"},
+ arr2: []string{"apple", "banana", "cherry"},
+ expected: []string{},
+ },
+ {
+ name: "Difference - some elements in a are not in b",
+ arr1: []string{"apple", "banana", "cherry", "date"},
+ arr2: []string{"apple", "banana"},
+ expected: []string{"cherry", "date"},
+ },
+ {
+ name: "All elements different - no elements in a are in b",
+ arr1: []string{"apple", "banana"},
+ arr2: []string{"cherry", "date"},
+ expected: []string{"apple", "banana"},
+ },
+ {
+ name: "Empty a - no elements to compare",
+ arr1: []string{},
+ arr2: []string{"apple", "banana"},
+ expected: []string{},
+ },
+ {
+ name: "Empty b - all elements in a should be returned",
+ arr1: []string{"apple", "banana"},
+ arr2: []string{},
+ expected: []string{"apple", "banana"},
+ },
+ {
+ name: "Both a and b empty - no elements to compare",
+ arr1: []string{},
+ arr2: []string{},
+ expected: []string{},
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := arrayDifference(tc.arr1, tc.arr2)
+ assert.ElementsMatch(t, tc.expected, result)
+ })
+ }
+}
+
+func TestHandleSubscriptionsList(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+
+ tests := []struct {
+ name string
+ channelID string
+ setup func()
+ assertions func(t *testing.T, result string)
+ }{
+ {
+ name: "Error retrieving subscriptions",
+ channelID: "channel1",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(errors.New("store error")).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Contains(t, result, "could not get subscriptions from KVStore: store error")
+ },
+ },
+ {
+ name: "No subscriptions in the channel",
+ channelID: "channel2",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{}}
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ assert.Equal(t, "Currently there are no subscriptions in this channel", result)
+ },
+ },
+ {
+ name: "Multiple subscriptions in the channel",
+ channelID: "channel3",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{
+ Repositories: map[string][]*Subscription{
+ "repo1": {
+ {
+ ChannelID: "channel3",
+ Repository: "repo1",
+ },
+ {
+ ChannelID: "channel4",
+ Repository: "repo1",
+ },
+ },
+ "repo2": {
+ {
+ ChannelID: "channel3",
+ Repository: "repo2",
+ },
+ },
+ },
+ }
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ expected := "### Subscriptions in this channel\n" +
+ "* `repo1` - \n" +
+ "* `repo2` - \n"
+ assert.Equal(t, expected, result)
+ },
+ },
+ {
+ name: "Subscriptions with flags",
+ channelID: "channel4",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{
+ Repositories: map[string][]*Subscription{
+ "repo3": {
+ {
+ ChannelID: "channel4",
+ Repository: "repo3",
+ Flags: SubscriptionFlags{
+ ExcludeOrgMembers: true,
+ RenderStyle: "compact",
+ ExcludeRepository: []string{"repoA", "repoB"},
+ },
+ },
+ },
+ },
+ }
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, result string) {
+ expected := "### Subscriptions in this channel\n* `repo3` - --exclude-org-member true,--render-style compact,--exclude repoA,repoB\n"
+ assert.Equal(t, expected, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ result := p.handleSubscriptionsList(nil, &model.CommandArgs{ChannelId: tc.channelID}, nil, nil)
+ tc.assertions(t, result)
+ })
+ }
+}
+
+func TestGetSubscribedFeatures(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+
+ tests := []struct {
+ name string
+ channelID string
+ owner string
+ repo string
+ setup func()
+ assertions func(t *testing.T, features Features, err error)
+ }{
+ {
+ name: "Error retrieving subscriptions",
+ channelID: "channel1",
+ owner: "owner1",
+ repo: "repo1",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(errors.New("store error")).Times(1)
+ },
+ assertions: func(t *testing.T, features Features, err error) {
+ assert.Error(t, err)
+ assert.ErrorContains(t, err, "store error")
+ assert.Empty(t, features)
+ },
+ },
+ {
+ name: "No subscriptions in the channel",
+ channelID: "channel2",
+ owner: "owner2",
+ repo: "repo2",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{}}
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, features Features, err error) {
+ assert.NoError(t, err)
+ assert.Empty(t, features)
+ },
+ },
+ {
+ name: "Subscribed features found for repo",
+ channelID: "channel3",
+ owner: "owner3",
+ repo: "repo3",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{
+ Repositories: map[string][]*Subscription{
+ "owner3/repo3": {
+ {
+ ChannelID: "channel3",
+ Repository: "owner3/repo3",
+ Features: Features("FeatureA"),
+ },
+ },
+ "owner4/repo4": {
+ {
+ ChannelID: "channel4",
+ Repository: "owner4/repo4",
+ Features: Features("FeatureB"),
+ },
+ },
+ },
+ }
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, features Features, err error) {
+ assert.NoError(t, err)
+ expectedFeatures := Features("FeatureA")
+ assert.Equal(t, expectedFeatures, features)
+ },
+ },
+ {
+ name: "Subscribed features not found for repo",
+ channelID: "channel4",
+ owner: "owner5",
+ repo: "repo5",
+ setup: func() {
+ mockKvStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{
+ Repositories: map[string][]*Subscription{
+ "owner6/repo6": {
+ {
+ ChannelID: "channel4",
+ Repository: "owner6/repo6",
+ Features: Features("FeatureC"),
+ },
+ },
+ },
+ }
+ return nil
+ }).Times(1)
+ },
+ assertions: func(t *testing.T, features Features, err error) {
+ assert.NoError(t, err)
+ assert.Empty(t, features)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+ features, err := p.getSubscribedFeatures(tc.channelID, tc.owner, tc.repo)
+ tc.assertions(t, features, err)
+ })
+ }
+}
+
+func TestCreatePost(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ post := &model.Post{
+ ChannelId: MockChannelID,
+ UserId: MockUserID,
+ Message: MockPostMessage,
+ }
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(t *testing.T, err error)
+ }{
+ {
+ name: "Error creating a post",
+ setup: func() {
+ mockAPI.On("CreatePost", post).Return(nil, &model.AppError{Message: "error creating post"}).Times(1)
+ mockAPI.On("LogWarn", "Error while creating post", "post", post, "error", "error creating post").Times(1)
+ },
+ assertions: func(t *testing.T, err error) {
+ assert.EqualError(t, err, "error creating post")
+ },
+ },
+ {
+ name: "Successfully create a post",
+ setup: func() {
+ mockAPI.On("CreatePost", post).Return(post, nil).Times(1)
+ },
+ assertions: func(t *testing.T, err error) {
+ assert.NoError(t, err)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+ err := p.createPost(MockChannelID, MockUserID, MockPostMessage)
+ tc.assertions(t, err)
+ })
+ }
+}
+
+func TestHandleUnsubscribe(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+ p.setConfiguration(&Configuration{})
+ post := &model.Post{
+ ChannelId: MockChannelID,
+ UserId: MockBotID,
+ }
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(result string)
+ }{
+ {
+ name: "No repository specified",
+ parameters: []string{},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Please specify a repository.", result)
+ },
+ },
+ {
+ name: "Invalid repository format",
+ parameters: []string{""},
+ setup: func() {
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "invalid repository", result)
+ },
+ },
+ {
+ name: "Failed to unsubscribe",
+ parameters: []string{"owner/repo"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(errors.New("error occurred getting subscriptions"))
+ mockAPI.On("LogWarn", "Failed to unsubscribe", "repo", "repo", "error", "could not get subscriptions: could not get subscriptions from KVStore: error occurred getting subscriptions")
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "Encountered an error trying to unsubscribe. Please try again.", result)
+ },
+ },
+ {
+ name: "Error getting user details",
+ parameters: []string{"owner/repo"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{
+ "owner/repo": {{ChannelID: "dummyChannelID", CreatorID: MockCreatorID, Repository: "owner/repo"}}}}
+ return nil
+ }).Times(1)
+ mockAPI.On("GetUser", MockUserID).Return(nil, &model.AppError{Message: "error getting user"}).Times(1)
+ mockAPI.On("LogWarn", "Error while fetching user details", "error", "error getting user").Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "error while fetching user details: error getting user", result)
+ },
+ },
+ {
+ name: "Error creating post of unsubscribe with no repo",
+ parameters: []string{"owner"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{
+ "owner": {{ChannelID: "dummyChannelID", CreatorID: MockCreatorID, Repository: ""}}}}
+ return nil
+ }).Times(1)
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Username: MockUsername}, nil).Times(1)
+ mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1)
+ post.Message = "@mockUsername unsubscribed this channel from [owner](https://github.com/owner)"
+ mockAPI.On("LogWarn", "Error while creating post", "post", post, "error", "error creating post").Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "@mockUsername unsubscribed this channel from [owner](https://github.com/owner) error creating the public post: error creating post", result)
+ },
+ },
+ {
+ name: "Success unsubscribing with no repo",
+ parameters: []string{"owner"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{
+ "owner": {{ChannelID: "dummyChannelID", CreatorID: MockCreatorID, Repository: ""}}}}
+ return nil
+ }).Times(1)
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Username: MockUsername}, nil).Times(1)
+ mockAPI.On("CreatePost", mock.Anything).Return(post, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Empty(t, result)
+ },
+ },
+ {
+ name: "Error creating post of unsubscribe with no repo",
+ parameters: []string{"owner/repo"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{
+ "owner/repo": {{ChannelID: "dummyChannelID", CreatorID: MockCreatorID, Repository: "owner/repo"}}}}
+ return nil
+ }).Times(1)
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Username: MockUsername}, nil).Times(1)
+ mockAPI.On("CreatePost", mock.Anything).Return(nil, &model.AppError{Message: "error creating post"}).Times(1)
+ post.Message = "@mockUsername Unsubscribed this channel from [owner/repo](https://github.com/owner/repo)\n Please delete the [webhook](https://github.com/owner/repo/settings/hooks) for this subscription unless it's required for other subscriptions."
+ mockAPI.On("LogWarn", "Error while creating post", "post", post, "error", "error creating post").Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "@mockUsername Unsubscribed this channel from [owner/repo](https://github.com/owner/repo)\n Please delete the [webhook](https://github.com/owner/repo/settings/hooks) for this subscription unless it's required for other subscriptions. error creating the public post: error creating post", result)
+ },
+ },
+ {
+ name: "Success unsubscribing with repo",
+ parameters: []string{"owner/repo"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).DoAndReturn(func(key string, value **Subscriptions) error {
+ *value = &Subscriptions{Repositories: map[string][]*Subscription{
+ "owner/repo": {{ChannelID: "dummyChannelID", CreatorID: MockCreatorID, Repository: "owner/repo"}}}}
+ return nil
+ }).Times(1)
+ mockAPI.ExpectedCalls = nil
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Username: MockUsername}, nil).Times(1)
+ mockAPI.On("CreatePost", mock.Anything).Return(post, nil).Times(1)
+ post.Message = ""
+ },
+ assertions: func(result string) {
+ assert.Empty(t, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+
+ args := &model.CommandArgs{
+ UserId: MockUserID,
+ ChannelId: MockChannelID,
+ }
+
+ result := p.handleUnsubscribe(nil, args, tc.parameters, nil)
+
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestHandleSettings(t *testing.T) {
+ mockKvStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKvStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(string)
+ expectedResult string
+ }{
+ {
+ name: "Error: Not enough parameters",
+ parameters: []string{
+ settingNotifications,
+ },
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, result, "Please specify both a setting and value. Use `/github help` for more usage information.")
+ },
+ expectedResult: "Please specify both a setting and value. Use `/github help` for more usage information.",
+ },
+ {
+ name: "Invalid setting value for notifications",
+ parameters: []string{
+ settingNotifications, "invalid",
+ },
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, result, "Invalid value. Accepted values are: \"on\" or \"off\".")
+ },
+ expectedResult: "Invalid value. Accepted values are: \"on\" or \"off\".",
+ },
+ {
+ name: "Successfully enable notifications",
+ parameters: []string{
+ settingNotifications, settingOn,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.GitHubUsername+githubUsernameKey, gomock.Any()).Return(true, nil).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Error enabling notifications",
+ parameters: []string{
+ settingNotifications, settingOn,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.GitHubUsername+githubUsernameKey, gomock.Any()).Return(false, errors.New("error setting notification")).Times(1)
+ mockAPI.On("LogWarn", "Failed to store GitHub to userID mapping", "userID", "mockUserID", "GitHub username", "mockUsername", "error", "encountered error saving github username mapping: error setting notification").Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Successfully disable notifications",
+ parameters: []string{
+ settingNotifications, settingOff,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.GitHubUsername+githubUsernameKey, gomock.Any()).Return(true, nil).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ mockKvStore.EXPECT().Delete(userInfo.GitHubUsername + githubUsernameKey).Return(nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Error disabling notifications",
+ parameters: []string{
+ settingNotifications, settingOff,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.GitHubUsername+githubUsernameKey, gomock.Any()).Return(true, nil).Times(1)
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ mockKvStore.EXPECT().Delete(userInfo.GitHubUsername + githubUsernameKey).Return(errors.New("error setting notification")).Times(1)
+ mockAPI.On("LogWarn", "Failed to delete GitHub to userID mapping", "userID", "mockUserID", "GitHub username", "mockUsername", "error", "error setting notification").Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Successfully set reminders to on",
+ parameters: []string{
+ settingReminders, settingOn,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Successfully set reminders to off",
+ parameters: []string{
+ settingReminders, settingOff,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Successfully set reminders to on-change",
+ parameters: []string{
+ settingReminders, settingOnChange,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(true, nil).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Settings updated.")
+ },
+ expectedResult: "Settings updated.",
+ },
+ {
+ name: "Invalid setting value for reminders",
+ parameters: []string{
+ settingReminders, "invalid",
+ },
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, result, "Invalid value. Accepted values are: \"on\" or \"off\" or \"on-change\" .")
+ },
+ expectedResult: "Invalid value. Accepted values are: \"on\" or \"off\" or \"on-change\" .",
+ },
+ {
+ name: "Unknown setting",
+ parameters: []string{
+ "unknownSetting", settingOn,
+ },
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, result, "Unknown setting unknownSetting")
+ },
+ expectedResult: "Unknown setting unknownSetting",
+ },
+ {
+ name: "Error while storing settings",
+ parameters: []string{
+ settingReminders, settingOnChange,
+ },
+ setup: func() {
+ mockKvStore.EXPECT().Set(userInfo.UserID+githubTokenKey, gomock.Any()).Return(false, errors.New("error storing user info")).Times(1)
+ mockAPI.On("LogWarn", "Failed to store github user info", "error", "error occurred while trying to store user info into KV store: error storing user info").Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, result, "Failed to store settings")
+ },
+ expectedResult: "Failed to store settings",
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+
+ result := p.handleSettings(nil, nil, tc.parameters, userInfo)
+
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestHandleIssue(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(result string)
+ }{
+ {
+ name: "Invalid command: no parameters",
+ parameters: []string{},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Invalid issue command. Available command is 'create'.", result)
+ },
+ },
+ {
+ name: "Unknown subcommand",
+ parameters: []string{"delete"},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Unknown subcommand delete", result)
+ },
+ },
+ {
+ name: "Create issue with title",
+ parameters: []string{"create", "Test issue title"},
+ setup: func() {
+ mockAPI.On("PublishWebSocketEvent", wsEventCreateIssue,
+ map[string]interface{}{
+ "title": "Test issue title",
+ "channel_id": "testChannelID",
+ },
+ &model.WebsocketBroadcast{UserId: "testUserID"},
+ ).Return(nil).Once()
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "", result)
+ mockAPI.AssertCalled(t, "PublishWebSocketEvent", wsEventCreateIssue,
+ map[string]interface{}{
+ "title": "Test issue title",
+ "channel_id": "testChannelID",
+ },
+ &model.WebsocketBroadcast{UserId: "testUserID"},
+ )
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+
+ args := &model.CommandArgs{
+ UserId: "testUserID",
+ ChannelId: "testChannelID",
+ }
+
+ result := p.handleIssue(nil, args, tc.parameters, userInfo)
+
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestIsAuthorizedSysAdmin(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(bool, error)
+ }{
+ {
+ name: "Error getting user",
+ setup: func() {
+ mockAPI.On("GetUser", MockUserID).Return(nil, &model.AppError{Message: "error getting user"}).Times(1)
+ },
+ assertions: func(result bool, err error) {
+ assert.False(t, result)
+ assert.EqualError(t, err, "error getting user")
+ },
+ },
+ {
+ name: "User is not a system admin",
+ setup: func() {
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Roles: "user"}, nil).Times(1)
+ },
+ assertions: func(result bool, err error) {
+ assert.NoError(t, err)
+ assert.False(t, result)
+ },
+ },
+ {
+ name: "Successfully authorized as system admin",
+ setup: func() {
+ mockAPI.On("GetUser", MockUserID).Return(&model.User{Roles: "system_admin"}, nil).Times(1)
+ },
+ assertions: func(result bool, err error) {
+ assert.NoError(t, err)
+ assert.True(t, result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+
+ result, err := p.isAuthorizedSysAdmin(MockUserID)
+
+ tc.assertions(result, err)
+ })
+ }
+}
+
+func TestHandleSubscribe(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(result string)
+ }{
+ {
+ name: "No parameters provided",
+ parameters: []string{},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Please specify a repository or 'list' command.", result)
+ },
+ },
+ {
+ name: "List command provided",
+ parameters: []string{"list"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(errors.New("error getting subscription")).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "could not get subscriptions: could not get subscriptions from KVStore: error getting subscription", result)
+ },
+ },
+ {
+ name: "default case, handleSubscribesAdd called",
+ parameters: []string{"invalid_parameter_1", "invalid_parameter_2", "invalid_parameter_3"},
+ setup: func() {
+
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "Please use the correct format for flags: -- ", result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ args := &model.CommandArgs{
+ UserId: "test-user-id",
+ ChannelId: "test-channel-id",
+ }
+
+ result := p.handleSubscribe(nil, args, tc.parameters, userInfo)
+
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestHandleSubscriptions(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+ userInfo, err := GetMockGHUserInfo(p)
+ assert.NoError(t, err)
+
+ tests := []struct {
+ name string
+ parameters []string
+ setup func()
+ assertions func(result string)
+ }{
+ {
+ name: "No parameters provided",
+ parameters: []string{},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Invalid subscribe command. Available commands are 'list', 'add' and 'delete'.", result)
+ },
+ },
+ {
+ name: "List command provided",
+ parameters: []string{"list"},
+ setup: func() {
+ mockKVStore.EXPECT().Get(SubscriptionsKey, gomock.Any()).Return(errors.New("error getting subscription")).Times(1)
+ },
+ assertions: func(result string) {
+ assert.Equal(t, "could not get subscriptions: could not get subscriptions from KVStore: error getting subscription", result)
+ },
+ },
+ {
+ name: "Add command provided",
+ parameters: []string{"add", "invalid_parameter_1", "invalid_parameter_2", "invalid_parameter_3"},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Please use the correct format for flags: -- ", result)
+ },
+ },
+ {
+ name: "Delete command provided",
+ parameters: []string{"delete"},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Please specify a repository.", result)
+ },
+ },
+ {
+ name: "Unknown subcommand",
+ parameters: []string{"unknown"},
+ setup: func() {},
+ assertions: func(result string) {
+ assert.Equal(t, "Unknown subcommand unknown", result)
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ tc.setup()
+
+ args := &model.CommandArgs{
+ UserId: "test-user-id",
+ ChannelId: "test-channel-id",
+ }
+
+ result := p.handleSubscriptions(nil, args, tc.parameters, userInfo)
+
+ tc.assertions(result)
+ })
+ }
+}
+
+func TestGetCommand(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+
+ // Creating a mock SVG file with dummy content.
+ tempDir := t.TempDir()
+ assetsDir := filepath.Join(tempDir, "assets")
+ err := os.Mkdir(assetsDir, 0755)
+ require.NoError(t, err)
+ tempFilePath := filepath.Join(assetsDir, "icon-bg.svg")
+ err = os.WriteFile(tempFilePath, []byte(""), 0600)
+ require.NoError(t, err)
+
+ tests := []struct {
+ name string
+ setup func()
+ assertions func(*model.Command, error)
+ }{
+ {
+ name: "Error getting icon data",
+ setup: func() {
+ mockAPI.On("GetBundlePath").Return("", errors.New("error getting bundle path")).Times(1)
+ },
+ assertions: func(cmd *model.Command, err error) {
+ assert.Nil(t, cmd)
+ assert.EqualError(t, err, "failed to get icon data: couldn't get bundle path: error getting bundle path")
+ },
+ },
+ {
+ name: "Successfully retrieves command",
+ setup: func() {
+ mockAPI.On("GetBundlePath").Return(tempDir, nil).Times(1)
+ },
+ assertions: func(cmd *model.Command, err error) {
+ assert.NoError(t, err)
+ assert.Contains(t, cmd.AutocompleteIconData, "data:image/svg+xml;base64,")
+ },
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ mockAPI.ExpectedCalls = nil
+ tc.setup()
+
+ cmd, err := p.getCommand(&Configuration{})
+
+ tc.assertions(cmd, err)
+ })
+ }
+}
+
+func TestHandleHelp(t *testing.T) {
+ mockKVStore, mockAPI, _, _, _ := GetTestSetup(t)
+ p := getPluginTest(mockAPI, mockKVStore)
+
+ t.Run("Successfully get help text", func(t *testing.T) {
+ response := p.handleHelp(&plugin.Context{}, &model.CommandArgs{}, []string{}, &GitHubUserInfo{})
+ assert.Contains(t, response, "###### Mattermost GitHub Plugin - Slash Command Help\n")
+ })
+}
+
+func TestFormattedString(t *testing.T) {
+ tests := []struct {
+ name string
+ features Features
+ expectedString string
+ }{
+ {
+ name: "Single feature",
+ features: "feature1",
+ expectedString: "`feature1`",
+ },
+ {
+ name: "Multiple features",
+ features: "feature1,feature2,feature3",
+ expectedString: "`feature1`, `feature2`, `feature3`",
+ },
+ {
+ name: "Empty features",
+ features: "",
+ expectedString: "``",
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := tc.features.FormattedString()
+ assert.Equal(t, tc.expectedString, result)
+ })
+ }
+}
+
+func TestToSlice(t *testing.T) {
+ tests := []struct {
+ name string
+ features Features
+ expectedSlice []string
+ }{
+ {
+ name: "Single feature",
+ features: "feature1",
+ expectedSlice: []string{"feature1"},
+ },
+ {
+ name: "Multiple features",
+ features: "feature1,feature2,feature3",
+ expectedSlice: []string{"feature1", "feature2", "feature3"},
+ },
+ {
+ name: "Empty features",
+ features: "",
+ expectedSlice: []string{""},
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := tc.features.ToSlice()
+ assert.Equal(t, tc.expectedSlice, result)
+ })
+ }
+}
+
+func TestSliceContainsString(t *testing.T) {
+ tests := []struct {
+ name string
+ slice []string
+ searchString string
+ expectedResult bool
+ }{
+ {
+ name: "Empty slice",
+ slice: []string{},
+ searchString: "testString1",
+ expectedResult: false,
+ },
+ {
+ name: "String exists in slice",
+ slice: []string{"testString1", "testString2", "testString3"},
+ searchString: "testString2",
+ expectedResult: true,
+ },
+ {
+ name: "String does not exist in slice",
+ slice: []string{"testString1", "testString2", "testString3"},
+ searchString: "testString4",
+ expectedResult: false,
+ },
+ {
+ name: "String is the first element in the slice",
+ slice: []string{"testString2", "testString1", "testString3"},
+ searchString: "testString1",
+ expectedResult: true,
+ },
+ {
+ name: "String is the last element in the slice",
+ slice: []string{"testString1", "testString3", "testString2"},
+ searchString: "testString2",
+ expectedResult: true,
+ },
+ {
+ name: "String with different case",
+ slice: []string{"testString1", "testString2", "TestString3"},
+ searchString: "testString3",
+ expectedResult: false,
+ },
+ {
+ name: "Search string is empty",
+ slice: []string{"testString1", "testString2", "testString3"},
+ searchString: "",
+ expectedResult: false,
+ },
+ {
+ name: "Slice contains empty string",
+ slice: []string{"testString1", "testString2", ""},
+ searchString: "",
+ expectedResult: true,
+ },
+ {
+ name: "Slice with multiple occurrences of the search string",
+ slice: []string{"testString2", "testString1", "testString2", "testString3"},
+ searchString: "testString2",
+ expectedResult: true,
+ },
+ }
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ result := SliceContainsString(tc.slice, tc.searchString)
+ assert.Equal(t, tc.expectedResult, result)
+ })
+ }
+}
diff --git a/server/plugin/flows.go b/server/plugin/flows.go
index 411d70e87..226bbca85 100644
--- a/server/plugin/flows.go
+++ b/server/plugin/flows.go
@@ -698,7 +698,7 @@ func (fm *FlowManager) submitWebhook(f *flow.Flow, submitted map[string]interfac
return "", nil, nil, errors.New("invalid format")
}
- webhookEvents := []string{"create", "delete", "issue_comment", "issues", "pull_request", "pull_request_review", "pull_request_review_comment", "push", "star"}
+ webhookEvents := []string{"create", "delete", "issue_comment", "issues", "pull_request", "pull_request_review", "pull_request_review_comment", "push", "star", "workflow_job", "workflow_run", "discussion", "discussion_comment", "release"}
webHookURL, err := buildPluginURL(fm.client, "webhook")
if err != nil {
diff --git a/server/plugin/subscriptions.go b/server/plugin/subscriptions.go
index aeb4787ea..85c67489b 100644
--- a/server/plugin/subscriptions.go
+++ b/server/plugin/subscriptions.go
@@ -17,17 +17,19 @@ import (
)
const (
- SubscriptionsKey = "subscriptions"
- flagExcludeOrgMember = "exclude-org-member"
- flagRenderStyle = "render-style"
- flagFeatures = "features"
- flagExcludeRepository = "exclude"
+ SubscriptionsKey = "subscriptions"
+ flagExcludeOrgMember = "exclude-org-member"
+ flagIncludeOnlyOrgMembers = "include-only-org-members"
+ flagRenderStyle = "render-style"
+ flagFeatures = "features"
+ flagExcludeRepository = "exclude"
)
type SubscriptionFlags struct {
- ExcludeOrgMembers bool
- RenderStyle string
- ExcludeRepository []string
+ ExcludeOrgMembers bool
+ IncludeOnlyOrgMembers bool
+ RenderStyle string
+ ExcludeRepository []string
}
func (s *SubscriptionFlags) AddFlag(flag string, value string) error {
@@ -38,6 +40,12 @@ func (s *SubscriptionFlags) AddFlag(flag string, value string) error {
return err
}
s.ExcludeOrgMembers = parsed
+ case flagIncludeOnlyOrgMembers:
+ parsed, err := strconv.ParseBool(value)
+ if err != nil {
+ return err
+ }
+ s.IncludeOnlyOrgMembers = parsed
case flagRenderStyle:
s.RenderStyle = value
case flagExcludeRepository:
@@ -59,6 +67,11 @@ func (s SubscriptionFlags) String() string {
flags = append(flags, flag)
}
+ if s.IncludeOnlyOrgMembers {
+ flag := "--" + flagIncludeOnlyOrgMembers + " true"
+ flags = append(flags, flag)
+ }
+
if s.RenderStyle != "" {
flag := "--" + flagRenderStyle + " " + s.RenderStyle
flags = append(flags, flag)
@@ -161,6 +174,10 @@ func (s *Subscription) ExcludeOrgMembers() bool {
return s.Flags.ExcludeOrgMembers
}
+func (s *Subscription) IncludeOnlyOrgMembers() bool {
+ return s.Flags.IncludeOnlyOrgMembers
+}
+
func (s *Subscription) RenderStyle() string {
return s.Flags.RenderStyle
}
@@ -190,6 +207,10 @@ func (p *Plugin) Subscribe(ctx context.Context, githubClient *github.Client, use
return errors.New("Unable to set --exclude-org-member flag. The GitHub plugin is not locked to a single organization.")
}
+ if flags.IncludeOnlyOrgMembers && !p.isOrganizationLocked() {
+ return errors.New("Unable to set --include-only-org-members flag. The GitHub plugin is not locked to a single organization.")
+ }
+
var err, cErr error
if repo == "" {
diff --git a/server/plugin/subscriptions_test.go b/server/plugin/subscriptions_test.go
index dfca197fe..56e12e479 100644
--- a/server/plugin/subscriptions_test.go
+++ b/server/plugin/subscriptions_test.go
@@ -4,8 +4,11 @@
package plugin
import (
+ "context"
"testing"
+ "github.com/google/go-github/v54/github"
+ "github.com/mattermost/mattermost/server/public/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -121,3 +124,102 @@ func TestPlugin_GetSubscriptionsByChannel(t *testing.T) {
})
}
}
+
+func TestAddFlag(t *testing.T) {
+ tests := []struct {
+ name string
+ flags SubscriptionFlags
+ flag string
+ value string
+ want bool
+ wantErr bool
+ }{
+ {
+ name: "IncludeOnlyOrgMembers flag is parsed",
+ flags: SubscriptionFlags{},
+ flag: "include-only-org-members",
+ value: "true",
+ want: true,
+ wantErr: false,
+ },
+ {
+ name: "IncludeOnlyOrgMembers flag cannot be parsed",
+ flags: SubscriptionFlags{},
+ flag: "include-only-org-members",
+ value: "test",
+ want: false,
+ wantErr: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Helper()
+
+ err := tt.flags.AddFlag(tt.flag, tt.value)
+ CheckError(t, tt.wantErr, err)
+ assert.Equal(t, tt.flags.IncludeOnlyOrgMembers, tt.want)
+ })
+ }
+}
+
+func TestString(t *testing.T) {
+ tests := []struct {
+ name string
+ flags SubscriptionFlags
+ flag string
+ value string
+ want string
+ }{
+ {
+ name: "Return --include-only-org-members string",
+ flags: SubscriptionFlags{},
+ flag: "include-only-org-members",
+ value: "true",
+ want: "--include-only-org-members true",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Helper()
+ _ = tt.flags.AddFlag(tt.flag, tt.value)
+ got := tt.flags.String()
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+func TestSubscribe(t *testing.T) {
+ tests := []struct {
+ name string
+ flags SubscriptionFlags
+ plugin *Plugin
+ errMsg string
+ }{
+ {
+ name: "Return error if GitHub organization is not set when --include-only-org-members flag is true",
+ flags: SubscriptionFlags{IncludeOnlyOrgMembers: true},
+ plugin: NewPlugin(),
+ errMsg: "Unable to set --include-only-org-members flag. The GitHub plugin is not locked to a single organization.",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Helper()
+ err := tt.plugin.Subscribe(
+ context.Background(),
+ github.NewClient(nil),
+ model.NewId(),
+ "test-owner",
+ "test-repo",
+ model.NewId(),
+ "test-features",
+ tt.flags,
+ )
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), tt.errMsg)
+ })
+ }
+}
diff --git a/server/plugin/template.go b/server/plugin/template.go
index 441bfbf4f..372f56d21 100644
--- a/server/plugin/template.go
+++ b/server/plugin/template.go
@@ -451,6 +451,7 @@ Reviewers: {{range $i, $el := .RequestedReviewers -}} {{- if $i}}, {{end}}{{temp
" * `discussion_comments` - includes new discussion comments\n" +
" * Defaults to `pulls,issues,creates,deletes`\n\n" +
" * `--exclude-org-member` - events triggered by organization members will not be delivered (the GitHub organization config should be set, otherwise this flag has not effect)\n" +
+ " * `--include-only-org-members` - events triggered only by organization members will be delivered (the GitHub organization config should be set, otherwise this flag has not effect)\n" +
" * `--render-style` - notifications will be delivered in the specified style (for example, the body of a pull request will not be displayed). Supported values are `collapsed`, `skip-body` or `default` (same as omitting the flag).\n" +
"* `/github subscriptions delete owner[/repo]` - Unsubscribe the current channel from a repository\n" +
"* `/github me` - Display the connected GitHub account\n" +
@@ -486,13 +487,22 @@ Step failed: {{.GetWorkflowJob.Steps | workflowJobFailedStep}}
{{- end -}}`))
template.Must(masterTemplate.New("newDiscussion").Funcs(funcMap).Parse(`
-{{template "user" .GetSender}} started a new discussion [#{{.GetDiscussion.GetNumber}} {{.GetDiscussion.GetTitle}}]({{.GetDiscussion.GetHTMLURL}}) on {{template "repo" .GetRepo}}
+{{template "user" .GetSender}}
+{{- if eq .GetAction "created" }} started a new
+{{- else if eq .GetAction "closed" }} closed a
+{{- else if eq .GetAction "reopened" }} reopened a
+{{- else if eq .GetAction "edited" }} edited a
+{{- end }} discussion [#{{.GetDiscussion.GetNumber}} {{.GetDiscussion.GetTitle}}]({{.GetDiscussion.GetHTMLURL}}) on {{template "repo" .GetRepo}}
`))
template.Must(masterTemplate.New("newDiscussionComment").Funcs(funcMap).Parse(`
-{{template "repo" .GetRepo}} New comment by {{template "user" .GetSender}} on discussion [#{{.GetDiscussion.GetNumber}} {{.GetDiscussion.GetTitle}}]({{.GetDiscussion.GetHTMLURL}}):
+{{template "repo" .GetRepo}}
+{{- if eq .GetAction "created" }} New comment
+{{- else if eq .GetAction "edited" }} Comment edited
+{{- else if eq .GetAction "deleted" }} Comment deleted
+{{- end }} by {{template "user" .GetSender}} on discussion [#{{.GetDiscussion.GetNumber}} {{.GetDiscussion.GetTitle}}]({{.GetDiscussion.GetHTMLURL}}):
-{{.GetComment.GetBody | trimBody | replaceAllGitHubUsernames}}
+> {{.GetComment.GetBody | trimBody | replaceAllGitHubUsernames}}
`))
}
diff --git a/server/plugin/test_utils.go b/server/plugin/test_utils.go
new file mode 100644
index 000000000..cc0b2e97d
--- /dev/null
+++ b/server/plugin/test_utils.go
@@ -0,0 +1,80 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package plugin
+
+import (
+ "context"
+ "testing"
+
+ "github.com/golang/mock/gomock"
+ "golang.org/x/oauth2"
+
+ "github.com/mattermost/mattermost-plugin-github/server/mocks"
+
+ "github.com/mattermost/mattermost/server/public/plugin/plugintest"
+)
+
+const (
+ MockUserID = "mockUserID"
+ MockUsername = "mockUsername"
+ MockAccessToken = "mockAccessToken"
+ MockChannelID = "mockChannelID"
+ MockCreatorID = "mockCreatorID"
+ MockBotID = "mockBotID"
+ MockPostMessage = "mockPostMessage"
+)
+
+func GetMockGHUserInfo(p *Plugin) (*GitHubUserInfo, error) {
+ encryptionKey := "dummyEncryptKey1"
+ p.setConfiguration(&Configuration{EncryptionKey: encryptionKey})
+ encryptedToken, err := encrypt([]byte(encryptionKey), MockAccessToken)
+ if err != nil {
+ return nil, err
+ }
+ gitHubUserInfo := &GitHubUserInfo{
+ UserID: MockUserID,
+ GitHubUsername: MockUsername,
+ Token: &oauth2.Token{AccessToken: encryptedToken},
+ Settings: &UserSettings{},
+ }
+
+ return gitHubUserInfo, nil
+}
+
+func GetTestSetup(t *testing.T) (*mocks.MockKvStore, *plugintest.API, *mocks.MockLogger, *mocks.MockLogger, *Context) {
+ mockCtrl := gomock.NewController(t)
+ defer mockCtrl.Finish()
+ mockKvStore := mocks.NewMockKvStore(mockCtrl)
+ mockAPI := &plugintest.API{}
+ mockLogger := mocks.NewMockLogger(mockCtrl)
+ mockLoggerWith := mocks.NewMockLogger(mockCtrl)
+ mockContext := GetMockContext(mockLogger)
+
+ return mockKvStore, mockAPI, mockLogger, mockLoggerWith, &mockContext
+}
+
+func GetMockContext(mockLogger *mocks.MockLogger) Context {
+ ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
+ defer cancel()
+
+ return Context{
+ Ctx: ctx,
+ UserID: MockUserID,
+ Log: mockLogger,
+ }
+}
+
+func GetMockUserContext(p *Plugin, mockLogger *mocks.MockLogger) (*UserContext, error) {
+ mockGHUserInfo, err := GetMockGHUserInfo(p)
+ if err != nil {
+ return nil, err
+ }
+
+ mockUserContext := &UserContext{
+ GetMockContext(mockLogger),
+ mockGHUserInfo,
+ }
+
+ return mockUserContext, nil
+}
diff --git a/server/plugin/utils.go b/server/plugin/utils.go
index 21784c0ad..283a3ec9c 100644
--- a/server/plugin/utils.go
+++ b/server/plugin/utils.go
@@ -44,14 +44,19 @@ func getYourAssigneeSearchQuery(username string, orgs []string) string {
return buildSearchQuery("is:open assignee:%v archived:false %v", username, orgs)
}
-func getIssuesSearchQuery(org, searchTerm string) string {
+func getIssuesSearchQuery(searchValue, searchTerm string) string {
query := "is:open is:issue archived:false %v %v"
- orgField := ""
- if len(org) != 0 {
- orgField = fmt.Sprintf("org:%v", org)
+ searchField := ""
+ if len(searchValue) != 0 {
+ searchField = fmt.Sprintf("org:%v", searchValue)
}
- return fmt.Sprintf(query, orgField, searchTerm)
+ // get all the issues which involve the user in case no organizational lock is set
+ // else {
+ // searchField = "involves:@me"
+ // }
+
+ return fmt.Sprintf(query, searchField, searchTerm)
}
func buildSearchQuery(query, username string, orgs []string) string {
diff --git a/server/plugin/webhook.go b/server/plugin/webhook.go
index 9a7dc6150..1b4ac7779 100644
--- a/server/plugin/webhook.go
+++ b/server/plugin/webhook.go
@@ -193,6 +193,7 @@ func (wb *WebhookBroker) Close() {
}
func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) {
+ p.client.Log.Info("Webhook event received")
config := p.getConfiguration()
body, err := io.ReadAll(r.Body)
if err != nil {
@@ -378,6 +379,26 @@ func (p *Plugin) excludeConfigOrgMember(user *github.User, subscription *Subscri
return p.isUserOrganizationMember(githubClient, user, info, organization)
}
+func (p *Plugin) shouldDenyEventDueToNotOrgMember(user *github.User, subscription *Subscription) bool {
+ if !subscription.IncludeOnlyOrgMembers() {
+ return false
+ }
+
+ githubClient, err := p.GetGitHubClient(context.Background(), subscription.CreatorID)
+ if err != nil {
+ p.client.Log.Warn("Failed to get user info", "error", err.Error())
+ return false
+ }
+
+ info, nErr := p.getGitHubUserInfo(subscription.CreatorID)
+ if nErr != nil {
+ p.client.Log.Warn("Failed to exclude org member", "error", nErr.Message)
+ return false
+ }
+
+ return !p.isUserOrganizationMember(githubClient, user, info, p.getConfiguration().GitHubOrg)
+}
+
func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
repo := event.GetRepo()
@@ -434,6 +455,10 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
label := sub.Label()
contained := false
@@ -629,6 +654,10 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
renderedMessage, err := renderTemplate(issueTemplate, GetEventWithRenderConfig(event, sub))
if err != nil {
p.client.Log.Warn("Failed to render template", "error", err.Error())
@@ -768,6 +797,10 @@ func (p *Plugin) postPushEvent(event *github.PushEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
post := p.makeBotPost(pushedCommitsMessage, "custom_git_push")
post.ChannelId = sub.ChannelID
@@ -805,6 +838,10 @@ func (p *Plugin) postCreateEvent(event *github.CreateEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
post := p.makeBotPost(newCreateMessage, "custom_git_create")
post.ChannelId = sub.ChannelID
@@ -844,6 +881,10 @@ func (p *Plugin) postDeleteEvent(event *github.DeleteEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
post := p.makeBotPost(newDeleteMessage, "custom_git_delete")
post.ChannelId = sub.ChannelID
if err = p.client.Post.CreatePost(post); err != nil {
@@ -885,6 +926,10 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
label := sub.Label()
contained := false
@@ -972,6 +1017,10 @@ func (p *Plugin) postPullRequestReviewEvent(event *github.PullRequestReviewEvent
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
label := sub.Label()
contained := false
@@ -1022,6 +1071,10 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
label := sub.Label()
contained := false
@@ -1430,6 +1483,10 @@ func (p *Plugin) postStarEvent(event *github.StarEvent) {
continue
}
+ if p.shouldDenyEventDueToNotOrgMember(event.GetSender(), sub) {
+ continue
+ }
+
post := p.makeBotPost(newStarMessage, "custom_git_star")
post.ChannelId = sub.ChannelID
@@ -1570,10 +1627,6 @@ func (p *Plugin) postDiscussionCommentEvent(event *github.DiscussionCommentEvent
return
}
- if event.GetAction() != actionCreated {
- return
- }
-
newDiscussionCommentMessage, err := renderTemplate("newDiscussionComment", event)
if err != nil {
p.client.Log.Warn("Failed to render template", "error", err.Error())
diff --git a/server/plugin/webhook_test.go b/server/plugin/webhook_test.go
new file mode 100644
index 000000000..4fb41396f
--- /dev/null
+++ b/server/plugin/webhook_test.go
@@ -0,0 +1,130 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package plugin
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "github.com/mattermost/mattermost/server/public/model"
+ "github.com/mattermost/mattermost/server/public/plugin/plugintest"
+ "github.com/mattermost/mattermost/server/public/plugin/plugintest/mock"
+ "github.com/mattermost/mattermost/server/public/pluginapi"
+ "golang.org/x/oauth2"
+
+ "github.com/google/go-github/v54/github"
+ "github.com/stretchr/testify/assert"
+)
+
+const webhookSecret = "whsecret"
+const orgMember = "org-member"
+const orgCollaborator = "org-collaborator"
+const gitHubOrginization = "test-org"
+
+func newPlugin(userID string, gitHubURL string) *Plugin {
+ p := NewPlugin()
+ p.initializeAPI()
+ p.SetDriver(&plugintest.Driver{})
+ p.store = &pluginapi.MemoryStore{}
+ token, _ := generateSecret()
+ encryptionKey, _ := generateSecret()
+ encryptedToken, _ := encrypt([]byte(encryptionKey), token)
+ _, _ = p.store.Set(userID+githubTokenKey, GitHubUserInfo{
+ UserID: userID,
+ Token: &oauth2.Token{
+ AccessToken: encryptedToken,
+ },
+ })
+ p.setConfiguration(&Configuration{
+ EncryptionKey: encryptionKey,
+ GitHubOrg: gitHubOrginization,
+ WebhookSecret: webhookSecret,
+ EnterpriseBaseURL: gitHubURL,
+ EnterpriseUploadURL: gitHubURL,
+ })
+
+ _ = p.AddSubscription(
+ gitHubOrginization+"/test-repo",
+ &Subscription{
+ ChannelID: "1",
+ CreatorID: userID,
+ Features: Features(strings.Join([]string{featureIssues, featureIssueCreation}, ",")),
+ Flags: SubscriptionFlags{IncludeOnlyOrgMembers: true},
+ },
+ )
+
+ return p
+}
+
+func mockGitHubServer(user string) *httptest.Server {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != fmt.Sprintf("/api/v3/orgs/%v/members/%v", gitHubOrginization, user) {
+ http.Error(w, "Not found", http.StatusNotFound)
+ return
+ }
+
+ if user == orgMember {
+ w.WriteHeader(http.StatusNoContent)
+ } else if user == orgCollaborator {
+ w.WriteHeader(http.StatusFound)
+ }
+ }))
+
+ return ts
+}
+
+func TestIncludeOnlyOrgMembers(t *testing.T) {
+ tests := []struct {
+ name string
+ user github.User
+ subscription Subscription
+ expectWarn bool
+ want bool
+ }{
+ {
+ name: "IncludeOnlyOrgMembers flag is false",
+ user: github.User{
+ Login: github.String(orgMember),
+ },
+ subscription: Subscription{
+ Flags: SubscriptionFlags{IncludeOnlyOrgMembers: false},
+ },
+ expectWarn: false,
+ want: false,
+ },
+ {
+ name: "Failed to get GitHub Client",
+ user: github.User{
+ Login: github.String(orgMember),
+ },
+ subscription: Subscription{
+ CreatorID: model.NewId(),
+ Flags: SubscriptionFlags{IncludeOnlyOrgMembers: true},
+ },
+ expectWarn: true,
+ want: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Helper()
+ user := *tt.user.Login
+ server := mockGitHubServer(user)
+ gitHubPlugin := newPlugin(model.NewId(), server.URL)
+ api := plugintest.NewAPI(t)
+ if tt.expectWarn {
+ api.On("LogWarn", mock.AnythingOfType("string"), "error", mock.AnythingOfType("string")).Return(nil)
+ }
+ gitHubPlugin.SetAPI(api)
+ gitHubPlugin.client = pluginapi.NewClient(gitHubPlugin.API, gitHubPlugin.Driver)
+
+ got := gitHubPlugin.shouldDenyEventDueToNotOrgMember(&tt.user, &tt.subscription)
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
diff --git a/webapp/package-lock.json b/webapp/package-lock.json
index 49b51da95..c0ad9e243 100644
--- a/webapp/package-lock.json
+++ b/webapp/package-lock.json
@@ -15,6 +15,7 @@
"react": "16.13.1",
"react-bootstrap": "1.3.0",
"react-custom-scrollbars": "4.2.1",
+ "react-dom": "16.13.1",
"react-markdown": "^8.0.5",
"react-redux": "7.2.1",
"react-select": "3.1.0",
@@ -35,6 +36,7 @@
"@emotion/babel-preset-css-prop": "10.0.27",
"@emotion/core": "10.0.35",
"@types/enzyme": "3.10.6",
+ "@types/enzyme-adapter-react-16": "1.0.9",
"@types/jest": "26.0.14",
"@types/node": "14.11.1",
"@types/react": "16.9.49",
@@ -78,7 +80,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -117,11 +118,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
- "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
@@ -129,10 +132,10 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz",
- "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==",
- "dev": true,
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
+ "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -141,7 +144,6 @@
"version": "7.11.6",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
"integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
- "dev": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.11.6",
@@ -169,26 +171,28 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz",
- "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
+ "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.6",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz",
- "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -198,7 +202,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz",
"integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==",
- "dev": true,
"dependencies": {
"@babel/traverse": "^7.24.7",
"@babel/types": "^7.24.7"
@@ -208,14 +211,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz",
- "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz",
+ "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==",
+ "license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.25.2",
- "@babel/helper-validator-option": "^7.24.8",
- "browserslist": "^4.23.1",
+ "@babel/compat-data": "^7.26.8",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
@@ -227,23 +230,22 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz",
- "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz",
+ "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/helper-replace-supers": "^7.25.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/traverse": "^7.25.4",
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.26.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/traverse": "^7.27.0",
"semver": "^6.3.1"
},
"engines": {
@@ -257,7 +259,6 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -266,7 +267,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz",
"integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==",
- "dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.24.7",
"regexpu-core": "^5.3.1",
@@ -283,30 +283,32 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
- "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
- "dev": true,
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz",
+ "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
- "node_modules/@babel/helper-function-name": {
+ "node_modules/@babel/helper-environment-visitor": {
"version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
- "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
+ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
"dependencies": {
- "@babel/template": "^7.24.7",
"@babel/types": "^7.24.7"
},
"engines": {
@@ -317,7 +319,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
"integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
- "dev": true,
"dependencies": {
"@babel/types": "^7.24.7"
},
@@ -326,40 +327,40 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz",
- "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.8",
- "@babel/types": "^7.24.8"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
- "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz",
- "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==",
- "dev": true,
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.24.7",
- "@babel/helper-simple-access": "^7.24.7",
- "@babel/helper-validator-identifier": "^7.24.7",
- "@babel/traverse": "^7.25.2"
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -369,35 +370,35 @@
}
},
"node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz",
- "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz",
- "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==",
- "dev": true,
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
+ "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz",
- "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
+ "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-wrap-function": "^7.25.0",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-wrap-function": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -407,14 +408,14 @@
}
},
"node_modules/@babel/helper-replace-supers": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz",
- "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==",
- "dev": true,
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz",
+ "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/traverse": "^7.26.5"
},
"engines": {
"node": ">=6.9.0"
@@ -423,116 +424,80 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-simple-access": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
- "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz",
- "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
- "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
- "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
- "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz",
- "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz",
- "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
+ "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
+ "license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz",
- "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
- "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
+ "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.7",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz",
- "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
+ "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.6"
+ "@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -546,7 +511,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz",
"integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.",
- "dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-plugin-utils": "^7.20.2",
@@ -565,7 +529,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
"integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.",
- "dev": true,
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.10.4",
"@babel/helper-plugin-utils": "^7.10.4"
@@ -579,7 +542,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
"integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3"
@@ -591,12 +553,27 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-proposal-export-default-from": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz",
+ "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-proposal-export-namespace-from": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
"integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.9",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
@@ -613,7 +590,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
"integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-json-strings": "^7.8.3"
@@ -630,7 +606,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz",
"integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-logical-assignment-operators instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.20.2",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
@@ -647,7 +622,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
"integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
@@ -664,7 +638,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
"integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
@@ -681,7 +654,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
"integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
@@ -696,7 +668,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
"integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
@@ -713,7 +684,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
"integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4",
"@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
@@ -728,7 +698,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
"integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
- "dev": true,
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -745,7 +714,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
"integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.",
- "dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -761,7 +729,6 @@
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
"integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -773,7 +740,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
"integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -785,7 +751,6 @@
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
"integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.12.13"
},
@@ -797,7 +762,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
"integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -805,11 +769,26 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-export-default-from": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz",
+ "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-export-namespace-from": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.3"
},
@@ -817,11 +796,26 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-flow": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz",
+ "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-import-meta": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
"integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4"
},
@@ -833,7 +827,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -842,12 +835,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz",
- "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -860,7 +853,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
"integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4"
},
@@ -872,7 +864,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
"integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -884,7 +875,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
"integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.10.4"
},
@@ -896,7 +886,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
"integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -908,7 +897,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
"integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -920,7 +908,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
"integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.8.0"
},
@@ -932,7 +919,6 @@
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.14.5"
},
@@ -944,12 +930,12 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz",
- "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -962,7 +948,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz",
"integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -973,11 +958,28 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz",
+ "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-remap-async-to-generator": "^7.25.9",
+ "@babel/traverse": "^7.26.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-async-to-generator": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz",
"integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==",
- "dev": true,
"dependencies": {
"@babel/helper-module-imports": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7",
@@ -994,7 +996,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz",
"integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1006,12 +1007,29 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz",
- "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz",
+ "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.26.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
+ "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1021,18 +1039,16 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz",
- "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
+ "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-compilation-targets": "^7.24.7",
- "@babel/helper-environment-visitor": "^7.24.7",
- "@babel/helper-function-name": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-replace-supers": "^7.24.7",
- "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
"globals": "^11.1.0"
},
"engines": {
@@ -1046,7 +1062,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz",
"integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/template": "^7.24.7"
@@ -1059,12 +1074,12 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz",
- "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
+ "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1077,7 +1092,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
"integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
- "dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1093,7 +1107,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
"integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1108,7 +1121,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz",
"integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==",
- "dev": true,
"dependencies": {
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1120,11 +1132,27 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-flow-strip-types": {
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz",
+ "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/plugin-syntax-flow": "^7.26.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-for-of": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz",
"integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
@@ -1137,14 +1165,14 @@
}
},
"node_modules/@babel/plugin-transform-function-name": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz",
- "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
+ "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.24.7",
- "@babel/helper-function-name": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1154,12 +1182,28 @@
}
},
"node_modules/@babel/plugin-transform-literals": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz",
- "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
+ "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
+ "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1172,7 +1216,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz",
"integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1187,7 +1230,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
"integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
- "dev": true,
"dependencies": {
"@babel/helper-module-transforms": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1200,14 +1242,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz",
- "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==",
- "dev": true,
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
+ "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-simple-access": "^7.24.7"
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1220,7 +1261,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz",
"integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==",
- "dev": true,
"dependencies": {
"@babel/helper-hoist-variables": "^7.24.7",
"@babel/helper-module-transforms": "^7.24.7",
@@ -1238,7 +1278,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
"integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
- "dev": true,
"dependencies": {
"@babel/helper-module-transforms": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1254,7 +1293,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz",
"integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==",
- "dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1270,7 +1308,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
"integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1281,11 +1318,60 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.26.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz",
+ "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.26.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-numeric-separator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
+ "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
+ "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-object-super": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz",
"integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-replace-supers": "^7.24.7"
@@ -1297,13 +1383,81 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
+ "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-parameters": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz",
- "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
+ "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
+ "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
+ "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1316,7 +1470,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz",
"integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1331,7 +1484,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz",
"integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1343,16 +1495,16 @@
}
},
"node_modules/@babel/plugin-transform-react-jsx": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz",
- "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
+ "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-module-imports": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-jsx": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1380,7 +1532,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz",
"integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1395,7 +1546,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz",
"integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1426,7 +1576,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz",
"integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7",
"regenerator-transform": "^0.15.2"
@@ -1442,7 +1591,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
"integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1453,11 +1601,41 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz",
+ "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "babel-plugin-polyfill-corejs2": "^0.4.10",
+ "babel-plugin-polyfill-corejs3": "^0.11.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/@babel/plugin-transform-shorthand-properties": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz",
"integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1472,7 +1650,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz",
"integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
@@ -1488,7 +1665,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz",
"integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1503,7 +1679,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz",
"integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1518,7 +1693,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz",
"integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1530,15 +1704,16 @@
}
},
"node_modules/@babel/plugin-transform-typescript": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz",
- "integrity": "sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz",
+ "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-typescript": "^7.24.7"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.27.0",
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-syntax-typescript": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1551,7 +1726,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
"integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.7"
},
@@ -1566,7 +1740,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz",
"integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==",
- "dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -1601,7 +1774,6 @@
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz",
"integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==",
- "dev": true,
"dependencies": {
"@babel/compat-data": "^7.11.0",
"@babel/helper-compilation-targets": "^7.10.4",
@@ -1676,11 +1848,28 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/preset-flow": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz",
+ "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/preset-modules": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
"integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
@@ -1723,11 +1912,30 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/register": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz",
+ "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "find-cache-dir": "^2.0.0",
+ "make-dir": "^2.1.0",
+ "pirates": "^4.0.6",
+ "source-map-support": "^0.5.16"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/regjsgen": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
- "dev": true
+ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
},
"node_modules/@babel/runtime": {
"version": "7.11.2",
@@ -1738,28 +1946,50 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
- "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
+ "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/parser": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/code-frame": "^7.26.2",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz",
- "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
+ "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.6",
- "@babel/parser": "^7.25.6",
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.27.0",
+ "@babel/parser": "^7.27.0",
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse--for-generate-function-map": {
+ "name": "@babel/traverse",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
+ "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.27.0",
+ "@babel/parser": "^7.27.0",
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1768,13 +1998,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz",
- "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
+ "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.24.8",
- "@babel/helper-validator-identifier": "^7.24.7",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2057,11 +2287,20 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@isaacs/ttlcache": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+ "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
"integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
- "dev": true,
"dependencies": {
"camelcase": "^5.3.1",
"find-up": "^4.1.0",
@@ -2077,7 +2316,6 @@
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
"integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -2312,6 +2550,123 @@
"node": ">=8"
}
},
+ "node_modules/@jest/create-cache-key-function": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
+ "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/create-cache-key-function/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@jest/environment": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
@@ -2508,6 +2863,19 @@
"node": ">=8"
}
},
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/@jest/source-map": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
@@ -2791,6 +3159,17 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -2875,6 +3254,591 @@
"react-native": ">=0.59"
}
},
+ "node_modules/@react-native/assets-registry": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.78.1.tgz",
+ "integrity": "sha512-SegfYQFuut05EQIQIVB/6QMGaxJ29jEtPmzFWJdIp/yc2mmhIq7MfWRjwOe6qbONzIdp6Ca8p835hiGiAGyeKQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/babel-plugin-codegen": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.78.1.tgz",
+ "integrity": "sha512-rD0tnct/yPEtoOc8eeFHIf8ZJJJEzLkmqLs8HZWSkt3w9VYWngqLXZxiDGqv0ngXjunAlC/Hpq+ULMVOvOnByw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.3",
+ "@react-native/codegen": "0.78.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/babel-preset": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.78.1.tgz",
+ "integrity": "sha512-yTVcHmEdNQH4Ju7lhvbiQaGxBpMcalgkBy/IvHowXKk/ex3nY1PolF16/mBG1BrefcUA/rtJpqTtk2Ii+7T/Lw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-proposal-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.24.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.4",
+ "@babel/plugin-transform-async-to-generator": "^7.24.7",
+ "@babel/plugin-transform-block-scoping": "^7.25.0",
+ "@babel/plugin-transform-class-properties": "^7.25.4",
+ "@babel/plugin-transform-classes": "^7.25.4",
+ "@babel/plugin-transform-computed-properties": "^7.24.7",
+ "@babel/plugin-transform-destructuring": "^7.24.8",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.2",
+ "@babel/plugin-transform-for-of": "^7.24.7",
+ "@babel/plugin-transform-function-name": "^7.25.1",
+ "@babel/plugin-transform-literals": "^7.25.2",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-numeric-separator": "^7.24.7",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.7",
+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.8",
+ "@babel/plugin-transform-parameters": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/plugin-transform-private-property-in-object": "^7.24.7",
+ "@babel/plugin-transform-react-display-name": "^7.24.7",
+ "@babel/plugin-transform-react-jsx": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@babel/plugin-transform-regenerator": "^7.24.7",
+ "@babel/plugin-transform-runtime": "^7.24.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.24.7",
+ "@babel/plugin-transform-spread": "^7.24.7",
+ "@babel/plugin-transform-sticky-regex": "^7.24.7",
+ "@babel/plugin-transform-typescript": "^7.25.2",
+ "@babel/plugin-transform-unicode-regex": "^7.24.7",
+ "@babel/template": "^7.25.0",
+ "@react-native/babel-plugin-codegen": "0.78.1",
+ "babel-plugin-syntax-hermes-parser": "0.25.1",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/babel-preset/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@react-native/babel-preset/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/babel-preset/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@react-native/codegen": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.78.1.tgz",
+ "integrity": "sha512-kGG5qAM9JdFtxzUwe7c6CyJbsU2PnaTrtCHA2dF8VEiNX1K3yd9yKPzfkxA7HPvmHoAn3ga1941O79BStWcM3A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.25.3",
+ "glob": "^7.1.1",
+ "hermes-parser": "0.25.1",
+ "invariant": "^2.2.4",
+ "jscodeshift": "^17.0.0",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@babel/preset-env": "^7.1.6"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/codegen/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/codegen/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@react-native/codegen/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.78.1.tgz",
+ "integrity": "sha512-S6vF4oWpFqThpt/dBLrqLQw5ED2M1kg5mVtiL6ZqpoYIg+/e0vg7LZ8EXNbcdMDH4obRnm2xbOd+qlC7mOzNBg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@react-native/dev-middleware": "0.78.1",
+ "@react-native/metro-babel-transformer": "0.78.1",
+ "chalk": "^4.0.0",
+ "debug": "^2.2.0",
+ "invariant": "^2.2.4",
+ "metro": "^0.81.0",
+ "metro-config": "^0.81.0",
+ "metro-core": "^0.81.0",
+ "readline": "^1.3.0",
+ "semver": "^7.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@react-native-community/cli": "*"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-community/cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@react-native/community-cli-plugin/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@react-native/debugger-frontend": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.78.1.tgz",
+ "integrity": "sha512-xev/B++QLxSDpEBWsc74GyCuq9XOHYTBwcGSpsuhOJDUha6WZIbEEvZe3LpVW+OiFso4oGIdnVSQntwippZdWw==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/dev-middleware": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.78.1.tgz",
+ "integrity": "sha512-l8p7/dXa1vWPOdj0iuACkex8lgbLpYyPZ3QXGkocMcpl0bQ24K7hf3Bj02tfptP5PAm16b2RuEi04sjIGHUzzg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.78.1",
+ "chrome-launcher": "^0.15.2",
+ "chromium-edge-launcher": "^0.2.0",
+ "connect": "^3.6.5",
+ "debug": "^2.2.0",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "open": "^7.0.3",
+ "selfsigned": "^2.4.1",
+ "serve-static": "^1.16.2",
+ "ws": "^6.2.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/dev-middleware/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "node_modules/@react-native/gradle-plugin": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.78.1.tgz",
+ "integrity": "sha512-v8GJU+8DzQDWO3iuTFI1nbuQ/kzuqbXv07VVtSIMLbdofHzuuQT14DGBacBkrIDKBDTVaBGAc/baDNsyxCghng==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/js-polyfills": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.78.1.tgz",
+ "integrity": "sha512-Ogcv4QOA1o3IyErrf/i4cDnP+nfNcIfGTgw6iNQyAPry1xjPOz4ziajskLpWG/3ADeneIZuyZppKB4A28rZSvg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@react-native/metro-babel-transformer": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.78.1.tgz",
+ "integrity": "sha512-jQWf69D+QTMvSZSWLR+cr3VUF16rGB6sbD+bItD8Czdfn3hajzfMoHJTkVFP7991cjK5sIVekNiQIObou8JSQw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@react-native/babel-preset": "0.78.1",
+ "hermes-parser": "0.25.1",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@babel/core": "*"
+ }
+ },
+ "node_modules/@react-native/metro-babel-transformer/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@react-native/metro-babel-transformer/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@react-native/metro-babel-transformer/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@react-native/normalize-colors": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.78.1.tgz",
+ "integrity": "sha512-h4wARnY4iBFgigN1NjnaKFtcegWwQyE9+CEBVG4nHmwMtr8lZBmc7ZKIM6hUc6lxqY/ugHg48aSQSynss7mJUg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
@@ -2894,6 +3858,13 @@
"react": ">=16.8.0"
}
},
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/@sinonjs/commons": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
@@ -2925,7 +3896,6 @@
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
"dependencies": {
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7",
@@ -2938,7 +3908,6 @@
"version": "7.6.8",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
"integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
- "dev": true,
"dependencies": {
"@babel/types": "^7.0.0"
}
@@ -2947,7 +3916,6 @@
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
"dependencies": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0"
@@ -2957,7 +3925,6 @@
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
"integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
- "dev": true,
"dependencies": {
"@babel/types": "^7.20.7"
}
@@ -2998,11 +3965,19 @@
"@types/react": "*"
}
},
+ "node_modules/@types/enzyme-adapter-react-16": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.9.tgz",
+ "integrity": "sha512-z24MMxGtUL8HhXdye3tWzjp+19QTsABqLaX2oOZpxMPHRJgLfahQmOeTTrEBQd9ogW20+UmPBXD9j+XOasFHvw==",
+ "dev": true,
+ "dependencies": {
+ "@types/enzyme": "*"
+ }
+ },
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
"integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
- "dev": true,
"dependencies": {
"@types/node": "*"
}
@@ -3043,14 +4018,12 @@
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
- "dev": true
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="
},
"node_modules/@types/istanbul-lib-report": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
- "dev": true,
"dependencies": {
"@types/istanbul-lib-coverage": "*"
}
@@ -3059,7 +4032,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
- "dev": true,
"dependencies": {
"@types/istanbul-lib-report": "*"
}
@@ -3102,8 +4074,17 @@
"node_modules/@types/node": {
"version": "14.11.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.1.tgz",
- "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw==",
- "dev": true
+ "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw=="
+ },
+ "node_modules/@types/node-forge": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
+ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
},
"node_modules/@types/normalize-package-data": {
"version": "2.4.4",
@@ -3216,8 +4197,7 @@
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
- "dev": true
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
"node_modules/@types/unist": {
"version": "2.0.10",
@@ -3241,8 +4221,7 @@
"node_modules/@types/yargs-parser": {
"version": "21.0.3",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
- "dev": true
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "4.1.1",
@@ -3619,6 +4598,33 @@
"deprecated": "Use your platform's native atob() and btoa() methods instead",
"dev": true
},
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@@ -3734,6 +4740,13 @@
"ajv": "^6.9.1"
}
},
+ "node_modules/anser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
+ "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -3762,7 +4775,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -3771,6 +4783,7 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
@@ -3782,7 +4795,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -3801,7 +4813,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
"dependencies": {
"sprintf-js": "~1.0.2"
}
@@ -3990,6 +5001,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
@@ -4041,6 +5059,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ast-types": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
+ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -4063,6 +5094,13 @@
],
"optional": true
},
+ "node_modules/async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -4267,7 +5305,6 @@
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
"integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
- "dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@istanbuljs/load-nyc-config": "^1.0.0",
@@ -4304,11 +5341,83 @@
"resolve": "^1.12.0"
}
},
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz",
+ "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-define-polyfill-provider": "^0.6.4",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz",
+ "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.3",
+ "core-js-compat": "^3.40.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz",
+ "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-syntax-hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-parser": "0.25.1"
+ }
+ },
"node_modules/babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
},
+ "node_modules/babel-plugin-transform-flow-enums": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz",
+ "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/plugin-syntax-flow": "^7.12.1"
+ }
+ },
"node_modules/babel-plugin-typescript-to-proptypes": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/babel-plugin-typescript-to-proptypes/-/babel-plugin-typescript-to-proptypes-1.4.1.tgz",
@@ -4332,7 +5441,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
"integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
- "dev": true,
"dependencies": {
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-bigint": "^7.8.3",
@@ -4400,8 +5508,7 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base": {
"version": "0.11.2",
@@ -4505,7 +5612,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4515,7 +5621,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
"dependencies": {
"fill-range": "^7.1.1"
},
@@ -4613,10 +5718,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
- "dev": true,
+ "version": "4.24.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
+ "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"funding": [
{
"type": "opencollective",
@@ -4631,11 +5735,12 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
- "node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "caniuse-lite": "^1.0.30001688",
+ "electron-to-chromium": "^1.5.73",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@@ -4648,7 +5753,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
"integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
- "dev": true,
"dependencies": {
"node-int64": "^0.4.0"
}
@@ -4667,8 +5771,7 @@
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/buffer-xor": {
"version": "1.0.3",
@@ -4744,6 +5847,42 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "callsites": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/caller-callsite/node_modules/callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "caller-callsite": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -4756,16 +5895,14 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001660",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz",
- "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==",
- "dev": true,
+ "version": "1.0.30001707",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz",
+ "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==",
"funding": [
{
"type": "opencollective",
@@ -4779,7 +5916,8 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ]
+ ],
+ "license": "CC-BY-4.0"
},
"node_modules/capture-exit": {
"version": "2.0.0",
@@ -4797,6 +5935,7 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -4892,6 +6031,38 @@
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"dev": true
},
+ "node_modules/chrome-launcher": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+ "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0"
+ },
+ "bin": {
+ "print-chrome-path": "bin/print-chrome-path.js"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
+ "node_modules/chrome-launcher/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/chrome-trace-event": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
@@ -4901,11 +6072,68 @@
"node": ">=6.0"
}
},
+ "node_modules/chromium-edge-launcher": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
+ "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0",
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chromium-edge-launcher/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/chromium-edge-launcher/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
- "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
- "dev": true
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
},
"node_modules/cipher-base": {
"version": "1.0.4",
@@ -5016,6 +6244,21 @@
"node": ">=0.8"
}
},
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -5049,6 +6292,7 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
"dependencies": {
"color-name": "1.1.3"
}
@@ -5056,7 +6300,8 @@
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
@@ -5090,8 +6335,7 @@
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
- "dev": true
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
},
"node_modules/component-emitter": {
"version": "1.2.1",
@@ -5101,8 +6345,7 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/concat-stream": {
"version": "1.6.2",
@@ -5119,6 +6362,39 @@
"typedarray": "^0.0.6"
}
},
+ "node_modules/connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/connect/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/connect/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/console-browserify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@@ -5181,12 +6457,12 @@
}
},
"node_modules/core-js-compat": {
- "version": "3.38.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
- "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
- "dev": true,
+ "version": "3.41.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz",
+ "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==",
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.23.3"
+ "browserslist": "^4.24.4"
},
"funding": {
"type": "opencollective",
@@ -5634,6 +6910,16 @@
"node": ">=0.4.0"
}
},
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -5652,6 +6938,17 @@
"minimalistic-assert": "^1.0.0"
}
},
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
"node_modules/detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
@@ -5852,17 +7149,25 @@
"stream-shift": "^1.0.0"
}
},
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/electron-to-chromium": {
- "version": "1.5.23",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.23.tgz",
- "integrity": "sha512-mBhODedOXg4v5QWwl21DjM5amzjmI1zw9EPrPK/5Wx7C8jt33bpZNrC7OhHUG3pxRtbLpr3W2dXT+Ph1SsfRZA==",
- "dev": true
+ "version": "1.5.123",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz",
+ "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==",
+ "license": "ISC"
},
"node_modules/elliptic": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
- "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
+ "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
@@ -5906,6 +7211,16 @@
"node": ">= 4"
}
},
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -6102,6 +7417,16 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.23.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
@@ -6242,14 +7567,21 @@
}
},
"node_modules/escalade": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
- "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
- "dev": true,
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -6783,7 +8115,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
@@ -6847,11 +8178,30 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@@ -7050,6 +8400,13 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/exponential-backoff": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
+ "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -7145,8 +8502,7 @@
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
@@ -7167,7 +8523,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
"integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
- "dev": true,
"dependencies": {
"bser": "2.1.1"
}
@@ -7236,7 +8591,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -7244,11 +8598,46 @@
"node": ">=8"
}
},
+ "node_modules/finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/find-cache-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
"dependencies": {
"commondir": "^1.0.1",
"make-dir": "^2.0.0",
@@ -7267,7 +8656,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
@@ -7447,6 +8835,23 @@
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
+ "node_modules/flow-enums-runtime": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+ "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/flow-parser": {
+ "version": "0.265.3",
+ "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.265.3.tgz",
+ "integrity": "sha512-YH50TTYgnzDnuaZlAxLYQ0UZtXSbbizMO3OCpoY8obvLReJmvQ5UUW22efsC3SZJmze/tATfQ0PtkKul2XwWBw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/flush-write-stream": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@@ -7501,6 +8906,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/from2": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
@@ -7533,14 +8948,12 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -7595,7 +9008,6 @@
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -7604,7 +9016,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -7632,7 +9043,6 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "dev": true,
"engines": {
"node": ">=8.0.0"
}
@@ -7708,7 +9118,6 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -7888,6 +9297,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
"engines": {
"node": ">=4"
}
@@ -8055,6 +9465,23 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
"node_modules/history": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
@@ -8151,6 +9578,33 @@
"entities": "^4.4.0"
}
},
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-errors/node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
@@ -8263,6 +9717,22 @@
"node": ">= 4"
}
},
+ "node_modules/image-size": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
+ "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "queue": "6.0.2"
+ },
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
"node_modules/immutable": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
@@ -8342,7 +9812,6 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -8351,8 +9820,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ini": {
"version": "1.3.8",
@@ -8596,12 +10064,20 @@
"node": ">= 0.4"
}
},
+ "node_modules/is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
- "dev": true,
- "optional": true,
"bin": {
"is-docker": "cli.js"
},
@@ -8679,7 +10155,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -8714,7 +10189,6 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
- "dev": true,
"dependencies": {
"isobject": "^3.0.1"
},
@@ -8853,8 +10327,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
- "dev": true,
- "optional": true,
"dependencies": {
"is-docker": "^2.0.0"
},
@@ -8878,7 +10350,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8887,7 +10358,6 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -8896,7 +10366,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
"integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
- "dev": true,
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/parser": "^7.14.7",
@@ -8912,7 +10381,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz",
"integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==",
- "dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.7",
@@ -8941,14 +10409,12 @@
"node_modules/istanbul-lib-instrument/node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"node_modules/istanbul-lib-instrument/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -11042,7 +12508,6 @@
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dev": true,
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -11056,6 +12521,149 @@
"resolved": "https://registry.npmjs.org/jsan/-/jsan-3.1.14.tgz",
"integrity": "sha512-wStfgOJqMv4QKktuH273f5fyi3D3vy2pHOiSDGPvpcS/q+wb/M7AK3vkCcaHbkZxDOlDU/lDJgccygKSG2OhtA=="
},
+ "node_modules/jsc-safe-url": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+ "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+ "license": "0BSD",
+ "peer": true
+ },
+ "node_modules/jscodeshift": {
+ "version": "17.3.0",
+ "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.3.0.tgz",
+ "integrity": "sha512-LjFrGOIORqXBU+jwfC9nbkjmQfFldtMIoS6d9z2LG/lkmyNXsJAySPT+2SWXJEoE68/bCWcxKpXH37npftgmow==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/plugin-transform-class-properties": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/preset-flow": "^7.24.7",
+ "@babel/preset-typescript": "^7.24.7",
+ "@babel/register": "^7.24.6",
+ "flow-parser": "0.*",
+ "graceful-fs": "^4.2.4",
+ "micromatch": "^4.0.7",
+ "neo-async": "^2.5.0",
+ "picocolors": "^1.0.1",
+ "recast": "^0.23.11",
+ "tmp": "^0.2.3",
+ "write-file-atomic": "^5.0.1"
+ },
+ "bin": {
+ "jscodeshift": "bin/jscodeshift.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "@babel/preset-env": "^7.1.6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/preset-env": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jscodeshift/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/@babel/preset-typescript": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz",
+ "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.26.3",
+ "@babel/plugin-transform-typescript": "^7.27.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/jscodeshift/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/jscodeshift/node_modules/write-file-atomic": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
+ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@@ -11121,21 +12729,21 @@
"dev": true
},
"node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
"node_modules/json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
@@ -11163,7 +12771,6 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
"bin": {
"json5": "lib/cli.js"
},
@@ -11188,7 +12795,6 @@
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11215,7 +12821,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -11224,7 +12829,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
"integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
- "dev": true,
"dependencies": {
"leven": "^3.1.0"
},
@@ -11245,6 +12849,34 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lighthouse-logger": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+ "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+ "license": "Apache-2.0",
+ "peer": true,
+ "dependencies": {
+ "debug": "^2.6.9",
+ "marky": "^1.2.2"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/lighthouse-logger/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -11339,7 +12971,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
"dependencies": {
"p-locate": "^4.1.0"
},
@@ -11357,6 +12988,13 @@
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/lodash.escape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
@@ -11375,6 +13013,13 @@
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
"dev": true
},
+ "node_modules/lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -11390,7 +13035,6 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
"dependencies": {
"yallist": "^3.0.2"
}
@@ -11399,7 +13043,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
- "dev": true,
"dependencies": {
"pify": "^4.0.1",
"semver": "^5.6.0"
@@ -11412,7 +13055,6 @@
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
"integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
"dependencies": {
"tmpl": "1.0.5"
}
@@ -11438,6 +13080,13 @@
"node": ">=0.10.0"
}
},
+ "node_modules/marky": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz",
+ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
"node_modules/mattermost-redux": {
"version": "5.33.1",
"resolved": "https://registry.npmjs.org/mattermost-redux/-/mattermost-redux-5.33.1.tgz",
@@ -11577,8 +13226,7 @@
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
},
"node_modules/merge2": {
"version": "1.4.1",
@@ -11589,262 +13237,1542 @@
"node": ">= 8"
}
},
- "node_modules/micromark": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz",
- "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.4.tgz",
+ "integrity": "sha512-78f0aBNPuwXW7GFnSc+Y0vZhbuQorXxdgqQfvSRqcSizqwg9cwF27I05h47tL8AzQcizS1JZncvq4xf5u/Qykw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "@types/debug": "^4.0.0",
- "debug": "^4.0.0",
- "decode-named-character-reference": "^1.0.0",
- "micromark-core-commonmark": "^1.0.1",
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-combine-extensions": "^1.0.0",
- "micromark-util-decode-numeric-character-reference": "^1.0.0",
- "micromark-util-encode": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-resolve-all": "^1.0.0",
- "micromark-util-sanitize-uri": "^1.0.0",
- "micromark-util-subtokenize": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.1",
- "uvu": "^0.5.0"
+ "@babel/code-frame": "^7.24.7",
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "accepts": "^1.3.7",
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "connect": "^3.6.5",
+ "debug": "^2.2.0",
+ "error-stack-parser": "^2.0.6",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "hermes-parser": "0.25.1",
+ "image-size": "^1.0.2",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "jsc-safe-url": "^0.2.2",
+ "lodash.throttle": "^4.1.1",
+ "metro-babel-transformer": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-cache-key": "0.81.4",
+ "metro-config": "0.81.4",
+ "metro-core": "0.81.4",
+ "metro-file-map": "0.81.4",
+ "metro-resolver": "0.81.4",
+ "metro-runtime": "0.81.4",
+ "metro-source-map": "0.81.4",
+ "metro-symbolicate": "0.81.4",
+ "metro-transform-plugins": "0.81.4",
+ "metro-transform-worker": "0.81.4",
+ "mime-types": "^2.1.27",
+ "nullthrows": "^1.1.1",
+ "serialize-error": "^2.1.0",
+ "source-map": "^0.5.6",
+ "throat": "^5.0.0",
+ "ws": "^7.5.10",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "metro": "src/cli.js"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-core-commonmark": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz",
- "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-babel-transformer": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.4.tgz",
+ "integrity": "sha512-WW0yswWrW+eTVK9sYD+b1HwWOiUlZlUoomiw9TIOk0C+dh2V90Wttn/8g62kYi0Y4i+cJfISerB2LbV4nuRGTA==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "decode-named-character-reference": "^1.0.0",
- "micromark-factory-destination": "^1.0.0",
- "micromark-factory-label": "^1.0.0",
- "micromark-factory-space": "^1.0.0",
- "micromark-factory-title": "^1.0.0",
- "micromark-factory-whitespace": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-classify-character": "^1.0.0",
- "micromark-util-html-tag-name": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-resolve-all": "^1.0.0",
- "micromark-util-subtokenize": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.1",
- "uvu": "^0.5.0"
+ "@babel/core": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "hermes-parser": "0.25.1",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-factory-destination": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
- "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-babel-transformer/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
}
},
- "node_modules/micromark-factory-label": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz",
- "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0"
+ "node_modules/metro-babel-transformer/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-babel-transformer/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/micromark-factory-space": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
- "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-cache": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.4.tgz",
+ "integrity": "sha512-sxCPH3gowDxazSaZZrwdNPEpnxR8UeXDnvPjBF9+5btDBNN2DpWvDAXPvrohkYkFImhc0LajS2V7eOXvu9PnvQ==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "exponential-backoff": "^3.1.1",
+ "flow-enums-runtime": "^0.0.6",
+ "metro-core": "0.81.4"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-factory-title": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz",
- "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-cache-key": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.4.tgz",
+ "integrity": "sha512-3SaWQybvf1ivasjBegIxzVKLJzOpcz+KsnGwXFOYADQq0VN4cnM7tT+u2jkOhk6yJiiO1WIjl68hqyMOQJRRLg==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-factory-whitespace": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz",
- "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-config": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.4.tgz",
+ "integrity": "sha512-QnhMy3bRiuimCTy7oi5Ug60javrSa3lPh0gpMAspQZHY9h6y86jwHtZPLtlj8hdWQESIlrbeL8inMSF6qI/i9Q==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "connect": "^3.6.5",
+ "cosmiconfig": "^5.0.5",
+ "flow-enums-runtime": "^0.0.6",
+ "jest-validate": "^29.7.0",
+ "metro": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-core": "0.81.4",
+ "metro-runtime": "0.81.4"
+ },
+ "engines": {
+ "node": ">=18.18"
}
},
- "node_modules/micromark-util-character": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz",
- "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-config/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/micromark-util-chunked": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz",
- "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-config/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-util-symbol": "^1.0.0"
+ "@types/yargs-parser": "*"
}
},
- "node_modules/micromark-util-classify-character": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz",
- "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
+ "node_modules/metro-config/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/micromark-util-combine-extensions": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz",
- "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-types": "^1.0.0"
+ "node_modules/metro-config/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/micromark-util-decode-numeric-character-reference": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz",
- "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
+ "node_modules/metro-config/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/metro-config/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/metro-config/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-config/node_modules/cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro-config/node_modules/import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-config/node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-config/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-config/node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/metro-config/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-config/node_modules/resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/metro-config/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro-core": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.4.tgz",
+ "integrity": "sha512-GdL4IgmgJhrMA/rTy2lRqXKeXfC77Rg+uvhUEkbhyfj/oz7PrdSgvIFzziapjdHwk1XYq0KyFh/CcVm8ZawG6A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "lodash.throttle": "^4.1.1",
+ "metro-resolver": "0.81.4"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-file-map": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.4.tgz",
+ "integrity": "sha512-qUIBzkiqOi3qEuscu4cJ83OYQ4hVzjON19FAySWqYys9GKCmxlKa7LkmwqdpBso6lQl+JXZ7nCacX90w5wQvPA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "^2.2.0",
+ "fb-watchman": "^2.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "nullthrows": "^1.1.1",
+ "walker": "^1.0.7"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-file-map/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro-file-map/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-file-map/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/metro-minify-terser": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.4.tgz",
+ "integrity": "sha512-oVvq/AGvqmbhuijJDZZ9npeWzaVyeBwQKtdlnjcQ9fH7nR15RiBr5y2zTdgTEdynqOIb1Kc16l8CQIUSzOWVFA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "terser": "^5.15.0"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-minify-terser/node_modules/acorn": {
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/metro-minify-terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-minify-terser/node_modules/terser": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
+ "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/metro-resolver": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.4.tgz",
+ "integrity": "sha512-Ng7G2mXjSExMeRzj6GC19G6IJ0mfIbOLgjArsMWJgtt9ViZiluCwgWsMW9juBC5NSwjJxUMK2x6pC5NIMFLiHA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-runtime": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.4.tgz",
+ "integrity": "sha512-fBoRgqkF69CwyPtBNxlDi5ha26Zc8f85n2THXYoh13Jn/Bkg8KIDCdKPp/A1BbSeNnkH/++H2EIIfnmaff4uRg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/runtime": "^7.25.0",
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-runtime/node_modules/@babel/runtime": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/metro-runtime/node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-source-map": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.4.tgz",
+ "integrity": "sha512-IOwVQ7mLqoqvsL70RZtl1EyE3f9jp43kVsAsb/B/zoWmu0/k4mwEhGLTxmjdXRkLJqPqPrh7WmFChAEf9trW4Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.3",
+ "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-symbolicate": "0.81.4",
+ "nullthrows": "^1.1.1",
+ "ob1": "0.81.4",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-symbolicate": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.4.tgz",
+ "integrity": "sha512-rWxTmYVN6/BOSaMDUHT8HgCuRf6acd0AjHkenYlHpmgxg7dqdnAG1hLq999q2XpW5rX+cMamZD5W5Ez2LqGaag==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-source-map": "0.81.4",
+ "nullthrows": "^1.1.1",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
+ },
+ "bin": {
+ "metro-symbolicate": "src/index.js"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-transform-plugins": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.4.tgz",
+ "integrity": "sha512-nlP069nDXm4v28vbll4QLApAlvVtlB66rP6h+ml8Q/CCQCPBXu2JLaoxUmkIOJQjLhMRUcgTyQHq+TXWJhydOQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "flow-enums-runtime": "^0.0.6",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-transform-plugins/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/metro-transform-plugins/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-transform-plugins/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/metro-transform-worker": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.4.tgz",
+ "integrity": "sha512-lKAeRZ8EUMtx2cA/Y4KvICr9bIr5SE03iK3lm+l9wyn2lkjLUuPjYVep159inLeDqC6AtSubsA8MZLziP7c03g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "metro": "0.81.4",
+ "metro-babel-transformer": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-cache-key": "0.81.4",
+ "metro-minify-terser": "0.81.4",
+ "metro-source-map": "0.81.4",
+ "metro-transform-plugins": "0.81.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
+ "node_modules/metro-transform-worker/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/metro-transform-worker/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro-transform-worker/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/metro/node_modules/@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/metro/node_modules/@babel/core/node_modules/debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/metro/node_modules/@babel/core/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/metro/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/metro/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/metro/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/metro/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/metro/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/metro/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro/node_modules/jest-util/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro/node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/metro/node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/metro/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/metro/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/metro/node_modules/serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/metro/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/metro/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/metro/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/metro/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/metro/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/micromark": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz",
+ "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-core-commonmark": "^1.0.1",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-combine-extensions": "^1.0.0",
+ "micromark-util-decode-numeric-character-reference": "^1.0.0",
+ "micromark-util-encode": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-resolve-all": "^1.0.0",
+ "micromark-util-sanitize-uri": "^1.0.0",
+ "micromark-util-subtokenize": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.1",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz",
+ "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-factory-destination": "^1.0.0",
+ "micromark-factory-label": "^1.0.0",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-factory-title": "^1.0.0",
+ "micromark-factory-whitespace": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-classify-character": "^1.0.0",
+ "micromark-util-html-tag-name": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-resolve-all": "^1.0.0",
+ "micromark-util-subtokenize": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.1",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-factory-destination": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
+ "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-label": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz",
+ "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-factory-space": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
+ "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-title": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz",
+ "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-whitespace": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz",
+ "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz",
+ "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-chunked": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz",
+ "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-classify-character": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz",
+ "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz",
+ "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz",
+ "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
"url": "https://opencollective.com/unified"
}
],
@@ -12014,7 +14942,6 @@
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
- "dev": true,
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@@ -12042,6 +14969,19 @@
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"dev": true
},
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -12086,7 +15026,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -12270,11 +15209,20 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
"node_modules/nice-try": {
"version": "1.0.5",
@@ -12320,11 +15268,20 @@
"webidl-conversions": "^3.0.0"
}
},
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "license": "(BSD-3-Clause OR GPL-2.0)",
+ "peer": true,
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
- "dev": true
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="
},
"node_modules/node-libs-browser": {
"version": "2.2.1",
@@ -12417,10 +15374,10 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
- "dev": true
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "license": "MIT"
},
"node_modules/normalize-package-data": {
"version": "2.5.0",
@@ -12438,7 +15395,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -12467,12 +15423,32 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/nullthrows": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
+ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/nwsapi": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz",
"integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==",
"dev": true
},
+ "node_modules/ob1": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.4.tgz",
+ "integrity": "sha512-EZLYM8hfPraC2SYOR5EWLFAPV5e6g+p83m2Jth9bzCpFxP1NDQJYXdmXRB2bfbaWQSmm6NkIQlbzk7uU5lLfgg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "engines": {
+ "node": ">=18.18"
+ }
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -12666,11 +15642,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
"dependencies": {
"wrappy": "1"
}
@@ -12690,6 +15678,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -12738,7 +15743,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
@@ -12753,7 +15757,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
"dependencies": {
"p-limit": "^2.2.0"
},
@@ -12765,7 +15768,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -12881,6 +15883,16 @@
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -12907,7 +15919,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -12916,7 +15927,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -12965,15 +15975,15 @@
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -12985,7 +15995,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -12994,7 +16003,6 @@
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -13003,7 +16011,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
"dependencies": {
"find-up": "^3.0.0"
},
@@ -13015,7 +16022,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
"dependencies": {
"locate-path": "^3.0.0"
},
@@ -13027,7 +16033,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
"dependencies": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
@@ -13040,7 +16045,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
"dependencies": {
"p-limit": "^2.0.0"
},
@@ -13052,7 +16056,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -13321,6 +16324,16 @@
"node": ">=0.4.0"
}
},
+ "node_modules/promise": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
+ "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "asap": "~2.0.6"
+ }
+ },
"node_modules/promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@@ -13419,292 +16432,1027 @@
"safe-buffer": "^5.1.2"
}
},
- "node_modules/public-encrypt/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
- },
- "node_modules/pump": {
+ "node_modules/public-encrypt/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "dependencies": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "node_modules/pumpify/node_modules/pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
+ "dev": true
+ },
+ "node_modules/qs": {
+ "version": "6.12.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
+ "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
+ "dev": true,
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
+ "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true
+ },
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "dependencies": {
+ "performance-now": "^2.1.0"
+ }
+ },
+ "node_modules/railroad-diagrams": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+ "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+ "dev": true
+ },
+ "node_modules/randexp": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+ "dev": true,
+ "dependencies": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/react": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
+ "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-bootstrap": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.3.0.tgz",
+ "integrity": "sha512-GYj0c6FO9mx7DaO8Xyz2zs0IcQ6CGCtM3O6/feIoCaG4N8B0+l4eqL7stlMcLpqO4d8NG2PoMO/AbUOD+MO7mg==",
+ "dependencies": {
+ "@babel/runtime": "^7.4.2",
+ "@restart/context": "^2.1.4",
+ "@restart/hooks": "^0.3.21",
+ "@types/classnames": "^2.2.10",
+ "@types/invariant": "^2.2.33",
+ "@types/prop-types": "^15.7.3",
+ "@types/react": "^16.9.35",
+ "@types/react-transition-group": "^4.4.0",
+ "@types/warning": "^3.0.0",
+ "classnames": "^2.2.6",
+ "dom-helpers": "^5.1.2",
+ "invariant": "^2.2.4",
+ "prop-types": "^15.7.2",
+ "prop-types-extra": "^1.1.0",
+ "react-overlays": "^4.1.0",
+ "react-transition-group": "^4.4.1",
+ "uncontrollable": "^7.0.0",
+ "warning": "^4.0.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/react-custom-scrollbars": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz",
+ "integrity": "sha512-VtJTUvZ7kPh/auZWIbBRceGPkE30XBYe+HktFxuMWBR2eVQQ+Ur6yFJMoaYcNpyGq22uYJ9Wx4UAEcC0K+LNPQ==",
+ "dependencies": {
+ "dom-css": "^2.0.0",
+ "prop-types": "^15.5.10",
+ "raf": "^3.1.0"
+ },
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16.0.0",
+ "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0"
+ }
+ },
+ "node_modules/react-devtools-core": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.1.tgz",
+ "integrity": "sha512-TFo1MEnkqE6hzAbaztnyR5uLTMoz6wnEWwWBsCUzNt+sVXJycuRJdDqvL078M4/h65BI/YO5XWTaxZDWVsW0fw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "shell-quote": "^1.6.1",
+ "ws": "^7"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
+ "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "scheduler": "^0.19.1"
+ },
+ "peerDependencies": {
+ "react": "^16.13.1"
+ }
+ },
+ "node_modules/react-input-autosize": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
+ "integrity": "sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==",
+ "dependencies": {
+ "prop-types": "^15.5.8"
+ },
+ "peerDependencies": {
+ "react": "^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0"
+ }
+ },
+ "node_modules/react-intl": {
+ "version": "6.6.8",
+ "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.8.tgz",
+ "integrity": "sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==",
+ "dev": true,
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.0.0",
+ "@formatjs/icu-messageformat-parser": "2.7.8",
+ "@formatjs/intl": "2.10.4",
+ "@formatjs/intl-displaynames": "6.6.8",
+ "@formatjs/intl-listformat": "7.5.7",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/react": "16 || 17 || 18",
+ "hoist-non-react-statics": "^3.3.2",
+ "intl-messageformat": "10.5.14",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "react": "^16.6.0 || 17 || 18",
+ "typescript": "^4.7 || 5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "node_modules/react-markdown": {
+ "version": "8.0.7",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz",
+ "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "@types/prop-types": "^15.0.0",
+ "@types/unist": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^2.0.0",
+ "prop-types": "^15.0.0",
+ "property-information": "^6.0.0",
+ "react-is": "^18.0.0",
+ "remark-parse": "^10.0.0",
+ "remark-rehype": "^10.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-object": "^0.4.0",
+ "unified": "^10.0.0",
+ "unist-util-visit": "^4.0.0",
+ "vfile": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16",
+ "react": ">=16"
+ }
+ },
+ "node_modules/react-markdown/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/react-native": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.78.1.tgz",
+ "integrity": "sha512-3CK/xxX02GeeVFyrXbsHvREZFVaXwHW43Km/EdYITn5G32cccWTGaqY9QdPddEBLw5O3BPip3LHbR1SywE0cpA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/create-cache-key-function": "^29.6.3",
+ "@react-native/assets-registry": "0.78.1",
+ "@react-native/codegen": "0.78.1",
+ "@react-native/community-cli-plugin": "0.78.1",
+ "@react-native/gradle-plugin": "0.78.1",
+ "@react-native/js-polyfills": "0.78.1",
+ "@react-native/normalize-colors": "0.78.1",
+ "@react-native/virtualized-lists": "0.78.1",
+ "abort-controller": "^3.0.0",
+ "anser": "^1.4.9",
+ "ansi-regex": "^5.0.0",
+ "babel-jest": "^29.7.0",
+ "babel-plugin-syntax-hermes-parser": "0.25.1",
+ "base64-js": "^1.5.1",
+ "chalk": "^4.0.0",
+ "commander": "^12.0.0",
+ "event-target-shim": "^5.0.1",
+ "flow-enums-runtime": "^0.0.6",
+ "glob": "^7.1.1",
+ "invariant": "^2.2.4",
+ "jest-environment-node": "^29.6.3",
+ "memoize-one": "^5.0.0",
+ "metro-runtime": "^0.81.0",
+ "metro-source-map": "^0.81.0",
+ "nullthrows": "^1.1.1",
+ "pretty-format": "^29.7.0",
+ "promise": "^8.3.0",
+ "react-devtools-core": "^6.0.1",
+ "react-refresh": "^0.14.0",
+ "regenerator-runtime": "^0.13.2",
+ "scheduler": "0.25.0",
+ "semver": "^7.1.3",
+ "stacktrace-parser": "^0.1.10",
+ "whatwg-fetch": "^3.0.0",
+ "ws": "^6.2.3",
+ "yargs": "^17.6.2"
+ },
+ "bin": {
+ "react-native": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.0.0",
+ "react": "^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-native/node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/@react-native/virtualized-lists": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.78.1.tgz",
+ "integrity": "sha512-v0jqDNMFXpnRnSlkDVvwNxXgPhifzzTFlxTSnHj9erKJsKpE26gSU5qB4hmJkEsscLG/ygdJ1c88aqinSh/wRA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^19.0.0",
+ "react": "*",
+ "react-native": "*"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-native/node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/react-native/node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/react-native/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/react-native/node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/react-native/node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/react-native/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/react-native/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/react-native/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/react-native/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-native/node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/react-native/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-native/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-native/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/react-native/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dev": true,
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
- "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "duplexify": "^3.6.0",
- "inherits": "^2.0.3",
- "pump": "^2.0.0"
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/pumpify/node_modules/pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
}
},
- "node_modules/punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
- "dev": true
- },
- "node_modules/qs": {
- "version": "6.12.1",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz",
- "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "side-channel": "^1.0.6"
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/querystring": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
- "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
- "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "node_modules/react-native/node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
"engines": {
- "node": ">=0.4.x"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/querystring-es3": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
- "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "license": "MIT",
+ "peer": true,
"engines": {
- "node": ">=0.4.x"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
- "dev": true
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/raf": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
- "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "node_modules/react-native/node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "performance-now": "^2.1.0"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/railroad-diagrams": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
- "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
- "dev": true
- },
- "node_modules/randexp": {
- "version": "0.4.6",
- "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
- "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "discontinuous-range": "1.0.0",
- "ret": "~0.1.10"
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
},
"engines": {
- "node": ">=0.12"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
+ "node_modules/react-native/node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "safe-buffer": "^5.1.0"
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/randomfill": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
- "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
- "dev": true,
+ "node_modules/react-native/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "randombytes": "^2.0.5",
- "safe-buffer": "^5.1.0"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/react": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
- "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
- "dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1",
- "prop-types": "^15.6.2"
+ "node_modules/react-native/node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/react-native/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-native/node_modules/scheduler": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
+ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-native/node_modules/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "license": "ISC",
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10"
}
},
- "node_modules/react-bootstrap": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-1.3.0.tgz",
- "integrity": "sha512-GYj0c6FO9mx7DaO8Xyz2zs0IcQ6CGCtM3O6/feIoCaG4N8B0+l4eqL7stlMcLpqO4d8NG2PoMO/AbUOD+MO7mg==",
+ "node_modules/react-native/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/react-native/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "@babel/runtime": "^7.4.2",
- "@restart/context": "^2.1.4",
- "@restart/hooks": "^0.3.21",
- "@types/classnames": "^2.2.10",
- "@types/invariant": "^2.2.33",
- "@types/prop-types": "^15.7.3",
- "@types/react": "^16.9.35",
- "@types/react-transition-group": "^4.4.0",
- "@types/warning": "^3.0.0",
- "classnames": "^2.2.6",
- "dom-helpers": "^5.1.2",
- "invariant": "^2.2.4",
- "prop-types": "^15.7.2",
- "prop-types-extra": "^1.1.0",
- "react-overlays": "^4.1.0",
- "react-transition-group": "^4.4.1",
- "uncontrollable": "^7.0.0",
- "warning": "^4.0.3"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
},
- "peerDependencies": {
- "react": ">=16.8.0",
- "react-dom": ">=16.8.0"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/react-custom-scrollbars": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz",
- "integrity": "sha512-VtJTUvZ7kPh/auZWIbBRceGPkE30XBYe+HktFxuMWBR2eVQQ+Ur6yFJMoaYcNpyGq22uYJ9Wx4UAEcC0K+LNPQ==",
+ "node_modules/react-native/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "dom-css": "^2.0.0",
- "prop-types": "^15.5.10",
- "raf": "^3.1.0"
+ "has-flag": "^4.0.0"
},
- "peerDependencies": {
- "react": "^0.14.0 || ^15.0.0 || ^16.0.0",
- "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/react-input-autosize": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
- "integrity": "sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==",
+ "node_modules/react-native/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "prop-types": "^15.5.8"
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
},
- "peerDependencies": {
- "react": "^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0"
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/react-intl": {
- "version": "6.6.8",
- "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.8.tgz",
- "integrity": "sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==",
- "dev": true,
+ "node_modules/react-native/node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "license": "ISC",
+ "peer": true,
"dependencies": {
- "@formatjs/ecma402-abstract": "2.0.0",
- "@formatjs/icu-messageformat-parser": "2.7.8",
- "@formatjs/intl": "2.10.4",
- "@formatjs/intl-displaynames": "6.6.8",
- "@formatjs/intl-listformat": "7.5.7",
- "@types/hoist-non-react-statics": "^3.3.1",
- "@types/react": "16 || 17 || 18",
- "hoist-non-react-statics": "^3.3.2",
- "intl-messageformat": "10.5.14",
- "tslib": "^2.4.0"
- },
- "peerDependencies": {
- "react": "^16.6.0 || 17 || 18",
- "typescript": "^4.7 || 5"
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
- "node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "node_modules/react-native/node_modules/ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "async-limiter": "~1.0.0"
+ }
},
- "node_modules/react-lifecycles-compat": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
- "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ "node_modules/react-native/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
},
- "node_modules/react-markdown": {
- "version": "8.0.7",
- "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz",
- "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==",
+ "node_modules/react-native/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "@types/hast": "^2.0.0",
- "@types/prop-types": "^15.0.0",
- "@types/unist": "^2.0.0",
- "comma-separated-tokens": "^2.0.0",
- "hast-util-whitespace": "^2.0.0",
- "prop-types": "^15.0.0",
- "property-information": "^6.0.0",
- "react-is": "^18.0.0",
- "remark-parse": "^10.0.0",
- "remark-rehype": "^10.0.0",
- "space-separated-tokens": "^2.0.0",
- "style-to-object": "^0.4.0",
- "unified": "^10.0.0",
- "unist-util-visit": "^4.0.0",
- "vfile": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
},
- "peerDependencies": {
- "@types/react": ">=16",
- "react": ">=16"
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/react-markdown/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ "node_modules/react-native/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ }
},
"node_modules/react-overlays": {
"version": "4.1.1",
@@ -13765,6 +17513,16 @@
}
}
},
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/react-select": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-3.1.0.tgz",
@@ -13971,6 +17729,40 @@
"node": ">=8.10.0"
}
},
+ "node_modules/readline": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
+ "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==",
+ "license": "BSD",
+ "peer": true
+ },
+ "node_modules/recast": {
+ "version": "0.23.11",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
+ "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ast-types": "^0.16.1",
+ "esprima": "~4.0.0",
+ "source-map": "~0.6.1",
+ "tiny-invariant": "^1.3.3",
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/recast/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/redux": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz",
@@ -14066,14 +17858,12 @@
"node_modules/regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
- "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
- "dev": true
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="
},
"node_modules/regenerate-unicode-properties": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz",
"integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==",
- "dev": true,
"dependencies": {
"regenerate": "^1.4.2"
},
@@ -14090,7 +17880,6 @@
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
"integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
- "dev": true,
"dependencies": {
"@babel/runtime": "^7.8.4"
}
@@ -14142,7 +17931,6 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
"integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
- "dev": true,
"dependencies": {
"@babel/regjsgen": "^0.8.0",
"regenerate": "^1.4.2",
@@ -14159,7 +17947,6 @@
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
"integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
- "dev": true,
"dependencies": {
"jsesc": "~0.5.0"
},
@@ -14171,7 +17958,6 @@
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
- "dev": true,
"bin": {
"jsesc": "bin/jsesc"
}
@@ -14255,7 +18041,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -14364,7 +18149,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -14999,7 +18783,6 @@
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
- "dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@@ -15023,15 +18806,100 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/selfsigned": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
"bin": {
"semver": "bin/semver"
}
},
+ "node_modules/send": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/send/node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/serialize-error": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-6.0.0.tgz",
@@ -15066,6 +18934,32 @@
"randombytes": "^2.1.0"
}
},
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-static/node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -15146,6 +19040,13 @@
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"dev": true
},
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC",
+ "peer": true
+ },
"node_modules/sha.js": {
"version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
@@ -15159,6 +19060,19 @@
"sha.js": "bin.js"
}
},
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/shallow-equals": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shallow-equals/-/shallow-equals-1.0.0.tgz",
@@ -15185,6 +19099,19 @@
"node": ">=8"
}
},
+ "node_modules/shell-quote": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
+ "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/shellwords": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
@@ -15213,8 +19140,7 @@
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/sisteransi": {
"version": "1.0.5",
@@ -15488,7 +19414,6 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -15498,7 +19423,6 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -15566,8 +19490,7 @@
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"node_modules/ssri": {
"version": "6.0.2",
@@ -15582,7 +19505,6 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
- "dev": true,
"dependencies": {
"escape-string-regexp": "^2.0.0"
},
@@ -15594,7 +19516,36 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
- "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+ "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/stacktrace-parser/node_modules/type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "license": "(MIT OR CC0-1.0)",
+ "peer": true,
"engines": {
"node": ">=8"
}
@@ -15637,6 +19588,16 @@
"node": ">= 0.4"
}
},
+ "node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/stream-browserify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
@@ -15812,7 +19773,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -15905,6 +19865,7 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
@@ -16102,7 +20063,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
"integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
- "dev": true,
"dependencies": {
"@istanbuljs/schema": "^0.1.2",
"glob": "^7.1.4",
@@ -16121,8 +20081,7 @@
"node_modules/throat": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
- "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
- "dev": true
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
},
"node_modules/through2": {
"version": "2.0.5",
@@ -16146,11 +20105,27 @@
"node": ">=0.6.0"
}
},
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/tmp": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
+ "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="
},
"node_modules/to-arraybuffer": {
"version": "1.0.1",
@@ -16166,14 +20141,6 @@
"to-space-case": "^1.0.0"
}
},
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/to-no-case": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
@@ -16228,7 +20195,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -16244,6 +20210,16 @@
"to-no-case": "^1.0.0"
}
},
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
"node_modules/tough-cookie": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
@@ -16343,8 +20319,7 @@
"node_modules/tslib": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
- "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
- "dev": true
+ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
},
"node_modules/tsutils": {
"version": "3.21.0",
@@ -16389,7 +20364,6 @@
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -16540,7 +20514,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
"integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -16549,7 +20522,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
"integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
- "dev": true,
"dependencies": {
"unicode-canonical-property-names-ecmascript": "^2.0.0",
"unicode-property-aliases-ecmascript": "^2.0.0"
@@ -16562,7 +20534,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
"integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -16571,7 +20542,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
"integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -16717,6 +20687,16 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -16777,10 +20757,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
- "dev": true,
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"funding": [
{
"type": "opencollective",
@@ -16795,9 +20774,10 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@@ -16881,6 +20861,16 @@
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
"dev": true
},
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@@ -16983,6 +20973,13 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/vlq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
+ "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -17015,7 +21012,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
"integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
"dependencies": {
"makeerror": "1.0.12"
}
@@ -17925,6 +21921,13 @@
"iconv-lite": "0.4.24"
}
},
+ "node_modules/whatwg-fetch": {
+ "version": "3.6.20",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/whatwg-mimetype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
@@ -18098,8 +22101,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/write": {
"version": "1.0.3",
@@ -18181,8 +22183,7 @@
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/yaml": {
"version": "1.10.2",
@@ -18262,7 +22263,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "dev": true,
"requires": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -18286,25 +22286,24 @@
}
},
"@babel/code-frame": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
- "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"requires": {
- "@babel/highlight": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
}
},
"@babel/compat-data": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz",
- "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==",
- "dev": true
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
+ "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ=="
},
"@babel/core": {
"version": "7.11.6",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
"integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
- "dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.11.6",
@@ -18325,44 +22324,42 @@
}
},
"@babel/generator": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz",
- "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
+ "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
"requires": {
- "@babel/types": "^7.25.6",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "jsesc": "^3.0.2"
}
},
"@babel/helper-annotate-as-pure": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz",
- "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"requires": {
- "@babel/types": "^7.24.7"
+ "@babel/types": "^7.25.9"
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz",
"integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==",
- "dev": true,
"requires": {
"@babel/traverse": "^7.24.7",
"@babel/types": "^7.24.7"
}
},
"@babel/helper-compilation-targets": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz",
- "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz",
+ "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==",
"requires": {
- "@babel/compat-data": "^7.25.2",
- "@babel/helper-validator-option": "^7.24.8",
- "browserslist": "^4.23.1",
+ "@babel/compat-data": "^7.26.8",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
@@ -18370,31 +22367,28 @@
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz",
- "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/helper-replace-supers": "^7.25.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/traverse": "^7.25.4",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz",
+ "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.26.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/traverse": "^7.27.0",
"semver": "^6.3.1"
},
"dependencies": {
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -18402,7 +22396,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz",
"integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==",
- "dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.24.7",
"regexpu-core": "^5.3.1",
@@ -18412,27 +22405,28 @@
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
- "@babel/helper-environment-visitor": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
- "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
- "dev": true,
+ "@babel/helper-define-polyfill-provider": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz",
+ "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==",
+ "peer": true,
"requires": {
- "@babel/types": "^7.24.7"
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
}
},
- "@babel/helper-function-name": {
+ "@babel/helper-environment-visitor": {
"version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
- "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
+ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
"requires": {
- "@babel/template": "^7.24.7",
"@babel/types": "^7.24.7"
}
},
@@ -18440,169 +22434,126 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
"integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
- "dev": true,
"requires": {
"@babel/types": "^7.24.7"
}
},
"@babel/helper-member-expression-to-functions": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz",
- "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
"requires": {
- "@babel/traverse": "^7.24.8",
- "@babel/types": "^7.24.8"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
}
},
"@babel/helper-module-imports": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
- "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
"requires": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
}
},
"@babel/helper-module-transforms": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz",
- "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==",
- "dev": true,
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
"requires": {
- "@babel/helper-module-imports": "^7.24.7",
- "@babel/helper-simple-access": "^7.24.7",
- "@babel/helper-validator-identifier": "^7.24.7",
- "@babel/traverse": "^7.25.2"
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
}
},
"@babel/helper-optimise-call-expression": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz",
- "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
"requires": {
- "@babel/types": "^7.24.7"
+ "@babel/types": "^7.25.9"
}
},
"@babel/helper-plugin-utils": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz",
- "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==",
- "dev": true
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
+ "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz",
- "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
+ "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-wrap-function": "^7.25.0",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-wrap-function": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
}
},
"@babel/helper-replace-supers": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz",
- "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==",
- "dev": true,
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz",
+ "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==",
"requires": {
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/traverse": "^7.25.0"
- }
- },
- "@babel/helper-simple-access": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
- "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
- "dev": true,
- "requires": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/traverse": "^7.26.5"
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz",
- "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
"requires": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
- "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
}
},
"@babel/helper-string-parser": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
- "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ=="
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="
},
"@babel/helper-validator-identifier": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
- "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w=="
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="
},
"@babel/helper-validator-option": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz",
- "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==",
- "dev": true
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="
},
"@babel/helper-wrap-function": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz",
- "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
+ "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
"requires": {
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
}
},
"@babel/helpers": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz",
- "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
+ "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
"requires": {
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6"
- }
- },
- "@babel/highlight": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
- "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.24.7",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0"
}
},
"@babel/parser": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz",
- "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
+ "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"requires": {
- "@babel/types": "^7.25.6"
+ "@babel/types": "^7.27.0"
}
},
"@babel/plugin-proposal-async-generator-functions": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz",
"integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==",
- "dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-plugin-utils": "^7.20.2",
@@ -18614,7 +22565,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
"integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
- "dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.10.4",
"@babel/helper-plugin-utils": "^7.10.4"
@@ -18624,17 +22574,24 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
"integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3"
}
},
+ "@babel/plugin-proposal-export-default-from": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz",
+ "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
"@babel/plugin-proposal-export-namespace-from": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
"integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.9",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
@@ -18644,7 +22601,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
"integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-json-strings": "^7.8.3"
@@ -18654,7 +22610,6 @@
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz",
"integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.20.2",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
@@ -18664,7 +22619,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
"integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
@@ -18674,7 +22628,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
"integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
@@ -18684,7 +22637,6 @@
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
"integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
@@ -18695,7 +22647,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
"integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
@@ -18705,7 +22656,6 @@
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
"integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4",
"@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
@@ -18716,7 +22666,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
"integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
- "dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -18726,7 +22675,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
"integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
- "dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
"@babel/helper-plugin-utils": "^7.18.6"
@@ -18736,7 +22684,6 @@
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
"integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18745,7 +22692,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
"integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18754,7 +22700,6 @@
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
"integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.12.13"
}
@@ -18763,25 +22708,40 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
"integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-export-default-from": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz",
+ "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
"@babel/plugin-syntax-export-namespace-from": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.3"
}
},
+ "@babel/plugin-syntax-flow": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz",
+ "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
"@babel/plugin-syntax-import-meta": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
"integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4"
}
@@ -18790,25 +22750,22 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-jsx": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz",
- "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
"integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4"
}
@@ -18817,7 +22774,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
"integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18826,7 +22782,6 @@
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
"integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4"
}
@@ -18835,7 +22790,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
"integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18844,7 +22798,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
"integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18853,7 +22806,6 @@
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
"integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
@@ -18862,34 +22814,41 @@
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.14.5"
}
},
"@babel/plugin-syntax-typescript": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz",
- "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-transform-arrow-functions": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz",
"integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
+ "@babel/plugin-transform-async-generator-functions": {
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz",
+ "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-remap-async-to-generator": "^7.25.9",
+ "@babel/traverse": "^7.26.8"
+ }
+ },
"@babel/plugin-transform-async-to-generator": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz",
"integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==",
- "dev": true,
"requires": {
"@babel/helper-module-imports": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7",
@@ -18900,33 +22859,38 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz",
"integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz",
- "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz",
+ "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.26.5"
}
},
- "@babel/plugin-transform-classes": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz",
- "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==",
- "dev": true,
+ "@babel/plugin-transform-class-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
+ "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
+ "peer": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-compilation-targets": "^7.24.7",
- "@babel/helper-environment-visitor": "^7.24.7",
- "@babel/helper-function-name": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-replace-supers": "^7.24.7",
- "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
+ "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
"globals": "^11.1.0"
}
},
@@ -18934,26 +22898,23 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz",
"integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/template": "^7.24.7"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz",
- "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
+ "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-transform-dotall-regex": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
"integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
- "dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -18963,7 +22924,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
"integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -18972,47 +22932,61 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz",
"integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==",
- "dev": true,
"requires": {
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
}
},
+ "@babel/plugin-transform-flow-strip-types": {
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz",
+ "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/plugin-syntax-flow": "^7.26.0"
+ }
+ },
"@babel/plugin-transform-for-of": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz",
"integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz",
- "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
+ "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
"requires": {
- "@babel/helper-compilation-targets": "^7.24.7",
- "@babel/helper-function-name": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
}
},
"@babel/plugin-transform-literals": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz",
- "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
+ "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
+ "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-transform-member-expression-literals": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz",
"integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19021,28 +22995,24 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
"integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
- "dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
}
},
"@babel/plugin-transform-modules-commonjs": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz",
- "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==",
- "dev": true,
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
+ "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
"requires": {
- "@babel/helper-module-transforms": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-simple-access": "^7.24.7"
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-transform-modules-systemjs": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz",
"integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==",
- "dev": true,
"requires": {
"@babel/helper-hoist-variables": "^7.24.7",
"@babel/helper-module-transforms": "^7.24.7",
@@ -19054,7 +23024,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
"integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
- "dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -19064,7 +23033,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz",
"integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==",
- "dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -19074,35 +23042,100 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
"integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
+ "@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.26.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz",
+ "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.26.5"
+ }
+ },
+ "@babel/plugin-transform-numeric-separator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
+ "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-object-rest-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
+ "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9"
+ }
+ },
"@babel/plugin-transform-object-super": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz",
"integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-replace-supers": "^7.24.7"
}
},
+ "@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
+ "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-optional-chaining": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ }
+ },
"@babel/plugin-transform-parameters": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz",
- "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
+ "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
"requires": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-private-methods": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
+ "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ }
+ },
+ "@babel/plugin-transform-private-property-in-object": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
+ "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
}
},
"@babel/plugin-transform-property-literals": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz",
"integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19111,22 +23144,20 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz",
"integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
"@babel/plugin-transform-react-jsx": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz",
- "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==",
- "dev": true,
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
+ "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-module-imports": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-jsx": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/types": "^7.25.9"
}
},
"@babel/plugin-transform-react-jsx-development": {
@@ -19142,7 +23173,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz",
"integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19151,7 +23181,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz",
"integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19170,7 +23199,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz",
"integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7",
"regenerator-transform": "^0.15.2"
@@ -19180,16 +23208,36 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
"integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
+ "@babel/plugin-transform-runtime": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz",
+ "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "babel-plugin-polyfill-corejs2": "^0.4.10",
+ "babel-plugin-polyfill-corejs3": "^0.11.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.1",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
+ }
+ },
"@babel/plugin-transform-shorthand-properties": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz",
"integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19198,7 +23246,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz",
"integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
@@ -19208,7 +23255,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz",
"integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19217,7 +23263,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz",
"integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19226,28 +23271,26 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz",
"integrity": "sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
},
"@babel/plugin-transform-typescript": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz",
- "integrity": "sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==",
- "dev": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz",
+ "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==",
"requires": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-typescript": "^7.24.7"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.27.0",
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-syntax-typescript": "^7.25.9"
}
},
"@babel/plugin-transform-unicode-escapes": {
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
"integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.24.7"
}
@@ -19256,7 +23299,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz",
"integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==",
- "dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.24.7",
"@babel/helper-plugin-utils": "^7.24.7"
@@ -19284,7 +23326,6 @@
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz",
"integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==",
- "dev": true,
"requires": {
"@babel/compat-data": "^7.11.0",
"@babel/helper-compilation-targets": "^7.10.4",
@@ -19356,11 +23397,21 @@
"semver": "^5.5.0"
}
},
+ "@babel/preset-flow": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz",
+ "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.9"
+ }
+ },
"@babel/preset-modules": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
"integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
@@ -19394,11 +23445,23 @@
"@babel/plugin-transform-typescript": "^7.10.4"
}
},
+ "@babel/register": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz",
+ "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==",
+ "peer": true,
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "find-cache-dir": "^2.0.0",
+ "make-dir": "^2.1.0",
+ "pirates": "^4.0.6",
+ "source-map-support": "^0.5.16"
+ }
+ },
"@babel/regjsgen": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
- "dev": true
+ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
},
"@babel/runtime": {
"version": "7.11.2",
@@ -19409,37 +23472,51 @@
}
},
"@babel/template": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
- "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
+ "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"requires": {
- "@babel/code-frame": "^7.24.7",
- "@babel/parser": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/code-frame": "^7.26.2",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0"
}
},
"@babel/traverse": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz",
- "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
+ "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+ "requires": {
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.27.0",
+ "@babel/parser": "^7.27.0",
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/traverse--for-generate-function-map": {
+ "version": "npm:@babel/traverse@7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
+ "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+ "peer": true,
"requires": {
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.6",
- "@babel/parser": "^7.25.6",
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.27.0",
+ "@babel/parser": "^7.27.0",
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0",
"debug": "^4.3.1",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz",
- "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
+ "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"requires": {
- "@babel/helper-string-parser": "^7.24.8",
- "@babel/helper-validator-identifier": "^7.24.7",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
}
},
"@bcoe/v8-coverage": {
@@ -19688,11 +23765,16 @@
"tslib": "^2.4.0"
}
},
+ "@isaacs/ttlcache": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+ "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+ "peer": true
+ },
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
"integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
- "dev": true,
"requires": {
"camelcase": "^5.3.1",
"find-up": "^4.1.0",
@@ -19704,8 +23786,7 @@
"@istanbuljs/schema": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
- "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
- "dev": true
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="
},
"@jest/console": {
"version": "26.6.2",
@@ -19880,6 +23961,89 @@
}
}
},
+ "@jest/create-cache-key-function": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
+ "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3"
+ },
+ "dependencies": {
+ "@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "peer": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"@jest/environment": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
@@ -20031,6 +24195,15 @@
}
}
},
+ "@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "peer": true,
+ "requires": {
+ "@sinclair/typebox": "^0.27.8"
+ }
+ },
"@jest/source-map": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
@@ -20245,6 +24418,16 @@
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="
},
+ "@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "peer": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
"@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
@@ -20300,17 +24483,448 @@
"@primer/octicons-react": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/@primer/octicons-react/-/octicons-react-10.1.0.tgz",
- "integrity": "sha512-WjIaetTaf4x66xxaG/gxwsWRL2JYG33n8CfeR/L134YcX2zl9TPps9crLzI2f3rxjOdKZgVFBoUh94Cim4Fflw=="
+ "integrity": "sha512-WjIaetTaf4x66xxaG/gxwsWRL2JYG33n8CfeR/L134YcX2zl9TPps9crLzI2f3rxjOdKZgVFBoUh94Cim4Fflw==",
+ "requires": {}
},
"@react-native-community/netinfo": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz",
- "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA=="
+ "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==",
+ "requires": {}
+ },
+ "@react-native/assets-registry": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.78.1.tgz",
+ "integrity": "sha512-SegfYQFuut05EQIQIVB/6QMGaxJ29jEtPmzFWJdIp/yc2mmhIq7MfWRjwOe6qbONzIdp6Ca8p835hiGiAGyeKQ==",
+ "peer": true
+ },
+ "@react-native/babel-plugin-codegen": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.78.1.tgz",
+ "integrity": "sha512-rD0tnct/yPEtoOc8eeFHIf8ZJJJEzLkmqLs8HZWSkt3w9VYWngqLXZxiDGqv0ngXjunAlC/Hpq+ULMVOvOnByw==",
+ "peer": true,
+ "requires": {
+ "@babel/traverse": "^7.25.3",
+ "@react-native/codegen": "0.78.1"
+ }
+ },
+ "@react-native/babel-preset": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.78.1.tgz",
+ "integrity": "sha512-yTVcHmEdNQH4Ju7lhvbiQaGxBpMcalgkBy/IvHowXKk/ex3nY1PolF16/mBG1BrefcUA/rtJpqTtk2Ii+7T/Lw==",
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-proposal-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-default-from": "^7.24.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-transform-arrow-functions": "^7.24.7",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.4",
+ "@babel/plugin-transform-async-to-generator": "^7.24.7",
+ "@babel/plugin-transform-block-scoping": "^7.25.0",
+ "@babel/plugin-transform-class-properties": "^7.25.4",
+ "@babel/plugin-transform-classes": "^7.25.4",
+ "@babel/plugin-transform-computed-properties": "^7.24.7",
+ "@babel/plugin-transform-destructuring": "^7.24.8",
+ "@babel/plugin-transform-flow-strip-types": "^7.25.2",
+ "@babel/plugin-transform-for-of": "^7.24.7",
+ "@babel/plugin-transform-function-name": "^7.25.1",
+ "@babel/plugin-transform-literals": "^7.25.2",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-numeric-separator": "^7.24.7",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.7",
+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.8",
+ "@babel/plugin-transform-parameters": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/plugin-transform-private-property-in-object": "^7.24.7",
+ "@babel/plugin-transform-react-display-name": "^7.24.7",
+ "@babel/plugin-transform-react-jsx": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@babel/plugin-transform-regenerator": "^7.24.7",
+ "@babel/plugin-transform-runtime": "^7.24.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.24.7",
+ "@babel/plugin-transform-spread": "^7.24.7",
+ "@babel/plugin-transform-sticky-regex": "^7.24.7",
+ "@babel/plugin-transform-typescript": "^7.25.2",
+ "@babel/plugin-transform-unicode-regex": "^7.24.7",
+ "@babel/template": "^7.25.0",
+ "@react-native/babel-plugin-codegen": "0.78.1",
+ "babel-plugin-syntax-hermes-parser": "0.25.1",
+ "babel-plugin-transform-flow-enums": "^0.0.2",
+ "react-refresh": "^0.14.0"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ }
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
+ }
+ },
+ "@react-native/codegen": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.78.1.tgz",
+ "integrity": "sha512-kGG5qAM9JdFtxzUwe7c6CyJbsU2PnaTrtCHA2dF8VEiNX1K3yd9yKPzfkxA7HPvmHoAn3ga1941O79BStWcM3A==",
+ "peer": true,
+ "requires": {
+ "@babel/parser": "^7.25.3",
+ "glob": "^7.1.1",
+ "hermes-parser": "0.25.1",
+ "invariant": "^2.2.4",
+ "jscodeshift": "^17.0.0",
+ "nullthrows": "^1.1.1",
+ "yargs": "^17.6.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "peer": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "peer": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "peer": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "peer": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "peer": true
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "peer": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "peer": true
+ }
+ }
+ },
+ "@react-native/community-cli-plugin": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.78.1.tgz",
+ "integrity": "sha512-S6vF4oWpFqThpt/dBLrqLQw5ED2M1kg5mVtiL6ZqpoYIg+/e0vg7LZ8EXNbcdMDH4obRnm2xbOd+qlC7mOzNBg==",
+ "peer": true,
+ "requires": {
+ "@react-native/dev-middleware": "0.78.1",
+ "@react-native/metro-babel-transformer": "0.78.1",
+ "chalk": "^4.0.0",
+ "debug": "^2.2.0",
+ "invariant": "^2.2.4",
+ "metro": "^0.81.0",
+ "metro-config": "^0.81.0",
+ "metro-core": "^0.81.0",
+ "readline": "^1.3.0",
+ "semver": "^7.1.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ },
+ "semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "peer": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "@react-native/debugger-frontend": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.78.1.tgz",
+ "integrity": "sha512-xev/B++QLxSDpEBWsc74GyCuq9XOHYTBwcGSpsuhOJDUha6WZIbEEvZe3LpVW+OiFso4oGIdnVSQntwippZdWw==",
+ "peer": true
+ },
+ "@react-native/dev-middleware": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.78.1.tgz",
+ "integrity": "sha512-l8p7/dXa1vWPOdj0iuACkex8lgbLpYyPZ3QXGkocMcpl0bQ24K7hf3Bj02tfptP5PAm16b2RuEi04sjIGHUzzg==",
+ "peer": true,
+ "requires": {
+ "@isaacs/ttlcache": "^1.4.1",
+ "@react-native/debugger-frontend": "0.78.1",
+ "chrome-launcher": "^0.15.2",
+ "chromium-edge-launcher": "^0.2.0",
+ "connect": "^3.6.5",
+ "debug": "^2.2.0",
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1",
+ "open": "^7.0.3",
+ "selfsigned": "^2.4.1",
+ "serve-static": "^1.16.2",
+ "ws": "^6.2.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ },
+ "ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "peer": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ }
+ }
+ },
+ "@react-native/gradle-plugin": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.78.1.tgz",
+ "integrity": "sha512-v8GJU+8DzQDWO3iuTFI1nbuQ/kzuqbXv07VVtSIMLbdofHzuuQT14DGBacBkrIDKBDTVaBGAc/baDNsyxCghng==",
+ "peer": true
+ },
+ "@react-native/js-polyfills": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.78.1.tgz",
+ "integrity": "sha512-Ogcv4QOA1o3IyErrf/i4cDnP+nfNcIfGTgw6iNQyAPry1xjPOz4ziajskLpWG/3ADeneIZuyZppKB4A28rZSvg==",
+ "peer": true
+ },
+ "@react-native/metro-babel-transformer": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.78.1.tgz",
+ "integrity": "sha512-jQWf69D+QTMvSZSWLR+cr3VUF16rGB6sbD+bItD8Czdfn3hajzfMoHJTkVFP7991cjK5sIVekNiQIObou8JSQw==",
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.25.2",
+ "@react-native/babel-preset": "0.78.1",
+ "hermes-parser": "0.25.1",
+ "nullthrows": "^1.1.1"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ }
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
+ }
+ },
+ "@react-native/normalize-colors": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.78.1.tgz",
+ "integrity": "sha512-h4wARnY4iBFgigN1NjnaKFtcegWwQyE9+CEBVG4nHmwMtr8lZBmc7ZKIM6hUc6lxqY/ugHg48aSQSynss7mJUg==",
+ "peer": true
},
"@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
- "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
+ "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q==",
+ "requires": {}
},
"@restart/hooks": {
"version": "0.3.27",
@@ -20320,6 +24934,12 @@
"dequal": "^2.0.2"
}
},
+ "@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "peer": true
+ },
"@sinonjs/commons": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
@@ -20348,7 +24968,6 @@
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
"requires": {
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7",
@@ -20361,7 +24980,6 @@
"version": "7.6.8",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
"integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
- "dev": true,
"requires": {
"@babel/types": "^7.0.0"
}
@@ -20370,7 +24988,6 @@
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
"requires": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0"
@@ -20380,7 +24997,6 @@
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
"integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
- "dev": true,
"requires": {
"@babel/types": "^7.20.7"
}
@@ -20420,11 +25036,19 @@
"@types/react": "*"
}
},
+ "@types/enzyme-adapter-react-16": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.9.tgz",
+ "integrity": "sha512-z24MMxGtUL8HhXdye3tWzjp+19QTsABqLaX2oOZpxMPHRJgLfahQmOeTTrEBQd9ogW20+UmPBXD9j+XOasFHvw==",
+ "dev": true,
+ "requires": {
+ "@types/enzyme": "*"
+ }
+ },
"@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
"integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
- "dev": true,
"requires": {
"@types/node": "*"
}
@@ -20464,14 +25088,12 @@
"@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
- "dev": true
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="
},
"@types/istanbul-lib-report": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
"integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
- "dev": true,
"requires": {
"@types/istanbul-lib-coverage": "*"
}
@@ -20480,7 +25102,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
"integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
- "dev": true,
"requires": {
"@types/istanbul-lib-report": "*"
}
@@ -20523,8 +25144,16 @@
"@types/node": {
"version": "14.11.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.1.tgz",
- "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw==",
- "dev": true
+ "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw=="
+ },
+ "@types/node-forge": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
+ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*"
+ }
},
"@types/normalize-package-data": {
"version": "2.4.4",
@@ -20638,8 +25267,7 @@
"@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
- "dev": true
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
"@types/unist": {
"version": "2.0.10",
@@ -20663,8 +25291,7 @@
"@types/yargs-parser": {
"version": "21.0.3",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
- "dev": true
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
},
"@typescript-eslint/eslint-plugin": {
"version": "4.1.1",
@@ -20958,6 +25585,25 @@
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
"dev": true
},
+ "abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "peer": true,
+ "requires": {
+ "event-target-shim": "^5.0.0"
+ }
+ },
+ "accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "peer": true,
+ "requires": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ }
+ },
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@@ -20978,7 +25624,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"acorn-walk": {
"version": "7.2.0",
@@ -21033,13 +25680,21 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
+ },
+ "anser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
+ "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+ "peer": true
},
"ansi-colors": {
"version": "4.1.3",
@@ -21059,13 +25714,13 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
"requires": {
"color-convert": "^1.9.0"
}
@@ -21074,7 +25729,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -21090,7 +25744,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
@@ -21222,6 +25875,12 @@
"is-shared-array-buffer": "^1.0.2"
}
},
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "peer": true
+ },
"asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
@@ -21274,6 +25933,15 @@
"integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==",
"dev": true
},
+ "ast-types": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
+ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
+ "peer": true,
+ "requires": {
+ "tslib": "^2.0.1"
+ }
+ },
"astral-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
@@ -21287,6 +25955,12 @@
"dev": true,
"optional": true
},
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "peer": true
+ },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -21436,7 +26110,6 @@
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
"integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
- "dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@istanbuljs/load-nyc-config": "^1.0.0",
@@ -21467,11 +26140,67 @@
"resolve": "^1.12.0"
}
},
+ "babel-plugin-polyfill-corejs2": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz",
+ "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==",
+ "peer": true,
+ "requires": {
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-define-polyfill-provider": "^0.6.4",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
+ }
+ },
+ "babel-plugin-polyfill-corejs3": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz",
+ "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.6.3",
+ "core-js-compat": "^3.40.0"
+ }
+ },
+ "babel-plugin-polyfill-regenerator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz",
+ "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.6.4"
+ }
+ },
+ "babel-plugin-syntax-hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==",
+ "peer": true,
+ "requires": {
+ "hermes-parser": "0.25.1"
+ }
+ },
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
"integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
},
+ "babel-plugin-transform-flow-enums": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz",
+ "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==",
+ "peer": true,
+ "requires": {
+ "@babel/plugin-syntax-flow": "^7.12.1"
+ }
+ },
"babel-plugin-typescript-to-proptypes": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/babel-plugin-typescript-to-proptypes/-/babel-plugin-typescript-to-proptypes-1.4.1.tgz",
@@ -21488,7 +26217,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
"integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
- "dev": true,
"requires": {
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-bigint": "^7.8.3",
@@ -21543,8 +26271,7 @@
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"base": {
"version": "0.11.2",
@@ -21621,7 +26348,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -21631,7 +26357,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
"requires": {
"fill-range": "^7.1.1"
}
@@ -21723,22 +26448,20 @@
}
},
"browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
- "dev": true,
+ "version": "4.24.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
+ "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"requires": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
- "node-releases": "^2.0.18",
- "update-browserslist-db": "^1.1.0"
+ "caniuse-lite": "^1.0.30001688",
+ "electron-to-chromium": "^1.5.73",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.1"
}
},
"bser": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
"integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
- "dev": true,
"requires": {
"node-int64": "^0.4.0"
}
@@ -21757,8 +26480,7 @@
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"buffer-xor": {
"version": "1.0.3",
@@ -21825,6 +26547,32 @@
"set-function-length": "^1.2.1"
}
},
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+ "peer": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+ "peer": true
+ }
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
+ "peer": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -21833,14 +26581,12 @@
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"caniuse-lite": {
- "version": "1.0.30001660",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz",
- "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==",
- "dev": true
+ "version": "1.0.30001707",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz",
+ "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw=="
},
"capture-exit": {
"version": "2.0.0",
@@ -21855,6 +26601,7 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -21923,17 +26670,73 @@
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"dev": true
},
+ "chrome-launcher": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+ "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "peer": true
+ }
+ }
+ },
"chrome-trace-event": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
"dev": true
},
+ "chromium-edge-launcher": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
+ "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "escape-string-regexp": "^4.0.0",
+ "is-wsl": "^2.2.0",
+ "lighthouse-logger": "^1.0.0",
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "peer": true
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "peer": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "peer": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
- "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
- "dev": true
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
},
"cipher-base": {
"version": "1.0.4",
@@ -22030,6 +26833,17 @@
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz",
"integrity": "sha512-h5FLmEMFHeuzqmpVRcDayNlVZ+k4uK1niyKQN6oUMe7ieJihv44Vc3dY/kDnnWX4PDQSwes48s965PG/D4GntQ=="
},
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "peer": true,
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -22056,6 +26870,7 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
"requires": {
"color-name": "1.1.3"
}
@@ -22063,7 +26878,8 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
},
"combined-stream": {
"version": "1.0.8",
@@ -22087,8 +26903,7 @@
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
- "dev": true
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
},
"component-emitter": {
"version": "1.2.1",
@@ -22098,8 +26913,7 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"concat-stream": {
"version": "1.6.2",
@@ -22113,6 +26927,35 @@
"typedarray": "^0.0.6"
}
},
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "peer": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ }
+ }
+ },
"console-browserify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@@ -22162,12 +27005,11 @@
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
},
"core-js-compat": {
- "version": "3.38.1",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
- "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
- "dev": true,
+ "version": "3.41.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz",
+ "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==",
"requires": {
- "browserslist": "^4.23.3"
+ "browserslist": "^4.24.4"
}
},
"core-util-is": {
@@ -22505,6 +27347,12 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
+ "depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "peer": true
+ },
"dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -22520,6 +27368,12 @@
"minimalistic-assert": "^1.0.0"
}
},
+ "destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "peer": true
+ },
"detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
@@ -22677,16 +27531,21 @@
"stream-shift": "^1.0.0"
}
},
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "peer": true
+ },
"electron-to-chromium": {
- "version": "1.5.23",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.23.tgz",
- "integrity": "sha512-mBhODedOXg4v5QWwl21DjM5amzjmI1zw9EPrPK/5Wx7C8jt33bpZNrC7OhHUG3pxRtbLpr3W2dXT+Ph1SsfRZA==",
- "dev": true
+ "version": "1.5.123",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz",
+ "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA=="
},
"elliptic": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
- "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
+ "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
"dev": true,
"requires": {
"bn.js": "^4.11.9",
@@ -22724,6 +27583,12 @@
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "peer": true
+ },
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -22878,6 +27743,15 @@
"is-arrayish": "^0.2.1"
}
},
+ "error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "peer": true,
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
"es-abstract": {
"version": "1.23.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
@@ -22994,10 +27868,15 @@
}
},
"escalade": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
- "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
- "dev": true
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "peer": true
},
"escape-string-regexp": {
"version": "1.0.5",
@@ -23268,7 +28147,8 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
"integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-plugin-import": {
"version": "2.22.0",
@@ -23352,7 +28232,8 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.2.tgz",
"integrity": "sha512-ykUeqkGyUGgwTtk78C0o8UG2fzwmgJ0qxBGPp2WqRKsTwcLuVf01kTDRAtOsd4u6whX2XOC8749n2vPydP82fg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-scope": {
"version": "5.1.1",
@@ -23409,8 +28290,7 @@
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"esquery": {
"version": "1.5.0",
@@ -23455,8 +28335,19 @@
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "peer": true
+ },
+ "event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "peer": true
},
"events": {
"version": "3.3.0",
@@ -23618,6 +28509,12 @@
}
}
},
+ "exponential-backoff": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
+ "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
+ "peer": true
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -23697,8 +28594,7 @@
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"fast-levenshtein": {
"version": "2.0.6",
@@ -23719,7 +28615,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
"integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
- "dev": true,
"requires": {
"bser": "2.1.1"
}
@@ -23773,16 +28668,46 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "peer": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ }
+ }
+ },
"find-cache-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
"requires": {
"commondir": "^1.0.1",
"make-dir": "^2.0.0",
@@ -23798,7 +28723,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
@@ -23950,6 +28874,18 @@
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
+ "flow-enums-runtime": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+ "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+ "peer": true
+ },
+ "flow-parser": {
+ "version": "0.265.3",
+ "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.265.3.tgz",
+ "integrity": "sha512-YH50TTYgnzDnuaZlAxLYQ0UZtXSbbizMO3OCpoY8obvLReJmvQ5UUW22efsC3SZJmze/tATfQ0PtkKul2XwWBw==",
+ "peer": true
+ },
"flush-write-stream": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@@ -23995,6 +28931,12 @@
"map-cache": "^0.2.2"
}
},
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "peer": true
+ },
"from2": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
@@ -24026,14 +28968,12 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"optional": true
},
"function-bind": {
@@ -24068,14 +29008,12 @@
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.2.4",
@@ -24093,8 +29031,7 @@
"get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
- "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "dev": true
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="
},
"get-params": {
"version": "0.1.2",
@@ -24148,7 +29085,6 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -24283,7 +29219,8 @@
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
},
"has-property-descriptors": {
"version": "1.0.2",
@@ -24406,6 +29343,21 @@
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
"integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng=="
},
+ "hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "peer": true
+ },
+ "hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "peer": true,
+ "requires": {
+ "hermes-estree": "0.25.1"
+ }
+ },
"history": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
@@ -24486,6 +29438,27 @@
"entities": "^4.4.0"
}
},
+ "http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "peer": true,
+ "requires": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "dependencies": {
+ "statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "peer": true
+ }
+ }
+ },
"http-proxy-agent": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
@@ -24563,6 +29536,15 @@
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
+ "image-size": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
+ "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+ "peer": true,
+ "requires": {
+ "queue": "6.0.2"
+ }
+ },
"immutable": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
@@ -24621,7 +29603,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@@ -24630,8 +29611,7 @@
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.8",
@@ -24798,12 +29778,16 @@
"is-data-descriptor": "^1.0.1"
}
},
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==",
+ "peer": true
+ },
"is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
- "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
- "dev": true,
- "optional": true
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
},
"is-extendable": {
"version": "1.0.1",
@@ -24850,8 +29834,7 @@
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-number-object": {
"version": "1.0.7",
@@ -24871,7 +29854,6 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
- "dev": true,
"requires": {
"isobject": "^3.0.1"
}
@@ -24965,8 +29947,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
- "dev": true,
- "optional": true,
"requires": {
"is-docker": "^2.0.0"
}
@@ -24986,20 +29966,17 @@
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
- "dev": true
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
},
"istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
- "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="
},
"istanbul-lib-instrument": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
"integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
- "dev": true,
"requires": {
"@babel/core": "^7.12.3",
"@babel/parser": "^7.14.7",
@@ -25012,7 +29989,6 @@
"version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz",
"integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==",
- "dev": true,
"requires": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.7",
@@ -25034,14 +30010,12 @@
"convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -25944,7 +30918,8 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"jest-regex-util": {
"version": "26.0.0",
@@ -26628,7 +31603,6 @@
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -26639,6 +31613,104 @@
"resolved": "https://registry.npmjs.org/jsan/-/jsan-3.1.14.tgz",
"integrity": "sha512-wStfgOJqMv4QKktuH273f5fyi3D3vy2pHOiSDGPvpcS/q+wb/M7AK3vkCcaHbkZxDOlDU/lDJgccygKSG2OhtA=="
},
+ "jsc-safe-url": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+ "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+ "peer": true
+ },
+ "jscodeshift": {
+ "version": "17.3.0",
+ "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-17.3.0.tgz",
+ "integrity": "sha512-LjFrGOIORqXBU+jwfC9nbkjmQfFldtMIoS6d9z2LG/lkmyNXsJAySPT+2SWXJEoE68/bCWcxKpXH37npftgmow==",
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/plugin-transform-class-properties": "^7.24.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.7",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
+ "@babel/plugin-transform-optional-chaining": "^7.24.7",
+ "@babel/plugin-transform-private-methods": "^7.24.7",
+ "@babel/preset-flow": "^7.24.7",
+ "@babel/preset-typescript": "^7.24.7",
+ "@babel/register": "^7.24.6",
+ "flow-parser": "0.*",
+ "graceful-fs": "^4.2.4",
+ "micromatch": "^4.0.7",
+ "neo-async": "^2.5.0",
+ "picocolors": "^1.0.1",
+ "recast": "^0.23.11",
+ "tmp": "^0.2.3",
+ "write-file-atomic": "^5.0.1"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ }
+ },
+ "@babel/preset-typescript": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz",
+ "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==",
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.26.5",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.26.3",
+ "@babel/plugin-transform-typescript": "^7.27.0"
+ }
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ },
+ "signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "peer": true
+ },
+ "write-file-atomic": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
+ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
+ "peer": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^4.0.1"
+ }
+ }
+ }
+ },
"jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@@ -26689,15 +31761,14 @@
}
},
"jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"json-parse-even-better-errors": {
"version": "2.3.1",
@@ -26724,8 +31795,7 @@
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"jsx-ast-utils": {
"version": "2.4.1",
@@ -26740,8 +31810,7 @@
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"kleur": {
"version": "3.0.3",
@@ -26758,14 +31827,12 @@
"leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "dev": true
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
},
"levenary": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz",
"integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==",
- "dev": true,
"requires": {
"leven": "^3.1.0"
}
@@ -26780,6 +31847,33 @@
"type-check": "~0.4.0"
}
},
+ "lighthouse-logger": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+ "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+ "peer": true,
+ "requires": {
+ "debug": "^2.6.9",
+ "marky": "^1.2.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ }
+ }
+ },
"lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -26831,240 +31925,1186 @@
"integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
"dev": true
},
- "loader-utils": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
- "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
- "dev": true,
+ "loader-utils": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
+ "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ }
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "peer": true
+ },
+ "lodash.escape": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
+ "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==",
+ "dev": true
+ },
+ "lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
+ "dev": true
+ },
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "dev": true
+ },
+ "lodash.throttle": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+ "peer": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "requires": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "marky": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz",
+ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==",
+ "peer": true
+ },
+ "mattermost-redux": {
+ "version": "5.33.1",
+ "resolved": "https://registry.npmjs.org/mattermost-redux/-/mattermost-redux-5.33.1.tgz",
+ "integrity": "sha512-fHTW5PeB0xAE5u6uMds+hlWaJsUeWgE1034vekUah1X4bZCzBcMK4fM+ycGaIQ7c5Ylj9ML6Ni10XJYiQpMo5w==",
+ "requires": {
+ "core-js": "3.8.3",
+ "form-data": "3.0.0",
+ "gfycat-sdk": "1.4.18",
+ "moment-timezone": "0.5.32",
+ "redux": "4.0.5",
+ "redux-action-buffer": "1.2.0",
+ "redux-offline": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df",
+ "redux-persist": "4.9.1",
+ "redux-persist-node-storage": "2.0.0",
+ "redux-thunk": "2.3.0",
+ "remote-redux-devtools": "0.5.16",
+ "reselect": "4.0.0",
+ "rudder-sdk-js": "1.0.14",
+ "serialize-error": "6.0.0",
+ "shallow-equals": "1.0.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz",
+ "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q=="
+ },
+ "form-data": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
+ "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "mdast-util-definitions": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
+ "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==",
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "unist-util-visit": "^4.0.0"
+ }
+ },
+ "mdast-util-from-markdown": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
+ "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==",
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "mdast-util-to-string": "^3.1.0",
+ "micromark": "^3.0.0",
+ "micromark-util-decode-numeric-character-reference": "^1.0.0",
+ "micromark-util-decode-string": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "uvu": "^0.5.0"
+ }
+ },
+ "mdast-util-to-hast": {
+ "version": "12.3.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz",
+ "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==",
+ "requires": {
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "mdast-util-definitions": "^5.0.0",
+ "micromark-util-sanitize-uri": "^1.1.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-generated": "^2.0.0",
+ "unist-util-position": "^4.0.0",
+ "unist-util-visit": "^4.0.0"
+ }
+ },
+ "mdast-util-to-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
+ "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==",
+ "requires": {
+ "@types/mdast": "^3.0.0"
+ }
+ },
+ "memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ },
+ "memory-fs": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz",
+ "integrity": "sha512-+y4mDxU4rvXXu5UDSGCGNiesFmwCHuefGMoPCO1WYucNYj7DsLqrFaa2fXVI0H+NNiPTwwzKwspn9yTZqUGqng==",
+ "dev": true
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "metro": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.4.tgz",
+ "integrity": "sha512-78f0aBNPuwXW7GFnSc+Y0vZhbuQorXxdgqQfvSRqcSizqwg9cwF27I05h47tL8AzQcizS1JZncvq4xf5u/Qykw==",
+ "peer": true,
+ "requires": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "accepts": "^1.3.7",
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "connect": "^3.6.5",
+ "debug": "^2.2.0",
+ "error-stack-parser": "^2.0.6",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "hermes-parser": "0.25.1",
+ "image-size": "^1.0.2",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "jsc-safe-url": "^0.2.2",
+ "lodash.throttle": "^4.1.1",
+ "metro-babel-transformer": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-cache-key": "0.81.4",
+ "metro-config": "0.81.4",
+ "metro-core": "0.81.4",
+ "metro-file-map": "0.81.4",
+ "metro-resolver": "0.81.4",
+ "metro-runtime": "0.81.4",
+ "metro-source-map": "0.81.4",
+ "metro-symbolicate": "0.81.4",
+ "metro-transform-plugins": "0.81.4",
+ "metro-transform-worker": "0.81.4",
+ "mime-types": "^2.1.27",
+ "nullthrows": "^1.1.1",
+ "serialize-error": "^2.1.0",
+ "source-map": "^0.5.6",
+ "throat": "^5.0.0",
+ "ws": "^7.5.10",
+ "yargs": "^17.6.2"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "peer": true,
+ "requires": {
+ "ms": "^2.1.3"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "peer": true
+ }
+ }
+ },
+ "@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "peer": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "peer": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "peer": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "peer": true
+ },
+ "jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "dependencies": {
+ "ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "peer": true
+ }
+ }
+ },
+ "jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ },
+ "serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "peer": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "peer": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "peer": true
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "peer": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "peer": true
+ }
+ }
+ },
+ "metro-babel-transformer": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.4.tgz",
+ "integrity": "sha512-WW0yswWrW+eTVK9sYD+b1HwWOiUlZlUoomiw9TIOk0C+dh2V90Wttn/8g62kYi0Y4i+cJfISerB2LbV4nuRGTA==",
+ "peer": true,
"requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^1.0.1"
+ "@babel/core": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "hermes-parser": "0.25.1",
+ "nullthrows": "^1.1.1"
},
"dependencies": {
- "json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
"requires": {
- "minimist": "^1.2.0"
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
}
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
}
}
},
- "locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
- "requires": {
- "p-locate": "^4.1.0"
- }
- },
- "lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
- },
- "lodash-es": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
- "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
- },
- "lodash.escape": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
- "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==",
- "dev": true
- },
- "lodash.flattendeep": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
- "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
- "dev": true
- },
- "lodash.isequal": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
- "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
- "dev": true
- },
- "loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "metro-cache": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.4.tgz",
+ "integrity": "sha512-sxCPH3gowDxazSaZZrwdNPEpnxR8UeXDnvPjBF9+5btDBNN2DpWvDAXPvrohkYkFImhc0LajS2V7eOXvu9PnvQ==",
+ "peer": true,
"requires": {
- "js-tokens": "^3.0.0 || ^4.0.0"
+ "exponential-backoff": "^3.1.1",
+ "flow-enums-runtime": "^0.0.6",
+ "metro-core": "0.81.4"
}
},
- "lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
+ "metro-cache-key": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.4.tgz",
+ "integrity": "sha512-3SaWQybvf1ivasjBegIxzVKLJzOpcz+KsnGwXFOYADQq0VN4cnM7tT+u2jkOhk6yJiiO1WIjl68hqyMOQJRRLg==",
+ "peer": true,
"requires": {
- "yallist": "^3.0.2"
+ "flow-enums-runtime": "^0.0.6"
}
},
- "make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
- "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
- "dev": true,
+ "metro-config": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.4.tgz",
+ "integrity": "sha512-QnhMy3bRiuimCTy7oi5Ug60javrSa3lPh0gpMAspQZHY9h6y86jwHtZPLtlj8hdWQESIlrbeL8inMSF6qI/i9Q==",
+ "peer": true,
"requires": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
+ "connect": "^3.6.5",
+ "cosmiconfig": "^5.0.5",
+ "flow-enums-runtime": "^0.0.6",
+ "jest-validate": "^29.7.0",
+ "metro": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-core": "0.81.4",
+ "metro-runtime": "0.81.4"
+ },
+ "dependencies": {
+ "@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "peer": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "peer": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "peer": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+ "peer": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "peer": true
+ },
+ "jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "peer": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "peer": true
+ }
+ }
+ },
+ "react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "peer": true
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
+ "peer": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
- "makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
+ "metro-core": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.4.tgz",
+ "integrity": "sha512-GdL4IgmgJhrMA/rTy2lRqXKeXfC77Rg+uvhUEkbhyfj/oz7PrdSgvIFzziapjdHwk1XYq0KyFh/CcVm8ZawG6A==",
+ "peer": true,
"requires": {
- "tmpl": "1.0.5"
+ "flow-enums-runtime": "^0.0.6",
+ "lodash.throttle": "^4.1.1",
+ "metro-resolver": "0.81.4"
}
},
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
- "dev": true
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
- "dev": true,
+ "metro-file-map": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.4.tgz",
+ "integrity": "sha512-qUIBzkiqOi3qEuscu4cJ83OYQ4hVzjON19FAySWqYys9GKCmxlKa7LkmwqdpBso6lQl+JXZ7nCacX90w5wQvPA==",
+ "peer": true,
"requires": {
- "object-visit": "^1.0.0"
+ "debug": "^2.2.0",
+ "fb-watchman": "^2.0.0",
+ "flow-enums-runtime": "^0.0.6",
+ "graceful-fs": "^4.2.4",
+ "invariant": "^2.2.4",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "nullthrows": "^1.1.1",
+ "walker": "^1.0.7"
+ },
+ "dependencies": {
+ "@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "peer": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "peer": true
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
}
},
- "mattermost-redux": {
- "version": "5.33.1",
- "resolved": "https://registry.npmjs.org/mattermost-redux/-/mattermost-redux-5.33.1.tgz",
- "integrity": "sha512-fHTW5PeB0xAE5u6uMds+hlWaJsUeWgE1034vekUah1X4bZCzBcMK4fM+ycGaIQ7c5Ylj9ML6Ni10XJYiQpMo5w==",
+ "metro-minify-terser": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.4.tgz",
+ "integrity": "sha512-oVvq/AGvqmbhuijJDZZ9npeWzaVyeBwQKtdlnjcQ9fH7nR15RiBr5y2zTdgTEdynqOIb1Kc16l8CQIUSzOWVFA==",
+ "peer": true,
"requires": {
- "core-js": "3.8.3",
- "form-data": "3.0.0",
- "gfycat-sdk": "1.4.18",
- "moment-timezone": "0.5.32",
- "redux": "4.0.5",
- "redux-action-buffer": "1.2.0",
- "redux-offline": "git+https://github.com/enahum/redux-offline.git#885024de96b6ec73650c340c8928066585c413df",
- "redux-persist": "4.9.1",
- "redux-persist-node-storage": "2.0.0",
- "redux-thunk": "2.3.0",
- "remote-redux-devtools": "0.5.16",
- "reselect": "4.0.0",
- "rudder-sdk-js": "1.0.14",
- "serialize-error": "6.0.0",
- "shallow-equals": "1.0.0"
+ "flow-enums-runtime": "^0.0.6",
+ "terser": "^5.15.0"
},
"dependencies": {
- "core-js": {
- "version": "3.8.3",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz",
- "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q=="
+ "acorn": {
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "peer": true
},
- "form-data": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
- "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "peer": true
+ },
+ "terser": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
+ "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
+ "peer": true,
"requires": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "mime-types": "^2.1.12"
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
}
}
}
},
- "md5.js": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
- "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
- "dev": true,
+ "metro-resolver": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.4.tgz",
+ "integrity": "sha512-Ng7G2mXjSExMeRzj6GC19G6IJ0mfIbOLgjArsMWJgtt9ViZiluCwgWsMW9juBC5NSwjJxUMK2x6pC5NIMFLiHA==",
+ "peer": true,
"requires": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
+ "flow-enums-runtime": "^0.0.6"
}
},
- "mdast-util-definitions": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
- "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==",
+ "metro-runtime": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.4.tgz",
+ "integrity": "sha512-fBoRgqkF69CwyPtBNxlDi5ha26Zc8f85n2THXYoh13Jn/Bkg8KIDCdKPp/A1BbSeNnkH/++H2EIIfnmaff4uRg==",
+ "peer": true,
"requires": {
- "@types/mdast": "^3.0.0",
- "@types/unist": "^2.0.0",
- "unist-util-visit": "^4.0.0"
+ "@babel/runtime": "^7.25.0",
+ "flow-enums-runtime": "^0.0.6"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+ "peer": true,
+ "requires": {
+ "regenerator-runtime": "^0.14.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+ "peer": true
+ }
}
},
- "mdast-util-from-markdown": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
- "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==",
+ "metro-source-map": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.4.tgz",
+ "integrity": "sha512-IOwVQ7mLqoqvsL70RZtl1EyE3f9jp43kVsAsb/B/zoWmu0/k4mwEhGLTxmjdXRkLJqPqPrh7WmFChAEf9trW4Q==",
+ "peer": true,
"requires": {
- "@types/mdast": "^3.0.0",
- "@types/unist": "^2.0.0",
- "decode-named-character-reference": "^1.0.0",
- "mdast-util-to-string": "^3.1.0",
- "micromark": "^3.0.0",
- "micromark-util-decode-numeric-character-reference": "^1.0.0",
- "micromark-util-decode-string": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "unist-util-stringify-position": "^3.0.0",
- "uvu": "^0.5.0"
+ "@babel/traverse": "^7.25.3",
+ "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-symbolicate": "0.81.4",
+ "nullthrows": "^1.1.1",
+ "ob1": "0.81.4",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
}
},
- "mdast-util-to-hast": {
- "version": "12.3.0",
- "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz",
- "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==",
+ "metro-symbolicate": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.4.tgz",
+ "integrity": "sha512-rWxTmYVN6/BOSaMDUHT8HgCuRf6acd0AjHkenYlHpmgxg7dqdnAG1hLq999q2XpW5rX+cMamZD5W5Ez2LqGaag==",
+ "peer": true,
"requires": {
- "@types/hast": "^2.0.0",
- "@types/mdast": "^3.0.0",
- "mdast-util-definitions": "^5.0.0",
- "micromark-util-sanitize-uri": "^1.1.0",
- "trim-lines": "^3.0.0",
- "unist-util-generated": "^2.0.0",
- "unist-util-position": "^4.0.0",
- "unist-util-visit": "^4.0.0"
+ "flow-enums-runtime": "^0.0.6",
+ "invariant": "^2.2.4",
+ "metro-source-map": "0.81.4",
+ "nullthrows": "^1.1.1",
+ "source-map": "^0.5.6",
+ "vlq": "^1.0.0"
}
},
- "mdast-util-to-string": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
- "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==",
+ "metro-transform-plugins": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.4.tgz",
+ "integrity": "sha512-nlP069nDXm4v28vbll4QLApAlvVtlB66rP6h+ml8Q/CCQCPBXu2JLaoxUmkIOJQjLhMRUcgTyQHq+TXWJhydOQ==",
+ "peer": true,
"requires": {
- "@types/mdast": "^3.0.0"
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/template": "^7.25.0",
+ "@babel/traverse": "^7.25.3",
+ "flow-enums-runtime": "^0.0.6",
+ "nullthrows": "^1.1.1"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ }
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
}
},
- "memoize-one": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
- "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
- },
- "memory-fs": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz",
- "integrity": "sha512-+y4mDxU4rvXXu5UDSGCGNiesFmwCHuefGMoPCO1WYucNYj7DsLqrFaa2fXVI0H+NNiPTwwzKwspn9yTZqUGqng==",
- "dev": true
- },
- "merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
- },
- "merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true
+ "metro-transform-worker": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.4.tgz",
+ "integrity": "sha512-lKAeRZ8EUMtx2cA/Y4KvICr9bIr5SE03iK3lm+l9wyn2lkjLUuPjYVep159inLeDqC6AtSubsA8MZLziP7c03g==",
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.25.2",
+ "@babel/generator": "^7.25.0",
+ "@babel/parser": "^7.25.3",
+ "@babel/types": "^7.25.2",
+ "flow-enums-runtime": "^0.0.6",
+ "metro": "0.81.4",
+ "metro-babel-transformer": "0.81.4",
+ "metro-cache": "0.81.4",
+ "metro-cache-key": "0.81.4",
+ "metro-minify-terser": "0.81.4",
+ "metro-source-map": "0.81.4",
+ "metro-transform-plugins": "0.81.4",
+ "nullthrows": "^1.1.1"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
+ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
+ "peer": true,
+ "requires": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.10",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.10",
+ "@babel/parser": "^7.26.10",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.10",
+ "@babel/types": "^7.26.10",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ }
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "peer": true
+ }
+ }
},
"micromark": {
"version": "3.2.0",
@@ -27281,7 +33321,6 @@
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
- "dev": true,
"requires": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@@ -27305,6 +33344,12 @@
}
}
},
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "peer": true
+ },
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -27340,7 +33385,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -27488,11 +33532,16 @@
}
}
},
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "peer": true
+ },
"neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
},
"nice-try": {
"version": "1.0.5",
@@ -27529,11 +33578,16 @@
}
}
},
+ "node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "peer": true
+ },
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
- "dev": true
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="
},
"node-libs-browser": {
"version": "2.2.1",
@@ -27618,10 +33672,9 @@
}
},
"node-releases": {
- "version": "2.0.18",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
- "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
- "dev": true
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="
},
"normalize-package-data": {
"version": "2.5.0",
@@ -27638,8 +33691,7 @@
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"npm-run-path": {
"version": "4.0.1",
@@ -27659,12 +33711,27 @@
"boolbase": "^1.0.0"
}
},
+ "nullthrows": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
+ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+ "peer": true
+ },
"nwsapi": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz",
"integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==",
"dev": true
},
+ "ob1": {
+ "version": "0.81.4",
+ "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.4.tgz",
+ "integrity": "sha512-EZLYM8hfPraC2SYOR5EWLFAPV5e6g+p83m2Jth9bzCpFxP1NDQJYXdmXRB2bfbaWQSmm6NkIQlbzk7uU5lLfgg==",
+ "peer": true,
+ "requires": {
+ "flow-enums-runtime": "^0.0.6"
+ }
+ },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -27803,11 +33870,19 @@
"es-object-atoms": "^1.0.0"
}
},
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "peer": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
"requires": {
"wrappy": "1"
}
@@ -27821,6 +33896,16 @@
"mimic-fn": "^2.1.0"
}
},
+ "open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "peer": true,
+ "requires": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ }
+ },
"optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -27857,7 +33942,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
"requires": {
"p-try": "^2.0.0"
}
@@ -27866,7 +33950,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
"requires": {
"p-limit": "^2.2.0"
}
@@ -27874,8 +33957,7 @@
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"pako": {
"version": "1.0.11",
@@ -27969,6 +34051,12 @@
"parse5": "^7.0.0"
}
},
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "peer": true
+ },
"pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -27991,14 +34079,12 @@
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
},
"path-key": {
"version": "3.1.1",
@@ -28035,33 +34121,29 @@
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
},
"pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg=="
},
"pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
"requires": {
"find-up": "^3.0.0"
},
@@ -28070,7 +34152,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
"requires": {
"locate-path": "^3.0.0"
}
@@ -28079,7 +34160,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
@@ -28089,7 +34169,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
"requires": {
"p-limit": "^2.0.0"
}
@@ -28097,8 +34176,7 @@
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="
}
}
},
@@ -28309,6 +34387,15 @@
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
+ "promise": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
+ "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+ "peer": true,
+ "requires": {
+ "asap": "~2.0.6"
+ }
+ },
"promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@@ -28469,6 +34556,15 @@
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true
},
+ "queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "peer": true,
+ "requires": {
+ "inherits": "~2.0.3"
+ }
+ },
"queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -28518,6 +34614,12 @@
"safe-buffer": "^5.1.0"
}
},
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "peer": true
+ },
"react": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
@@ -28563,6 +34665,27 @@
"raf": "^3.1.0"
}
},
+ "react-devtools-core": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.1.tgz",
+ "integrity": "sha512-TFo1MEnkqE6hzAbaztnyR5uLTMoz6wnEWwWBsCUzNt+sVXJycuRJdDqvL078M4/h65BI/YO5XWTaxZDWVsW0fw==",
+ "peer": true,
+ "requires": {
+ "shell-quote": "^1.6.1",
+ "ws": "^7"
+ }
+ },
+ "react-dom": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
+ "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.6.2",
+ "scheduler": "^0.19.1"
+ }
+ },
"react-input-autosize": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
@@ -28628,6 +34751,495 @@
}
}
},
+ "react-native": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.78.1.tgz",
+ "integrity": "sha512-3CK/xxX02GeeVFyrXbsHvREZFVaXwHW43Km/EdYITn5G32cccWTGaqY9QdPddEBLw5O3BPip3LHbR1SywE0cpA==",
+ "peer": true,
+ "requires": {
+ "@jest/create-cache-key-function": "^29.6.3",
+ "@react-native/assets-registry": "0.78.1",
+ "@react-native/codegen": "0.78.1",
+ "@react-native/community-cli-plugin": "0.78.1",
+ "@react-native/gradle-plugin": "0.78.1",
+ "@react-native/js-polyfills": "0.78.1",
+ "@react-native/normalize-colors": "0.78.1",
+ "@react-native/virtualized-lists": "0.78.1",
+ "abort-controller": "^3.0.0",
+ "anser": "^1.4.9",
+ "ansi-regex": "^5.0.0",
+ "babel-jest": "^29.7.0",
+ "babel-plugin-syntax-hermes-parser": "0.25.1",
+ "base64-js": "^1.5.1",
+ "chalk": "^4.0.0",
+ "commander": "^12.0.0",
+ "event-target-shim": "^5.0.1",
+ "flow-enums-runtime": "^0.0.6",
+ "glob": "^7.1.1",
+ "invariant": "^2.2.4",
+ "jest-environment-node": "^29.6.3",
+ "memoize-one": "^5.0.0",
+ "metro-runtime": "^0.81.0",
+ "metro-source-map": "^0.81.0",
+ "nullthrows": "^1.1.1",
+ "pretty-format": "^29.7.0",
+ "promise": "^8.3.0",
+ "react-devtools-core": "^6.0.1",
+ "react-refresh": "^0.14.0",
+ "regenerator-runtime": "^0.13.2",
+ "scheduler": "0.25.0",
+ "semver": "^7.1.3",
+ "stacktrace-parser": "^0.1.10",
+ "whatwg-fetch": "^3.0.0",
+ "ws": "^6.2.3",
+ "yargs": "^17.6.2"
+ },
+ "dependencies": {
+ "@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "peer": true,
+ "requires": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ }
+ },
+ "@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ }
+ },
+ "@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ }
+ },
+ "@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@react-native/virtualized-lists": {
+ "version": "0.78.1",
+ "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.78.1.tgz",
+ "integrity": "sha512-v0jqDNMFXpnRnSlkDVvwNxXgPhifzzTFlxTSnHj9erKJsKpE26gSU5qB4hmJkEsscLG/ygdJ1c88aqinSh/wRA==",
+ "peer": true,
+ "requires": {
+ "invariant": "^2.2.4",
+ "nullthrows": "^1.1.1"
+ }
+ },
+ "@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "peer": true,
+ "requires": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "peer": true,
+ "requires": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "peer": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "peer": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "peer": true,
+ "requires": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "peer": true,
+ "requires": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ }
+ },
+ "babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "peer": true,
+ "requires": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "peer": true
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "peer": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "peer": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "peer": true
+ },
+ "commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "peer": true
+ },
+ "convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "peer": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "peer": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "peer": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "peer": true
+ },
+ "jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "peer": true,
+ "requires": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ }
+ },
+ "jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "fsevents": "^2.3.2",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ }
+ },
+ "jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "peer": true,
+ "requires": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ }
+ },
+ "jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ }
+ },
+ "jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "peer": true
+ },
+ "jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "peer": true,
+ "requires": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "peer": true,
+ "requires": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "peer": true
+ }
+ }
+ },
+ "react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "peer": true
+ },
+ "scheduler": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
+ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+ "peer": true
+ },
+ "semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "peer": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "peer": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "peer": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "peer": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ }
+ },
+ "ws": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
+ "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "peer": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "peer": true
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "peer": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "peer": true
+ }
+ }
+ },
"react-overlays": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz",
@@ -28670,6 +35282,12 @@
"react-is": "^16.9.0"
}
},
+ "react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "peer": true
+ },
"react-select": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-3.1.0.tgz",
@@ -28838,6 +35456,33 @@
"picomatch": "^2.2.1"
}
},
+ "readline": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz",
+ "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==",
+ "peer": true
+ },
+ "recast": {
+ "version": "0.23.11",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
+ "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
+ "peer": true,
+ "requires": {
+ "ast-types": "^0.16.1",
+ "esprima": "~4.0.0",
+ "source-map": "~0.6.1",
+ "tiny-invariant": "^1.3.3",
+ "tslib": "^2.0.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "peer": true
+ }
+ }
+ },
"redux": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz",
@@ -28921,14 +35566,12 @@
"regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
- "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
- "dev": true
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="
},
"regenerate-unicode-properties": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz",
"integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==",
- "dev": true,
"requires": {
"regenerate": "^1.4.2"
}
@@ -28942,7 +35585,6 @@
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
"integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
- "dev": true,
"requires": {
"@babel/runtime": "^7.8.4"
}
@@ -28979,7 +35621,6 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
"integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
- "dev": true,
"requires": {
"@babel/regjsgen": "^0.8.0",
"regenerate": "^1.4.2",
@@ -28993,7 +35634,6 @@
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
"integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
- "dev": true,
"requires": {
"jsesc": "~0.5.0"
},
@@ -29001,8 +35641,7 @@
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
- "dev": true
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="
}
}
},
@@ -29069,8 +35708,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-main-filename": {
"version": "2.0.0",
@@ -29156,8 +35794,7 @@
"resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="
},
"resolve-pkg-maps": {
"version": "1.0.0",
@@ -29626,7 +36263,6 @@
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
- "dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@@ -29643,11 +36279,81 @@
"ajv-keywords": "^3.5.2"
}
},
+ "selfsigned": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
+ "peer": true,
+ "requires": {
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
+ }
+ },
"semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
+ },
+ "send": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "peer": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "peer": true
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "peer": true
+ },
+ "on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "peer": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "peer": true
+ }
+ }
},
"serialize-error": {
"version": "6.0.0",
@@ -29673,6 +36379,26 @@
"randombytes": "^2.1.0"
}
},
+ "serve-static": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "peer": true,
+ "requires": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "dependencies": {
+ "encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "peer": true
+ }
+ }
+ },
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -29740,6 +36466,12 @@
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"dev": true
},
+ "setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "peer": true
+ },
"sha.js": {
"version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
@@ -29750,6 +36482,15 @@
"safe-buffer": "^5.0.1"
}
},
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "peer": true,
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
"shallow-equals": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shallow-equals/-/shallow-equals-1.0.0.tgz",
@@ -29770,6 +36511,12 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
+ "shell-quote": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
+ "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
+ "peer": true
+ },
"shellwords": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
@@ -29792,8 +36539,7 @@
"signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"sisteransi": {
"version": "1.0.5",
@@ -30010,7 +36756,6 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
@@ -30019,8 +36764,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
@@ -30079,8 +36823,7 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"ssri": {
"version": "6.0.2",
@@ -30095,7 +36838,6 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
- "dev": true,
"requires": {
"escape-string-regexp": "^2.0.0"
},
@@ -30103,8 +36845,30 @@
"escape-string-regexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
- "dev": true
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
+ }
+ }
+ },
+ "stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "peer": true
+ },
+ "stacktrace-parser": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+ "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+ "peer": true,
+ "requires": {
+ "type-fest": "^0.7.1"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "peer": true
}
}
},
@@ -30139,6 +36903,12 @@
}
}
},
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "peer": true
+ },
"stream-browserify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
@@ -30283,7 +37053,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -30347,6 +37116,7 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
"requires": {
"has-flag": "^3.0.0"
}
@@ -30493,7 +37263,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
"integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
- "dev": true,
"requires": {
"@istanbuljs/schema": "^0.1.2",
"glob": "^7.1.4",
@@ -30509,8 +37278,7 @@
"throat": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
- "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
- "dev": true
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
},
"through2": {
"version": "2.0.5",
@@ -30531,11 +37299,22 @@
"setimmediate": "^1.0.4"
}
},
+ "tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "peer": true
+ },
+ "tmp": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
+ "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
+ "peer": true
+ },
"tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="
},
"to-arraybuffer": {
"version": "1.0.1",
@@ -30551,11 +37330,6 @@
"to-space-case": "^1.0.0"
}
},
- "to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="
- },
"to-no-case": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz",
@@ -30603,7 +37377,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"requires": {
"is-number": "^7.0.0"
}
@@ -30616,6 +37389,12 @@
"to-no-case": "^1.0.0"
}
},
+ "toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "peer": true
+ },
"tough-cookie": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
@@ -30695,8 +37474,7 @@
"tslib": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
- "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
- "dev": true
+ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
},
"tsutils": {
"version": "3.21.0",
@@ -30733,8 +37511,7 @@
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
"type-fest": {
"version": "0.21.3",
@@ -30841,14 +37618,12 @@
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
- "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
- "dev": true
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ=="
},
"unicode-match-property-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
"integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
- "dev": true,
"requires": {
"unicode-canonical-property-names-ecmascript": "^2.0.0",
"unicode-property-aliases-ecmascript": "^2.0.0"
@@ -30857,14 +37632,12 @@
"unicode-match-property-value-ecmascript": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
- "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
- "dev": true
+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA=="
},
"unicode-property-aliases-ecmascript": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
- "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
- "dev": true
+ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w=="
},
"unified": {
"version": "10.1.2",
@@ -30972,6 +37745,12 @@
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
"dev": true
},
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "peer": true
+ },
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -31020,13 +37799,12 @@
"optional": true
},
"update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
- "dev": true,
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"requires": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
}
},
"uri-js": {
@@ -31101,6 +37879,12 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
},
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "peer": true
+ },
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@@ -31180,6 +37964,12 @@
"unist-util-stringify-position": "^3.0.0"
}
},
+ "vlq": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
+ "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+ "peer": true
+ },
"vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@@ -31208,7 +37998,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
"integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
"requires": {
"makeerror": "1.0.12"
}
@@ -31948,6 +38737,12 @@
"iconv-lite": "0.4.24"
}
},
+ "whatwg-fetch": {
+ "version": "3.6.20",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+ "peer": true
+ },
"whatwg-mimetype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
@@ -32084,8 +38879,7 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"write": {
"version": "1.0.3",
@@ -32111,7 +38905,8 @@
"ws": {
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
- "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "requires": {}
},
"xml": {
"version": "1.0.1",
@@ -32146,8 +38941,7 @@
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"yaml": {
"version": "1.10.2",
diff --git a/webapp/package.json b/webapp/package.json
index 684d72cfa..70e353061 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -27,6 +27,7 @@
"@emotion/babel-preset-css-prop": "10.0.27",
"@emotion/core": "10.0.35",
"@types/enzyme": "3.10.6",
+ "@types/enzyme-adapter-react-16": "1.0.9",
"@types/jest": "26.0.14",
"@types/node": "14.11.1",
"@types/react": "16.9.49",
@@ -76,6 +77,7 @@
"react": "16.13.1",
"react-bootstrap": "1.3.0",
"react-custom-scrollbars": "4.2.1",
+ "react-dom": "16.13.1",
"react-markdown": "^8.0.5",
"react-redux": "7.2.1",
"react-select": "3.1.0",
@@ -98,6 +100,7 @@
"text-summary"
],
"moduleNameMapper": {
+ "^@/(.*)$": "/src/$1",
"^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "identity-obj-proxy",
"^.+\\.(css|less|scss)$": "identity-obj-proxy",
"^.*i18n.*\\.(json)$": "/tests/i18n_mock.json",
@@ -118,6 +121,9 @@
"setupFiles": [
"jest-canvas-mock"
],
+ "setupFilesAfterEnv": [
+ "/tests/setup.tsx"
+ ],
"testURL": "http://localhost:8065"
}
}
diff --git a/webapp/src/components/github_repo_selector/github_repo_selector.jsx b/webapp/src/components/github_repo_selector/github_repo_selector.jsx
index f6b72a8b6..c69eee4b1 100644
--- a/webapp/src/components/github_repo_selector/github_repo_selector.jsx
+++ b/webapp/src/components/github_repo_selector/github_repo_selector.jsx
@@ -48,7 +48,7 @@ export default class GithubRepoSelector extends PureComponent {
}
render() {
- const repoOptions = this.props.yourRepos.repos.map((item) => ({value: item.full_name, label: item.full_name}));
+ const repoOptions = this.props.yourRepos.repos ? this.props.yourRepos.repos.map((item) => ({value: item.full_name, label: item.full_name})) : [];
return (
diff --git a/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap b/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
new file mode 100644
index 000000000..42cb01f85
--- /dev/null
+++ b/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
@@ -0,0 +1,105 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CreateOrUpdateIssueModal should render correctly with default props 1`] = `
+
+
+
+ Create GitHub Issue
+
+
+
+
+`;
diff --git a/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx b/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
new file mode 100644
index 000000000..bed1bcba0
--- /dev/null
+++ b/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
@@ -0,0 +1,116 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import CreateOrUpdateIssueModal from './create_update_issue';
+
+jest.mock('utils/user_utils', () => ({
+ getErrorMessage: jest.fn(() => 'Error occurred'),
+}));
+
+describe('CreateOrUpdateIssueModal', () => {
+ const defaultProps = {
+ close: jest.fn(),
+ create: jest.fn(() => Promise.resolve({})),
+ update: jest.fn(),
+ getIssueInfo: jest.fn(),
+ post: null,
+ theme: {
+ centerChannelColor: '#000',
+ centerChannelBg: '#fff',
+ },
+ visible: true,
+ };
+
+
+ it('should render correctly with default props', () => {
+ const wrapper = shallow(
);
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it('should call close prop when handleClose is called', () => {
+ const wrapper = shallow(
);
+ wrapper.instance().handleClose();
+ expect(defaultProps.close).toHaveBeenCalled();
+ });
+
+ it('should display error message when create returns an error', async () => {
+ const mockCreateFunction = jest.fn().mockResolvedValue({error: {message: 'Some error'}});
+
+ const errorProps = {
+ ...defaultProps,
+ create: mockCreateFunction,
+ messageData: {
+ repo_owner: 'owner',
+ repo_name: 'repo',
+ },
+ };
+
+ const wrapper = shallow(
);
+ wrapper.setState({issueTitle: 'Test Issue'});
+
+ await wrapper.instance().handleCreateOrUpdate({preventDefault: jest.fn()});
+ wrapper.update();
+
+ expect(wrapper.find('.help-text.error-text').text()).toEqual('Error occurred');
+ });
+
+ it('should show validation error when issueTitle is empty', async () => {
+ const wrapper = shallow(
);
+ wrapper.setState({ issueTitle: '' });
+
+ await wrapper.instance().handleCreateOrUpdate({ preventDefault: jest.fn() });
+
+ expect(wrapper.state('issueTitleValid')).toBe(false);
+ expect(wrapper.state('showErrors')).toBe(true);
+ });
+
+ it('should update repo state when handleRepoChange is called', () => {
+ const wrapper = shallow(
);
+ const repo = {name: 'repo-name'};
+
+ wrapper.instance().handleRepoChange(repo);
+ expect(wrapper.state('repo')).toEqual(repo);
+ });
+
+ it('should update labels state when handleLabelsChange is called', () => {
+ const wrapper = shallow(
);
+ const labels = ['label1', 'label2'];
+
+ wrapper.instance().handleLabelsChange(labels);
+ expect(wrapper.state('labels')).toEqual(labels);
+ });
+
+ it('should update assignees state when handleAssigneesChange is called', () => {
+ const wrapper = shallow(
);
+ const assignees = ['user1', 'user2'];
+
+ wrapper.instance().handleAssigneesChange(assignees);
+ expect(wrapper.state('assignees')).toEqual(assignees);
+ });
+
+ it('should set issueDescription state when post prop is updated', () => {
+ const wrapper = shallow(
);
+ const post = {message: 'test post'};
+ wrapper.setProps({post});
+
+ expect(wrapper.state('issueDescription')).toEqual(post.message);
+ });
+
+ it('should not display attribute selectors when repo does not have push permissions', () => {
+ const wrapper = shallow(
);
+ wrapper.setState({repo: {name: 'repo-name', permissions: {push: false}}});
+
+ expect(wrapper.instance().renderIssueAttributeSelectors()).toBeNull();
+ });
+
+ it('should display attribute selectors when repo has push permissions', () => {
+ const wrapper = shallow(
);
+ wrapper.setState({repo: {name: 'repo-name', permissions: {push: true}}});
+
+ const selectors = wrapper.instance().renderIssueAttributeSelectors();
+ expect(selectors).not.toBeNull();
+ });
+});
diff --git a/webapp/tests/setup.tsx b/webapp/tests/setup.tsx
new file mode 100644
index 000000000..87151a3a4
--- /dev/null
+++ b/webapp/tests/setup.tsx
@@ -0,0 +1,7 @@
+// Copyright (c) 2018-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import Adapter from 'enzyme-adapter-react-16';
+import {configure} from 'enzyme';
+
+configure({adapter: new Adapter()});
From 762a3530e7e9dca734bacd0f697c3e86665d98ee Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Mon, 21 Apr 2025 15:52:04 +0530
Subject: [PATCH 13/18] updated snapshot
---
.../__snapshots__/create_update_issue.test.jsx.snap | 1 -
1 file changed, 1 deletion(-)
diff --git a/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap b/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
index 42cb01f85..d0f6e2a35 100644
--- a/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
+++ b/webapp/src/components/modals/create_update_issue/__snapshots__/create_update_issue.test.jsx.snap
@@ -57,7 +57,6 @@ exports[`CreateOrUpdateIssueModal should render correctly with default props 1`]
value={null}
/>
Date: Mon, 21 Apr 2025 16:07:00 +0530
Subject: [PATCH 14/18] fixed lint
---
.../create_update_issue.test.jsx | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx b/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
index bed1bcba0..5b90f16c5 100644
--- a/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
+++ b/webapp/src/components/modals/create_update_issue/create_update_issue.test.jsx
@@ -23,7 +23,6 @@ describe('CreateOrUpdateIssueModal', () => {
},
visible: true,
};
-
it('should render correctly with default props', () => {
const wrapper = shallow();
@@ -38,7 +37,7 @@ describe('CreateOrUpdateIssueModal', () => {
it('should display error message when create returns an error', async () => {
const mockCreateFunction = jest.fn().mockResolvedValue({error: {message: 'Some error'}});
-
+
const errorProps = {
...defaultProps,
create: mockCreateFunction,
@@ -47,22 +46,22 @@ describe('CreateOrUpdateIssueModal', () => {
repo_name: 'repo',
},
};
-
+
const wrapper = shallow();
wrapper.setState({issueTitle: 'Test Issue'});
-
+
await wrapper.instance().handleCreateOrUpdate({preventDefault: jest.fn()});
wrapper.update();
-
+
expect(wrapper.find('.help-text.error-text').text()).toEqual('Error occurred');
- });
+ });
it('should show validation error when issueTitle is empty', async () => {
- const wrapper = shallow();
- wrapper.setState({ issueTitle: '' });
-
- await wrapper.instance().handleCreateOrUpdate({ preventDefault: jest.fn() });
-
+ const wrapper = shallow();
+ wrapper.setState({issueTitle: ''});
+
+ await wrapper.instance().handleCreateOrUpdate({preventDefault: jest.fn()});
+
expect(wrapper.state('issueTitleValid')).toBe(false);
expect(wrapper.state('showErrors')).toBe(true);
});
From fc3e0c0620abed26483985ee82edc18a9207a505 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Mon, 21 Apr 2025 18:57:11 +0530
Subject: [PATCH 15/18] convert comment custom post to interactive dialog
---
server/plugin/api.go | 182 +++++++++++++++++++++++++++----------------
1 file changed, 115 insertions(+), 67 deletions(-)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 394afd3ec..9a44e24a6 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -112,7 +112,7 @@ const (
KeyIssueID string = "issue_id"
KeyStatus string = "status"
KeyChannelID string = "channel_id"
- KeyPostID string = "postId"
+ KeyPostID string = "post_id"
WebsocketEventOpenCommentModal string = "open_comment_modal"
WebsocketEventOpenStatusModal string = "open_status_modal"
@@ -121,6 +121,8 @@ const (
PathOpenIssueCommentModal string = "/open-comment-modal"
PathOpenIssueEditModal string = "/open-edit-modal"
PathOpenIssueStatusModal string = "/open-status-modal"
+
+ PathHandleOpenIssueCommentModal string = "/submit_issue_comment_dialog"
)
func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
@@ -190,6 +192,7 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc(PathOpenIssueCommentModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueCommentModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathOpenIssueEditModal, p.checkAuth(p.attachUserContext(p.handleOpenEditIssueModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathOpenIssueStatusModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueStatusModal), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc(PathHandleOpenIssueCommentModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueCommentDialog), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/config", checkPluginRequest(p.getConfig)).Methods(http.MethodGet)
apiRouter.HandleFunc("/token", checkPluginRequest(p.getToken)).Methods(http.MethodGet)
@@ -908,71 +911,55 @@ func getFailReason(code int, repo string, username string) string {
return cause
}
-func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *http.Request) {
- type CreateIssueCommentRequest struct {
- PostID string `json:"post_id"`
- Owner string `json:"owner"`
- Repo string `json:"repo"`
- Number int `json:"number"`
- Comment string `json:"comment"`
- ShowAttachedMessage bool `json:"show_attached_message"`
- }
+type CreateIssueCommentRequest struct {
+ PostID string `json:"post_id"`
+ Owner string `json:"owner"`
+ Repo string `json:"repo"`
+ Number int `json:"number"`
+ Comment string `json:"comment"`
+ ShowAttachedMessage bool `json:"show_attached_message"`
+}
+func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *http.Request) {
req := &CreateIssueCommentRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
c.Log.WithError(err).Warnf("Error decoding CreateIssueCommentRequest JSON body")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
- return
- }
-
- if req.PostID == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid post id", StatusCode: http.StatusBadRequest})
return
}
- if req.Owner == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository owner.", StatusCode: http.StatusBadRequest})
- return
- }
-
- if req.Repo == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository.", StatusCode: http.StatusBadRequest})
+ result, statusCode, err := p.handleCreateIssueComment(c, req)
+ if err != nil {
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: err.Error(), StatusCode: statusCode})
return
}
- if req.Number == 0 {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid issue number.", StatusCode: http.StatusBadRequest})
- return
- }
+ p.writeJSON(w, result)
+}
- if req.Comment == "" {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid non empty comment.", StatusCode: http.StatusBadRequest})
- return
+func (p *Plugin) handleCreateIssueComment(c *UserContext, req *CreateIssueCommentRequest) (*github.IssueComment, int, error) {
+ if req.PostID == "" || req.Owner == "" || req.Repo == "" || req.Number == 0 || req.Comment == "" {
+ p.client.Log.Error("Error creating comment on issue", "missing request fields")
+ return nil, http.StatusBadRequest, errors.New("invalid request fields")
}
-
githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
post, err := p.client.Post.GetPost(req.PostID)
- if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
- return
- }
- if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
- return
+ if err != nil || post == nil {
+ p.client.Log.Error("Error getting Post ID", "postID", req.PostID)
+ return nil, http.StatusInternalServerError, fmt.Errorf("failed to load post: %w", err)
}
commentUsername, err := p.getUsername(post.UserId)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
- return
+ p.client.Log.Error("Error getting username", "UserID", post.UserId, "error", err.Error())
+ return nil, http.StatusInternalServerError, fmt.Errorf("failed to get username: %w", err)
}
currentUsername := c.GHInfo.GitHubUsername
permalink, err := p.getPermaLink(req.PostID)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to generate permalink", StatusCode: http.StatusInternalServerError})
- return
+ p.client.Log.Error("Error getting permalink for the post", "PostID", req.PostID, "error", err.Error())
+ return nil, http.StatusInternalServerError, fmt.Errorf("failed to generate permalink: %w", err)
}
permalinkMessage := fmt.Sprintf("*@%s attached a* [message](%s) *from %s*\n\n", currentUsername, permalink, commentUsername)
@@ -987,10 +974,7 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
var rawResponse *github.Response
if cErr := p.useGitHubClient(c.GHInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
result, rawResponse, err = githubClient.Issues.CreateComment(c.Ctx, req.Owner, req.Repo, req.Number, comment)
- if err != nil {
- return err
- }
- return nil
+ return err
}); cErr != nil {
statusCode := 500
if rawResponse != nil {
@@ -1001,8 +985,7 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
"repo": req.Repo,
"number": req.Number,
}).Errorf("failed to create an issue comment")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to create an issue comment: " + getFailReason(statusCode, req.Repo, currentUsername), StatusCode: statusCode})
- return
+ return nil, statusCode, fmt.Errorf("GitHub comment creation failed: %w", err)
}
rootID := req.PostID
@@ -1023,13 +1006,48 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht
UserId: c.UserID,
}
- err = p.client.Post.CreatePost(reply)
+ if err := p.client.Post.CreatePost(reply); err != nil {
+ p.client.Log.Error("Error creating post for issue comment", "error", err.Error())
+ return nil, http.StatusInternalServerError, fmt.Errorf("failed to create reply post: %w", err)
+ }
+
+ return result, http.StatusOK, nil
+}
+
+func (p *Plugin) handleSubmitIssueCommentDialog(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ var submission model.SubmitDialogRequest
+ if err := json.NewDecoder(r.Body).Decode(&submission); err != nil {
+ p.client.Log.Error("Error decoding the request body for submit issue comment dialog handling", "error", err.Error())
+ http.Error(w, "invalid payload", http.StatusBadRequest)
+ return
+ }
+
+ state := make(map[string]string)
+ if err := json.Unmarshal([]byte(submission.State), &state); err != nil {
+ p.client.Log.Error("Error unmarshalling state for submit issue comment dialog handling", "error", err.Error())
+ http.Error(w, "invalid state", http.StatusBadRequest)
+ return
+ }
+
+ comment := submission.Submission["comment"].(string)
+ issueNumber, _ := strconv.Atoi(state["issue_number"])
+
+ req := &CreateIssueCommentRequest{
+ PostID: state[KeyPostID],
+ Owner: state[KeyRepoOwner],
+ Repo: state[KeyRepoName],
+ Number: issueNumber,
+ Comment: comment,
+ ShowAttachedMessage: false,
+ }
+
+ _, status, err := p.handleCreateIssueComment(c, req)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ http.Error(w, err.Error(), status)
return
}
- p.writeJSON(w, result)
+ w.WriteHeader(http.StatusOK)
}
func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*graphql.GithubPRDetails, assignmentResp []*github.Issue, openPRResp []*graphql.GithubPRDetails, err error) {
@@ -1951,29 +1969,59 @@ func (p *Plugin) handleOpenIssueStatusModal(c *UserContext, w http.ResponseWrite
}
func (p *Plugin) handleOpenIssueCommentModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
- response := &model.PostActionIntegrationResponse{}
decoder := json.NewDecoder(r.Body)
postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
- p.returnPostActionIntegrationResponse(w, response)
- return
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ triggerID := postActionIntegrationRequest.TriggerId
+ if triggerID == "" {
+ p.API.LogError("Trigger ID missing in request")
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ dialog := model.OpenDialogRequest{
+ TriggerId: triggerID,
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathHandleOpenIssueCommentModal),
+ Dialog: model.Dialog{
+ CallbackId: "create_issue_comment",
+ Title: "Create a comment to GitHub Issue",
+ SubmitLabel: "Attach",
+ NotifyOnCancel: false,
+ Elements: []model.DialogElement{
+ {
+ DisplayName: "Create a comment",
+ Name: "comment",
+ Type: "textarea",
+ Placeholder: "Enter your comment here...",
+ Optional: false,
+ },
+ },
+ State: toJSON(map[string]string{
+ KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner].(string),
+ KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName].(string),
+ KeyIssueNumber: fmt.Sprintf("%v", postActionIntegrationRequest.Context[KeyIssueNumber]),
+ KeyPostID: postActionIntegrationRequest.PostId,
+ }),
+ },
}
- p.client.Frontend.PublishWebSocketEvent(
- WebsocketEventOpenCommentModal,
- map[string]interface{}{
- KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
- KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
- KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
- KeyPostID: postActionIntegrationRequest.PostId,
- KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
- KeyChannelID: postActionIntegrationRequest.ChannelId,
- },
- &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
- )
+ if appErr := p.API.OpenInteractiveDialog(dialog); appErr != nil {
+ p.API.LogError("Failed to open interactive dialog", "Error", appErr.Error())
+ }
- p.returnPostActionIntegrationResponse(w, response)
+ p.API.LogInfo("Dialog Title", "Title", dialog.Dialog.Title)
+
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+}
+
+func toJSON(v interface{}) string {
+ b, _ := json.Marshal(v)
+ return string(b)
}
// parseRepo parses the owner & repository name from the repo query parameter
From a235186d4f4db42ce4ad3f352fa6d5bb007996cc Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Fri, 25 Apr 2025 16:11:09 +0530
Subject: [PATCH 16/18] convert close/reopen issue custom modal to interactive
dialog
---
server/plugin/api.go | 211 +++++++++++++++++++++++++++++++++----------
1 file changed, 162 insertions(+), 49 deletions(-)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 9a44e24a6..c688109f4 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -106,13 +106,17 @@ const (
// ResponseTypePlain indicates that response type is text plain
ResponseTypePlain ResponseType = "TEXT_RESPONSE"
- KeyRepoName string = "repo_name"
- KeyRepoOwner string = "repo_owner"
- KeyIssueNumber string = "issue_number"
- KeyIssueID string = "issue_id"
- KeyStatus string = "status"
- KeyChannelID string = "channel_id"
- KeyPostID string = "post_id"
+ KeyRepoName string = "repo_name"
+ KeyRepoOwner string = "repo_owner"
+ KeyIssueNumber string = "issue_number"
+ KeyIssueID string = "issue_id"
+ KeyIssueComment string = "issue_comment"
+ KeyStatus string = "status"
+ KeyStatusReason string = "status_reason"
+ KeyChannelID string = "channel_id"
+ KeyPostID string = "post_id"
+
+ IssueOpen string = "open"
WebsocketEventOpenCommentModal string = "open_comment_modal"
WebsocketEventOpenStatusModal string = "open_status_modal"
@@ -122,7 +126,8 @@ const (
PathOpenIssueEditModal string = "/open-edit-modal"
PathOpenIssueStatusModal string = "/open-status-modal"
- PathHandleOpenIssueCommentModal string = "/submit_issue_comment_dialog"
+ PathHandleOpenIssueCommentModal string = "/submit_issue_comment_dialog"
+ PathHandleOpenIssueCloseReopenModal string = "/submit_issue_close_reopen_dialog"
)
func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
@@ -193,6 +198,7 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc(PathOpenIssueEditModal, p.checkAuth(p.attachUserContext(p.handleOpenEditIssueModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathOpenIssueStatusModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueStatusModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathHandleOpenIssueCommentModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueCommentDialog), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc(PathHandleOpenIssueCloseReopenModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueCloseReopenDialog), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/config", checkPluginRequest(p.getConfig)).Methods(http.MethodGet)
apiRouter.HandleFunc("/token", checkPluginRequest(p.getToken)).Methods(http.MethodGet)
@@ -921,13 +927,13 @@ type CreateIssueCommentRequest struct {
}
func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *http.Request) {
- req := &CreateIssueCommentRequest{}
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ createIssueCommentRequest := &CreateIssueCommentRequest{}
+ if err := json.NewDecoder(r.Body).Decode(&createIssueCommentRequest); err != nil {
c.Log.WithError(err).Warnf("Error decoding CreateIssueCommentRequest JSON body")
return
}
- result, statusCode, err := p.handleCreateIssueComment(c, req)
+ result, statusCode, err := p.handleCreateIssueComment(c, createIssueCommentRequest)
if err != nil {
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: err.Error(), StatusCode: statusCode})
return
@@ -1050,6 +1056,47 @@ func (p *Plugin) handleSubmitIssueCommentDialog(c *UserContext, w http.ResponseW
w.WriteHeader(http.StatusOK)
}
+func (p *Plugin) handleSubmitIssueCloseReopenDialog(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ var submission model.SubmitDialogRequest
+ if err := json.NewDecoder(r.Body).Decode(&submission); err != nil {
+ p.client.Log.Error("Error decoding the request body for submit issue close/reopen dialog", "error", err.Error())
+ http.Error(w, "invalid payload", http.StatusBadRequest)
+ return
+ }
+
+ state := make(map[string]string)
+ if err := json.Unmarshal([]byte(submission.State), &state); err != nil {
+ p.client.Log.Error("Error unmarshalling state for issue close/reopen dialog", "error", err.Error())
+ http.Error(w, "invalid state", http.StatusBadRequest)
+ return
+ }
+
+ issueNumber, _ := strconv.Atoi(state[KeyIssueNumber])
+
+ req := &CommentAndCloseRequest{
+ PostID: state[KeyPostID],
+ ChannelID: state[KeyChannelID],
+ Owner: state[KeyRepoOwner],
+ Repository: state[KeyRepoName],
+ Number: issueNumber,
+ Status: state[KeyStatus],
+ IssueComment: submission.Submission[KeyIssueComment].(string),
+ }
+
+ if req.Status == IssueOpen {
+ req.StatusReason = submission.Submission[KeyStatusReason].(string)
+ } else {
+ req.StatusReason = state[KeyStatusReason]
+ }
+
+ if req.ChannelID == "" || req.Owner == "" || req.Repository == "" || req.Number == 0 || req.PostID == "" {
+ http.Error(w, "missing required issue data", http.StatusBadRequest)
+ return
+ }
+
+ p.handleCloseOrReopenIssue(c, w, req)
+}
+
func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*graphql.GithubPRDetails, assignmentResp []*github.Issue, openPRResp []*graphql.GithubPRDetails, err error) {
graphQLClient := p.graphQLConnect(c.GHInfo)
@@ -1686,33 +1733,38 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
p.writeJSON(w, result)
}
+type CommentAndCloseRequest struct {
+ ChannelID string `json:"channel_id"`
+ IssueComment string `json:"issue_comment"`
+ StatusReason string `json:"status_reason"`
+ Number int `json:"number"`
+ Owner string `json:"owner"`
+ Repository string `json:"repo"`
+ Status string `json:"status"`
+ PostID string `json:"postId"`
+}
+
func (p *Plugin) closeOrReopenIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
- type CommentAndCloseRequest struct {
- ChannelID string `json:"channel_id"`
- IssueComment string `json:"issue_comment"`
- StatusReason string `json:"status_reason"`
- Number int `json:"number"`
- Owner string `json:"owner"`
- Repository string `json:"repo"`
- Status string `json:"status"`
- PostID string `json:"postId"`
- }
-
- req := &CommentAndCloseRequest{}
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+ closeReopenIssueRequest := &CommentAndCloseRequest{}
+ if err := json.NewDecoder(r.Body).Decode(&closeReopenIssueRequest); err != nil {
c.Log.WithError(err).Warnf("Error decoding the JSON body")
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid JSON object.", StatusCode: http.StatusBadRequest})
return
}
- post, appErr := p.API.GetPost(req.PostID)
+ p.handleCloseOrReopenIssue(c, w, closeReopenIssueRequest)
+}
+
+func (p *Plugin) handleCloseOrReopenIssue(c *UserContext, w http.ResponseWriter, closeReopenIssueRequest *CommentAndCloseRequest) {
+ post, appErr := p.API.GetPost(closeReopenIssueRequest.PostID)
if appErr != nil {
- p.client.Log.Error("Unable to get the post", "PostID", req.PostID, "Error", appErr.Error())
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", req.PostID), StatusCode: http.StatusInternalServerError})
+ p.client.Log.Error("Unable to get the post", "PostID", closeReopenIssueRequest.PostID, "Error", appErr.Error())
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", closeReopenIssueRequest.PostID), StatusCode: http.StatusInternalServerError})
return
}
+
if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", req.PostID), StatusCode: http.StatusNotFound})
+ p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", closeReopenIssueRequest.PostID), StatusCode: http.StatusNotFound})
return
}
@@ -1721,15 +1773,17 @@ func (p *Plugin) closeOrReopenIssue(c *UserContext, w http.ResponseWriter, r *ht
p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to get username", StatusCode: http.StatusInternalServerError})
return
}
- if req.IssueComment != "" {
- p.CreateCommentToIssue(c, w, req.IssueComment, req.Owner, req.Repository, post, req.Number)
+
+ if closeReopenIssueRequest.IssueComment != "" {
+ p.CreateCommentToIssue(c, w, closeReopenIssueRequest.IssueComment, closeReopenIssueRequest.Owner, closeReopenIssueRequest.Repository, post, closeReopenIssueRequest.Number)
}
- if req.Status == statusClose {
- p.CloseOrReopenIssue(c, w, issueClose, req.StatusReason, req.Owner, req.Repository, post, req.Number)
- } else {
- p.CloseOrReopenIssue(c, w, issueOpen, req.StatusReason, req.Owner, req.Repository, post, req.Number)
+ status := issueOpen
+ if closeReopenIssueRequest.Status == IssueOpen {
+ status = issueClose
}
+
+ p.CloseOrReopenIssue(c, w, status, closeReopenIssueRequest.StatusReason, closeReopenIssueRequest.Owner, closeReopenIssueRequest.Repository, post, closeReopenIssueRequest.Number)
}
func (p *Plugin) createIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
@@ -1943,29 +1997,88 @@ func (p *Plugin) returnPostActionIntegrationResponse(w http.ResponseWriter, res
}
func (p *Plugin) handleOpenIssueStatusModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
- response := &model.PostActionIntegrationResponse{}
decoder := json.NewDecoder(r.Body)
postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
- if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
+ if err := decoder.Decode(postActionIntegrationRequest); err != nil {
p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
- p.returnPostActionIntegrationResponse(w, response)
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
return
}
- p.client.Frontend.PublishWebSocketEvent(
- WebsocketEventOpenStatusModal,
- map[string]interface{}{
- KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
- KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
- KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
- KeyPostID: postActionIntegrationRequest.PostId,
- KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
- KeyChannelID: postActionIntegrationRequest.ChannelId,
+ triggerID := postActionIntegrationRequest.TriggerId
+ if triggerID == "" {
+ p.API.LogError("Trigger ID missing in request")
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ repoOwner := postActionIntegrationRequest.Context[KeyRepoOwner].(string)
+ repoName := postActionIntegrationRequest.Context[KeyRepoName].(string)
+ issueNumber := fmt.Sprintf("%v", postActionIntegrationRequest.Context[KeyIssueNumber])
+ postID := postActionIntegrationRequest.PostId
+ channelID := postActionIntegrationRequest.ChannelId
+ status := postActionIntegrationRequest.Context[KeyStatus].(string)
+
+ dialogTitle := "Reopen Issue"
+ submitLabel := "Reopen Issue"
+ elements := []model.DialogElement{
+ {
+ DisplayName: "Leave a comment",
+ Name: KeyIssueComment,
+ Type: "textarea",
+ Placeholder: "Add a comment...",
+ Optional: true,
},
- &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
- )
+ }
- p.returnPostActionIntegrationResponse(w, response)
+ stateMap := map[string]string{
+ KeyChannelID: channelID,
+ KeyStatus: status,
+ KeyIssueNumber: issueNumber,
+ KeyRepoOwner: repoOwner,
+ KeyRepoName: repoName,
+ KeyPostID: postID,
+ }
+
+ if status == IssueOpen {
+ status = statusClose
+ dialogTitle = "Close Issue"
+ submitLabel = "Close Issue"
+
+ elements = append(elements, model.DialogElement{
+ DisplayName: "Mark issue as",
+ Name: KeyStatusReason,
+ Type: "radio",
+ Optional: false,
+ Options: []*model.PostActionOptions{
+ {Text: "Completed", Value: "completed"},
+ {Text: "Not planned", Value: "not_planned"},
+ },
+ })
+ } else {
+ stateMap[KeyStatusReason] = "reopened"
+ }
+
+ state := toJSON(stateMap)
+
+ dialog := model.OpenDialogRequest{
+ TriggerId: triggerID,
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathHandleOpenIssueCloseReopenModal),
+ Dialog: model.Dialog{
+ CallbackId: "close_or_reopen_issue",
+ Title: dialogTitle,
+ SubmitLabel: submitLabel,
+ NotifyOnCancel: false,
+ Elements: elements,
+ State: state,
+ },
+ }
+
+ if appErr := p.API.OpenInteractiveDialog(dialog); appErr != nil {
+ p.API.LogError("Failed to open interactive dialog", "Error", appErr.Error())
+ }
+
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
}
func (p *Plugin) handleOpenIssueCommentModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
From ea9e9efb2689f749990bb16096c29c8199cbfab6 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Tue, 29 Apr 2025 19:46:18 +0530
Subject: [PATCH 17/18] convert edit issue custom modal to interactive dialog
---
server/plugin/api.go | 498 ++++++++++++++++++++++++++++++-------------
1 file changed, 349 insertions(+), 149 deletions(-)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index c688109f4..484794cf0 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -115,6 +115,11 @@ const (
KeyStatusReason string = "status_reason"
KeyChannelID string = "channel_id"
KeyPostID string = "post_id"
+ KeyTitle string = "title"
+ KeyAssignees string = "assignees"
+ KeyLabels string = "labels"
+ KeyDescription string = "description"
+ KeyRepoFullName string = "repo_full_name"
IssueOpen string = "open"
@@ -128,6 +133,7 @@ const (
PathHandleOpenIssueCommentModal string = "/submit_issue_comment_dialog"
PathHandleOpenIssueCloseReopenModal string = "/submit_issue_close_reopen_dialog"
+ PathHandleOpenIssueEditModal string = "/submit_issue_edit_dialog"
)
func (p *Plugin) writeJSON(w http.ResponseWriter, v interface{}) {
@@ -199,6 +205,7 @@ func (p *Plugin) initializeAPI() {
apiRouter.HandleFunc(PathOpenIssueStatusModal, p.checkAuth(p.attachUserContext(p.handleOpenIssueStatusModal), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathHandleOpenIssueCommentModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueCommentDialog), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc(PathHandleOpenIssueCloseReopenModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueCloseReopenDialog), ResponseTypePlain)).Methods(http.MethodPost)
+ apiRouter.HandleFunc(PathHandleOpenIssueEditModal, p.checkAuth(p.attachUserContext(p.handleSubmitIssueEditDialog), ResponseTypePlain)).Methods(http.MethodPost)
apiRouter.HandleFunc("/config", checkPluginRequest(p.getConfig)).Methods(http.MethodGet)
apiRouter.HandleFunc("/token", checkPluginRequest(p.getToken)).Methods(http.MethodGet)
@@ -1097,6 +1104,57 @@ func (p *Plugin) handleSubmitIssueCloseReopenDialog(c *UserContext, w http.Respo
p.handleCloseOrReopenIssue(c, w, req)
}
+func (p *Plugin) handleSubmitIssueEditDialog(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ defer r.Body.Close()
+
+ var submission model.SubmitDialogRequest
+ if err := json.NewDecoder(r.Body).Decode(&submission); err != nil {
+ c.Log.WithError(err).Warnf("Failed to decode SubmitDialogRequest")
+ http.Error(w, "Invalid request", http.StatusBadRequest)
+ return
+ }
+
+ var state map[string]interface{}
+ if err := json.Unmarshal([]byte(submission.State), &state); err != nil {
+ c.Log.WithError(err).Warnf("Failed to decode dialog state")
+ http.Error(w, "Invalid state", http.StatusBadRequest)
+ return
+ }
+
+ issueNumberStr := fmt.Sprintf("%v", state[KeyIssueNumber])
+ issueNumber, err := strconv.Atoi(issueNumberStr)
+ if err != nil {
+ c.Log.WithError(err).Warnf("Invalid issue number in state")
+ http.Error(w, "Invalid issue number", http.StatusBadRequest)
+ return
+ }
+
+ milestone := 0
+ if v, ok := submission.Submission["milestone"].(string); ok && v != "" {
+ milestone, _ = strconv.Atoi(v)
+ }
+
+ issue := &UpdateIssueRequest{
+ Title: submission.Submission["Title"].(string),
+ Body: submission.Submission["Description"].(string),
+ Repo: fmt.Sprintf("%v/%v", state[KeyRepoOwner], state[KeyRepoName]),
+ PostID: fmt.Sprintf("%v", state[KeyPostID]),
+ ChannelID: fmt.Sprintf("%v", state[KeyChannelID]),
+ Labels: []string{submission.Submission["Label"].(string)},
+ Assignees: []string{submission.Submission["Assignee"].(string)},
+ Milestone: milestone,
+ IssueNumber: issueNumber,
+ }
+
+ if _, err := p.updateGithubIssue(c, issue); err != nil {
+ c.Log.WithError(err).Warnf("Failed to update issue")
+ http.Error(w, "Failed to update issue", http.StatusInternalServerError)
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+}
+
func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*graphql.GithubPRDetails, assignmentResp []*github.Issue, openPRResp []*graphql.GithubPRDetails, err error) {
graphQLClient := p.graphQLConnect(c.GHInfo)
@@ -1178,23 +1236,11 @@ func (p *Plugin) updateSettings(c *UserContext, w http.ResponseWriter, r *http.R
p.writeJSON(w, info.Settings)
}
-func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner := r.FormValue(ownerQueryParam)
- repo := r.FormValue(repoQueryParam)
- number := r.FormValue(numberQueryParam)
- postID := r.FormValue(postIDQueryParam)
+func (p *Plugin) getGitHubIssueInfo(c *UserContext, owner, repo string, issueNumber int, postID string) (map[string]interface{}, *APIErrorResponse) {
+ client := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- issueNumber, err := strconv.Atoi(number)
+ issue, _, err := client.Issues.Get(c.Context.Ctx, owner, repo, issueNumber)
if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
- return
- }
-
- githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
- issue, _, err := githubClient.Issues.Get(c.Ctx, owner, repo, issueNumber)
- if err != nil {
- // If the issue is not found, it probably belongs to a private repo.
- // Return an empty response in that case.
var gerr *github.ErrorResponse
if errors.As(err, &gerr) && gerr.Response.StatusCode == http.StatusNotFound {
c.Log.WithError(err).With(logger.LogContext{
@@ -1202,8 +1248,7 @@ func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Req
"repo": repo,
"number": issueNumber,
}).Debugf("Issue not found")
- p.writeJSON(w, nil)
- return
+ return nil, nil
}
c.Log.WithError(err).With(logger.LogContext{
@@ -1211,8 +1256,16 @@ func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Req
"repo": repo,
"number": issueNumber,
}).Debugf("Could not get the issue")
- p.writeAPIError(w, &APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError})
- return
+ return nil, &APIErrorResponse{Message: "Could not get the issue", StatusCode: http.StatusInternalServerError}
+ }
+
+ post, appErr := p.API.GetPost(postID)
+ if appErr != nil {
+ p.client.Log.Error("Unable to get the post", "PostID", postID, "Error", appErr.Error())
+ return nil, &APIErrorResponse{Message: fmt.Sprintf("failed to load the post %s", postID), StatusCode: http.StatusInternalServerError}
+ }
+ if post == nil {
+ return nil, &APIErrorResponse{Message: fmt.Sprintf("failed to load the post %s : not found", postID), StatusCode: http.StatusNotFound}
}
description := ""
@@ -1231,34 +1284,47 @@ func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Req
}
milestoneTitle := ""
- var milestoneNumber int
+ milestoneNumber := 0
if issue.Milestone != nil && issue.Milestone.Title != nil {
milestoneTitle = *issue.Milestone.Title
milestoneNumber = *issue.Milestone.Number
}
- post, appErr := p.API.GetPost(postID)
- if appErr != nil {
- p.client.Log.Error("Unable to get the post", "PostID", postID, "Error", appErr.Error())
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", postID), StatusCode: http.StatusInternalServerError})
+ return map[string]interface{}{
+ KeyTitle: issue.GetTitle(),
+ KeyChannelID: post.ChannelId,
+ KeyPostID: postID,
+ "milestone_title": milestoneTitle,
+ "milestone_number": milestoneNumber,
+ KeyAssignees: assignees,
+ KeyLabels: labels,
+ KeyDescription: description,
+ KeyRepoFullName: fmt.Sprintf("%s/%s", owner, repo),
+ "issue_number": issue.GetNumber(),
+ }, nil
+}
+
+func (p *Plugin) getIssueInfo(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner := r.FormValue(ownerQueryParam)
+ repo := r.FormValue(repoQueryParam)
+ number := r.FormValue(numberQueryParam)
+ postID := r.FormValue(postIDQueryParam)
+
+ issueNumber, err := strconv.Atoi(number)
+ if err != nil {
+ p.writeAPIError(w, &APIErrorResponse{Message: "Invalid param 'number'.", StatusCode: http.StatusBadRequest})
return
}
- if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", postID), StatusCode: http.StatusNotFound})
+
+ issueInfo, apiErr := p.getGitHubIssueInfo(c, owner, repo, issueNumber, postID)
+
+ if apiErr != nil {
+ p.writeAPIError(w, apiErr)
return
}
-
- issueInfo := map[string]interface{}{
- "title": *issue.Title,
- "channel_id": post.ChannelId,
- "postId": postID,
- "milestone_title": milestoneTitle,
- "milestone_number": milestoneNumber,
- "assignees": assignees,
- "labels": labels,
- "description": description,
- "repo_full_name": fmt.Sprintf("%s/%s", owner, repo),
- "issue_number": *issue.Number,
+ if issueInfo == nil {
+ p.writeJSON(w, nil)
+ return
}
p.writeJSON(w, issueInfo)
@@ -1360,33 +1426,21 @@ func (p *Plugin) getPrByNumber(c *UserContext, w http.ResponseWriter, r *http.Re
p.writeJSON(w, result)
}
-func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
- if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
- return
- }
-
- githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+func (p *Plugin) fetchLabels(ctx context.Context, ghInfo *GitHubUserInfo, owner, repo string) ([]*github.Label, error) {
+ githubClient := p.githubConnectUser(ctx, ghInfo)
var allLabels []*github.Label
opt := github.ListOptions{PerPage: 50}
for {
var labels []*github.Label
var resp *github.Response
- if cErr := p.useGitHubClient(c.GHInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
- labels, resp, err = githubClient.Issues.ListLabels(c.Ctx, owner, repo, &opt)
- if err != nil {
- return err
- }
- return nil
- }); cErr != nil {
- c.Log.WithError(cErr).With(logger.LogContext{
- "owner": owner,
- "repo": repo,
- }).Warnf("Failed to list labels")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
- return
+ err := p.useGitHubClient(ghInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
+ var e error
+ labels, resp, e = githubClient.Issues.ListLabels(ctx, owner, repo, &opt)
+ return e
+ })
+ if err != nil {
+ return nil, err
}
allLabels = append(allLabels, labels...)
if resp.NextPage == 0 {
@@ -1395,36 +1449,24 @@ func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Reques
opt.Page = resp.NextPage
}
- p.writeJSON(w, allLabels)
+ return allLabels, nil
}
-func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
- if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
- return
- }
-
- githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+func (p *Plugin) fetchAssignees(ctx context.Context, ghInfo *GitHubUserInfo, owner, repo string) ([]*github.User, error) {
+ githubClient := p.githubConnectUser(ctx, ghInfo)
var allAssignees []*github.User
opt := github.ListOptions{PerPage: 50}
for {
var assignees []*github.User
var resp *github.Response
- if cErr := p.useGitHubClient(c.GHInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
- assignees, resp, err = githubClient.Issues.ListAssignees(c.Ctx, owner, repo, &opt)
- if err != nil {
- return err
- }
- return nil
- }); cErr != nil {
- c.Log.WithError(cErr).With(logger.LogContext{
- "owner": owner,
- "repo": repo,
- }).Warnf("Failed to list assignees")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
- return
+ err := p.useGitHubClient(ghInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
+ var e error
+ assignees, resp, e = githubClient.Issues.ListAssignees(ctx, owner, repo, &opt)
+ return e
+ })
+ if err != nil {
+ return nil, err
}
allAssignees = append(allAssignees, assignees...)
if resp.NextPage == 0 {
@@ -1433,36 +1475,24 @@ func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Req
opt.Page = resp.NextPage
}
- p.writeJSON(w, allAssignees)
+ return allAssignees, nil
}
-func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Request) {
- owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
- if err != nil {
- p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
- return
- }
-
- githubClient := p.githubConnectUser(c.Context.Ctx, c.GHInfo)
+func (p *Plugin) fetchMilestones(ctx context.Context, ghInfo *GitHubUserInfo, owner, repo string) ([]*github.Milestone, error) {
+ githubClient := p.githubConnectUser(ctx, ghInfo)
var allMilestones []*github.Milestone
opt := github.ListOptions{PerPage: 50}
for {
var milestones []*github.Milestone
var resp *github.Response
- if cErr := p.useGitHubClient(c.GHInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
- milestones, resp, err = githubClient.Issues.ListMilestones(c.Ctx, owner, repo, &github.MilestoneListOptions{ListOptions: opt})
- if err != nil {
- return err
- }
- return nil
- }); cErr != nil {
- c.Log.WithError(cErr).With(logger.LogContext{
- "owner": owner,
- "repo": repo,
- }).Warnf("Failed to list milestones")
- p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
- return
+ err := p.useGitHubClient(ghInfo, func(info *GitHubUserInfo, token *oauth2.Token) error {
+ var e error
+ milestones, resp, e = githubClient.Issues.ListMilestones(ctx, owner, repo, &github.MilestoneListOptions{ListOptions: opt})
+ return e
+ })
+ if err != nil {
+ return nil, err
}
allMilestones = append(allMilestones, milestones...)
if resp.NextPage == 0 {
@@ -1471,7 +1501,58 @@ func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Re
opt.Page = resp.NextPage
}
- p.writeJSON(w, allMilestones)
+ return allMilestones, nil
+}
+
+func (p *Plugin) getLabels(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
+ if err != nil {
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ labels, err := p.fetchLabels(c.Context.Ctx, c.GHInfo, owner, repo)
+ if err != nil {
+ c.Log.WithError(err).Warnf("Failed to list labels")
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch labels", StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ p.writeJSON(w, labels)
+}
+
+func (p *Plugin) getAssignees(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
+ if err != nil {
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ assignees, err := p.fetchAssignees(c.Context.Ctx, c.GHInfo, owner, repo)
+ if err != nil {
+ c.Log.WithError(err).Warnf("Failed to list assignees")
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch assignees", StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ p.writeJSON(w, assignees)
+}
+
+func (p *Plugin) getMilestones(c *UserContext, w http.ResponseWriter, r *http.Request) {
+ owner, repo, err := parseRepo(r.URL.Query().Get("repo"))
+ if err != nil {
+ p.writeAPIError(w, &APIErrorResponse{Message: err.Error(), StatusCode: http.StatusBadRequest})
+ return
+ }
+
+ milestones, err := p.fetchMilestones(c.Context.Ctx, c.GHInfo, owner, repo)
+ if err != nil {
+ c.Log.WithError(err).Warnf("Failed to list milestones")
+ p.writeAPIError(w, &APIErrorResponse{Message: "Failed to fetch milestones", StatusCode: http.StatusInternalServerError})
+ return
+ }
+
+ p.writeJSON(w, milestones)
}
func (p *Plugin) getRepositoryList(c context.Context, ghInfo *GitHubUserInfo, userName string, githubClient *github.Client, opt github.ListOptions) ([]*github.Repository, error) {
@@ -1627,7 +1708,6 @@ func (p *Plugin) getRepositories(c *UserContext, w http.ResponseWriter, r *http.
}
func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Request) {
- // get data for the issue from the request body and fill UpdateIssueRequest to update the issue
issue := &UpdateIssueRequest{}
if err := json.NewDecoder(r.Body).Decode(&issue); err != nil {
c.Log.WithError(err).Warnf("Error decoding the JSON body")
@@ -1639,18 +1719,26 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
return
}
+ result, apiErr := p.updateGithubIssue(c, issue)
+ if apiErr != nil {
+ p.writeAPIError(w, apiErr)
+ return
+ }
+
+ p.writeJSON(w, result)
+}
+
+func (p *Plugin) updateGithubIssue(c *UserContext, issue *UpdateIssueRequest) (*github.Issue, *APIErrorResponse) {
var post *model.Post
if issue.PostID != "" {
var appErr *model.AppError
post, appErr = p.API.GetPost(issue.PostID)
if appErr != nil {
p.client.Log.Error("Unable to get the post", "PostID", issue.PostID, "Error", appErr.Error())
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError})
- return
+ return nil, &APIErrorResponse{Message: fmt.Sprintf("failed to load the post %s", issue.PostID), StatusCode: http.StatusInternalServerError}
}
if post == nil {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to load the post %s : not found", issue.PostID), StatusCode: http.StatusNotFound})
- return
+ return nil, &APIErrorResponse{Message: fmt.Sprintf("post %s not found", issue.PostID), StatusCode: http.StatusNotFound}
}
}
@@ -1660,9 +1748,6 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
Labels: &issue.Labels,
Assignees: &issue.Assignees,
}
-
- // submitting the request with an invalid milestone ID results in a 422 error
- // we should make sure it's not zero here because the webapp client might have left this field empty
if issue.Milestone > 0 {
githubIssue.Milestone = &issue.Milestone
}
@@ -1670,13 +1755,12 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
currentUser, appErr := p.API.GetUser(c.UserID)
if appErr != nil {
p.client.Log.Error("Unable to get the user", "UserID", c.UserID, "Error", appErr.Error())
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "failed to load current user", StatusCode: http.StatusInternalServerError})
- return
+ return nil, &APIErrorResponse{Message: "failed to load current user", StatusCode: http.StatusInternalServerError}
}
splittedRepo := strings.Split(issue.Repo, "/")
if len(splittedRepo) < 2 {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Please provide a valid repository", StatusCode: http.StatusBadRequest})
+ return nil, &APIErrorResponse{Message: "Please provide a valid repository", StatusCode: http.StatusBadRequest}
}
owner, repoName := splittedRepo[0], splittedRepo[1]
@@ -1685,20 +1769,13 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
result, resp, err := githubClient.Issues.Edit(c.Ctx, owner, repoName, issue.IssueNumber, githubIssue)
if err != nil {
if resp != nil && resp.Response.StatusCode == http.StatusGone {
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed})
- return
+ return nil, &APIErrorResponse{Message: "Issues are disabled on this repository.", StatusCode: http.StatusMethodNotAllowed}
}
-
c.Log.WithError(err).Warnf("Failed to update the issue")
- p.writeAPIError(w, &APIErrorResponse{
- ID: "",
- Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode,
- issue.Repo,
- currentUser.Username,
- )),
+ return nil, &APIErrorResponse{
+ Message: fmt.Sprintf("failed to update the issue: %s", getFailReason(resp.StatusCode, issue.Repo, currentUser.Username)),
StatusCode: resp.StatusCode,
- })
- return
+ }
}
rootID := issue.PostID
@@ -1719,18 +1796,20 @@ func (p *Plugin) updateIssue(c *UserContext, w http.ResponseWriter, r *http.Requ
}
if post != nil {
- _, appErr = p.API.CreatePost(reply)
+ if _, appErr = p.API.CreatePost(reply); appErr != nil {
+ c.Log.WithError(appErr).Warnf("failed to create notification post")
+ return nil, &APIErrorResponse{
+ Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID),
+ StatusCode: http.StatusInternalServerError,
+ }
+ }
} else {
_ = p.API.SendEphemeralPost(c.UserID, reply)
}
- if appErr != nil {
- c.Log.WithError(appErr).Warnf("failed to create the notification post")
- p.writeAPIError(w, &APIErrorResponse{ID: "", Message: fmt.Sprintf("failed to create the notification post, postID: %s, channelID: %s", issue.PostID, channelID), StatusCode: http.StatusInternalServerError})
- return
- }
- p.updatePost(issue, w)
- p.writeJSON(w, result)
+ p.updatePost(issue, nil)
+
+ return result, nil
}
type CommentAndCloseRequest struct {
@@ -1963,29 +2042,150 @@ func (p *Plugin) getToken(w http.ResponseWriter, r *http.Request) {
}
func (p *Plugin) handleOpenEditIssueModal(c *UserContext, w http.ResponseWriter, r *http.Request) {
- response := &model.PostActionIntegrationResponse{}
decoder := json.NewDecoder(r.Body)
postActionIntegrationRequest := &model.PostActionIntegrationRequest{}
- if err := decoder.Decode(&postActionIntegrationRequest); err != nil {
+ if err := decoder.Decode(postActionIntegrationRequest); err != nil {
p.API.LogError("Error decoding PostActionIntegrationRequest params", "Error", err.Error())
- p.returnPostActionIntegrationResponse(w, response)
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
return
}
- p.client.Frontend.PublishWebSocketEvent(
- WebsocketEventOpenEditModal,
- map[string]interface{}{
- KeyRepoName: postActionIntegrationRequest.Context[KeyRepoName],
- KeyRepoOwner: postActionIntegrationRequest.Context[KeyRepoOwner],
- KeyIssueNumber: postActionIntegrationRequest.Context[KeyIssueNumber],
- KeyPostID: postActionIntegrationRequest.PostId,
- KeyStatus: postActionIntegrationRequest.Context[KeyStatus],
- KeyChannelID: postActionIntegrationRequest.ChannelId,
+ triggerID := postActionIntegrationRequest.TriggerId
+ if triggerID == "" {
+ p.API.LogError("Trigger ID missing in request")
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ repoOwner := postActionIntegrationRequest.Context[KeyRepoOwner].(string)
+ repoName := postActionIntegrationRequest.Context[KeyRepoName].(string)
+ issueNumber := fmt.Sprintf("%v", postActionIntegrationRequest.Context[KeyIssueNumber])
+ postID := postActionIntegrationRequest.PostId
+ channelID := postActionIntegrationRequest.ChannelId
+ status := postActionIntegrationRequest.Context[KeyStatus].(string)
+
+ issueNum, err := strconv.Atoi(issueNumber)
+ if err != nil {
+ p.API.LogError("Invalid issue number", "IssueNumber", issueNumber, "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ issueInfo, apiErr := p.getGitHubIssueInfo(c, repoOwner, repoName, issueNum, postID)
+ if apiErr != nil {
+ p.API.LogError("Failed to fetch issue info", "Error", apiErr.Message)
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ issueTitle, _ := issueInfo[KeyTitle].(string)
+ assigneesList, _ := issueInfo[KeyAssignees].([]string)
+ labelsList, _ := issueInfo[KeyLabels].([]string)
+ description, _ := issueInfo[KeyDescription].(string)
+ repoFullName, _ := issueInfo[KeyRepoFullName].(string)
+
+ labels, err := p.fetchLabels(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
+ if err != nil {
+ p.API.LogError("Failed to fetch labels", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+ assignees, err := p.fetchAssignees(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
+ if err != nil {
+ p.API.LogError("Failed to fetch assignees", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+ milestones, err := p.fetchMilestones(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
+ if err != nil {
+ p.API.LogError("Failed to fetch milestones", "Error", err.Error())
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
+ return
+ }
+
+ milestoneDefaultValue := ""
+ if len(milestones) > 0 {
+ milestoneDefaultValue = fmt.Sprintf("%d", milestones[0].GetNumber())
+ }
+
+ labelValues := []*model.PostActionOptions{}
+ for _, label := range labels {
+ name := label.GetName()
+ labelValues = append(labelValues, &model.PostActionOptions{Text: name, Value: name})
+ }
+
+ assigneeValues := []*model.PostActionOptions{}
+ for _, user := range assignees {
+ login := user.GetLogin()
+ assigneeValues = append(assigneeValues, &model.PostActionOptions{Text: login, Value: login})
+ }
+
+ milestoneValues := []*model.PostActionOptions{}
+ for _, milestone := range milestones {
+ milestoneValues = append(milestoneValues, &model.PostActionOptions{Text: milestone.GetTitle(), Value: fmt.Sprintf("%d", milestone.GetNumber())})
+ }
+
+ var elements []model.DialogElement
+
+ elements = append(elements, model.DialogElement{
+ DisplayName: "Title for the GitHub Issue",
+ Name: "Title",
+ Type: "text",
+ Optional: false,
+ Default: issueTitle,
+ })
+
+ elements = append(elements, model.DialogElement{
+ DisplayName: "Description for the GitHub Issue",
+ Name: "Description",
+ Placeholder: "Add description to the issue...",
+ Type: "textarea",
+ Optional: true,
+ Default: description,
+ })
+
+ elements = append(elements, model.DialogElement{
+ DisplayName: "Milestone",
+ Name: "Milestone",
+ Type: "select",
+ Placeholder: "Select...",
+ Optional: true,
+ Options: milestoneValues,
+ Default: milestoneDefaultValue,
+ })
+
+ stateMap := map[string]string{
+ KeyChannelID: channelID,
+ KeyStatus: status,
+ KeyIssueNumber: issueNumber,
+ KeyRepoOwner: repoOwner,
+ KeyRepoName: repoName,
+ KeyPostID: postID,
+ }
+
+ state := toJSON(stateMap)
+
+ introduction := fmt.Sprintf("##### Repository: `%s`\n ##### Labels: `%s` \n ##### Assignees: `%s`", repoFullName, strings.Join(labelsList, ", "), strings.Join(assigneesList, ", "))
+
+ dialog := model.OpenDialogRequest{
+ TriggerId: triggerID,
+ URL: fmt.Sprintf("%s%s", p.GetPluginAPIPath(), PathHandleOpenIssueEditModal),
+ Dialog: model.Dialog{
+ CallbackId: "edit_issue",
+ Title: "Update GitHub Issue",
+ IntroductionText: introduction,
+ SubmitLabel: "Submit",
+ NotifyOnCancel: false,
+ Elements: elements,
+ State: state,
},
- &model.WebsocketBroadcast{UserId: postActionIntegrationRequest.UserId},
- )
+ }
+
+ if appErr := p.API.OpenInteractiveDialog(dialog); appErr != nil {
+ p.API.LogError("Failed to open interactive dialog", "Error", appErr.Error())
+ }
- p.returnPostActionIntegrationResponse(w, response)
+ p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
}
func (p *Plugin) returnPostActionIntegrationResponse(w http.ResponseWriter, res *model.PostActionIntegrationResponse) {
From 5e5e35231653f1b87eb08adac1f1686f1077d947 Mon Sep 17 00:00:00 2001
From: kshitij katiyar
Date: Wed, 30 Apr 2025 11:12:39 +0530
Subject: [PATCH 18/18] Lint fixes
---
server/plugin/api.go | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/server/plugin/api.go b/server/plugin/api.go
index 484794cf0..7d8be91cc 100644
--- a/server/plugin/api.go
+++ b/server/plugin/api.go
@@ -2084,18 +2084,6 @@ func (p *Plugin) handleOpenEditIssueModal(c *UserContext, w http.ResponseWriter,
description, _ := issueInfo[KeyDescription].(string)
repoFullName, _ := issueInfo[KeyRepoFullName].(string)
- labels, err := p.fetchLabels(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
- if err != nil {
- p.API.LogError("Failed to fetch labels", "Error", err.Error())
- p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
- return
- }
- assignees, err := p.fetchAssignees(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
- if err != nil {
- p.API.LogError("Failed to fetch assignees", "Error", err.Error())
- p.returnPostActionIntegrationResponse(w, &model.PostActionIntegrationResponse{})
- return
- }
milestones, err := p.fetchMilestones(c.Context.Ctx, c.GHInfo, repoOwner, repoName)
if err != nil {
p.API.LogError("Failed to fetch milestones", "Error", err.Error())
@@ -2108,18 +2096,6 @@ func (p *Plugin) handleOpenEditIssueModal(c *UserContext, w http.ResponseWriter,
milestoneDefaultValue = fmt.Sprintf("%d", milestones[0].GetNumber())
}
- labelValues := []*model.PostActionOptions{}
- for _, label := range labels {
- name := label.GetName()
- labelValues = append(labelValues, &model.PostActionOptions{Text: name, Value: name})
- }
-
- assigneeValues := []*model.PostActionOptions{}
- for _, user := range assignees {
- login := user.GetLogin()
- assigneeValues = append(assigneeValues, &model.PostActionOptions{Text: login, Value: login})
- }
-
milestoneValues := []*model.PostActionOptions{}
for _, milestone := range milestones {
milestoneValues = append(milestoneValues, &model.PostActionOptions{Text: milestone.GetTitle(), Value: fmt.Sprintf("%d", milestone.GetNumber())})
@@ -2241,7 +2217,6 @@ func (p *Plugin) handleOpenIssueStatusModal(c *UserContext, w http.ResponseWrite
}
if status == IssueOpen {
- status = statusClose
dialogTitle = "Close Issue"
submitLabel = "Close Issue"