diff --git a/.gitignore b/.gitignore index f9d8f2ea1..8d4eb5fcc 100755 --- a/.gitignore +++ b/.gitignore @@ -246,3 +246,11 @@ cla-backend/run-python-test-example-*.py out *.secret *log*.json + +# Cypress test outputs +**/cypress/screenshots/ +**/cypress/videos/ +**/cypress/reports/ + +# Local env vars +.env diff --git a/cla-backend-go/auth/auth0.go b/cla-backend-go/auth/auth0.go index 2d0dc717f..dcaa3ef98 100644 --- a/cla-backend-go/auth/auth0.go +++ b/cla-backend-go/auth/auth0.go @@ -24,7 +24,7 @@ type Validator struct { } // NewAuthValidator creates a new auth0 validator based on the specified parameters -func NewAuthValidator(domain, clientID, usernameClaim, algorithm string) (Validator, error) { // nolint +func NewAuthValidator(domain, clientID, usernameClaim, nameClaim, emailClaim, algorithm string) (Validator, error) { // nolint if domain == "" { return Validator{}, errors.New("missing Domain") } @@ -43,8 +43,8 @@ func NewAuthValidator(domain, clientID, usernameClaim, algorithm string) (Valida usernameClaim: usernameClaim, algorithm: algorithm, wellKnownURL: "https://" + path.Join(domain, ".well-known/jwks.json"), - nameClaim: "name", - emailClaim: "email", + nameClaim: nameClaim, + emailClaim: emailClaim, } return validator, nil diff --git a/cla-backend-go/cmd/response_metrics.go b/cla-backend-go/cmd/response_metrics.go index e3241a290..98eee4e7c 100644 --- a/cla-backend-go/cmd/response_metrics.go +++ b/cla-backend-go/cmd/response_metrics.go @@ -4,6 +4,7 @@ package cmd import ( + "sync" "time" "github.com/linuxfoundation/easycla/cla-backend-go/utils" @@ -18,32 +19,36 @@ type responseMetrics struct { expire time.Time } -var reqMap = make(map[string]*responseMetrics, 5) +var reqMap sync.Map // requestStart holds the request ID, method and timing information in a small structure func requestStart(reqID, method string) { now, _ := utils.CurrentTime() - reqMap[reqID] = &responseMetrics{ + rm := &responseMetrics{ reqID: reqID, method: method, start: now, elapsed: 0, expire: now.Add(time.Minute * 5), } + reqMap.Store(reqID, rm) } // getRequestMetrics returns the response metrics based on the request id value func getRequestMetrics(reqID string) *responseMetrics { - if x, found := reqMap[reqID]; found { + if val, found := reqMap.Load(reqID); found { + rm, ok := val.(*responseMetrics) + if !ok { + return nil + } now, _ := utils.CurrentTime() - x.elapsed = now.Sub(x.start) - return x + rm.elapsed = now.Sub(rm.start) + return rm } - return nil } // clearRequestMetrics removes the request from the map func clearRequestMetrics(reqID string) { - delete(reqMap, reqID) + reqMap.Delete(reqID) } diff --git a/cla-backend-go/cmd/server.go b/cla-backend-go/cmd/server.go index 10fd7eae3..c6def26ca 100644 --- a/cla-backend-go/cmd/server.go +++ b/cla-backend-go/cmd/server.go @@ -236,11 +236,24 @@ func server(localMode bool) http.Handler { } // LG: to test with manual tokens - // configFile.Auth0.UsernameClaim = "http://lfx.dev/claims/username" + customClaimUsername := os.Getenv("AUTH0_USERNAME_CLAIM_CLI") + if customClaimUsername != "" { + configFile.Auth0.UsernameClaim = customClaimUsername + } + nameClaimName := os.Getenv("AUTH0_NAME_CLAIM_CLI") + if nameClaimName == "" { + nameClaimName = "name" + } + emailClaimName := os.Getenv("AUTH0_EMAIL_CLAIM_CLI") + if emailClaimName == "" { + emailClaimName = "email" + } authValidator, err := auth.NewAuthValidator( configFile.Auth0.Domain, configFile.Auth0.ClientID, configFile.Auth0.UsernameClaim, + nameClaimName, + emailClaimName, configFile.Auth0.Algorithm) if err != nil { logrus.Panic(err) @@ -336,7 +349,7 @@ func server(localMode bool) http.Handler { // Setup our API handlers users.Configure(api, usersService, eventsService) project.Configure(api, v1ProjectService, eventsService, gerritService, v1RepositoriesService, v1SignaturesService) - v2Project.Configure(v2API, v1ProjectService, v2ProjectService, eventsService) + v2Project.Configure(v2API, v1ProjectService, v2ProjectService, eventsService, v1ProjectClaGroupService, v2RepositoriesService, gerritService) health.Configure(api, healthService) v2Health.Configure(v2API, healthService) template.Configure(api, templateService, eventsService) diff --git a/cla-backend-go/github/bots.go b/cla-backend-go/github/bots.go index 2fbc0a51f..0dce87015 100644 --- a/cla-backend-go/github/bots.go +++ b/cla-backend-go/github/bots.go @@ -222,6 +222,7 @@ func SkipAllowlistedBots(ev events.Service, orgModel *models.GithubOrganization, } log.WithFields(f).Debugf("final skip_cla config for repo %s is %+v; actorsMissingCLA: [%s]", orgRepo, configArray, strings.Join(actorDebugData, ", ")) + seenActors := make(map[string]struct{}) for _, actor := range actorsMissingCLA { if actor == nil { continue @@ -229,22 +230,25 @@ func SkipAllowlistedBots(ev events.Service, orgModel *models.GithubOrganization, actorData := actorToString(actor) log.WithFields(f).Debugf("Checking actor: %s for skip_cla config: %+v", actorData, configArray) if isActorSkipped(actor, configArray) { - msg := fmt.Sprintf( - "Skipping CLA check for repo='%s', actor: %s due to skip_cla config: %+v", - orgRepo, actorData, configArray, - ) - log.WithFields(f).Info(msg) - eventData := events.BypassCLAEventData{ - Repo: orgRepo, - Config: config, - Actor: actorData, + _, seen := seenActors[actorData] + if !seen { + seenActors[actorData] = struct{}{} + msg := fmt.Sprintf( + "Skipping CLA check for repo='%s', actor: %s due to skip_cla config: %+v", + orgRepo, actorData, configArray, + ) + log.WithFields(f).Info(msg) + eventData := events.BypassCLAEventData{ + Repo: orgRepo, + Config: config, + Actor: actorData, + } + ev.LogEvent(&events.LogEventArgs{ + EventType: events.BypassCLA, + EventData: &eventData, + ProjectID: projectID, + }) } - ev.LogEvent(&events.LogEventArgs{ - EventType: events.BypassCLA, - EventData: &eventData, - ProjectID: projectID, - }) - log.WithFields(f).Debugf("event logged") actor.Authorized = true allowlistedActors = append(allowlistedActors, actor) } else { diff --git a/cla-backend-go/project/mocks/mock_repo.go b/cla-backend-go/project/mocks/mock_repo.go index e5b2a39be..684a2c2e3 100644 --- a/cla-backend-go/project/mocks/mock_repo.go +++ b/cla-backend-go/project/mocks/mock_repo.go @@ -83,6 +83,21 @@ func (mr *MockProjectRepositoryMockRecorder) GetCLAGroupByID(ctx, claGroupID, lo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCLAGroupByID", reflect.TypeOf((*MockProjectRepository)(nil).GetCLAGroupByID), ctx, claGroupID, loadRepoDetails) } +// GetCLAGroupByIDCompat mocks base method. +func (m *MockProjectRepository) GetCLAGroupByIDCompat(ctx context.Context, claGroupID string, loadRepoDetails bool) (*models.ClaGroup, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCLAGroupByIDCompat", ctx, claGroupID, loadRepoDetails) + ret0, _ := ret[0].(*models.ClaGroup) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCLAGroupByIDCompat indicates an expected call of GetCLAGroupByIDCompat. +func (mr *MockProjectRepositoryMockRecorder) GetCLAGroupByIDCompat(ctx, claGroupID, loadRepoDetails interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCLAGroupByIDCompat", reflect.TypeOf((*MockProjectRepository)(nil).GetCLAGroupByIDCompat), ctx, claGroupID, loadRepoDetails) +} + // GetCLAGroupByName mocks base method. func (m *MockProjectRepository) GetCLAGroupByName(ctx context.Context, claGroupName string) (*models.ClaGroup, error) { m.ctrl.T.Helper() diff --git a/cla-backend-go/project/mocks/mock_service.go b/cla-backend-go/project/mocks/mock_service.go index d534036a2..eab7941ce 100644 --- a/cla-backend-go/project/mocks/mock_service.go +++ b/cla-backend-go/project/mocks/mock_service.go @@ -83,6 +83,21 @@ func (mr *MockServiceMockRecorder) GetCLAGroupByID(ctx, claGroupID interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCLAGroupByID", reflect.TypeOf((*MockService)(nil).GetCLAGroupByID), ctx, claGroupID) } +// GetCLAGroupByIDCompat mocks base method. +func (m *MockService) GetCLAGroupByIDCompat(ctx context.Context, claGroupID string) (*models.ClaGroup, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCLAGroupByIDCompat", ctx, claGroupID) + ret0, _ := ret[0].(*models.ClaGroup) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCLAGroupByIDCompat indicates an expected call of GetCLAGroupByIDCompat. +func (mr *MockServiceMockRecorder) GetCLAGroupByIDCompat(ctx, claGroupID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCLAGroupByIDCompat", reflect.TypeOf((*MockService)(nil).GetCLAGroupByIDCompat), ctx, claGroupID) +} + // GetCLAGroupByName mocks base method. func (m *MockService) GetCLAGroupByName(ctx context.Context, projectName string) (*models.ClaGroup, error) { m.ctrl.T.Helper() diff --git a/cla-backend-go/project/repository/repository.go b/cla-backend-go/project/repository/repository.go index a14441a34..093d27db5 100644 --- a/cla-backend-go/project/repository/repository.go +++ b/cla-backend-go/project/repository/repository.go @@ -50,6 +50,7 @@ const ( type ProjectRepository interface { //nolint CreateCLAGroup(ctx context.Context, claGroupModel *models.ClaGroup) (*models.ClaGroup, error) GetCLAGroupByID(ctx context.Context, claGroupID string, loadRepoDetails bool) (*models.ClaGroup, error) + GetCLAGroupByIDCompat(ctx context.Context, claGroupID string, loadRepoDetails bool) (*models.ClaGroup, error) GetCLAGroupsByExternalID(ctx context.Context, params *project.GetProjectsByExternalIDParams, loadRepoDetails bool) (*models.ClaGroups, error) GetCLAGroupByName(ctx context.Context, claGroupName string) (*models.ClaGroup, error) GetExternalCLAGroup(ctx context.Context, claGroupExternalID string) (*models.ClaGroup, error) @@ -149,7 +150,7 @@ func (repo *repo) CreateCLAGroup(ctx context.Context, claGroupModel *models.ClaG return claGroupModel, nil } -func (repo *repo) getCLAGroupByID(ctx context.Context, claGroupID string, loadCLAGroupDetails bool) (*models.ClaGroup, error) { +func (repo *repo) getCLAGroupByID(ctx context.Context, claGroupID string, loadCLAGroupDetails bool, claEnabledDefaultIsTrue bool) (*models.ClaGroup, error) { f := logrus.Fields{ "functionName": "project.repository.getCLAGroupByID", utils.XREQUESTID: ctx.Value(utils.XREQUESTID), @@ -188,11 +189,21 @@ func (repo *repo) getCLAGroupByID(ctx context.Context, claGroupID string, loadCL return nil, &utils.CLAGroupNotFound{CLAGroupID: claGroupID} } var dbModel models2.DBProjectModel - err = dynamodbattribute.UnmarshalMap(results.Items[0], &dbModel) + rawItem := results.Items[0] + err = dynamodbattribute.UnmarshalMap(rawItem, &dbModel) if err != nil { log.WithFields(f).Warnf("error unmarshalling db cla group model, error: %+v", err) return nil, err } + if claEnabledDefaultIsTrue { + // If missing, assume true like Pynamo default=True + if _, ok := rawItem["project_icla_enabled"]; !ok { + dbModel.ProjectIclaEnabled = true + } + if _, ok := rawItem["project_ccla_enabled"]; !ok { + dbModel.ProjectCclaEnabled = true + } + } // Convert the database model to an API response model return repo.buildCLAGroupModel(ctx, dbModel, loadCLAGroupDetails), nil @@ -200,7 +211,14 @@ func (repo *repo) getCLAGroupByID(ctx context.Context, claGroupID string, loadCL // GetCLAGroupByID returns the cla group model associated for the specified claGroupID func (repo *repo) GetCLAGroupByID(ctx context.Context, claGroupID string, loadRepoDetails bool) (*models.ClaGroup, error) { - return repo.getCLAGroupByID(ctx, claGroupID, loadRepoDetails) + return repo.getCLAGroupByID(ctx, claGroupID, loadRepoDetails, false) +} + +// GetCLAGroupByIDCompat returns the cla group model associated for the specified claGroupID +func (repo *repo) GetCLAGroupByIDCompat(ctx context.Context, claGroupID string, loadRepoDetails bool) (*models.ClaGroup, error) { + // Uses compatible mode (with python v2): claEnabledDefaultIsTrue - means if project_ccla_enabled or project_icla_enabled + // aren't set on dynamoDB item - they will default to true as in Py V2 API + return repo.getCLAGroupByID(ctx, claGroupID, loadRepoDetails, true) } // GetCLAGroupsByExternalID queries the database and returns a list of the cla groups @@ -383,7 +401,7 @@ func (repo *repo) GetClaGroupByProjectSFID(ctx context.Context, projectSFID stri log.WithFields(f).Debugf("found CLA Group ID: %s for project SFID: %s", claGroupProject.ClaGroupID, projectSFID) - return repo.getCLAGroupByID(ctx, claGroupProject.ClaGroupID, loadRepoDetails) + return repo.getCLAGroupByID(ctx, claGroupProject.ClaGroupID, loadRepoDetails, false) } // GetCLAGroupByName returns the project model associated for the specified project name diff --git a/cla-backend-go/project/service/service.go b/cla-backend-go/project/service/service.go index c9f246ea5..6c6e5c108 100644 --- a/cla-backend-go/project/service/service.go +++ b/cla-backend-go/project/service/service.go @@ -30,6 +30,7 @@ type Service interface { CreateCLAGroup(ctx context.Context, project *models.ClaGroup) (*models.ClaGroup, error) GetCLAGroups(ctx context.Context, params *project.GetProjectsParams) (*models.ClaGroups, error) GetCLAGroupByID(ctx context.Context, claGroupID string) (*models.ClaGroup, error) + GetCLAGroupByIDCompat(ctx context.Context, claGroupID string) (*models.ClaGroup, error) GetCLAGroupsByExternalSFID(ctx context.Context, projectSFID string) (*models.ClaGroups, error) GetCLAGroupsByExternalID(ctx context.Context, params *project.GetProjectsByExternalIDParams) (*models.ClaGroups, error) GetCLAGroupByName(ctx context.Context, projectName string) (*models.ClaGroup, error) @@ -75,6 +76,16 @@ func (s ProjectService) GetCLAGroups(ctx context.Context, params *project.GetPro // GetCLAGroupByID service method func (s ProjectService) GetCLAGroupByID(ctx context.Context, claGroupID string) (*models.ClaGroup, error) { + return s.getCLAGroupByID(ctx, claGroupID, false) +} + +// GetCLAGroupByIDCompat service method +func (s ProjectService) GetCLAGroupByIDCompat(ctx context.Context, claGroupID string) (*models.ClaGroup, error) { + return s.getCLAGroupByID(ctx, claGroupID, true) +} + +// getCLAGroupByID service method +func (s ProjectService) getCLAGroupByID(ctx context.Context, claGroupID string, claEnabledDefaultIsTrue bool) (*models.ClaGroup, error) { f := logrus.Fields{ "functionName": "GetCLAGroupByID", utils.XREQUESTID: ctx.Value(utils.XREQUESTID), @@ -83,7 +94,15 @@ func (s ProjectService) GetCLAGroupByID(ctx context.Context, claGroupID string) } log.WithFields(f).Debug("locating CLA Group by ID...") - project, err := s.repo.GetCLAGroupByID(ctx, claGroupID, repository.LoadRepoDetails) + var ( + project *models.ClaGroup + err error + ) + if claEnabledDefaultIsTrue { + project, err = s.repo.GetCLAGroupByIDCompat(ctx, claGroupID, repository.LoadRepoDetails) + } else { + project, err = s.repo.GetCLAGroupByID(ctx, claGroupID, repository.LoadRepoDetails) + } if err != nil { return nil, err } diff --git a/cla-backend-go/swagger/cla.v1.yaml b/cla-backend-go/swagger/cla.v1.yaml index 15656711f..7cef11d43 100644 --- a/cla-backend-go/swagger/cla.v1.yaml +++ b/cla-backend-go/swagger/cla.v1.yaml @@ -141,6 +141,34 @@ paths: tags: - users + /user-compat/{userID}: + parameters: + - $ref: "#/parameters/x-request-id" + - $ref: "#/parameters/userPathUuid" + get: + summary: Get user by ID (returns data in the same format as Py V2 API) + security: [ ] + operationId: getUserCompat + responses: + '200': + description: 'Success' + headers: + x-request-id: + type: string + description: The unique request ID value - assigned/set by the API Gateway based on the session + schema: + $ref: '#/definitions/user-compat' + '400': + $ref: '#/responses/invalid-request' + '401': + $ref: '#/responses/unauthorized' + '403': + $ref: '#/responses/forbidden' + '404': + $ref: '#/responses/not-found' + tags: + - users + /users/{userID}: get: summary: Get User by ID @@ -2429,6 +2457,13 @@ paths: # Common parameters parameters: + userPathUuid: + name: userID + in: path + required: true + description: The user ID (UUID string) + type: string + pattern: '^[a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}$' # this is any UUID, not only v4 x-request-id: name: X-REQUEST-ID description: The unique request ID value - assigned/set by the API Gateway based on the login session @@ -2677,6 +2712,9 @@ definitions: user: $ref: './common/user.yaml' + user-compat: + $ref: './common/user-compat.yaml' + user-update: type: object title: User @@ -2690,6 +2728,8 @@ definitions: type: string lfEmail: type: string + lfSub: + type: string lfUsername: type: string companyID: diff --git a/cla-backend-go/swagger/cla.v2.yaml b/cla-backend-go/swagger/cla.v2.yaml index 672b96e6f..68ac7e726 100644 --- a/cla-backend-go/swagger/cla.v2.yaml +++ b/cla-backend-go/swagger/cla.v2.yaml @@ -889,6 +889,34 @@ paths: tags: - project + /project-compat/{projectID}: + parameters: + - $ref: "#/parameters/x-request-id" + - $ref: "#/parameters/projectPathUuid" + get: + summary: Get project by ID (returns data in the same format as Py V2 API) + security: [ ] + operationId: getProjectCompat + responses: + '200': + description: 'Success' + headers: + x-request-id: + type: string + description: The unique request ID value - assigned/set by the API Gateway based on the session + schema: + $ref: '#/definitions/project-compat' + '400': + $ref: '#/responses/invalid-request' + '401': + $ref: '#/responses/unauthorized' + '403': + $ref: '#/responses/forbidden' + '404': + $ref: '#/responses/not-found' + tags: + - project + /events/recent: get: summary: List recent events - requires Admin-level access @@ -2413,6 +2441,44 @@ paths: tags: - signatures + /user/{userID}/active-signature: + parameters: + - $ref: "#/parameters/x-request-id" + - $ref: "#/parameters/userPathUuid" + get: + summary: | + Returns all metadata associated with a user's active signature. + { + 'user_id': , + 'project_id': , + 'repository_id': (as string), + 'pull_request_id': (PR number as string), + *'merge_request_id': (optional MR number as string - this property can be missing in JSON), + 'return_url': (for example itHub PR path)' + } + Returns null if the user does not have an active signature. + security: [ ] + operationId: getUserActiveSignature + responses: + '200': + description: 'Success' + headers: + x-request-id: + type: string + description: The unique request ID value - assigned/set by the API Gateway based on the session + schema: + $ref: '#/definitions/user-active-signature' + '400': + $ref: '#/responses/invalid-request' + '401': + $ref: '#/responses/unauthorized' + '403': + $ref: '#/responses/forbidden' + '404': + $ref: '#/responses/not-found' + tags: + - sign + /signatures/project/{projectSFID}/company/{companyID}/employee: get: summary: Get project company signatures for the employees @@ -4450,6 +4516,20 @@ responses: # Common parameters parameters: + userPathUuid: + name: userID + in: path + required: true + description: The user ID (UUID string) + type: string + pattern: '^[a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}$' # this is any UUID, not only v4 + projectPathUuid: + name: projectID + in: path + required: true + description: The project ID (UUID string) + type: string + pattern: '^[a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}$' # this is any UUID, not only v4 pageSize: name: pageSize description: The maximum number of results per page, value must be a positive integer value @@ -4956,6 +5036,9 @@ definitions: sf-project-summary: $ref: './common/sf-project-summary.yaml' + project-compat: + $ref: './common/project-compat.yaml' + # --------------------------------------------------------------------------- # CLA Template Definitions # --------------------------------------------------------------------------- @@ -4971,6 +5054,9 @@ definitions: user: $ref: './common/user.yaml' + user-active-signature: + $ref: './common/user-active-signature.yaml' + signatures: $ref: './common/signatures.yaml' diff --git a/cla-backend-go/swagger/common/project-compat.yaml b/cla-backend-go/swagger/common/project-compat.yaml new file mode 100644 index 000000000..1b10db60b --- /dev/null +++ b/cla-backend-go/swagger/common/project-compat.yaml @@ -0,0 +1,126 @@ +# Copyright The Linux Foundation and each contributor to CommunityBridge. +# SPDX-License-Identifier: MIT + +type: object +x-nullable: false +title: Project Model in Py V2 format +description: Project Model - in Py V2 - minimal fields needed by FE +properties: + project_id: + description: Project's UUID + $ref: './common/properties/uuid.yaml' + x-omitempty: false + project_name: + description: Project name + example: 'Cloud Native Computing Foundation' + type: string + x-omitempty: false + foundation_sfid: + description: The salesforce foundation ID + example: 'a09410000182dD2AAI' + type: string + x-omitempty: false + project_ccla_enabled: + description: Is CCLA enabled? + example: true + type: boolean + x-omitempty: false + project_icla_enabled: + description: Is ICLA enabled? + example: true + type: boolean + x-omitempty: false + project_ccla_requires_icla_signature: + description: CCLA requires ICLA signature? + example: true + type: boolean + x-omitempty: false + signed_at_foundation_level: + description: Is signed at the foundation level? + example: true + type: boolean + x-omitempty: false + project_individual_documents: + type: array + items: + type: object + properties: + document_major_version: + description: Document major version + example: '2' + type: string + x-omitempty: false + document_minor_version: + description: Document minor version + example: '0' + type: string + x-omitempty: false + project_corporate_documents: + type: array + items: + type: object + properties: + document_major_version: + description: Document major version + example: '2' + type: string + x-omitempty: false + document_minor_version: + description: Document minor version + example: '0' + type: string + x-omitempty: false + projects: + type: array + items: + type: object + properties: + cla_group_id: + description: Project's UUID + $ref: './common/properties/uuid.yaml' + x-omitempty: false + foundation_sfid: + description: The salesforce foundation ID + example: 'a09410000182dD2AAI' + type: string + x-omitempty: false + project_sfid: + description: The salesforce project ID + example: 'a09410000182dD2AAI' + type: string + x-omitempty: false + project_name: + description: Project name + example: 'Kubernetes' + type: string + x-omitempty: false + github_repos: + type: array + items: + type: object + properties: + repository_name: + description: Repository name + example: 'cncf/devstats' + type: string + x-omitempty: false + gitlab_repos: + type: array + items: + type: object + properties: + repository_name: + description: Repository name + example: 'cncf/devstats' + type: string + x-omitempty: false + gerrit_repos: + type: array + items: + type: object + properties: + gerrit_url: + description: Repository URL + example: 'cncf/devstats' + type: string + x-omitempty: false diff --git a/cla-backend-go/swagger/common/properties/uuid.yaml b/cla-backend-go/swagger/common/properties/uuid.yaml new file mode 100644 index 000000000..1d2830418 --- /dev/null +++ b/cla-backend-go/swagger/common/properties/uuid.yaml @@ -0,0 +1,6 @@ +# Copyright The Linux Foundation and each contributor to CommunityBridge. +# SPDX-License-Identifier: MIT + +type: string +example: 'a1b86c26-d8e8-4fd8-9f8d-5c723d5dac9f' +pattern: '^[a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}$' diff --git a/cla-backend-go/swagger/common/user-active-signature.yaml b/cla-backend-go/swagger/common/user-active-signature.yaml new file mode 100644 index 000000000..c99b937ed --- /dev/null +++ b/cla-backend-go/swagger/common/user-active-signature.yaml @@ -0,0 +1,34 @@ +# Copyright The Linux Foundation and each contributor to CommunityBridge. +# SPDX-License-Identifier: MIT + +type: object +x-nullable: true +title: User Active Signature +description: > + Returns all metadata associated with a user's active signature. + Returns `null` if the user does not have an active signature. +properties: + user_id: + $ref: './common/properties/uuid.yaml' + description: The unique internal UUID of the user + project_id: + $ref: './common/properties/uuid.yaml' + description: The unique UUID of the associated project + repository_id: + type: string + description: The unique ID of the associated repository (number stored as string) + example: '168926425' + pull_request_id: + type: string + description: The pull request ID related to the signature (number stored as string) + example: '456' + merge_request_id: + type: string + description: The merge request ID related to the signature (optional number stored as string, this property can be missing in JSON) + example: '456' + x-nullable: true + return_url: + type: string + format: uri + description: The return URL where the user initiated the signature (for example GitHub PR path) + example: https://github.com/veer-missingid2/repo03/pull/3 diff --git a/cla-backend-go/swagger/common/user-compat.yaml b/cla-backend-go/swagger/common/user-compat.yaml new file mode 100644 index 000000000..018b9c164 --- /dev/null +++ b/cla-backend-go/swagger/common/user-compat.yaml @@ -0,0 +1,101 @@ +# Copyright The Linux Foundation and each contributor to CommunityBridge. +# SPDX-License-Identifier: MIT + +type: object +x-nullable: false +title: User Model in Py V2 format +description: User Model - in Py V2 - minimal fields needed by FE +properties: + user_id: + description: User's UUID + $ref: './common/properties/uuid.yaml' + x-omitempty: false + x-nullable: false + user_external_id: + description: External user ID + $ref: './common/properties/external-id.yaml' + x-omitempty: false + x-nullable: true + user_emails: + description: Set of user emails (may be empty) + type: array + items: + type: string + format: email + example: user@example.com + example: ["user@example.com"] + x-omitempty: false + x-nullable: false + user_name: + description: User's name + type: string + example: "Jane Smith" + x-omitempty: false + x-nullable: true + user_company_id: + description: User's company ID + $ref: './common/properties/uuid.yaml' + x-omitempty: false + x-nullable: true + user_github_id: + description: User's GitHub numeric ID + type: string + example: "123456" + x-omitempty: false + x-nullable: true + user_github_username: + description: User's GitHub username + type: string + example: "lukaszgryglicki" + x-omitempty: false + x-nullable: true + user_gitlab_id: + description: User's GitLab numeric ID + type: string + example: "78910" + x-omitempty: false + x-nullable: true + user_gitlab_username: + description: User's GitLab username + type: string + example: "gitlabUser" + x-omitempty: false + x-nullable: true + user_ldap_id: + description: User's LDAP ID + type: string + x-omitempty: false + x-nullable: true + note: + description: Optional admin note + type: string + example: "Pending verification" + x-omitempty: false + x-nullable: true + lf_email: + description: LF email + $ref: './common/properties/email.yaml' + x-omitempty: false + x-nullable: true + lf_username: + description: Linux Foundation username + type: string + example: "janesmith" + x-omitempty: false + x-nullable: true + lf_sub: + type: string + x-omitempty: false + x-nullable: true + is_sanctioned: + type: boolean + description: "Is this user OFAC sanctioned? This field comes from users's company" + example: true + x-omitempty: false + x-nullable: true + version: + type: string + description: the version identifier for this record + example: 'v1' + x-omitempty: false + x-nullable: false diff --git a/cla-backend-go/swagger/common/user.yaml b/cla-backend-go/swagger/common/user.yaml index 511adb31e..d18ae8613 100644 --- a/cla-backend-go/swagger/common/user.yaml +++ b/cla-backend-go/swagger/common/user.yaml @@ -22,6 +22,8 @@ properties: $ref: './common/properties/email.yaml' lfUsername: type: string + lfSub: + type: string companyID: $ref: './common/properties/internal-id.yaml' description: the user's optional company ID diff --git a/cla-backend-go/users/handlers.go b/cla-backend-go/users/handlers.go index 931d92fb2..8d585f4bc 100644 --- a/cla-backend-go/users/handlers.go +++ b/cla-backend-go/users/handlers.go @@ -248,6 +248,28 @@ func Configure(api *operations.ClaAPI, service Service, eventsService events.Ser return users.NewSearchUsersOK().WithPayload(userModel) }) + + // Get User by ID compat handler + api.UsersGetUserCompatHandler = users.GetUserCompatHandlerFunc(func(params users.GetUserCompatParams) middleware.Responder { + f := logrus.Fields{"" + + "functionName": "users.GetUserCompatHandlerFunc", + "paramsUserID": params.UserID, + } + + userModel, err := service.GetUser(params.UserID) + if err != nil { + log.WithFields(f).Warnf("error retrieving user for user_id: %s, error: %+v", params.UserID, err) + return users.NewGetUserCompatBadRequest().WithPayload(errorResponse(err)) + } + + compatModel, err := service.ConvertUserModelToUserCompatModel(userModel) + if err != nil { + log.WithFields(f).Warnf("error converting user model to compat model for user_id: %s, error: %+v", params.UserID, err) + return users.NewGetUserCompatBadRequest().WithPayload(errorResponse(err)) + } + log.WithFields(f).Debugf("returning compat user model %+v from user model %+v for user_id: %s", compatModel, userModel, params.UserID) + return users.NewGetUserCompatOK().WithPayload(compatModel) + }) } type codedResponse interface { diff --git a/cla-backend-go/users/models.go b/cla-backend-go/users/models.go index d4b733178..4f4a01016 100644 --- a/cla-backend-go/users/models.go +++ b/cla-backend-go/users/models.go @@ -21,6 +21,7 @@ type DBUser struct { UserGitlabUsername string `json:"user_gitlab_username"` UserCompanyID string `json:"user_company_id"` Note string `json:"note"` + LFSub string `json:"lf_sub"` } type UserEmails struct { diff --git a/cla-backend-go/users/repository.go b/cla-backend-go/users/repository.go index d12925f83..8d6dc083e 100644 --- a/cla-backend-go/users/repository.go +++ b/cla-backend-go/users/repository.go @@ -129,6 +129,12 @@ func (repo repository) CreateUser(user *models.User) (*models.User, error) { } } + if user.LfSub != "" { + attributes["lf_sub"] = &dynamodb.AttributeValue{ + S: aws.String(user.LfSub), + } + } + if len(user.Emails) > 0 { attributes["user_emails"] = &dynamodb.AttributeValue{ SS: utils.ArrayStringPointer(user.Emails), @@ -363,6 +369,13 @@ func (repo repository) Save(user *models.UserUpdate) (*models.User, error) { updateExpression = updateExpression + " #E = :e, " } + if user.LfSub != "" && oldUserModel.LfSub != user.LfSub { + log.WithFields(f).Debugf("building query - adding lf_sub: %s", user.LfSub) + expressionAttributeNames["#SU"] = aws.String("lf_sub") + expressionAttributeValues[":su"] = &dynamodb.AttributeValue{S: aws.String(user.LfSub)} + updateExpression = updateExpression + " #SU = :su, " + } + if user.UserExternalID != "" && oldUserModel.UserExternalID != user.UserExternalID { log.WithFields(f).Debugf("building query - adding user_external_id: %s", user.UserExternalID) expressionAttributeNames["#UE"] = aws.String("user_external_id") @@ -1313,6 +1326,7 @@ func convertDBUserModel(user DBUser) *models.User { UserExternalID: user.UserExternalID, Admin: user.Admin, LfEmail: strfmt.Email(user.LFEmail), + LfSub: user.LFSub, LfUsername: user.LFUsername, DateCreated: user.DateCreated, DateModified: user.DateModified, @@ -1336,6 +1350,7 @@ func buildUserProjection() expression.ProjectionBuilder { expression.Name("user_company_id"), expression.Name("admin"), expression.Name("lf_email"), + expression.Name("lf_sub"), expression.Name("lf_username"), expression.Name("user_name"), expression.Name("user_emails"), diff --git a/cla-backend-go/users/service.go b/cla-backend-go/users/service.go index 99325f06a..6dd55f01d 100644 --- a/cla-backend-go/users/service.go +++ b/cla-backend-go/users/service.go @@ -6,6 +6,7 @@ package users import ( "errors" + "github.com/go-openapi/strfmt" "github.com/linuxfoundation/easycla/cla-backend-go/events" "github.com/linuxfoundation/easycla/cla-backend-go/gen/v1/models" "github.com/linuxfoundation/easycla/cla-backend-go/user" @@ -27,6 +28,7 @@ type Service interface { GetUserByGitLabUsername(gitlabUsername string) (*models.User, error) SearchUsers(field string, searchTerm string, fullMatch bool) (*models.Users, error) UpdateUserCompanyID(userID, companyID, note string) error + ConvertUserModelToUserCompatModel(*models.User) (*models.UserCompat, error) } type service struct { @@ -192,3 +194,46 @@ func (s service) SearchUsers(searchField string, searchTerm string, fullMatch bo func (s service) UpdateUserCompanyID(userID, companyID, note string) error { return s.repo.UpdateUserCompanyID(userID, companyID, note) } + +func stringPtr(s string) *string { + if s == "" { + return nil + } + return &s +} + +func boolPtr(b bool) *bool { + return &b +} + +// ConvertUserModelToUserCompatModel converts User to UserCompat +func (s service) ConvertUserModelToUserCompatModel(user *models.User) (*models.UserCompat, error) { + userEmails := make([]strfmt.Email, len(user.Emails)) + for i, e := range user.Emails { + userEmails[i] = strfmt.Email(e) + } + + var lfEmail *strfmt.Email + if user.LfEmail != "" { + lfEmail = &user.LfEmail + } + + return &models.UserCompat{ + IsSanctioned: boolPtr(user.IsSanctioned), + LfEmail: lfEmail, + LfSub: stringPtr(user.LfSub), + LfUsername: stringPtr(user.LfUsername), + Note: stringPtr(user.Note), + UserCompanyID: stringPtr(user.CompanyID), + UserEmails: userEmails, + UserExternalID: stringPtr(user.UserExternalID), + UserGithubID: stringPtr(user.GithubID), + UserGithubUsername: stringPtr(user.GithubUsername), + UserGitlabID: stringPtr(user.GitlabID), + UserGitlabUsername: stringPtr(user.GitlabUsername), + UserID: user.UserID, + UserLdapID: nil, + UserName: stringPtr(user.Username), + Version: "v1", + }, nil +} diff --git a/cla-backend-go/v2/project/handlers.go b/cla-backend-go/v2/project/handlers.go index e248ca195..ce5ad3164 100644 --- a/cla-backend-go/v2/project/handlers.go +++ b/cla-backend-go/v2/project/handlers.go @@ -6,8 +6,12 @@ package project import ( "context" "fmt" + "sort" + "github.com/linuxfoundation/easycla/cla-backend-go/gerrits" v1Project "github.com/linuxfoundation/easycla/cla-backend-go/project/service" + "github.com/linuxfoundation/easycla/cla-backend-go/projects_cla_groups" + v2Repositories "github.com/linuxfoundation/easycla/cla-backend-go/v2/repositories" projectService "github.com/linuxfoundation/easycla/cla-backend-go/v2/project-service" v2ProjectServiceModels "github.com/linuxfoundation/easycla/cla-backend-go/v2/project-service/models" @@ -22,6 +26,7 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/linuxfoundation/easycla/cla-backend-go/events" + v1Models "github.com/linuxfoundation/easycla/cla-backend-go/gen/v1/models" v1ProjectOps "github.com/linuxfoundation/easycla/cla-backend-go/gen/v1/restapi/operations/project" "github.com/linuxfoundation/easycla/cla-backend-go/gen/v2/models" "github.com/linuxfoundation/easycla/cla-backend-go/gen/v2/restapi/operations" @@ -30,7 +35,9 @@ import ( ) // Configure establishes the middleware handlers for the project service -func Configure(api *operations.EasyclaAPI, service v1Project.Service, v2Service Service, eventsService events.Service) { //nolint +func Configure(api *operations.EasyclaAPI, service v1Project.Service, v2Service Service, eventsService events.Service, projectsClaGroupsService projects_cla_groups.Service, v2RepositoriesService v2Repositories.ServiceInterface, gerritService gerrits.Service) { //nolint + + const projectDoesNotExist = "project does not exist" // Get Projects api.ProjectGetProjectsHandler = project.GetProjectsHandlerFunc(func(params project.GetProjectsParams, authUser *auth.User) middleware.Responder { reqID := utils.GetRequestID(params.XREQUESTID) @@ -74,7 +81,7 @@ func Configure(api *operations.EasyclaAPI, service v1Project.Service, v2Service claGroupModel, err := service.GetCLAGroupByID(ctx, params.ProjectSfdcID) if err != nil { - if err.Error() == "project does not exist" { + if err.Error() == projectDoesNotExist { return project.NewGetProjectByIDNotFound().WithXRequestID(reqID).WithPayload(errorResponse(reqID, err)) } return project.NewGetProjectByIDBadRequest().WithXRequestID(reqID).WithPayload(errorResponse(reqID, err)) @@ -332,6 +339,127 @@ func Configure(api *operations.EasyclaAPI, service v1Project.Service, v2Service summary := buildSFProjectSummary(sfProject, parentName) return project.NewGetSFProjectInfoByIDOK().WithXRequestID(reqID).WithPayload(summary) }) + + api.ProjectGetProjectCompatHandler = project.GetProjectCompatHandlerFunc(func(params project.GetProjectCompatParams) middleware.Responder { + reqID := utils.GetRequestID(params.XREQUESTID) + ctx := context.WithValue(context.Background(), utils.XREQUESTID, reqID) // nolint + f := logrus.Fields{ + "functionName": "v2.project.handlers.ProjectGetProjectCompatHandler", + utils.XREQUESTID: ctx.Value(utils.XREQUESTID), + "projectID": params.ProjectID, + } + + proj, err := service.GetCLAGroupByIDCompat(ctx, params.ProjectID) + if err != nil { + if err.Error() == projectDoesNotExist { + return project.NewGetProjectCompatNotFound().WithXRequestID(reqID).WithPayload(errorResponse(reqID, err)) + } + log.WithFields(f).WithError(err).Warnf("unable to load compat project by ID: %s: %+v", params.ProjectID, err) + return project.NewGetProjectCompatBadRequest().WithXRequestID(reqID).WithPayload(errorResponse(reqID, err)) + } + if proj == nil { + return project.NewGetProjectCompatNotFound().WithXRequestID(reqID) + } + projectsClaGroups, err := projectsClaGroupsService.GetProjectsIdsForClaGroup(ctx, params.ProjectID) + if err != nil { + return project.NewGetProjectCompatBadRequest().WithXRequestID(reqID).WithPayload(errorResponse(reqID, err)) + } + sfidReposMap := make(map[string][][2]string) + for _, prjClaGrp := range projectsClaGroups { + sfid := prjClaGrp.ProjectSFID + if sfid == "" { + continue + } + _, ok := sfidReposMap[sfid] + if ok { + continue + } + repos, reposErr := v2RepositoriesService.GetRepositoriesByProjectSFID(ctx, sfid) + if reposErr != nil { + log.WithFields(f).WithError(reposErr).Warnf("unable to get github/gitlab repos list for SFID: %s: %+v", sfid, reposErr) + } + gerrits, gerritsErr := gerritService.GetGerritsByProjectSFID(ctx, sfid) + if gerritsErr != nil { + log.WithFields(f).WithError(gerritsErr).Warnf("unable to get gerrit repos list for SFID: %s: %+v", sfid, gerritsErr) + } + entry := [][2]string{} + if reposErr == nil { + for _, repo := range repos { + entry = append(entry, [2]string{repo.RepositoryType, repo.RepositoryName}) + } + } + if gerritsErr == nil { + for _, repo := range gerrits.List { + entry = append(entry, [2]string{"gerrit", string(repo.GerritURL)}) + } + } + sort.Slice(entry, func(i, j int) bool { + return entry[i][1] < entry[j][1] + }) + sfidReposMap[sfid] = entry + } + compatProject := buildCompatProject(proj, projectsClaGroups, sfidReposMap) + return project.NewGetProjectCompatOK().WithXRequestID(reqID).WithPayload(compatProject) + }) +} + +func buildCompatProject(project *v1Models.ClaGroup, projectClaGroups []*projects_cla_groups.ProjectClaGroup, sfidReposMap map[string][][2]string) *models.ProjectCompat { + projectCorporateDocuments := []*models.ProjectCompatProjectCorporateDocumentsItems0{} + for _, doc := range project.ProjectCorporateDocuments { + projectCorporateDocuments = append(projectCorporateDocuments, &models.ProjectCompatProjectCorporateDocumentsItems0{ + DocumentMajorVersion: doc.DocumentMajorVersion, + DocumentMinorVersion: doc.DocumentMinorVersion, + }) + } + projectIndividualDocuments := []*models.ProjectCompatProjectIndividualDocumentsItems0{} + for _, doc := range project.ProjectIndividualDocuments { + projectIndividualDocuments = append(projectIndividualDocuments, &models.ProjectCompatProjectIndividualDocumentsItems0{ + DocumentMajorVersion: doc.DocumentMajorVersion, + DocumentMinorVersion: doc.DocumentMinorVersion, + }) + } + projects := []*models.ProjectCompatProjectsItems0{} + for _, prjClaGrp := range projectClaGroups { + gerritRepos := []*models.ProjectCompatProjectsItems0GerritReposItems0{} + githubRepos := []*models.ProjectCompatProjectsItems0GithubReposItems0{} + gitlabRepos := []*models.ProjectCompatProjectsItems0GitlabReposItems0{} + sfid := prjClaGrp.ProjectSFID + if sfid != "" { + repos, ok := sfidReposMap[sfid] + if ok { + for _, repo := range repos { + if repo[0] == "github" { + githubRepos = append(githubRepos, &models.ProjectCompatProjectsItems0GithubReposItems0{RepositoryName: repo[1]}) + } else if repo[0] == "gitlab" { + gitlabRepos = append(gitlabRepos, &models.ProjectCompatProjectsItems0GitlabReposItems0{RepositoryName: repo[1]}) + } else if repo[0] == "gerrit" { + gerritRepos = append(gerritRepos, &models.ProjectCompatProjectsItems0GerritReposItems0{GerritURL: repo[1]}) + } + } + } + } + projects = append(projects, &models.ProjectCompatProjectsItems0{ + ClaGroupID: prjClaGrp.ClaGroupID, + FoundationSfid: prjClaGrp.FoundationSFID, + ProjectName: prjClaGrp.ProjectName, + ProjectSfid: prjClaGrp.ProjectSFID, + GerritRepos: gerritRepos, + GithubRepos: githubRepos, + GitlabRepos: gitlabRepos, + }) + } + return &models.ProjectCompat{ + FoundationSfid: project.FoundationSFID, + ProjectName: project.ProjectName, + ProjectCclaEnabled: project.ProjectCCLAEnabled, + ProjectCclaRequiresIclaSignature: project.ProjectCCLARequiresICLA, + ProjectIclaEnabled: project.ProjectICLAEnabled, + ProjectID: project.ProjectID, + SignedAtFoundationLevel: project.FoundationLevelCLA, + ProjectCorporateDocuments: projectCorporateDocuments, + ProjectIndividualDocuments: projectIndividualDocuments, + Projects: projects, + } } func buildSFProjectSummary(sfProject *v2ProjectServiceModels.ProjectOutputDetailed, parentName string) *models.SfProjectSummary { diff --git a/cla-backend-go/v2/repositories/repository.go b/cla-backend-go/v2/repositories/repository.go index 7496ed75b..c31a94858 100644 --- a/cla-backend-go/v2/repositories/repository.go +++ b/cla-backend-go/v2/repositories/repository.go @@ -6,6 +6,7 @@ package repositories import ( "context" "fmt" + "reflect" "strconv" "strings" @@ -28,6 +29,7 @@ type RepositoryInterface interface { GitHubGetRepositoriesByCLAGroupDisabled(ctx context.Context, claGroupID string) ([]*repoModels.RepositoryDBModel, error) GitHubGetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*repoModels.RepositoryDBModel, error) GitHubGetRepositoriesByOrganizationName(ctx context.Context, orgName string) ([]*repoModels.RepositoryDBModel, error) + GetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*repoModels.RepositoryDBModel, error) GitLabGetRepository(ctx context.Context, repositoryID string) (*repoModels.RepositoryDBModel, error) GitLabGetRepositoryByName(ctx context.Context, repositoryName string) (*repoModels.RepositoryDBModel, error) @@ -244,6 +246,16 @@ func (r *Repository) GitHubGetRepositoriesByCLAGroupDisabled(ctx context.Context return records, nil } +// GetRepositoriesByProjectSFID returns a list of repositories associated with the specified project +func (r *Repository) GetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*repoModels.RepositoryDBModel, error) { + condition := expression.Key(repoModels.RepositoryProjectIDColumn).Equal(expression.Value(projectSFID)) + records, err := r.getRepositoriesWithConditionFilter(ctx, condition, expression.ConditionBuilder{}, repoModels.RepositoryProjectSFIDIndex) + if err != nil { + return nil, err + } + return records, nil +} + // GitHubGetRepositoriesByProjectSFID returns a list of repositories associated with the specified project func (r *Repository) GitHubGetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*repoModels.RepositoryDBModel, error) { condition := expression.Key(repoModels.RepositoryProjectIDColumn).Equal(expression.Value(projectSFID)) @@ -548,6 +560,10 @@ func (r *Repository) getRepositoryWithConditionFilter(ctx context.Context, condi return repositories[0], nil } +func isZeroCondition(filter expression.ConditionBuilder) bool { + return reflect.ValueOf(filter).IsZero() +} + // getRepositoriesWithConditionFilter fetches the repository entry based on the specified condition and filter criteria // using the provided index func (r *Repository) getRepositoriesWithConditionFilter(ctx context.Context, condition expression.KeyConditionBuilder, filter expression.ConditionBuilder, indexName string) ([]*repoModels.RepositoryDBModel, error) { @@ -557,7 +573,11 @@ func (r *Repository) getRepositoriesWithConditionFilter(ctx context.Context, con "indexName": indexName, } - expr, err := expression.NewBuilder().WithKeyCondition(condition).WithFilter(filter).Build() + builder := expression.NewBuilder().WithKeyCondition(condition) + if !isZeroCondition(filter) { + builder = builder.WithFilter(filter) + } + expr, err := builder.Build() if err != nil { log.WithFields(f).WithError(err).Warn("problem creating builder") return nil, err diff --git a/cla-backend-go/v2/repositories/service.go b/cla-backend-go/v2/repositories/service.go index 7615e4682..85c19895a 100644 --- a/cla-backend-go/v2/repositories/service.go +++ b/cla-backend-go/v2/repositories/service.go @@ -69,6 +69,9 @@ type ServiceInterface interface { GitLabEnrollCLAGroupRepositories(ctx context.Context, claGroupID string, enrollValue bool) error GitLabDeleteRepositories(ctx context.Context, gitLabGroupPath string) error GitLabDeleteRepositoryByExternalID(ctx context.Context, gitLabExternalID int64) error + + // All + GetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*v1Repositories.RepositoryDBModel, error) } // GitLabOrgRepo redefine the interface here to avoid circular dependency issues @@ -664,3 +667,12 @@ func (s *Service) GitHubDisableCLAGroupRepositories(ctx context.Context, claGrou } return nil } + +// GetRepositoriesByProjectSFID service function +func (s *Service) GetRepositoriesByProjectSFID(ctx context.Context, projectSFID string) ([]*v1Repositories.RepositoryDBModel, error) { + data, err := s.gitV2Repository.GetRepositoriesByProjectSFID(ctx, projectSFID) + if err != nil { + return nil, err + } + return data, nil +} diff --git a/cla-backend-go/v2/sign/handlers.go b/cla-backend-go/v2/sign/handlers.go index 74a44da81..d99437f83 100644 --- a/cla-backend-go/v2/sign/handlers.go +++ b/cla-backend-go/v2/sign/handlers.go @@ -24,6 +24,8 @@ import ( "github.com/linuxfoundation/easycla/cla-backend-go/gen/v2/restapi/operations/sign" "github.com/linuxfoundation/easycla/cla-backend-go/utils" "github.com/linuxfoundation/easycla/cla-backend-go/v2/organization-service/client/organizations" + + "github.com/go-openapi/runtime" ) var ( @@ -248,6 +250,34 @@ func Configure(api *operations.EasyclaAPI, service Service, userService users.Se return sign.NewCclaCallbackOK() }) + api.SignGetUserActiveSignatureHandler = sign.GetUserActiveSignatureHandlerFunc( + func(params sign.GetUserActiveSignatureParams) middleware.Responder { + reqId := utils.GetRequestID(params.XREQUESTID) + ctx := context.WithValue(params.HTTPRequest.Context(), utils.XREQUESTIDKey, reqId) + f := logrus.Fields{ + "functionName": "v2.sign.handlers.SignGetUserActiveSignatureHandler", + utils.XREQUESTID: ctx.Value(utils.XREQUESTID), + "userID": params.UserID, + } + var resp *models.UserActiveSignature + var err error + + log.WithFields(f).Debug("getting user active signature") + resp, err = service.GetUserActiveSignature(ctx, params.UserID) + if err != nil { + return sign.NewGetUserActiveSignatureBadRequest().WithPayload(errorResponse(reqId, err)) + } + if resp == nil { + return middleware.ResponderFunc(func(w http.ResponseWriter, _ runtime.Producer) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + if _, err := w.Write([]byte("null")); err != nil { + log.WithFields(f).WithError(err).Warn("failed to write null response") + } + }) + } + return sign.NewGetUserActiveSignatureOK().WithPayload(resp) + }) } type codedResponse interface { diff --git a/cla-backend-go/v2/sign/service.go b/cla-backend-go/v2/sign/service.go index 00d4cf8c5..424affc15 100644 --- a/cla-backend-go/v2/sign/service.go +++ b/cla-backend-go/v2/sign/service.go @@ -90,6 +90,7 @@ type Service interface { SignedIndividualCallbackGitlab(ctx context.Context, payload []byte, userID, organizationID, repositoryID, mergeRequestID string) error SignedIndividualCallbackGerrit(ctx context.Context, payload []byte, userID string) error SignedCorporateCallback(ctx context.Context, payload []byte, companyID, projectID string) error + GetUserActiveSignature(ctx context.Context, userID string) (*models.UserActiveSignature, error) } // service @@ -1539,7 +1540,7 @@ func (s *service) getIndividualSignatureCallbackURLGitlab(ctx context.Context, u if found, ok := metadata["merge_request_id"].(string); ok { mergeRequestID = found } else { - log.WithFields(f).WithError(err).Warnf("unable to get pull request ID for user: %s", userID) + log.WithFields(f).WithError(err).Warnf("unable to get merge request ID for user: %s", userID) return "", err } @@ -1607,11 +1608,28 @@ func (s *service) getIndividualSignatureCallbackURL(ctx context.Context, userID log.WithFields(f).Debugf("found pull request ID: %s", pullRequestID) // Get installation ID through a helper function - log.WithFields(f).Debugf("getting repository...") + installationId, err = s.getInstallationIDFromRepositoryID(ctx, repositoryID) + if err != nil { + log.WithFields(f).WithError(err).Warnf("unable to get github organization for repository ID: %s", repositoryID) + return "", err + } + + callbackURL := fmt.Sprintf("%s/v4/signed/individual/%d/%s/%s", s.ClaV4ApiURL, installationId, repositoryID, pullRequestID) + return callbackURL, nil +} + +func (s *service) getInstallationIDFromRepositoryID(ctx context.Context, repositoryID string) (int64, error) { + var installationId int64 + f := logrus.Fields{ + "functionName": "sign.getInstallationIDFromRepositoryID", + "repositoryID": repositoryID, + } + // Get installation ID through a helper function + log.WithFields(f).Debugf("getting repository for ID=%s...", repositoryID) githubRepository, err := s.repositoryService.GetRepositoryByExternalID(ctx, repositoryID) if err != nil { log.WithFields(f).WithError(err).Warnf("unable to get installation ID for repository ID: %s", repositoryID) - return "", err + return 0, err } // Get github organization @@ -1620,17 +1638,16 @@ func (s *service) getIndividualSignatureCallbackURL(ctx context.Context, userID if err != nil { log.WithFields(f).WithError(err).Warnf("unable to get github organization for repository ID: %s", repositoryID) - return "", err + return 0, err } installationId = githubOrg.OrganizationInstallationID if installationId == 0 { - log.WithFields(f).WithError(err).Warnf("unable to get installation ID for repository ID: %s", repositoryID) - return "", err + log.WithFields(f).Warnf("unable to get installation ID for repository ID: %s", repositoryID) + return 0, err } - callbackURL := fmt.Sprintf("%s/v4/signed/individual/%d/%s/%s", s.ClaV4ApiURL, installationId, repositoryID, pullRequestID) - return callbackURL, nil + return installationId, nil } //nolint:gocyclo @@ -2769,3 +2786,117 @@ func claSignatoryEmailContent(params ClaSignatoryEmailParams) (string, string) { return emailSubject, emailBody } + +func (s *service) getActiveSignatureReturnURL(ctx context.Context, userID string, metadata map[string]interface{}) (string, error) { + + f := logrus.Fields{ + "functionName": "sign.getActiveSignatureReturnURL", + } + + var returnURL, rId string + var err, err2 error + var pullRequestID int + var repositoryID int64 + var installationID int64 + + if found, ok := metadata["pull_request_id"]; ok && found != nil { + prId := fmt.Sprintf("%v", found) + pullRequestID, err2 = strconv.Atoi(prId) + if err2 != nil { + log.WithFields(f).WithError(err2).Warnf("unable to get pull request ID for user: %s", userID) + return "", err2 + } + } else { + err2 = errors.New("missing pull_request_id in metadata") + log.WithFields(f).WithError(err2).Warnf("unable to get pull request ID for user: %s", userID) + return "", err2 + } + + if found, ok := metadata["repository_id"]; ok && found != nil { + rId = fmt.Sprintf("%v", found) + repositoryID, err2 = strconv.ParseInt(rId, 10, 64) + if err2 != nil { + log.WithFields(f).WithError(err2).Warnf("unable to get repository ID for user: %s", userID) + return "", err2 + } + } else { + err2 = errors.New("missing repository_id in metadata") + log.WithFields(f).WithError(err2).Warnf("unable to get repository ID for user: %s", userID) + return "", err2 + } + + // Get installation ID through a helper function + installationID, err = s.getInstallationIDFromRepositoryID(ctx, rId) + if err != nil { + log.WithFields(f).WithError(err).Warnf("unable to get github organization for repository ID: %v", repositoryID) + return "", err + } + + returnURL, err = github.GetReturnURL(ctx, installationID, repositoryID, pullRequestID) + + if err != nil { + return "", err + } + + return returnURL, nil +} + +func (s *service) GetUserActiveSignature(ctx context.Context, userID string) (*models.UserActiveSignature, error) { + f := logrus.Fields{ + "functionName": "sign.GetUserActiveSignature", + utils.XREQUESTID: ctx.Value(utils.XREQUESTID), + "userID": userID, + } + activeSignatureMetadata, err := s.storeRepository.GetActiveSignatureMetaData(ctx, userID) + if err != nil { + log.WithFields(f).WithError(err).Warnf("unable to get active signature meta data for user: %s", userID) + return nil, err + } + log.WithFields(f).Debugf("active signature metadata: %+v", activeSignatureMetadata) + if len(activeSignatureMetadata) == 0 { + return nil, nil + } + var ( + mergeRequestId *string + isGitlab bool + returnURL string + pullRequestId string + repositoryId string + ) + if mrId, ok := activeSignatureMetadata["merge_request_id"]; ok && mrId != nil { + mrStr := fmt.Sprintf("%v", mrId) + mergeRequestId = &mrStr + isGitlab = true + } + if isGitlab { + var ok bool + returnURL, ok = activeSignatureMetadata["return_url"].(string) + if !ok { + log.WithFields(f).Warnf("missing return_url in metadata while merge_request_id is present: %+v", activeSignatureMetadata) + } + } else { + returnURL, err = s.getActiveSignatureReturnURL(ctx, userID, activeSignatureMetadata) + if err != nil { + log.WithFields(f).WithError(err).Warnf("unable to get active signature return url for user: %s", userID) + return nil, err + } + } + projectId, ok := activeSignatureMetadata["project_id"].(string) + if !ok { + log.WithFields(f).Warnf("missing project_id in metadata: %+v", activeSignatureMetadata) + } + if val, ok := activeSignatureMetadata["pull_request_id"]; ok && val != nil { + pullRequestId = fmt.Sprintf("%v", val) + } + if val, ok := activeSignatureMetadata["repository_id"]; ok && val != nil { + repositoryId = fmt.Sprintf("%v", val) + } + return &models.UserActiveSignature{ + MergeRequestID: mergeRequestId, + ProjectID: projectId, + PullRequestID: pullRequestId, + RepositoryID: repositoryId, + ReturnURL: strfmt.URI(returnURL), + UserID: userID, + }, nil +} diff --git a/cla-backend-go/v2/signatures/mock_users/mock_service.go b/cla-backend-go/v2/signatures/mock_users/mock_service.go index 32a6388ca..9cd506ead 100644 --- a/cla-backend-go/v2/signatures/mock_users/mock_service.go +++ b/cla-backend-go/v2/signatures/mock_users/mock_service.go @@ -245,3 +245,11 @@ func (mr *MockServiceMockRecorder) UpdateUserCompanyID(userID, companyID, note i mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserCompanyID", reflect.TypeOf((*MockService)(nil).UpdateUserCompanyID), userID, companyID, note) } + +func (m *MockService) ConvertUserModelToUserCompatModel(user *models.User) (*models.UserCompat, error) { + ret := m.ctrl.Call(m, "ConvertUserModelToUserCompatModel", user) + ret0, _ := ret[0].(*models.UserCompat) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + diff --git a/cla-backend/cla/models/github_models.py b/cla-backend/cla/models/github_models.py index 1bfe59229..dac3c37af 100644 --- a/cla-backend/cla/models/github_models.py +++ b/cla-backend/cla/models/github_models.py @@ -1091,6 +1091,7 @@ def skip_allowlisted_bots(self, org_model, org_repo, actors_missing_cla) -> Tupl cla.log.debug("final skip_cla config for repo %s is %s; actors_missing_cla: [%s]", org_repo, config, ", ".join(actor_debug_data)) out_actors_missing_cla = [] allowlisted_actors = [] + seen_actors = set() for actor in actors_missing_cla: if actor is None: continue @@ -1103,19 +1104,21 @@ def skip_allowlisted_bots(self, org_model, org_repo, actors_missing_cla) -> Tupl ) cla.log.debug("Checking actor: %s for skip_cla config: %s", actor_data, config) if self.is_actor_skipped(actor, config): - msg = "Skipping CLA check for repo='{}', actor: {} due to skip_cla config: '{}'".format( - org_repo, - actor_data, - config, - ) - cla.log.info(msg) - Event.create_event( - event_type=EventType.BypassCLA, - event_data=msg, - event_summary=msg, - event_user_name=actor_data, - contains_pii=True, - ) + if not actor_data in seen_actors: + seen_actors.add(actor_data) + msg = "Skipping CLA check for repo='{}', actor: {} due to skip_cla config: '{}'".format( + org_repo, + actor_data, + config, + ) + cla.log.info(msg) + Event.create_event( + event_type=EventType.BypassCLA, + event_data=msg, + event_summary=msg, + event_user_name=actor_data, + contains_pii=True, + ) actor.authorized = True allowlisted_actors.append(actor) continue diff --git a/cla-backend/cla/routes.py b/cla-backend/cla/routes.py index d9683759c..bbc56fa91 100755 --- a/cla-backend/cla/routes.py +++ b/cla-backend/cla/routes.py @@ -100,6 +100,7 @@ def get_health(request): # +# LG: This is ported to golang and no longer used in dev (still used in prod) @hug.get("/user/{user_id}", versions=2) def get_user(user_id: hug.types.uuid): """ @@ -232,6 +233,7 @@ def request_company_ccla( # return cla.controllers.user.request_company_admin_access(str(user_id), str(company_id)) +# LG: This is ported to golang and no longer used in dev (still used in prod) @hug.get("/user/{user_id}/active-signature", versions=2) def get_user_active_signature(user_id: hug.types.uuid): """ @@ -773,7 +775,7 @@ def get_projects(auth_user: check_auth): del project["project_external_id"] return projects - +# LG: This is ported to golang and no longer used in dev (still used in prod). @hug.get("/project/{project_id}", versions=2) def get_project(project_id: hug.types.uuid): """ diff --git a/docs/Python_APIs.md b/docs/Python_APIs.md index 1e1d30328..b075c33f4 100644 --- a/docs/Python_APIs.md +++ b/docs/Python_APIs.md @@ -13,7 +13,6 @@ - `/v2/check-prepare-employee-signature`. - `/v2/request-employee-signature`. - `/v2/user//project//last-signature`. -- `/v2/project/`. 3. EasyCLA corporate console [here](https://github.com/LF-Engineering/lfx-corp-cla-console/blob/main/backend/src/data/cla-api.ts): diff --git a/docs/Python_APIs_updates.md b/docs/Python_APIs_updates.md new file mode 100644 index 000000000..80645ddba --- /dev/null +++ b/docs/Python_APIs_updates.md @@ -0,0 +1,67 @@ +# V1/V2 python APIs still used + +1. EasyCLA backend [here](https://github.com/linuxfoundation/easycla/blob/main/.github/workflows/deploy-prod.yml#L127). +- `/v2/health`. Health check while `dev`/`prod` deployment. + + +2. EasyCLA contributor console [here](https://github.com/communitybridge/easycla-contributor-console/blob/main/src/app/core/services/cla-contributor.service.ts), found via `` find.sh . '*' /vN ``. +- `/v1/api/health` [here](https://github.com/communitybridge/easycla-contributor-console/blob/main/test/functional/cypress/integration/api-tests/health-check.spec.ts#L4). +- `/v1/user/gerrit`. +- `/v2/user/`. Porting to `/v3/user-compat/`. +- `/v2/project/`. Ported to `/v4/project-compat/`. +- `/v2/user//active-signature`. Ported to `/v4/user//active-signature`. +- `/v2/check-prepare-employee-signature`. +- `/v2/request-employee-signature`. +- `/v2/user//project//last-signature`. + + +3. EasyCLA corporate console [here](https://github.com/LF-Engineering/lfx-corp-cla-console/blob/main/backend/src/data/cla-api.ts): +- No V1 or V2 APIs used. + + +4. PCC [here](https://github.com/linuxfoundation/lfx-pcc/blob/main/apps/v1-backend/src/modules/cla-services/model/index.ts): +- No V1 or V2 APIs used. + + +5. GitHub/Gitlab/Gerrit ({provider}) app/bot [here]() (there is no list of which particular APIs are used by GitHub/GitLab/Gerrit): +- `/v2/github/activity`. +- `/v2/repository-provider/{provider}/sign/{installation_id}/{github_repository_id}/{change_request_id}`. +- `/v2/github/installation`. +- `/v1/user/gerrit`. +- `/v2/signed/individual/{installation_id}/{github_repository_id}/{change_request_id}` ? +- `/v2/repository-provider/{provider}/activity` ? +- `/v2/repository-provider/{provider}/oauth2_redirect` ? +- `/v2/signed/gitlab/individual/{user_id}/{organization_id}/{gitlab_repository_id}/{merge_request_id}` ? +- `/v2/signed/gerrit/individual/{user_id}` ? +- `cla-backend/cla/routes.py`: `GitHub Routes`, `Gerrit Routes`, `Gerrit instance routes`. + + +6. Manually check which APIs were actually called on `dev` and `prod` via: + +- `prod` analysis: `` DEBUG=1 NO_ECHO=1 STAGE=prod REGION=us-east-1 DTFROM='10 days ago' DTTO='1 second ago' OUT=api-logs-prod.json ./utils/search_aws_logs.sh 'LG:api-request-path' && jq -r '.[].message' api-logs-prod.json | grep -o 'LG:api-request-path:[^[:space:]]*' | sed 's/^LG:api-request-path://' | sed -E 's/[0-9a-fA-F-]{36}//g' | sed -E 's/\b[0-9]{2,}\b//g' | sort | uniq -c | sort -nr ``: +``` + 529509 /v2/github/activity + 2572 /v2/repository-provider/github/sign/// + 534 /v2/github/installation + 234 /v2/return-url/ + 228 /v2/check-prepare-employee-signature + 89 /v2/request-employee-signature + 16 /v1/file/icon/seo/.png + 13 /v2/gerrit//corporate/agreementUrl.html + 9 /v1/user/gerrit + 2 /v2/health +``` + +- `dev` analysis (but this can contain API calls made by developer and not actually used): `` DEBUG=1 STAGE=dev REGION=us-east-1 DTFROM='10 days ago' DTTO='1 second ago' OUT=api-logs-dev.json ./utils/search_aws_logs.sh 'LG:api-request-path' && jq -r '.[].message' api-logs-dev.json | grep -o 'LG:api-request-path:[^[:space:]]*' | sed 's/^LG:api-request-path://' | sed -E 's/[0-9a-fA-F-]{36}//g' | sed -E ':a;s#/([0-9]{1,})(/|$)#/\2#g;ta' | sort | uniq -c | sort -nr ``: +``` + 39 /v2/github/activity + 13 /v2/repository-provider/github/sign/// + 12 /v2/user-from-token + 8 /v2/github/installation + 6 /v2/health + 1 /v2/return-url/ + 1 /v2/gerrit//individual/agreementUrl.html + 1 /v2/check-prepare-employee-signature +``` + + diff --git a/tests/functional/README.md b/tests/functional/README.md new file mode 100644 index 000000000..dc2ffa8f7 --- /dev/null +++ b/tests/functional/README.md @@ -0,0 +1,102 @@ +# Cypress Framework + +This repository contains a Cypress framework setup for automated testing. The framework is structured as follows: + +## Project Folder Structure + +Project Folder
+├── node_modules
+└── cypress
+       â”œâ”€â”€ appConfig
+       â”œâ”€â”€ downloads
+       â”œâ”€â”€ e2e
+       â”œâ”€â”€ fixtures
+       â”œâ”€â”€ reports
+       â”œâ”€â”€ screenshot
+       â”œâ”€â”€ support
+       â”œâ”€â”€ video
+ +├─ cypress.config.ts
+│ .eslintrc.json
+│ readme.md
+│ .gitignore
+│ package-lock.json
+│ package.json
+│ tsconfig.json
+├─ .github
+│        â””── workflows
+│                 └── main.yml
+ +## Description + +- `.gitignore`: Specifies intentionally untracked files to ignore in Git. +- `package-lock.json` and `package.json`: Node.js package files specifying project dependencies. +- `cypress.config.ts`: Configuration file for Playwright settings. +- `tsconfig.json`: TypeScript compiler options file. + +### `.GitHub` + +- `.GitHub/workflows/main.yml`: GitLub Actions workflow file for continuous integration. + +### `node_modules` + +- Directory containing Node.js modules installed by npm. + +### `Cypress-report` + +- Directory for storing Cypress test reports. + +### `src` + +- Source code directory containing project files. + +#### `api` + +- Directory for API-related scripts. + +#### `config` + +- Directory containing environment configuration files and authentication data. + +#### `fixtures` + +- Directory for test fixtures, such as reusable functions for mock. + +### `test-results` + +- Directory for storing test execution results, including screenshots, trace files, and videos. + +## Usage + +Make sure that you have `node` and `npm` installed. + +Clone the repository and install dependencies using `npm install`. + +Create `.env` file under `tests/functional` (it is git-ignored), with contents like this: + +``` +APP_URL=https://api-gw.dev.platform.linuxfoundation.org/ +AUTH0_TOKEN_API=https://linuxfoundation-dev.auth0.com/oauth/token +AUTH0_USER_NAME=[your-username] +AUTH0_PASSWORD=[your-password] +LFX_API_TOKEN=[token] +AUTH0_CLIENT_SECRET=[client-secret] +AUTH0_CLIENT_ID=[client-id] +CYPRESS_ENV=dev +``` + +You can ask for example `.env` file over slack. + +- Run `npx cypress install` +- Run tests using cmd `npx cypress run`. +- Run tests using UI `npx cypress open`. Choose **E2E testing**, select **Chrome** browser. +- View test reports in the `cypress-report` directory. +- Explore source code files for detailed implementation. + +## Contributing + +Contributions are welcome! Please follow the established coding style and guidelines. If you find any issues or have suggestions for improvements, feel free to open an issue or submit a pull request. + +## License + +This project is licensed under the [](LICENSE). diff --git a/tests/functional/cypress.config.ts b/tests/functional/cypress.config.ts index 38e231b9f..9d01f6f98 100644 --- a/tests/functional/cypress.config.ts +++ b/tests/functional/cypress.config.ts @@ -1,14 +1,24 @@ -import { defineConfig } from 'cypress' +import { defineConfig } from 'cypress'; +import * as dotenv from 'dotenv'; +dotenv.config(); export default defineConfig({ - defaultCommandTimeout: 20000, - requestTimeout: 200000, - "reporter": "cypress-mochawesome-reporter", + defaultCommandTimeout: 30000, + requestTimeout: 300000, + reporter: 'cypress-mochawesome-reporter', e2e: { // baseUrl: 'http://localhost:1234', specPattern: 'cypress/e2e/**/**/*.{js,jsx,ts,tsx}', - } , - "env": { - "file": "cypress.env.json" + }, + env: { + APP_URL: process.env.APP_URL, + AUTH0_TOKEN_API: process.env.AUTH0_TOKEN_API, + AUTH0_USER_NAME: process.env.AUTH0_USER_NAME, + AUTH0_PASSWORD: process.env.AUTH0_PASSWORD, + LFX_API_TOKEN: process.env.LFX_API_TOKEN, + AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET, + AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID, + CYPRESS_ENV: process.env.CYPRESS_ENV, } -}) \ No newline at end of file +}); + diff --git a/tests/functional/cypress.env.json b/tests/functional/cypress.env.json deleted file mode 100644 index 8cab24919..000000000 --- a/tests/functional/cypress.env.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "APP_URL": "https://api-gw.dev.platform.linuxfoundation.org/", - "AUTH0_TOKEN_API":"https://linuxfoundation-dev.auth0.com/oauth/token", - "AUTH0_USER_NAME":"vthakur", - "AUTH0_PASSWORD":"Test@123", - "LFX_API_TOKEN":"gDYBt6VYW6cmXelL/a3wTmHMa9sD37Xo9gsgaIjncbw=", - "AUTH0_CLIENT_SECRET":"eyJuYW1lIjoiYXV0aDAuanMtdWxwIiwidmVyc2lvbiI6IjkuMTIuMiJ9", - "AUTH0_CLIENT_ID":"hquZHO8JNsaIScoayPtCS5VELdn7TnVq", - "CYPRESS_ENV" :"dev" -} \ No newline at end of file diff --git a/tests/functional/package-lock.json b/tests/functional/package-lock.json index 0e8af9872..c243e0f21 100644 --- a/tests/functional/package-lock.json +++ b/tests/functional/package-lock.json @@ -8,9 +8,16 @@ "name": "lfx-easycla-service-cypress-api-testing", "version": "1.0.0", "license": "ISC", + "dependencies": { + "ajv": "^8.12.0", + "cypress-mochawesome-reporter": "^3.5.1", + "mochawesome-merge": "^4.3.0", + "mochawesome-report-generator": "^6.2.0" + }, "devDependencies": { "@types/node": "^20.5.0", "cypress": "^12.17.3", + "cypress-dotenv": "^3.0.1", "typescript": "^5.1.6" } }, @@ -18,7 +25,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -29,7 +35,6 @@ "version": "2.88.12", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "aws-sign2": "~0.7.0", @@ -59,7 +64,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^3.1.0", @@ -70,44 +74,147 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, - "node_modules/@cypress/xvfb/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==", - "dev": true, - "license": "MIT" + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT", + "peer": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } }, "node_modules/@types/node": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", - "dev": true + "devOptional": true }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true, "license": "MIT" }, "node_modules/@types/sizzle": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -118,7 +225,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -128,11 +234,26 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -142,7 +263,6 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.21.3" @@ -158,7 +278,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -168,7 +287,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -184,7 +302,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, "funding": [ { "type": "github", @@ -201,11 +318,17 @@ ], "license": "MIT" }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0", + "peer": true + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" @@ -215,7 +338,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8" @@ -225,7 +347,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -235,21 +356,18 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true, "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, "license": "ISC", "engines": { "node": ">= 4.0.0" @@ -259,7 +377,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -269,21 +386,18 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true, "license": "MIT" }, "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, "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -304,7 +418,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" @@ -314,32 +427,35 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true, "license": "Apache-2.0" }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, "license": "MIT" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "license": "ISC", + "peer": true + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -364,7 +480,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" @@ -374,7 +489,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -384,7 +498,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1", @@ -394,18 +507,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true, "license": "Apache-2.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -422,7 +545,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -435,17 +557,31 @@ "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "peer": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, "funding": [ { "type": "github", @@ -461,7 +597,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -471,7 +606,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" @@ -484,7 +618,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, "license": "MIT", "dependencies": { "string-width": "^4.2.0" @@ -500,7 +633,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, "license": "MIT", "dependencies": { "slice-ansi": "^3.0.0", @@ -513,11 +645,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "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==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -530,21 +675,18 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -557,7 +699,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -567,7 +708,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4.0.0" @@ -577,21 +717,18 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -606,7 +743,6 @@ "version": "12.17.3", "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz", "integrity": "sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -660,17 +796,83 @@ "node": "^14.0.0 || ^16.0.0 || >=18.0.0" } }, + "node_modules/cypress-dotenv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cypress-dotenv/-/cypress-dotenv-3.0.1.tgz", + "integrity": "sha512-k1EGr8JJZdUxTsV7MbnVKGhgiU2q8LsFdDfGfmvofAQTODNhiHnqP7Hp8Cy7fhzVYb/7rkGcto0tPLLr2QCggA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.3.0", + "dotenv-parse-variables": "^2.0.0", + "lodash.clonedeep": "^4.5.0" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">= 10.x" + }, + "peerDependencies": { + "cypress": ">= 10.x", + "dotenv": ">= 10.x" + } + }, + "node_modules/cypress-mochawesome-reporter": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/cypress-mochawesome-reporter/-/cypress-mochawesome-reporter-3.8.4.tgz", + "integrity": "sha512-ytn8emXyR5nz2+uqqgwqEwpeR9oILEIFSWl2lt2eyHICb2d0s/Hu7bPPo02bEf8UkqJohwg00yZ+jDH6oUqmzw==", + "license": "MIT", + "dependencies": { + "commander": "^10.0.1", + "fs-extra": "^10.0.1", + "mochawesome": "^7.1.3", + "mochawesome-merge": "^4.2.1", + "mochawesome-report-generator": "^6.2.0" + }, + "bin": { + "generate-mochawesome-report": "cli.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/LironEr" + }, + "peerDependencies": { + "cypress": ">=6.2.0" + } + }, + "node_modules/cypress-mochawesome-reporter/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/cypress-mochawesome-reporter/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/cypress/node_modules/@types/node": { "version": "16.18.40", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.40.tgz", - "integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==", - "dev": true + "integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==" }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -679,21 +881,28 @@ "node": ">=0.10" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/dayjs": { "version": "1.11.9", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==", - "dev": true, "license": "MIT" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -704,21 +913,77 @@ } } }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-parse-variables": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dotenv-parse-variables/-/dotenv-parse-variables-2.0.0.tgz", + "integrity": "sha512-/Tezlx6xpDqR6zKg1V4vLCeQtHWiELhWoBz5A/E0+A1lXN9iIkNbbfc4THSymS0LQUo8F1PMiIwVG8ai/HrnSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.1", + "is-string-and-not-blank": "^0.0.2" + }, + "engines": { + "node": ">= 8.3.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT", + "peer": true + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, "license": "MIT", "dependencies": { "jsbn": "~0.1.0", @@ -729,14 +994,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -746,7 +1009,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-colors": "^4.1.1", @@ -756,11 +1018,25 @@ "node": ">=8.6" } }, + "node_modules/escalade": { + "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" + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -770,14 +1046,12 @@ "version": "6.4.7", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true, "license": "MIT" }, "node_modules/execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, "license": "MIT", "dependencies": { "cross-spawn": "^7.0.0", @@ -801,7 +1075,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^2.2.0" @@ -814,14 +1087,12 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true, "license": "MIT" }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -842,17 +1113,37 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, "engines": [ "node >=0.6.0" ], "license": "MIT" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" @@ -862,7 +1153,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" @@ -874,11 +1164,67 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "peer": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/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/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -888,7 +1234,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -903,7 +1248,6 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", @@ -919,21 +1263,33 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, "license": "ISC" }, + "node_modules/fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "license": "MIT" + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true, "license": "MIT" }, + "node_modules/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==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1", @@ -949,7 +1305,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -965,7 +1320,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, "license": "MIT", "dependencies": { "async": "^3.2.0" @@ -975,7 +1329,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -985,7 +1338,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -1006,7 +1358,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, "license": "MIT", "dependencies": { "ini": "2.0.0" @@ -1022,14 +1373,12 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.1" @@ -1042,7 +1391,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1052,7 +1400,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1065,7 +1412,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1074,11 +1420,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "peer": true, + "bin": { + "he": "bin/he" + } + }, "node_modules/http-signature": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", @@ -1093,7 +1448,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8.12.0" @@ -1103,7 +1457,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -1124,7 +1477,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1134,7 +1486,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, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -1145,14 +1496,12 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/ini": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -1162,7 +1511,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, "license": "MIT", "dependencies": { "ci-info": "^3.2.0" @@ -1175,7 +1523,6 @@ "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==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1185,7 +1532,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, "license": "MIT", "dependencies": { "global-dirs": "^3.0.0", @@ -1202,17 +1548,25 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1221,18 +1575,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-string-and-not-blank": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/is-string-and-not-blank/-/is-string-and-not-blank-0.0.2.tgz", + "integrity": "sha512-FyPGAbNVyZpTeDCTXnzuwbu9/WpNXbCfbHXLpCRpN4GANhS00eEIP5Ef+k5HYSNIzIhdN9zRDoBj6unscECvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-string-blank": "^1.0.1" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/is-string-blank": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-string-blank/-/is-string-blank-1.0.1.tgz", + "integrity": "sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw==", + "dev": true, + "license": "MIT" + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -1245,42 +1617,77 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true, "license": "MIT" }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true, "license": "MIT" }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, "license": "ISC" }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -1293,7 +1700,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, "engines": [ "node >=0.6.0" ], @@ -1309,7 +1715,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true, "license": "MIT", "engines": { "node": "> 0.8" @@ -1319,7 +1724,6 @@ "version": "3.14.0", "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, "license": "MIT", "dependencies": { "cli-truncate": "^2.1.0", @@ -1343,25 +1747,69 @@ } } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", "dev": true, "license": "MIT" }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==", + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "license": "MIT" + }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true, "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -1378,7 +1826,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, "license": "MIT", "dependencies": { "ansi-escapes": "^4.3.0", @@ -1397,7 +1844,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -1415,7 +1861,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -1426,11 +1871,22 @@ "node": ">=8" } }, + "node_modules/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==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -1443,14 +1899,12 @@ "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, "license": "MIT" }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -1460,7 +1914,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -1473,7 +1926,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1483,7 +1935,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -1496,24 +1947,379 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", + "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", + "license": "MIT", + "peer": true, + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/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/mocha/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mochawesome": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz", + "integrity": "sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "diff": "^5.0.0", + "json-stringify-safe": "^5.0.1", + "lodash.isempty": "^4.4.0", + "lodash.isfunction": "^3.0.9", + "lodash.isobject": "^3.0.2", + "lodash.isstring": "^4.0.1", + "mochawesome-report-generator": "^6.2.0", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2" + }, + "peerDependencies": { + "mocha": ">=7" + } + }, + "node_modules/mochawesome-merge": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.4.1.tgz", + "integrity": "sha512-QCzsXrfH5ewf4coUGvrAOZSpRSl9Vg39eqL2SpKKGkUw390f18hx9C90BNWTA4f/teD2nA0Inb1yxYPpok2gvg==", + "license": "MIT", + "dependencies": { + "fs-extra": "^7.0.1", + "glob": "^7.1.6", + "yargs": "^15.3.1" + }, + "bin": { + "mochawesome-merge": "bin/mochawesome-merge.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mochawesome-merge/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mochawesome-merge/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/mochawesome-merge/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mochawesome-merge/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/mochawesome-merge/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/mochawesome-merge/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mochawesome-merge/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/mochawesome-merge/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/mochawesome-merge/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mochawesome-merge/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mochawesome-report-generator": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz", + "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "dateformat": "^4.5.1", + "escape-html": "^1.0.3", + "fs-extra": "^10.0.0", + "fsu": "^1.1.1", + "lodash.isfunction": "^3.0.9", + "opener": "^1.5.2", + "prop-types": "^15.7.2", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "validator": "^13.6.0", + "yargs": "^17.2.1" + }, + "bin": { + "marge": "bin/cli.js" + } + }, + "node_modules/mochawesome-report-generator/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mochawesome/node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.0.0" @@ -1522,11 +2328,19 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1536,7 +2350,6 @@ "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, "license": "ISC", "dependencies": { "wrappy": "1" @@ -1546,7 +2359,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -1558,18 +2370,57 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, "node_modules/ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true, "license": "MIT" }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" @@ -1581,11 +2432,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0", + "peer": true + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/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, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1595,31 +2470,58 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC", + "peer": true + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, "license": "MIT" }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true, "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC", + "peer": true + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1629,7 +2531,6 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1638,25 +2539,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true, "license": "MIT" }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true, "license": "MIT" }, "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, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -1667,7 +2576,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1677,7 +2585,6 @@ "version": "6.10.5", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.5.tgz", "integrity": "sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" @@ -1693,31 +2600,81 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true, "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.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==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, "license": "MIT", "dependencies": { "throttleit": "^1.0.0" } }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, "license": "MIT" }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, "license": "MIT", "dependencies": { "onetime": "^5.1.0", @@ -1731,14 +2688,12 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true, "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -1754,7 +2709,6 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -1764,7 +2718,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -1785,14 +2738,12 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" @@ -1804,11 +2755,26 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -1821,7 +2787,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1831,7 +2796,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.0", @@ -1846,14 +2810,12 @@ "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, "license": "ISC" }, "node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -1868,7 +2830,6 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dev": true, "license": "MIT", "dependencies": { "asn1": "~0.2.3", @@ -1894,7 +2855,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -1905,11 +2865,26 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "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/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -1918,21 +2893,46 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "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==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -1944,25 +2944,37 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "license": "MIT" + }, + "node_modules/tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "license": "MIT", + "dependencies": { + "tcomb": "^3.0.0" + } + }, "node_modules/throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==", - "dev": true, "license": "MIT" }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, "license": "MIT" }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, "license": "MIT", "dependencies": { "rimraf": "^3.0.0" @@ -1975,7 +2987,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", @@ -1991,7 +3002,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" @@ -2001,14 +3011,12 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", - "dev": true, "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -2021,14 +3029,12 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true, "license": "Unlicense" }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -2055,7 +3061,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -2065,7 +3070,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2075,7 +3079,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "license": "MIT", "dependencies": { "querystringify": "^2.1.1", @@ -2086,17 +3089,24 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, + "node_modules/validator": { + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, "engines": [ "node >=0.6.0" ], @@ -2111,7 +3121,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", - "dev": true, "engines": [ "node >=0.6.0" ], @@ -2121,7 +3130,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -2133,11 +3141,23 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/workerpool": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", + "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", + "license": "Apache-2.0", + "peer": true + }, "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==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -2151,30 +3171,111 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "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/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, "license": "ISC" }, + "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", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, "license": "ISC" }, + "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", + "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/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", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "license": "MIT", + "peer": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/tests/functional/package.json b/tests/functional/package.json index 03004cfa9..34901f490 100644 --- a/tests/functional/package.json +++ b/tests/functional/package.json @@ -24,6 +24,7 @@ "devDependencies": { "@types/node": "^20.5.0", "cypress": "^12.17.3", + "cypress-dotenv": "^3.0.1", "typescript": "^5.1.6" }, "dependencies": { diff --git a/tests/functional/run-dev-cli.sh b/tests/functional/run-dev-cli.sh old mode 100644 new mode 100755 diff --git a/tests/functional/run-local-cli.sh b/tests/functional/run-local-cli.sh old mode 100644 new mode 100755 diff --git a/tests/functional/yarn.lock b/tests/functional/yarn.lock index 9fa20045c..e734f1f98 100644 --- a/tests/functional/yarn.lock +++ b/tests/functional/yarn.lock @@ -39,6 +39,23 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@types/node@*", "@types/node@^20.5.0": version "20.5.0" resolved "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz" @@ -75,14 +92,14 @@ aggregate-error@^3.0.0: indent-string "^4.0.0" ajv@^8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + version "8.17.1" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" ansi-colors@^4.1.1: version "4.1.3" @@ -101,6 +118,11 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" @@ -108,11 +130,21 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + arch@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + asn1@~0.2.3: version "0.2.6" resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" @@ -120,7 +152,7 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" -assert-plus@1.0.0, assert-plus@^1.0.0: +assert-plus@^1.0.0, assert-plus@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== @@ -190,6 +222,18 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" @@ -218,9 +262,14 @@ call-bind@^1.0.0: camelcase@^5.0.0: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0, camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" @@ -239,6 +288,13 @@ check-more-types@^2.24.0: resolved "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz" integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + ci-info@^3.2.0: version "3.8.0" resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz" @@ -275,7 +331,7 @@ cli-truncate@^2.1.0: cliui@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" @@ -284,7 +340,7 @@ cliui@^6.0.0: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -315,6 +371,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^6.2.1: version "6.2.1" resolved "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz" @@ -335,26 +396,36 @@ core-util-is@1.0.2: resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -cross-spawn@^7.0.0: - version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== +cross-spawn@^7.0.0, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" +cypress-dotenv@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/cypress-dotenv/-/cypress-dotenv-3.0.1.tgz" + integrity sha512-k1EGr8JJZdUxTsV7MbnVKGhgiU2q8LsFdDfGfmvofAQTODNhiHnqP7Hp8Cy7fhzVYb/7rkGcto0tPLLr2QCggA== + dependencies: + camelcase "^6.3.0" + dotenv-parse-variables "^2.0.0" + lodash.clonedeep "^4.5.0" + cypress-mochawesome-reporter@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/cypress-mochawesome-reporter/-/cypress-mochawesome-reporter-3.5.1.tgz#7ede2777e2ce559cd4619d1e070f0230e574c822" - integrity sha512-/5ahFTyTxLujdzfTvmQrzKrJ8GWv12rUbOHvzWfVRYlAp/088ffU/1QbcfacEa2HTs28onSIIBiIKqSOID/bTw== + version "3.8.4" + resolved "https://registry.npmjs.org/cypress-mochawesome-reporter/-/cypress-mochawesome-reporter-3.8.4.tgz" + integrity sha512-ytn8emXyR5nz2+uqqgwqEwpeR9oILEIFSWl2lt2eyHICb2d0s/Hu7bPPo02bEf8UkqJohwg00yZ+jDH6oUqmzw== dependencies: + commander "^10.0.1" fs-extra "^10.0.1" mochawesome "^7.1.3" mochawesome-merge "^4.2.1" mochawesome-report-generator "^6.2.0" -cypress@^12.17.3: +cypress@^12.17.3, "cypress@>= 10.x", cypress@>=6.2.0: version "12.17.3" resolved "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz" integrity sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg== @@ -411,7 +482,7 @@ dashdash@^1.12.0: dateformat@^4.5.1: version "4.6.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== dayjs@^1.10.4: @@ -426,27 +497,55 @@ debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^4.1.1, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.3.5: + version "4.4.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: - ms "2.1.2" + ms "^2.1.3" decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== diff@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" - integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + version "5.2.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +diff@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz" + integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== + +dotenv-parse-variables@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/dotenv-parse-variables/-/dotenv-parse-variables-2.0.0.tgz" + integrity sha512-/Tezlx6xpDqR6zKg1V4vLCeQtHWiELhWoBz5A/E0+A1lXN9iIkNbbfc4THSymS0LQUo8F1PMiIwVG8ai/HrnSA== + dependencies: + debug "^4.3.1" + is-string-and-not-blank "^0.0.2" + +"dotenv@>= 10.x": + version "17.2.1" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz" + integrity sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== ecc-jsbn@~0.1.1: version "0.1.2" @@ -461,6 +560,11 @@ emoji-regex@^8.0.0: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" @@ -468,7 +572,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.6: +enquirer@^2.3.6, "enquirer@>= 2.3.0 < 3": version "2.4.1" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz" integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== @@ -477,13 +581,13 @@ enquirer@^2.3.6: strip-ansi "^6.0.1" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.2.0" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: @@ -491,6 +595,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + eventemitter2@6.4.7: version "6.4.7" resolved "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz" @@ -534,21 +643,26 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - extsprintf@^1.2.0: version "1.4.1" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-deep-equal@^3.1.1: +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz" @@ -565,12 +679,33 @@ figures@^3.2.0: find-up@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" @@ -585,9 +720,18 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -fs-extra@^10.0.0, fs-extra@^10.0.1: +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^10.0.1: version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" @@ -596,7 +740,7 @@ fs-extra@^10.0.0, fs-extra@^10.0.1: fs-extra@^7.0.1: version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" @@ -620,7 +764,7 @@ fs.realpath@^1.0.0: fsu@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/fsu/-/fsu-1.1.1.tgz#bd36d3579907c59d85b257a75b836aa9e0c31834" + resolved "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz" integrity sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A== function-bind@^1.1.1: @@ -630,7 +774,7 @@ function-bind@^1.1.1: get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.2: @@ -664,6 +808,18 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob@^10.4.5: + version "10.4.5" + resolved "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" @@ -710,6 +866,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + http-signature@~1.3.6: version "1.3.6" resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz" @@ -777,11 +938,28 @@ is-path-inside@^3.0.2: resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-string-and-not-blank@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/is-string-and-not-blank/-/is-string-and-not-blank-0.0.2.tgz" + integrity sha512-FyPGAbNVyZpTeDCTXnzuwbu9/WpNXbCfbHXLpCRpN4GANhS00eEIP5Ef+k5HYSNIzIhdN9zRDoBj6unscECvtQ== + dependencies: + is-string-blank "^1.0.1" + +is-string-blank@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/is-string-blank/-/is-string-blank-1.0.1.tgz" + integrity sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw== + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" @@ -802,11 +980,27 @@ isstream@~0.1.2: resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" @@ -814,7 +1008,7 @@ jsbn@~0.1.0: json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json-schema@0.4.0: @@ -829,7 +1023,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: jsonfile@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" @@ -874,29 +1068,41 @@ listr2@^3.8.3: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + lodash.isempty@^4.4.0: version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" + resolved "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz" integrity sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg== lodash.isfunction@^3.0.9: version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + resolved "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz" integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== lodash.isobject@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" + resolved "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz" integrity sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA== lodash.isstring@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== lodash.once@^4.1.1: @@ -909,7 +1115,7 @@ lodash@^4.17.21: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^4.0.0: +log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -929,11 +1135,16 @@ log-update@^4.0.0: loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" @@ -970,15 +1181,53 @@ minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.4, minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.8: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mocha@>=7: + version "11.7.1" + resolved "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz" + integrity sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^7.0.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^9.0.5" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^9.2.0" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + mochawesome-merge@^4.2.1, mochawesome-merge@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/mochawesome-merge/-/mochawesome-merge-4.3.0.tgz#7cc5d5730c7d8d1b034c8d8fecf3cd36e0010297" - integrity sha512-1roR6g+VUlfdaRmL8dCiVpKiaUhbPVm1ZQYUM6zHX46mWk+tpsKVZR6ba98k2zc8nlPvYd71yn5gyH970pKBSw== + version "4.4.1" + resolved "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.4.1.tgz" + integrity sha512-QCzsXrfH5ewf4coUGvrAOZSpRSl9Vg39eqL2SpKKGkUw390f18hx9C90BNWTA4f/teD2nA0Inb1yxYPpok2gvg== dependencies: fs-extra "^7.0.1" glob "^7.1.6" @@ -986,7 +1235,7 @@ mochawesome-merge@^4.2.1, mochawesome-merge@^4.3.0: mochawesome-report-generator@^6.2.0: version "6.2.0" - resolved "https://registry.yarnpkg.com/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz#65a30a11235ba7a68e1cf0ca1df80d764b93ae78" + resolved "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz" integrity sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg== dependencies: chalk "^4.1.2" @@ -1004,7 +1253,7 @@ mochawesome-report-generator@^6.2.0: mochawesome@^7.1.3: version "7.1.3" - resolved "https://registry.yarnpkg.com/mochawesome/-/mochawesome-7.1.3.tgz#07b358138f37f5b07b51a1b255d84babfa36fa83" + resolved "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz" integrity sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ== dependencies: chalk "^4.1.2" @@ -1018,12 +1267,7 @@ mochawesome@^7.1.3: strip-ansi "^6.0.1" uuid "^8.3.2" -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -1037,7 +1281,7 @@ npm-run-path@^4.0.0: object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.9.0: @@ -1061,7 +1305,7 @@ onetime@^5.1.0: opener@^1.5.2: version "1.5.2" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== ospath@^1.2.2: @@ -1071,18 +1315,32 @@ ospath@^1.2.2: p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" @@ -1092,12 +1350,17 @@ p-map@^4.0.0: p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: @@ -1110,6 +1373,14 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + pend@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" @@ -1120,6 +1391,11 @@ performance-now@^2.1.0: resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + pify@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" @@ -1132,7 +1408,7 @@ pretty-bytes@^5.6.0: prop-types@^15.7.2: version "15.8.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" @@ -1157,7 +1433,7 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.1: version "2.3.0" resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== @@ -1174,11 +1450,23 @@ querystringify@^2.1.1: resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + react-is@^16.13.1: version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + request-progress@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz" @@ -1188,17 +1476,17 @@ request-progress@^3.0.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: @@ -1233,7 +1521,7 @@ rxjs@^7.5.1: dependencies: tslib "^2.1.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.2: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -1250,9 +1538,16 @@ semver@^7.5.3: dependencies: lru-cache "^6.0.0" +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== shebang-command@^2.0.0: @@ -1281,6 +1576,11 @@ signal-exit@^3.0.2: resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" @@ -1314,6 +1614,15 @@ sshpk@^1.14.1: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -1323,6 +1632,22 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -1330,11 +1655,23 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" @@ -1351,14 +1688,14 @@ supports-color@^8.1.1: tcomb-validation@^3.3.0: version "3.4.1" - resolved "https://registry.yarnpkg.com/tcomb-validation/-/tcomb-validation-3.4.1.tgz#a7696ec176ce56a081d9e019f8b732a5a8894b65" + resolved "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz" integrity sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA== dependencies: tcomb "^3.0.0" tcomb@^3.0.0, tcomb@^3.2.17: version "3.2.29" - resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-3.2.29.tgz#32404fe9456d90c2cf4798682d37439f1ccc386c" + resolved "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz" integrity sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ== throttleit@^1.0.0: @@ -1412,12 +1749,12 @@ type-fest@^0.21.3: typescript@^5.1.6: version "5.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz" integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== universalify@^0.1.0: version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^0.2.0: @@ -1435,13 +1772,6 @@ untildify@^4.0.0: resolved "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - url-parse@^1.5.3: version "1.5.10" resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz" @@ -1456,9 +1786,9 @@ uuid@^8.3.2: integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== validator@^13.6.0: - version "13.11.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" - integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== + version "13.15.15" + resolved "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz" + integrity sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A== verror@1.10.0: version "1.10.0" @@ -1471,7 +1801,7 @@ verror@1.10.0: which-module@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== which@^2.0.1: @@ -1481,6 +1811,20 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +workerpool@^9.2.0: + version "9.3.3" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz" + integrity sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" @@ -1499,6 +1843,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" @@ -1506,12 +1859,12 @@ wrappy@1: y18n@^4.0.0: version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^4.0.0: @@ -1521,7 +1874,7 @@ yallist@^4.0.0: yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" @@ -1529,12 +1882,22 @@ yargs-parser@^18.1.2: yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + yargs@^15.3.1: version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" @@ -1549,9 +1912,9 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.2.1: +yargs@^17.2.1, yargs@^17.7.2: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -1569,3 +1932,8 @@ yauzl@^2.10.0: dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/tests/py2go/Makefile b/tests/py2go/Makefile new file mode 100644 index 000000000..4841a492e --- /dev/null +++ b/tests/py2go/Makefile @@ -0,0 +1,5 @@ +.phony: fmt test +test: fmt + go test -v +fmt: + go fmt *.go diff --git a/tests/py2go/README.md b/tests/py2go/README.md new file mode 100644 index 000000000..031f5e592 --- /dev/null +++ b/tests/py2go/README.md @@ -0,0 +1,33 @@ +# Testing porting APIs from Python to golang + +1) Start `python` API backend: +- `` source setenv.sh; cd cla-backend; source .venv/bin/activate; yarn serve:ext ``. + +2) Start `golang` API backend: +- `` source setenv.sh; cd cla-backend-go; make swagger; make build-linux ``. +- `` PORT=5001 AUTH0_USERNAME_CLAIM_CLI='http://lfx.dev/claims/username' AUTH0_EMAIL_CLAIM_CLI='http://lfx.dev/claims/email' AUTH0_NAME_CLAIM_CLI='http://lfx.dev/claims/username' ./bin/cla ``. +- Or: `` ../utils/run_go_api_server.sh ``. + +3) Get `auth0` token from browser session (login using `LFID`): +- `` ./get_oauth_token.sh ``. Copy the token value. + +3) Exacute API tests: +- `` export TOKEN='' ``. +- `` export XACL="$(cat ../../x-acl.secret)" ``. +- `` make ``. +- `` DEBUG=1 PROJECT_UUID=88ee12de-122b-4c46-9046-19422054ed8d PY_API_URL=https://api.lfcla.dev.platform.linuxfoundation.org GO_API_URL=https://api-gw.dev.platform.linuxfoundation.org/cla-service make ``. +- `` MAX_PARALLEL=8 PY_API_URL=https://api.lfcla.dev.platform.linuxfoundation.org go test -v -run '^TestAllProjectsCompatAPI$' ``. +- To run a specific test case(s): `` DEBUG=1 PROJECT_UUID=88ee12de-122b-4c46-9046-19422054ed8d PY_API_URL=https://api.lfcla.dev.platform.linuxfoundation.org go test -v -run '^TestProjectCompatAPI$' ``. +- Manually via `cURL`: `` curl -s -XGET http://127.0.0.1:5001/v4/project-compat/01af041c-fa69-4052-a23c-fb8c1d3bef24 | jq . ``. +- To manually see given project values if APIs differ (to dewbug): `` aws --region us-east-1 --profile lfproduct-dev dynamodb get-item --table-name cla-dev-projects --key '{"project_id": {"S": "4a855799-0aea-4e01-98b7-ef3da09df478"}}' | jq '.Item' ``. +- And `` aws --region us-east-1 --profile lfproduct-dev dynamodb query --table-name cla-dev-projects-cla-groups --index-name cla-group-id-index --key-condition-expression "cla_group_id = :project_id" --expression-attribute-values '{":project_id":{"S":"4a855799-0aea-4e01-98b7-ef3da09df478"}}' | jq '.Items' ``. +- `` DEBUG='' USER_UUID=b817eb57-045a-4fe0-8473-fbb416a01d70 PY_API_URL=https://api.lfcla.dev.platform.linuxfoundation.org go test -v -run '^TestUserActiveSignatureAPI$' ``. +- `` REPO_ID=466156917 PR_ID=3 DEBUG=1 go test -v -run '^TestUserActiveSignatureAPI$' ``. +- `` MAX_PARALLEL=2 DEBUG='' go test -v -run '^TestAllUserActiveSignatureAPI$' ``. +- `` [STAGE=prod] [PY_API_URL=local|dev|prod] [GO_API_URL=local|dev|prod] make ``. +- `` GO_API_URL=dev PY_API_URL=dev go test -v -run '^TestUserActiveSignatureAPIWithNonV4UUID$' ``. +- `` GO_API_URL=dev PY_API_URL=dev go test -v -run '^TestUserActiveSignatureAPIWithInvalidUUID$' ``. +- `` GO_API_URL=dev PY_API_URL=dev go test -v -run '^TestProjectCompatAPIWithNonV4UUID$' ``. +- `` GO_API_URL=dev PY_API_URL=dev go test -v -run '^TestProjectCompatAPIWithInvalidUUID$' ``. +- `` GO_API_URL=local PY_API_URL=dev go test -v -run '^TestAllUsersCompatAPI$' ``. +- `` USER_UUID=7b596ccc-b087-11ef-b61d-6a99096124c1 GO_API_URL=local PY_API_URL=dev go test -v -run '^TestUserCompatAPI$' ``. diff --git a/tests/py2go/api_test.go b/tests/py2go/api_test.go new file mode 100644 index 000000000..9f9c0a576 --- /dev/null +++ b/tests/py2go/api_test.go @@ -0,0 +1,1152 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "math/rand" + "net/http" + "os" + "runtime" + "sort" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +const ( + ExampleRepoID = 466156917 + ExamplePRNumber = 3 + InvalidUUIDProvided = "Invalid UUID provided" + GoUUIDValidationError = " in path should match '^[a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}$'" +) + +var ( + TOKEN string + XACL string + PY_API_URL string + GO_API_URL string + DEBUG bool + MAX_PARALLEL int + PROJECT_UUID string + USER_UUID string + REPO_ID int64 + PR_ID int64 + ProjectAPIPath = [3]string{"/v2/project/%s", "/v4/project/%s", "/v4/project-compat/%s"} + ProjectAPIKeyMapping = map[string]string{ + "date_created": "dateCreated", + "date_modified": "dateModified", + "project_name": "projectName", + "foundation_sfid": "foundationSFID", + "project_acl": "projectACL", + "project_ccla_enabled": "projectCCLAEnabled", + "project_ccla_requires_icla_signature": "projectCCLARequiresICLA", + "project_icla_enabled": "projectICLAEnabled", + "project_id": "projectID", + "project_live": "projectLive", + "version": "version", + // "project_individual_documents": "projectIndividualDocuments", + // "project_corporate_documents": "projectCorporateDocuments", + // "project_member_documents": "projectMemberDocuments", + // "signed_at_foundation_level": "foundationLevelCLA", + // "root_project_repositories_count": "rootProjectRepositoriesCount", + } + ProjectCompatAPIKeyMapping = map[string]interface{}{ + "foundation_sfid": nil, + "project_ccla_enabled": nil, + "project_ccla_requires_icla_signature": nil, + "project_icla_enabled": nil, + "project_id": nil, + "project_name": nil, + "project_individual_documents": []interface{}{map[string]interface{}{ + "document_major_version": nil, + "document_minor_version": nil, + }}, + "project_corporate_documents": []interface{}{map[string]interface{}{ + "document_major_version": nil, + "document_minor_version": nil, + }}, + "projects": []interface{}{map[string]interface{}{ + "cla_group_id": nil, + "foundation_sfid": nil, + "project_name": nil, + "project_sfid": nil, + "github_repos": []interface{}{map[string]interface{}{"repository_name": nil}}, + "gitlab_repos": []interface{}{map[string]interface{}{"repository_name": nil}}, + "gerrit_repos": []interface{}{map[string]interface{}{"gerrit_url": nil}}, + }}, + // "signed_at_foundation_level": nil, + } + ProjectCompatAPISortMap = map[string]interface{}{ + "github_repos": "repository_name", + "gitlab_repos": "repository_name", + "gerrit_repos": "gerrit_url", + } + UserActiveSignatureAPIPath = [2]string{"/v2/user/%s/active-signature", "/v4/user/%s/active-signature"} + // Optional field: true means the key may be missing in both APIs and still be valid + UserActiveSignatureAPIKeyMapping = map[string]interface{}{ + "project_id": nil, + "pull_request_id": nil, + "repository_id": nil, + "return_url": nil, + "user_id": nil, + "merge_request_id": true, + } + UserCompatAPIPath = [2]string{"/v2/user/%s", "/v3/user-compat/%s"} + // If the value is array with an empty interface it means that each array element should be checked + UserCompatAPIKeyMapping = map[string]interface{}{ + "lf_email": nil, + "lf_sub": nil, + "lf_username": nil, + "note": nil, + "user_company_id": nil, + "user_external_id": nil, + "user_github_id": nil, + "user_github_username": nil, + "user_gitlab_id": nil, + "user_gitlab_username": nil, + "user_id": nil, + "user_ldap_id": nil, + "user_name": nil, + "is_sanctioned": nil, + "version": nil, + "user_emails": []interface{}{map[string]interface{}{}}, + } + UserCompatAPISortMap = map[string]interface{}{ + "user_emails": nil, + } +) + +func init() { + TOKEN = os.Getenv("TOKEN") + XACL = os.Getenv("XACL") + PY_API_URL = os.Getenv("PY_API_URL") + switch PY_API_URL { + case "local", "": + PY_API_URL = "http://127.0.0.1:5000" + case "dev": + PY_API_URL = "https://api.lfcla.dev.platform.linuxfoundation.org" + case "prod": + PY_API_URL = "https://api.easycla.lfx.linuxfoundation.org" + } + GO_API_URL = os.Getenv("GO_API_URL") + switch GO_API_URL { + case "local", "": + GO_API_URL = "http://127.0.0.1:5001" + case "dev": + GO_API_URL = "https://api-gw.dev.platform.linuxfoundation.org/cla-service" + case "prod": + GO_API_URL = "https://api-gw.platform.linuxfoundation.org/cla-service" + } + DEBUG = os.Getenv("DEBUG") != "" + MAX_PARALLEL = runtime.NumCPU() + par := os.Getenv("MAX_PARALLEL") + if par != "" { + iPar, err := strconv.Atoi(par) + if err != nil { + fmt.Printf("MAX_PARALLEL environment value should be integer >= 1\n") + } else if iPar > 0 { + MAX_PARALLEL = iPar + } + } + PROJECT_UUID = os.Getenv("PROJECT_UUID") + USER_UUID = os.Getenv("USER_UUID") + REPO_ID = ExampleRepoID + par = os.Getenv("REPO_ID") + if par != "" { + iPar, err := strconv.ParseInt(par, 10, 64) + if err != nil { + fmt.Printf("REPO_ID environment value should be integer >= 1\n") + } else if iPar > 0 { + REPO_ID = iPar + } + } + PR_ID = ExamplePRNumber + par = os.Getenv("PR_ID") + if par != "" { + iPar, err := strconv.ParseInt(par, 10, 64) + if err != nil { + fmt.Printf("PR_ID environment value should be integer >= 1\n") + } else if iPar > 0 { + PR_ID = iPar + } + } + rand.Seed(time.Now().UnixNano()) +} + +func tryParseTime(val interface{}) (time.Time, bool) { + str, ok := val.(string) + if !ok { + return time.Time{}, false + } + layouts := []string{ + time.RFC3339, + "2006-01-02T15:04:05.000000Z0700", + "2006-01-02T15:04:05Z07:00", + "2006-01-02T15:04:05", + "2006-01-02 15:04:05", + } + for _, layout := range layouts { + if t, err := time.Parse(layout, str); err == nil { + return t.UTC(), true + } + } + return time.Time{}, false +} + +func compareMappedFields(t *testing.T, pyData, goData map[string]interface{}, keyMapping map[string]string) { + for pyKey, goKey := range keyMapping { + Debugf("checking %s - %s\n", pyKey, goKey) + + pyVal, pyOk := pyData[pyKey] + goVal, goOk := goData[goKey] + + if !pyOk { + t.Errorf("Missing key in Python response: %s", pyKey) + continue + } + if !goOk { + t.Errorf("Missing key in Go response: %s", goKey) + continue + } + + pyTime, okPyTime := tryParseTime(pyVal) + goTime, okGoTime := tryParseTime(goVal) + + if okPyTime && okGoTime { + if !pyTime.Equal(goTime) { + t.Errorf("Datetime mismatch for key '%s' (Go: '%s'): py:%s != go:%s", pyKey, goKey, pyTime, goTime) + } + continue + } + + if (pyVal == nil && goVal == "") || (goVal == nil && pyVal == "") { + continue + } + + if fmt.Sprint(pyVal) != fmt.Sprint(goVal) { + t.Errorf("Mismatch for key '%s' (Go: '%s'): py:%+v != go:%+v", pyKey, goKey, pyVal, goVal) + } + } +} + +func sortByKey(arr []interface{}, key interface{}) { + keyStr, okStr := key.(string) + if okStr { + sort.Slice(arr, func(i, j int) bool { + m1, _ := arr[i].(map[string]interface{}) + m2, _ := arr[j].(map[string]interface{}) + s1 := fmt.Sprint(m1[keyStr]) + s2 := fmt.Sprint(m2[keyStr]) + return s1 < s2 + }) + } else { + sort.Slice(arr, func(i, j int) bool { + return fmt.Sprintf("%v", arr[i]) < fmt.Sprintf("%v", arr[j]) + }) + } +} + +func compareNestedFields(t *testing.T, pyData, goData, keyMapping map[string]interface{}, sortMap map[string]interface{}) { + for k, v := range keyMapping { + bV, bVOK := v.(bool) + if v == nil || bVOK { + Debugf("checking values of '%s'\n", k) + } + + pyVal, pyOk := pyData[k] + goVal, goOk := goData[k] + + // true means fields are optional (nullable), so if v is true and fileds are missing in both Py and go then this is OK + if bVOK && bV && !pyOk && !goOk { + Debugf("'%s' is not set in both responses, this is ok\n", k) + continue + } + if !pyOk { + t.Errorf("Missing key in Python response: %s", k) + continue + } + if !goOk { + t.Errorf("Missing key in Go response: %s", k) + continue + } + + nestedMapping, nested := v.(map[string]interface{}) + if nested { + Debugf("checking nested object '%s'\n", k) + pyNestedVal, pyOk := pyVal.(map[string]interface{}) + goNestedVal, goOk := goVal.(map[string]interface{}) + if !pyOk { + t.Errorf("%s value in Python response is not a nested object: %+v", k, pyVal) + continue + } + if !goOk { + t.Errorf("%s value in Go response is not a nested object: %+v", k, goVal) + continue + } + compareNestedFields(t, pyNestedVal, goNestedVal, nestedMapping, sortMap) + continue + } + + arrayMapping, array := v.([]interface{}) + if array { + Debugf("checking nested array '%s'\n", k) + if len(arrayMapping) < 1 { + t.Errorf("%s value in key mapping should be array of single object: %+v", k, v) + continue + } + nestedMapping, nested := arrayMapping[0].(map[string]interface{}) + if !nested { + t.Errorf("%s value in key mapping should be array of single object: %+v", k, v) + continue + } + pyArrayVal, pyOk := pyVal.([]interface{}) + goArrayVal, goOk := goVal.([]interface{}) + if pyOk && len(pyArrayVal) == 0 && goVal == nil { + Debugf("py returned [] and go returned nil - this is OK\n") + continue + } + if goOk && len(goArrayVal) == 0 && pyVal == nil { + Debugf("py returned null and go returned [] - this is OK\n") + continue + } + if goVal == nil && pyVal == nil { + Debugf("both py and go returned null - this is OK\n") + continue + } + if !pyOk { + t.Errorf("%s value in Python response is not an array: %+v", k, pyVal) + continue + } + if !goOk { + t.Errorf("%s value in Go response is not an array: %+v", k, goVal) + continue + } + lenPyArrayVal := len(pyArrayVal) + lenGoArrayVal := len(goArrayVal) + if lenPyArrayVal != lenGoArrayVal { + t.Errorf("%s arrays length mismatch: %d != %d", k, lenPyArrayVal, lenGoArrayVal) + continue + } + sortKey, needSort := sortMap[k] + if needSort { + Debugf("sorting '%s' key values by %v\n", k, sortKey) + sortByKey(pyArrayVal, sortKey) + sortByKey(goArrayVal, sortKey) + } + // This is to support plain arrays - they have single item: []interface{}{map[string]interface{}{}} + if len(nestedMapping) == 0 { + for idx := range pyArrayVal { + pyVal := pyArrayVal[idx] + goVal := goArrayVal[idx] + pyTime, okPyTime := tryParseTime(pyVal) + goTime, okGoTime := tryParseTime(goVal) + + if okPyTime && okGoTime { + if !pyTime.Equal(goTime) { + t.Errorf("Datetime mismatch for key '%s'[%d]: py:%s != go:%s", k, idx, pyTime, goTime) + } + continue + } + + if (pyVal == nil && goVal == "") || (goVal == nil && pyVal == "") { + continue + } + + if fmt.Sprint(pyVal) != fmt.Sprint(goVal) { + t.Errorf("Mismatch for key '%s'[%d]: py:%+v != go:%+v", k, idx, pyVal, goVal) + } + } + continue + } + for idx := range pyArrayVal { + pyNestedVal, pyOk := pyArrayVal[idx].(map[string]interface{}) + goNestedVal, goOk := goArrayVal[idx].(map[string]interface{}) + if !pyOk { + t.Errorf("%s:%d value in Python response is not a nested object: %+v", k, idx, pyArrayVal[idx]) + continue + } + if !goOk { + t.Errorf("%s:%d value in Go response is not a nested object: %+v", k, idx, goArrayVal[idx]) + continue + } + compareNestedFields(t, pyNestedVal, goNestedVal, nestedMapping, sortMap) + } + continue + } + + pyTime, okPyTime := tryParseTime(pyVal) + goTime, okGoTime := tryParseTime(goVal) + + if okPyTime && okGoTime { + if !pyTime.Equal(goTime) { + t.Errorf("Datetime mismatch for key '%s': py:%s != go:%s", k, pyTime, goTime) + } + continue + } + + if (pyVal == nil && goVal == "") || (goVal == nil && pyVal == "") { + continue + } + + if fmt.Sprint(pyVal) != fmt.Sprint(goVal) { + t.Errorf("Mismatch for key '%s': py:%+v != go:%+v", k, pyVal, goVal) + } + } +} + +func expectedPyInvalidUUID(field string) map[string]interface{} { + return map[string]interface{}{ + "errors": map[string]interface{}{ + field: InvalidUUIDProvided, + }, + } +} + +func expectedGoInvalidUUID(field string) map[string]interface{} { + return map[string]interface{}{ + "code": float64(605), + "message": field + GoUUIDValidationError, + } +} + +func runProjectCompatAPIForProject(t *testing.T, projectId string) { + apiURL := PY_API_URL + fmt.Sprintf(ProjectAPIPath[0], projectId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, oldResp.StatusCode, "Expected 200 from PY API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(ProjectAPIPath[2], projectId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, newResp.StatusCode, "Expected 200 from GO API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + oldMap, ok1 := oldJSON.(map[string]interface{}) + newMap, ok2 := newJSON.(map[string]interface{}) + + if !ok1 || !ok2 { + t.Fatalf("Expected both responses to be JSON objects") + } + compareNestedFields(t, oldMap, newMap, ProjectCompatAPIKeyMapping, ProjectCompatAPISortMap) + + if DEBUG { + oky := []string{} + for k, _ := range oldMap { + oky = append(oky, k) + } + sort.Strings(oky) + nky := []string{} + for k, _ := range newMap { + nky = append(nky, k) + } + sort.Strings(nky) + Debugf("old keys: %+v\n", oky) + Debugf("new keys: %+v\n", nky) + } +} + +func runProjectCompatAPIForProjectExpectFail(t *testing.T, projectId string) { + apiURL := PY_API_URL + fmt.Sprintf(ProjectAPIPath[0], projectId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusBadRequest, oldResp.StatusCode, "Expected 400 from Py API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(ProjectAPIPath[2], projectId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusUnprocessableEntity, newResp.StatusCode, "Expected 422 from Go API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + assert.Equal(t, expectedPyInvalidUUID("project_id"), oldJSON) + assert.Equal(t, expectedGoInvalidUUID("projectID"), newJSON) +} + +func TestProjectCompatAPI(t *testing.T) { + projectId := PROJECT_UUID + if projectId == "" { + projectId = uuid.New().String() + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{ + "project_name": "CNCF", + "project_icla_enabled": true, + "project_ccla_enabled": true, + "project_ccla_requires_icla_signature": true, + "date_created": "2022-11-21T10:31:31Z", + "date_modified": "2023-02-23T13:14:48Z", + "foundation_sfid": "a09410000182dD2AAI", + "version": "2", + }, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + } + + runProjectCompatAPIForProject(t, projectId) +} + +func TestProjectCompatAPIWithNonV4UUID(t *testing.T) { + projectId := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" // Non-v4 UUID + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{ + "project_name": "CNCF", + "project_icla_enabled": true, + "project_ccla_enabled": true, + "project_ccla_requires_icla_signature": true, + "date_created": "2022-11-21T10:31:31Z", + "date_modified": "2023-02-23T13:14:48Z", + "foundation_sfid": "a09410000182dD2AAI", + "version": "2", + }, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + + runProjectCompatAPIForProject(t, projectId) +} + +func TestProjectCompatAPIWithInvalidUUID(t *testing.T) { + projectId := "6ba7b810-9dad-11d1-80b4-00c04fd430cg" // Invalid UUID - "g" is not a hex digit + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{ + "project_name": "CNCF", + "project_icla_enabled": true, + "project_ccla_enabled": true, + "project_ccla_requires_icla_signature": true, + "date_created": "2022-11-21T10:31:31Z", + "date_modified": "2023-02-23T13:14:48Z", + "foundation_sfid": "a09410000182dD2AAI", + "version": "2", + }, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + + runProjectCompatAPIForProjectExpectFail(t, projectId) +} + +func TestAllProjectsCompatAPI(t *testing.T) { + allProjects := getAllPrimaryKeys("projects", "project_id", "S") + + var failedProjects []string + var mtx sync.Mutex + sem := make(chan struct{}, MAX_PARALLEL) + var wg sync.WaitGroup + + for _, projectID := range allProjects { + projID, ok := projectID.(string) + if !ok { + t.Errorf("Expected string project_id, got: %T", projectID) + continue + } + + wg.Add(1) + sem <- struct{}{} + + go func(projID string) { + defer wg.Done() + defer func() { <-sem }() + + // Use t.Run in a thread-safe wrapper with a dummy parent test + t.Run(fmt.Sprintf("ProjectId=%s", projID), func(t *testing.T) { + runProjectCompatAPIForProject(t, projID) + if t.Failed() { + mtx.Lock() + failedProjects = append(failedProjects, projID) + mtx.Unlock() + } + }) + }(projID) + } + + wg.Wait() + + if len(failedProjects) > 0 { + fmt.Fprintf(os.Stderr, "\nFailed Project IDs (%d):\n%s\n\n", + len(failedProjects), + strings.Join(failedProjects, "\n"), + ) + t.Fail() // Mark test as failed + } else { + fmt.Println("\nAll projects passed.") + } +} + +func TestProjectAPI(t *testing.T) { + if TOKEN == "" || XACL == "" { + t.Fatalf("TOKEN and XACL environment variables must be set") + } + projectId := PROJECT_UUID + if projectId == "" { + projectId = uuid.New().String() + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{ + "project_name": "CNCF", + "project_icla_enabled": true, + "project_ccla_enabled": true, + "project_ccla_requires_icla_signature": true, + "date_created": "2022-11-21T10:31:31Z", + "date_modified": "2023-02-23T13:14:48Z", + "foundation_sfid": "a09410000182dD2AAI", + "version": "2", + }, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + } + + apiURL := PY_API_URL + fmt.Sprintf(ProjectAPIPath[0], projectId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, oldResp.StatusCode, "Expected 200 from PY API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(ProjectAPIPath[1], projectId) + Debugf("Go API call: %s\n", apiURL) + // newResp, err := http.Get(apiURL) + req, err := http.NewRequest("GET", apiURL, nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + + req.Header.Set("Authorization", "Bearer "+TOKEN) + req.Header.Set("X-ACL", XACL) + + newResp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, newResp.StatusCode, "Expected 200 from GO API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + // For full equality + // Strict + // assert.Equal(t, oldJSON, newJSON) + // Smart - ignore keys order + // assert.JSONEq(t, string(oldBody), string(newBody)) + oldMap, ok1 := oldJSON.(map[string]interface{}) + newMap, ok2 := newJSON.(map[string]interface{}) + + if !ok1 || !ok2 { + t.Fatalf("Expected both responses to be JSON objects") + } + compareMappedFields(t, oldMap, newMap, ProjectAPIKeyMapping) + + if DEBUG { + oky := []string{} + for k, _ := range oldMap { + oky = append(oky, k) + } + sort.Strings(oky) + nky := []string{} + for k, _ := range newMap { + nky = append(nky, k) + } + sort.Strings(nky) + Debugf("old keys: %+v\n", oky) + Debugf("new keys: %+v\n", nky) + } +} + +func runUserActiveSignatureAPIForUser(t *testing.T, userId string) { + apiURL := PY_API_URL + fmt.Sprintf(UserActiveSignatureAPIPath[0], userId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, oldResp.StatusCode, "Expected 200 from PY API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(UserActiveSignatureAPIPath[1], userId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, newResp.StatusCode, "Expected 200 from GO API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + if string(oldBody) == "null" && string(newBody) == "null" { + return + } + + oldMap, ok1 := oldJSON.(map[string]interface{}) + newMap, ok2 := newJSON.(map[string]interface{}) + + if !ok1 || !ok2 { + t.Fatalf("Expected both responses to be JSON objects") + } + compareNestedFields(t, oldMap, newMap, UserActiveSignatureAPIKeyMapping, map[string]interface{}{}) + + if DEBUG { + oky := []string{} + for k, _ := range oldMap { + oky = append(oky, k) + } + sort.Strings(oky) + nky := []string{} + for k, _ := range newMap { + nky = append(nky, k) + } + sort.Strings(nky) + Debugf("old keys: %+v\n", oky) + Debugf("new keys: %+v\n", nky) + } +} + +func runUserActiveSignatureAPIForUserExpectFail(t *testing.T, userId string) { + apiURL := PY_API_URL + fmt.Sprintf(UserActiveSignatureAPIPath[0], userId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusBadRequest, oldResp.StatusCode, "Expected 400 from Py API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(UserActiveSignatureAPIPath[1], userId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusUnprocessableEntity, newResp.StatusCode, "Expected 422 from Go API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + assert.Equal(t, expectedPyInvalidUUID("user_id"), oldJSON) + assert.Equal(t, expectedGoInvalidUUID("userID"), newJSON) +} + +func TestUserActiveSignatureAPIWithInvalidUUID(t *testing.T) { + userId := "6ba7b810-9dad-11d1-80b4-00c04fd430cg" // Invalid UUID "g" is not a hex digit + projectId := uuid.New().String() + key := "active_signature:" + userId + expire := time.Now().Add(time.Hour).Unix() + iValue := map[string]interface{}{ + "user_id": userId, + "project_id": projectId, + "repository_id": fmt.Sprintf("%d", REPO_ID), + "pull_request_id": fmt.Sprintf("%d", PR_ID), + } + value, err := json.Marshal(iValue) + if err != nil { + t.Fatalf("failed to marshal value: %+v", err) + } + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{}, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + putTestItem("store", "key", key, "S", map[string]interface{}{ + "value": string(value), + "expire": expire, + }, DEBUG) + defer deleteTestItem("store", "key", key, "S", DEBUG) + runUserActiveSignatureAPIForUserExpectFail(t, userId) +} + +func TestUserActiveSignatureAPIWithNonV4UUID(t *testing.T) { + userId := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" // Non-v4 UUID + projectId := uuid.New().String() + key := "active_signature:" + userId + expire := time.Now().Add(time.Hour).Unix() + iValue := map[string]interface{}{ + "user_id": userId, + "project_id": projectId, + "repository_id": fmt.Sprintf("%d", REPO_ID), + "pull_request_id": fmt.Sprintf("%d", PR_ID), + } + if rand.Intn(2) == 0 { + mrId := rand.Intn(100) + iValue["merge_request_id"] = fmt.Sprintf("%d", mrId) + iValue["return_url"] = fmt.Sprintf("https://gitlab.com/gitlab-org/gitlab/-/merge_requests/%d", mrId) + } + value, err := json.Marshal(iValue) + if err != nil { + t.Fatalf("failed to marshal value: %+v", err) + } + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{}, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + putTestItem("store", "key", key, "S", map[string]interface{}{ + "value": string(value), + "expire": expire, + }, DEBUG) + defer deleteTestItem("store", "key", key, "S", DEBUG) + runUserActiveSignatureAPIForUser(t, userId) +} + +func TestUserActiveSignatureAPI(t *testing.T) { + userId := USER_UUID + if userId == "" { + userId = uuid.New().String() + projectId := uuid.New().String() + key := "active_signature:" + userId + expire := time.Now().Add(time.Hour).Unix() + iValue := map[string]interface{}{ + "user_id": userId, + "project_id": projectId, + "repository_id": fmt.Sprintf("%d", REPO_ID), + "pull_request_id": fmt.Sprintf("%d", PR_ID), + } + if rand.Intn(2) == 0 { + mrId := rand.Intn(100) + iValue["merge_request_id"] = fmt.Sprintf("%d", mrId) + iValue["return_url"] = fmt.Sprintf("https://gitlab.com/gitlab-org/gitlab/-/merge_requests/%d", mrId) + } + value, err := json.Marshal(iValue) + if err != nil { + t.Fatalf("failed to marshal value: %+v", err) + } + putTestItem("projects", "project_id", projectId, "S", map[string]interface{}{}, DEBUG) + defer deleteTestItem("projects", "project_id", projectId, "S", DEBUG) + putTestItem("store", "key", key, "S", map[string]interface{}{ + "value": string(value), + "expire": expire, + }, DEBUG) + defer deleteTestItem("store", "key", key, "S", DEBUG) + } + + runUserActiveSignatureAPIForUser(t, userId) +} + +func TestAllUserActiveSignatureAPI(t *testing.T) { + allUserActiveSignatures := getAllPrimaryKeys("store", "key", "S") + + var failed []string + var mtx sync.Mutex + sem := make(chan struct{}, MAX_PARALLEL) + var wg sync.WaitGroup + + for _, key := range allUserActiveSignatures { + ky, ok := key.(string) + if !ok { + t.Errorf("Expected string key, got: %T", key) + continue + } + if !strings.HasPrefix(ky, "active_signature:") { + continue + } + userId := strings.TrimPrefix(ky, "active_signature:") + + wg.Add(1) + sem <- struct{}{} + + go func(userId string) { + defer wg.Done() + defer func() { <-sem }() + + t.Run(fmt.Sprintf("UserId=%s", userId), func(t *testing.T) { + runUserActiveSignatureAPIForUser(t, userId) + if t.Failed() { + mtx.Lock() + failed = append(failed, userId) + mtx.Unlock() + } + }) + }(userId) + } + + wg.Wait() + + if len(failed) > 0 { + fmt.Fprintf(os.Stderr, "\nFailed User IDs (%d):\n%s\n\n", + len(failed), + strings.Join(failed, "\n"), + ) + t.Fail() + } else { + fmt.Println("\nAll user active signatures passed.") + } +} + +func runUserCompatAPIForUser(t *testing.T, userId string) { + apiURL := PY_API_URL + fmt.Sprintf(UserCompatAPIPath[0], userId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, oldResp.StatusCode, "Expected 200 from PY API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(UserCompatAPIPath[1], userId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusOK, newResp.StatusCode, "Expected 200 from GO API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + oldMap, ok1 := oldJSON.(map[string]interface{}) + newMap, ok2 := newJSON.(map[string]interface{}) + + if !ok1 || !ok2 { + t.Fatalf("Expected both responses to be JSON objects") + } + compareNestedFields(t, oldMap, newMap, UserCompatAPIKeyMapping, UserCompatAPISortMap) + + if DEBUG { + oky := []string{} + for k, _ := range oldMap { + oky = append(oky, k) + } + sort.Strings(oky) + nky := []string{} + for k, _ := range newMap { + nky = append(nky, k) + } + sort.Strings(nky) + Debugf("old keys: %+v\n", oky) + Debugf("new keys: %+v\n", nky) + } +} + +func runUserCompatAPIForUserExpectFail(t *testing.T, userId string) { + apiURL := PY_API_URL + fmt.Sprintf(UserCompatAPIPath[0], userId) + Debugf("Py API call: %s\n", apiURL) + oldResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusBadRequest, oldResp.StatusCode, "Expected 400 from Py API") + defer oldResp.Body.Close() + oldBody, _ := io.ReadAll(oldResp.Body) + var oldJSON interface{} + err = json.Unmarshal(oldBody, &oldJSON) + assert.NoError(t, err) + Debugf("Py raw response: %+v\n", string(oldBody)) + Debugf("Py response: %+v\n", oldJSON) + + apiURL = GO_API_URL + fmt.Sprintf(UserCompatAPIPath[1], userId) + Debugf("Go API call: %s\n", apiURL) + newResp, err := http.Get(apiURL) + if err != nil { + t.Fatalf("Failed to call API: %v", err) + } + assert.Equal(t, http.StatusUnprocessableEntity, newResp.StatusCode, "Expected 422 from Go API") + defer newResp.Body.Close() + newBody, _ := io.ReadAll(newResp.Body) + var newJSON interface{} + err = json.Unmarshal(newBody, &newJSON) + assert.NoError(t, err) + Debugf("Go raw Response: %+v\n", string(newBody)) + Debugf("Go response: %+v\n", newJSON) + + assert.Equal(t, expectedPyInvalidUUID("user_id"), oldJSON) + assert.Equal(t, expectedGoInvalidUUID("userID"), newJSON) +} + +func TestUserCompatAPI(t *testing.T) { + userId := USER_UUID + if userId == "" { + userId = uuid.New().String() + companyId := uuid.New().String() + putTestItem("companies", "company_id", companyId, "S", map[string]interface{}{ + "is_sanctioned": true, + }, DEBUG) + defer deleteTestItem("companies", "company_id", companyId, "S", DEBUG) + putTestItem("users", "user_id", userId, "S", map[string]interface{}{ + "lf_email": "lgryglicki@cncf.io", + "lf_sub": nil, + "lf_username": "lukaszgryglicki", + "note": "Example note", + "user_company_id": companyId, + "user_external_id": "00117000015vpjXAAQ", + "user_github_id": 43778, + "user_github_username": "lukaszgryglicki", + "user_gitlab_id": 567, + "user_gitlab_username": "lgryglicki", + "user_ldap_id": nil, + "user_name": "lgryglickilf", + "version": "v1", + "user_emails": []string{"lgryglicki@cncf.io", "lukaszgryglicki@o2.pl", "lgryglicki@contractor.linuxfoundation.com", "lukaszgryglicki1982@gmail.com"}, + }, DEBUG) + defer deleteTestItem("users", "user_id", userId, "S", DEBUG) + } + + runUserCompatAPIForUser(t, userId) +} + +func TestUserCompatAPIWithNonV4UUID(t *testing.T) { + userId := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" // Non-v4 UUID + companyId := uuid.New().String() + putTestItem("companies", "company_id", companyId, "S", map[string]interface{}{ + "is_sanctioned": true, + }, DEBUG) + defer deleteTestItem("companies", "company_id", companyId, "S", DEBUG) + putTestItem("users", "user_id", userId, "S", map[string]interface{}{ + "lf_email": "lgryglicki@cncf.io", + "lf_sub": nil, + "lf_username": "lukaszgryglicki", + "note": "Example note", + "user_company_id": companyId, + "user_external_id": "00117000015vpjXAAQ", + "user_github_id": 43778, + "user_github_username": "lukaszgryglicki", + "user_gitlab_id": 567, + "user_gitlab_username": "lgryglicki", + "user_ldap_id": nil, + "user_name": "lgryglickilf", + "version": "v1", + "user_emails": []string{"lgryglicki@cncf.io", "lukaszgryglicki@o2.pl", "lgryglicki@contractor.linuxfoundation.com", "lukaszgryglicki1982@gmail.com"}, + }, DEBUG) + defer deleteTestItem("users", "user_id", userId, "S", DEBUG) + + runUserCompatAPIForUser(t, userId) +} + +func TestUserCompatAPIWithInvalidUUID(t *testing.T) { + userId := "6ba7b810-9dad-11d1-80b4-00c04fd430cg" // Invalid UUID - "g" is not a hex digit + companyId := uuid.New().String() + putTestItem("companies", "company_id", companyId, "S", map[string]interface{}{ + "is_sanctioned": true, + }, DEBUG) + defer deleteTestItem("companies", "company_id", companyId, "S", DEBUG) + putTestItem("users", "user_id", userId, "S", map[string]interface{}{ + "lf_email": "lgryglicki@cncf.io", + "lf_sub": nil, + "lf_username": "lukaszgryglicki", + "note": "Example note", + "user_company_id": companyId, + "user_external_id": "00117000015vpjXAAQ", + "user_github_id": 43778, + "user_github_username": "lukaszgryglicki", + "user_gitlab_id": 567, + "user_gitlab_username": "lgryglicki", + "user_ldap_id": nil, + "user_name": "lgryglickilf", + "version": "v1", + "user_emails": []string{"lgryglicki@cncf.io", "lukaszgryglicki@o2.pl", "lgryglicki@contractor.linuxfoundation.com", "lukaszgryglicki1982@gmail.com"}, + }, DEBUG) + defer deleteTestItem("users", "user_id", userId, "S", DEBUG) + + runUserCompatAPIForUserExpectFail(t, userId) +} + +func TestAllUsersCompatAPI(t *testing.T) { + allUsers := getAllPrimaryKeys("users", "user_id", "S") + + var failedUsers []string + var mtx sync.Mutex + sem := make(chan struct{}, MAX_PARALLEL) + var wg sync.WaitGroup + + for _, userID := range allUsers { + usrID, ok := userID.(string) + if !ok { + t.Errorf("Expected string user_id, got: %T", userID) + continue + } + + wg.Add(1) + sem <- struct{}{} + + go func(usrID string) { + defer wg.Done() + defer func() { <-sem }() + + // Use t.Run in a thread-safe wrapper with a dummy parent test + t.Run(fmt.Sprintf("UserId=%s", usrID), func(t *testing.T) { + runUserCompatAPIForUser(t, usrID) + if t.Failed() { + mtx.Lock() + failedUsers = append(failedUsers, usrID) + mtx.Unlock() + } + }) + }(usrID) + } + + wg.Wait() + + if len(failedUsers) > 0 { + fmt.Fprintf(os.Stderr, "\nFailed User IDs (%d):\n%s\n\n", + len(failedUsers), + strings.Join(failedUsers, "\n"), + ) + t.Fail() // Mark test as failed + } else { + fmt.Println("\nAll users passed.") + } +} diff --git a/tests/py2go/dynamo.go b/tests/py2go/dynamo.go new file mode 100644 index 000000000..4da83ce56 --- /dev/null +++ b/tests/py2go/dynamo.go @@ -0,0 +1,193 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/dynamodb" + "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" +) + +var ( + STAGE string + PROFILE string + REGION string +) + +func init() { + REGION = os.Getenv("AWS_REGION") + if REGION == "" { + REGION = "us-east-1" + } + STAGE = os.Getenv("STAGE") + if STAGE == "" { + STAGE = "dev" + } + PROFILE = os.Getenv("AWS_PROFILE") + if PROFILE == "" { + PROFILE = "lfproduct-" + STAGE + } +} + +func putTestItem(tableName, keyName string, keyValue interface{}, keyType string, extraFields map[string]interface{}, dbg bool) { + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(REGION), + config.WithSharedConfigProfile(PROFILE), + ) + if err != nil { + log.Fatalf("unable to load SDK config, %v", err) + } + client := dynamodb.NewFromConfig(cfg) + + item := make(map[string]types.AttributeValue) + + switch keyType { + case "S": + item[keyName] = &types.AttributeValueMemberS{Value: fmt.Sprint(keyValue)} + case "N": + item[keyName] = &types.AttributeValueMemberN{Value: fmt.Sprint(keyValue)} + default: + log.Fatalf("Unsupported key type: %s", keyType) + } + + for k, v := range extraFields { + switch val := v.(type) { + case string: + item[k] = &types.AttributeValueMemberS{Value: val} + case int, int64, float64: + item[k] = &types.AttributeValueMemberN{Value: fmt.Sprint(val)} + case bool: + item[k] = &types.AttributeValueMemberBOOL{Value: val} + case []string: + item[k] = &types.AttributeValueMemberSS{Value: val} + case []interface{}: + Debugf("Skipping field %s: generic list not supported directly\n", k) + case nil: + Debugf("Skipping nil field %s\n", k) + default: + Debugf("Unsupported type for field %s: %T\n", k, v) + } + } + + tName := "cla-" + STAGE + "-" + tableName + _, err = client.PutItem(context.TODO(), &dynamodb.PutItemInput{ + TableName: aws.String(tName), + Item: item, + }) + if err != nil { + log.Fatalf("PutItem error: %v", err) + } + Debugf("created entry in %s: %s=%s, %+v\n", tName, keyName, keyValue, extraFields) +} + +func deleteTestItem(tableName, keyName string, keyValue interface{}, keyType string, dbg bool) { + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(REGION), + config.WithSharedConfigProfile(PROFILE), + ) + if err != nil { + log.Fatalf("unable to load SDK config, %v", err) + } + client := dynamodb.NewFromConfig(cfg) + + var key types.AttributeValue + + switch keyType { + case "S": + key = &types.AttributeValueMemberS{Value: fmt.Sprint(keyValue)} + case "N": + key = &types.AttributeValueMemberN{Value: fmt.Sprint(keyValue)} + case "BOOL": + b, ok := keyValue.(bool) + if !ok { + log.Fatalf("Key value must be boolean for BOOL type") + } + key = &types.AttributeValueMemberBOOL{Value: b} + default: + log.Fatalf("Unsupported key type: %s", keyType) + } + + tName := "cla-" + STAGE + "-" + tableName + _, err = client.DeleteItem(context.TODO(), &dynamodb.DeleteItemInput{ + TableName: aws.String(tName), + Key: map[string]types.AttributeValue{ + keyName: key, + }, + }) + if err != nil { + log.Fatalf("DeleteItem error: %v", err) + } + Debugf("deleted entry in %s: %s=%s\n", tName, keyName, keyValue) +} + +func getAllPrimaryKeys(tableName, keyName, keyType string) []interface{} { + cfg, err := config.LoadDefaultConfig( + context.TODO(), + config.WithRegion(REGION), + config.WithSharedConfigProfile(PROFILE), + ) + if err != nil { + log.Fatalf("unable to load SDK config, %v", err) + } + client := dynamodb.NewFromConfig(cfg) + + tName := "cla-" + STAGE + "-" + tableName + Debugf("getting all keys form %s\n", tName) + var results []interface{} + var lastEvaluatedKey map[string]types.AttributeValue + + for { + input := &dynamodb.ScanInput{ + TableName: aws.String(tName), + ProjectionExpression: aws.String("#k"), + ExpressionAttributeNames: map[string]string{ + "#k": keyName, + }, + ExclusiveStartKey: lastEvaluatedKey, + } + + output, err := client.Scan(context.TODO(), input) + if err != nil { + log.Fatalf("Scan error on table %s: %v", tName, err) + } + + for _, item := range output.Items { + attr, ok := item[keyName] + if !ok { + Debugf("Key %s not found in item: %+v\n", keyName, item) + continue + } + + switch keyType { + case "S": + if v, ok := attr.(*types.AttributeValueMemberS); ok { + results = append(results, v.Value) + } + case "N": + if v, ok := attr.(*types.AttributeValueMemberN); ok { + results = append(results, v.Value) + } + case "BOOL": + if v, ok := attr.(*types.AttributeValueMemberBOOL); ok { + results = append(results, v.Value) + } + default: + log.Fatalf("Unsupported key type: %s", keyType) + } + } + + if output.LastEvaluatedKey == nil || len(output.LastEvaluatedKey) == 0 { + break + } + lastEvaluatedKey = output.LastEvaluatedKey + } + + Debugf("got keys: %+v\n", results) + return results +} diff --git a/tests/py2go/go.mod b/tests/py2go/go.mod new file mode 100644 index 000000000..9af2fb2a0 --- /dev/null +++ b/tests/py2go/go.mod @@ -0,0 +1,29 @@ +module github.com/linuxfoundation/easycla/tests/py2go + +go 1.24.4 + +require ( + github.com/aws/aws-sdk-go-v2 v1.36.5 + github.com/aws/aws-sdk-go-v2/config v1.29.17 + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.10.0 +) + +require ( + github.com/aws/aws-sdk-go-v2/credentials v1.17.70 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect + github.com/aws/smithy-go v1.22.4 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/tests/py2go/go.sum b/tests/py2go/go.sum new file mode 100644 index 000000000..54cfa5aec --- /dev/null +++ b/tests/py2go/go.sum @@ -0,0 +1,42 @@ +github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= +github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= +github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0 h1:A99gjqZDbdhjtjJVZrmVzVKO2+p3MSg35bDWtbMQVxw= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.44.0/go.mod h1:mWB0GE1bqcVSvpW7OtFA0sKuHk52+IqtnsYU2jUfYAs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.17 h1:x187MqiHwBGjMGAed8Y8K1VGuCtFvQvXb24r+bwmSdo= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.17/go.mod h1:mC9qMbA6e1pwEq6X3zDGtZRXMG2YaElJkbJlMVHLs5I= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tests/py2go/log.go b/tests/py2go/log.go new file mode 100644 index 000000000..a39fe0267 --- /dev/null +++ b/tests/py2go/log.go @@ -0,0 +1,11 @@ +package main + +import ( + "fmt" +) + +func Debugf(format string, args ...interface{}) { + if DEBUG { + fmt.Printf(format, args...) + } +} diff --git a/utils/active_signature_go.sh b/utils/active_signature_go.sh new file mode 100755 index 000000000..f468e67ff --- /dev/null +++ b/utils/active_signature_go.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# user_id='9dcf5bbc-2492-11ed-97c7-3e2a23ea20b5' +# select key, data:expire from fivetran_ingest.dynamodb_product_us_east1_dev.cla_dev_store where key like 'active_signature:%' order by data:expire desc limit 1; +# select key, data:expire from fivetran_ingest.dynamodb_product_us_east_1.cla_prod_store where key like 'active_signature:%' order by data:expire desc limit 1; +# API_URL=https://api-gw.dev.platform.linuxfoundation.org/cla-service DEBUG=1 ./utils/active_signature_go.sh '4b344ac4-f8d9-11ed-ac9b-b29c4ace74e9' +# API_URL=https://api-gw.dev.platform.linuxfoundation.org/cla-service DEBUG=1 ./utils/active_signature_go.sh '4b344ac4-f8d9-11ed-ac9b-b29c4ace74e9' +# API_URL=http://localhost:5001 DEBUG='' ./utils/active_signature_go.sh '564e571e-12d7-4857-abd4-898939accdd7' +# ./utils/add_store_active_signature.sh b817eb57-045a-4fe0-8473-fbb416a01d70 d8cead54-92b7-48c5-a2c8-b1e295e8f7f1 +# DEBUG='' ./utils/active_signature_go.sh b817eb57-045a-4fe0-8473-fbb416a01d70 | jq '.' + +if [ -z "$1" ] +then + echo "$0: you need to specify user_id as a 1st parameter" + exit 1 +fi +export user_id="$1" + +if [ -z "$API_URL" ] +then + export API_URL="http://localhost:5001" +fi + +if [ ! -z "$DEBUG" ] +then + echo "curl -s -XGET -H 'Content-Type: application/json' \"${API_URL}/v4/user/${user_id}/active-signature\"" + curl -s -XGET -H "Content-Type: application/json" "${API_URL}/v4/user/${user_id}/active-signature" +else + curl -s -XGET -H "Content-Type: application/json" "${API_URL}/v4/user/${user_id}/active-signature" | jq -r '.' +fi diff --git a/utils/active_signature_py.sh b/utils/active_signature_py.sh index a08b6b2fc..57bec1567 100755 --- a/utils/active_signature_py.sh +++ b/utils/active_signature_py.sh @@ -5,6 +5,8 @@ # API_URL=https://api.lfcla.dev.platform.linuxfoundation.org DEBUG=1 ./utils/active_signature_py.sh '4b344ac4-f8d9-11ed-ac9b-b29c4ace74e9' # API_URL=https://api.lfcla.dev.platform.linuxfoundation.org DEBUG=1 ./utils/active_signature_py.sh '4b344ac4-f8d9-11ed-ac9b-b29c4ace74e9' # API_URL=https://api.easycla.lfx.linuxfoundation.org DEBUG='' ./utils/active_signature_py.sh '564e571e-12d7-4857-abd4-898939accdd7' +# ./utils/add_store_active_signature.sh b817eb57-045a-4fe0-8473-fbb416a01d70 d8cead54-92b7-48c5-a2c8-b1e295e8f7f1 +# DEBUG='' ./utils/active_signature_py.sh b817eb57-045a-4fe0-8473-fbb416a01d70 | jq '.' if [ -z "$1" ] then diff --git a/utils/add_store_active_signature.sh b/utils/add_store_active_signature.sh new file mode 100755 index 000000000..5756eef2b --- /dev/null +++ b/utils/add_store_active_signature.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# repo: aws --region us-east-1 --profile lfproduct-dev dynamodb scan --table-name "cla-dev-repositories" +if [ -z "$STAGE" ] +then + STAGE=dev +fi +if [ -z "${1}" ] +then + echo "$0: you must specify user ID value as a 1st argument, like: 'b817eb57-045a-4fe0-8473-fbb416a01d70'" + exit 1 +fi +if [ -z "${2}" ] +then + echo "$0: you must specify project ID value as a 2nd argument, like: 'd8cead54-92b7-48c5-a2c8-b1e295e8f7f1'" + exit 2 +fi +EXPIRE_TS=$(date -d 'tomorrow' +%s) +aws --profile "lfproduct-${STAGE}" dynamodb put-item --table-name "cla-${STAGE}-store" --item '{ + "key": { + "S": "active_signature:'"${1}"'" + }, + "value": { + "S": "{\"user_id\": \"'"${1}"'\", \"project_id\": \"'"${2}"'\", \"repository_id\": \"466156917\", \"pull_request_id\": \"3\"}" + }, + "expire": { + "N": "'"${EXPIRE_TS}"'" + } + }' diff --git a/utils/get_user_compat_go.sh b/utils/get_user_compat_go.sh new file mode 100755 index 000000000..58f14f2d9 --- /dev/null +++ b/utils/get_user_compat_go.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# API_URL=https://[xyz].ngrok-free.app (defaults to localhost:5001) +# API_URL=https://api-gw.platform.linuxfoundation.org/cla-service +if [ -z "$1" ] +then + echo "$0: you need to specify user_id as a 1st parameter, example '9dcf5bbc-2492-11ed-97c7-3e2a23ea20b5', '55775b48-69c1-474d-a07a-2a329e7012b4'" + exit 1 +fi +export user_id="$1" + +if [ -z "$API_URL" ] +then + export API_URL="http://localhost:5001" +fi + +API="${API_URL}/v3/user-compat/${user_id}" + +if [ ! -z "$DEBUG" ] +then + echo "curl -s -XGET -H \"Content-Type: application/json\" \"${API}\"" + curl -s -XGET -H "Content-Type: application/json" "${API}" +else + curl -s -XGET -H "Content-Type: application/json" "${API}" | jq -r '.' +fi diff --git a/utils/get_user_from_token_go.sh b/utils/get_user_from_token_go.sh index 4fbce0966..a8a6c001a 100755 --- a/utils/get_user_from_token_go.sh +++ b/utils/get_user_from_token_go.sh @@ -8,6 +8,8 @@ # on local (non remote) computer: ~/get_oauth_token.sh (or ~/get_oauth_token_prod.sh) (will open browser, authenticate to LF, and return token data) # edit 'cla-backend-go/cmd/server.go' - look for "LG: to test with manual tokens", then 'cla-backend-go/auth/authorizer.go': LG: to allow local testing", then run ./bin/cla # then TOKEN='value from the get_oauth_token.sh script' DEBUG='' ./utils/get_user_from_token_go.sh +# DEBUG=1 API_URL='https://api-gw.dev.platform.linuxfoundation.org/cla-service' TOKEN='...' ./utils/get_user_from_token_go.sh +# DEBUG=1 API_URL='http://localhost:5001/cla-service' TOKEN='...' ./utils/get_user_from_token_go.sh if [ -z "$TOKEN" ] then diff --git a/utils/run_go_api_server.sh b/utils/run_go_api_server.sh new file mode 100755 index 000000000..bb725cf72 --- /dev/null +++ b/utils/run_go_api_server.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make build-linux && PORT=5001 AUTH0_USERNAME_CLAIM_CLI='http://lfx.dev/claims/username' AUTH0_EMAIL_CLAIM_CLI='http://lfx.dev/claims/email' AUTH0_NAME_CLAIM_CLI='http://lfx.dev/claims/username' ./bin/cla diff --git a/utils/scan_store.sh b/utils/scan_store.sh new file mode 100755 index 000000000..dac1c1771 --- /dev/null +++ b/utils/scan_store.sh @@ -0,0 +1,10 @@ +#!/bin/bash +if [ -z "$STAGE" ] +then + STAGE=dev +fi +if [ ! -z "${DEBUG}" ] +then + echo "aws --profile \"lfproduct-${STAGE}\" dynamodb scan --table-name \"cla-${STAGE}-store\" --max-items 100 | jq -r '.Items'" +fi +aws --profile "lfproduct-${STAGE}" dynamodb scan --table-name "cla-${STAGE}-store" --max-items 100 | jq -r '.Items' diff --git a/utils/set_store_expire.sh b/utils/set_store_expire.sh new file mode 100755 index 000000000..2c1c1be2f --- /dev/null +++ b/utils/set_store_expire.sh @@ -0,0 +1,15 @@ +#!/bin/bash +if [ -z "$STAGE" ] +then + STAGE=dev +fi +if [ -z "${1}" ] +then + echo "$0: you must specify ID value as a 1st argument, like: 'b817eb57-045a-4fe0-8473-fbb416a01d70'" + exit 1 +fi +if [ ! -z "${DEBUG}" ] +then + echo "aws --profile \"lfproduct-${STAGE}\" dynamodb update-item --table-name \"cla-${STAGE}-store\" --key '{\"key\": {\"S\": \"${1}\"}}' --update-expression \"SET expire = :newval\" --expression-attribute-values '{\":newval\": {\"N\": \"'\"$(date -d '+1 day' +%s)\"'\"}}'" +fi +aws --profile "lfproduct-${STAGE}" dynamodb update-item --table-name "cla-${STAGE}-store" --key "{\"key\": {\"S\": \"${1}\"}}" --update-expression "SET expire = :newval" --expression-attribute-values '{":newval": {"N": "'"$(date -d '+1 day' +%s)"'"}}'