diff --git a/.buildkite/ftr_oblt_serverless_configs.yml b/.buildkite/ftr_oblt_serverless_configs.yml index 737add5ebccf6..dfee2d3863771 100644 --- a/.buildkite/ftr_oblt_serverless_configs.yml +++ b/.buildkite/ftr_oblt_serverless_configs.yml @@ -6,8 +6,6 @@ disabled: - x-pack/test_serverless/functional/test_suites/observability/cypress/config_headless.ts - x-pack/test_serverless/functional/test_suites/observability/cypress/config_runner.ts -defaultQueue: 'n2-4-spot' -enabled: - x-pack/test_serverless/api_integration/test_suites/observability/config.ts - x-pack/test_serverless/api_integration/test_suites/observability/config.feature_flags.ts - x-pack/test_serverless/api_integration/test_suites/observability/common_configs/config.group1.ts @@ -31,3 +29,7 @@ enabled: # serverless config files that run deployment-agnostic tests - x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts - x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.apm.serverless.config.ts + +# Serverless tests only run on main +defaultQueue: 'n2-4-spot' +enabled: diff --git a/.buildkite/ftr_search_serverless_configs.yml b/.buildkite/ftr_search_serverless_configs.yml index 20f3e8165e1e4..46d14cc5bd066 100644 --- a/.buildkite/ftr_search_serverless_configs.yml +++ b/.buildkite/ftr_search_serverless_configs.yml @@ -1,8 +1,6 @@ disabled: # Base config files, only necessary to inform config finding script -defaultQueue: 'n2-4-spot' -enabled: - x-pack/test_serverless/api_integration/test_suites/search/config.ts - x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts - x-pack/test_serverless/api_integration/test_suites/search/common_configs/config.group1.ts @@ -22,3 +20,7 @@ enabled: - x-pack/test_serverless/functional/test_suites/search/common_configs/config.group8.ts # serverless config files that run deployment-agnostic tests - x-pack/test/api_integration/deployment_agnostic/configs/serverless/search.serverless.config.ts + +# Serverless tests only run on main +defaultQueue: 'n2-4-spot' +enabled: diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml index 57d0c977795fa..ee4b6db08fb8b 100644 --- a/.buildkite/ftr_security_serverless_configs.yml +++ b/.buildkite/ftr_security_serverless_configs.yml @@ -22,8 +22,6 @@ disabled: # MKI only configs files - x-pack/test_serverless/functional/test_suites/security/config.mki_only.ts -defaultQueue: 'n2-4-spot' -enabled: - x-pack/test_serverless/api_integration/test_suites/security/config.ts - x-pack/test_serverless/api_integration/test_suites/security/config.feature_flags.ts - x-pack/test_serverless/api_integration/test_suites/security/common_configs/config.group1.ts @@ -129,3 +127,7 @@ enabled: - x-pack/test/api_integration/deployment_agnostic/configs/serverless/security.serverless.config.ts - x-pack/test/spaces_api_integration/deployment_agnostic/security_and_spaces/serverless.config.ts - x-pack/test/spaces_api_integration/deployment_agnostic/security_and_spaces/serverless.copy_to_space.config.ts + +# Serverless tests only run on main +defaultQueue: 'n2-4-spot' +enabled: diff --git a/.buildkite/pipelines/chrome_forward_testing.yml b/.buildkite/pipelines/chrome_forward_testing.yml index adfea5d63fafc..d65653d668bf0 100644 --- a/.buildkite/pipelines/chrome_forward_testing.yml +++ b/.buildkite/pipelines/chrome_forward_testing.yml @@ -61,76 +61,6 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_entity_analytics.sh - label: 'Serverless Entity Analytics - Security Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 3 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_explore.sh - label: 'Serverless Explore - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 2 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_investigations.sh - label: 'Serverless Investigations - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 10 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management.sh - label: 'Serverless Rule Management - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management_prebuilt_rules.sh - label: 'Serverless Rule Management - Prebuilt Rules - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_rule_management.sh label: 'Rule Management - Security Solution Cypress Tests' agents: @@ -159,34 +89,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine.sh - label: 'Serverless Detection Engine - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine_exceptions.sh - label: 'Serverless Detection Engine - Exceptions - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 4 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_detection_engine.sh label: 'Detection Engine - Security Solution Cypress Tests' agents: @@ -215,20 +117,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_ai_assistant.sh - label: 'Serverless AI Assistant - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_ai_assistant.sh label: 'AI Assistant - Security Solution Cypress Tests' agents: @@ -299,20 +187,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh - label: 'Osquery Cypress Tests on Serverless' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 8 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/defend_workflows.sh label: 'Defend Workflows Cypress Tests' agents: @@ -327,20 +201,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh - label: 'Defend Workflows Cypress Tests on Serverless' - agents: - enableNestedVirtualization: true - machineType: n2-standard-4 - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 14 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - wait: ~ continue_on_failure: true diff --git a/.buildkite/pipelines/pointer_compression.yml b/.buildkite/pipelines/pointer_compression.yml index 8a9dda84def5d..d84833938cd2e 100644 --- a/.buildkite/pipelines/pointer_compression.yml +++ b/.buildkite/pipelines/pointer_compression.yml @@ -49,91 +49,6 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_entity_analytics.sh - label: 'Serverless Entity Analytics - Security Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 3 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_explore.sh - label: 'Serverless Explore - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 2 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_investigations.sh - label: 'Serverless Investigations - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 10 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management.sh - label: 'Serverless Rule Management - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management_prebuilt_rules.sh - label: 'Serverless Rule Management - Prebuilt Rules - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_rule_management.sh label: 'Rule Management - Security Solution Cypress Tests' agents: @@ -168,40 +83,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine.sh - label: 'Serverless Detection Engine - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine_exceptions.sh - label: 'Serverless Detection Engine - Exceptions - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 4 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_detection_engine.sh label: 'Detection Engine - Security Solution Cypress Tests' agents: @@ -236,23 +117,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_ai_assistant.sh - label: 'Serverless AI Assistant - Security Solution Cypress Tests' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_ai_assistant.sh label: 'AI Assistant - Security Solution Cypress Tests' agents: @@ -338,23 +202,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh - label: 'Osquery Cypress Tests on Serverless' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 8 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/defend_workflows.sh label: 'Defend Workflows Cypress Tests' agents: @@ -372,23 +219,6 @@ steps: - exit_status: '-1' limit: 1 - - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh - label: 'Defend Workflows Cypress Tests on Serverless' - agents: - image: family/kibana-ubuntu-2004 - imageProject: elastic-images-prod - provider: gcp - enableNestedVirtualization: true - machineType: n2-standard-4 - depends_on: - - build - timeout_in_minutes: 60 - parallelism: 14 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - wait: ~ continue_on_failure: true diff --git a/.buildkite/pipelines/pull_request/security_solution/ai_assistant.yml b/.buildkite/pipelines/pull_request/security_solution/ai_assistant.yml index ca185a684d0c7..9f9b606dced1d 100644 --- a/.buildkite/pipelines/pull_request/security_solution/ai_assistant.yml +++ b/.buildkite/pipelines/pull_request/security_solution/ai_assistant.yml @@ -1,24 +1,4 @@ steps: - - command: .buildkite/scripts/steps/functional/security_serverless_ai_assistant.sh - label: 'Serverless AI Assistant - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_ai_assistant.sh label: 'AI Assistant - Security Solution Cypress Tests' agents: diff --git a/.buildkite/pipelines/pull_request/security_solution/cloud_security_posture.yml b/.buildkite/pipelines/pull_request/security_solution/cloud_security_posture.yml index e1ba84bf4f661..4795b624591cc 100644 --- a/.buildkite/pipelines/pull_request/security_solution/cloud_security_posture.yml +++ b/.buildkite/pipelines/pull_request/security_solution/cloud_security_posture.yml @@ -18,23 +18,3 @@ steps: automatic: - exit_status: '-1' limit: 1 - - - command: .buildkite/scripts/steps/functional/cloud_security_posture_serverless.sh - label: 'Cloud Security Posture Cypress Tests on Serverless' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 \ No newline at end of file diff --git a/.buildkite/pipelines/pull_request/security_solution/cypress_burn.yml b/.buildkite/pipelines/pull_request/security_solution/cypress_burn.yml index 8b2e8e3d09f0d..14d81aa9d3520 100644 --- a/.buildkite/pipelines/pull_request/security_solution/cypress_burn.yml +++ b/.buildkite/pipelines/pull_request/security_solution/cypress_burn.yml @@ -18,25 +18,6 @@ steps: retry: automatic: false - - command: .buildkite/scripts/steps/functional/defend_workflows_serverless_burn.sh - label: '[Soft fail] Defend Workflows Cypress Tests on Serverless, burning changed specs' - agents: - enableNestedVirtualization: true - machineType: n2-standard-4 - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - soft_fail: true - parallelism: 1 - retry: - automatic: false - - command: .buildkite/scripts/steps/functional/security_solution_burn.sh label: '[Soft fail] Security Solution Cypress tests, burning changed specs' agents: diff --git a/.buildkite/pipelines/pull_request/security_solution/defend_workflows.yml b/.buildkite/pipelines/pull_request/security_solution/defend_workflows.yml index a8ac3e742c23c..28cc4f2812b5a 100644 --- a/.buildkite/pipelines/pull_request/security_solution/defend_workflows.yml +++ b/.buildkite/pipelines/pull_request/security_solution/defend_workflows.yml @@ -18,23 +18,3 @@ steps: automatic: - exit_status: '-1' limit: 1 - - - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh - label: 'Defend Workflows Cypress Tests on Serverless' - agents: - enableNestedVirtualization: true - machineType: n2-standard-4 - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 14 - retry: - automatic: - - exit_status: '-1' - limit: 1 diff --git a/.buildkite/pipelines/pull_request/security_solution/detection_engine.yml b/.buildkite/pipelines/pull_request/security_solution/detection_engine.yml index c5ca79fc78ece..e1eada596dee0 100644 --- a/.buildkite/pipelines/pull_request/security_solution/detection_engine.yml +++ b/.buildkite/pipelines/pull_request/security_solution/detection_engine.yml @@ -1,44 +1,4 @@ steps: - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine.sh - label: 'Serverless Detection Engine - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_detection_engine_exceptions.sh - label: 'Serverless Detection Engine - Exceptions - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 4 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_detection_engine.sh label: 'Detection Engine - Security Solution Cypress Tests' agents: diff --git a/.buildkite/pipelines/pull_request/security_solution/entity_analytics.yml b/.buildkite/pipelines/pull_request/security_solution/entity_analytics.yml index d031c8f382a49..1ff0999d33afd 100644 --- a/.buildkite/pipelines/pull_request/security_solution/entity_analytics.yml +++ b/.buildkite/pipelines/pull_request/security_solution/entity_analytics.yml @@ -1,24 +1,4 @@ steps: - - command: .buildkite/scripts/steps/functional/security_serverless_entity_analytics.sh - label: 'Serverless Entity Analytics - Security Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 3 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_entity_analytics.sh label: 'Entity Analytics - Security Solution Cypress Tests' agents: diff --git a/.buildkite/pipelines/pull_request/security_solution/explore.yml b/.buildkite/pipelines/pull_request/security_solution/explore.yml index 730bcaafff745..085b396c956d5 100644 --- a/.buildkite/pipelines/pull_request/security_solution/explore.yml +++ b/.buildkite/pipelines/pull_request/security_solution/explore.yml @@ -18,23 +18,3 @@ steps: automatic: - exit_status: '-1' limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_explore.sh - label: 'Serverless Explore - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 2 - retry: - automatic: - - exit_status: '-1' - limit: 1 diff --git a/.buildkite/pipelines/pull_request/security_solution/investigations.yml b/.buildkite/pipelines/pull_request/security_solution/investigations.yml index e001402daf725..a4340acf7a261 100644 --- a/.buildkite/pipelines/pull_request/security_solution/investigations.yml +++ b/.buildkite/pipelines/pull_request/security_solution/investigations.yml @@ -18,23 +18,3 @@ steps: automatic: - exit_status: '-1' limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_investigations.sh - label: 'Serverless Investigations - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 10 - retry: - automatic: - - exit_status: '-1' - limit: 1 diff --git a/.buildkite/pipelines/pull_request/security_solution/osquery_cypress.yml b/.buildkite/pipelines/pull_request/security_solution/osquery_cypress.yml index c2de20aa5975d..55e5b7842f4f1 100644 --- a/.buildkite/pipelines/pull_request/security_solution/osquery_cypress.yml +++ b/.buildkite/pipelines/pull_request/security_solution/osquery_cypress.yml @@ -18,23 +18,3 @@ steps: automatic: - exit_status: '-1' limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_osquery.sh - label: 'Osquery Cypress Tests on Serverless' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 8 - retry: - automatic: - - exit_status: '-1' - limit: 1 diff --git a/.buildkite/pipelines/pull_request/security_solution/playwright.yml b/.buildkite/pipelines/pull_request/security_solution/playwright.yml index c92506297ea07..af29f1e545ca2 100644 --- a/.buildkite/pipelines/pull_request/security_solution/playwright.yml +++ b/.buildkite/pipelines/pull_request/security_solution/playwright.yml @@ -1,24 +1,4 @@ steps: - - command: .buildkite/scripts/steps/functional/security_serverless_playwright.sh - label: 'Serverless Playwright - Security Solution Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_playwright.sh label: 'Playwright - Security Solution Tests' agents: diff --git a/.buildkite/pipelines/pull_request/security_solution/rule_management.yml b/.buildkite/pipelines/pull_request/security_solution/rule_management.yml index e247dc2972620..085df0f65eeb5 100644 --- a/.buildkite/pipelines/pull_request/security_solution/rule_management.yml +++ b/.buildkite/pipelines/pull_request/security_solution/rule_management.yml @@ -1,44 +1,4 @@ steps: - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management.sh - label: 'Serverless Rule Management - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 5 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - - command: .buildkite/scripts/steps/functional/security_serverless_rule_management_prebuilt_rules.sh - label: 'Serverless Rule Management - Prebuilt Rules - Security Solution Cypress Tests' - agents: - machineType: n2-standard-4 - preemptible: true - depends_on: - - build - - quick_checks - - checks - - linting - - linting_with_types - - check_types - - check_oas_snapshot - timeout_in_minutes: 60 - parallelism: 1 - retry: - automatic: - - exit_status: '-1' - limit: 1 - - command: .buildkite/scripts/steps/functional/security_solution_rule_management.sh label: 'Rule Management - Security Solution Cypress Tests' agents: diff --git a/.buildkite/pipelines/pull_request/webpack_bundle_analyzer.yml b/.buildkite/pipelines/pull_request/webpack_bundle_analyzer.yml index 6b265c3146a63..d14bcfa8fee58 100644 --- a/.buildkite/pipelines/pull_request/webpack_bundle_analyzer.yml +++ b/.buildkite/pipelines/pull_request/webpack_bundle_analyzer.yml @@ -2,7 +2,7 @@ steps: - command: .buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh label: 'Build Webpack Bundle Analyzer reports' agents: - machineType: n2-standard-4 + machineType: n2-standard-8 preemptible: true key: webpack_bundle_analyzer timeout_in_minutes: 60 diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index e79cdbfae2cd8..70f84c414bbe1 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -279,9 +279,10 @@ const getPipeline = (filename: string, removeSteps = true) => { pipeline.push( getPipeline('.buildkite/pipelines/pull_request/security_solution/ai_assistant.yml') ); - pipeline.push( - getPipeline('.buildkite/pipelines/pull_request/security_solution/automatic_import.yml') - ); + // Serverless tests only run on main + // pipeline.push( + // getPipeline('.buildkite/pipelines/pull_request/security_solution/automatic_import.yml') + // ); pipeline.push( getPipeline('.buildkite/pipelines/pull_request/security_solution/detection_engine.yml') ); diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.ts b/.buildkite/scripts/steps/storybooks/build_and_upload.ts index 6e0d0a7125673..6b1432b2cbb08 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.ts +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts @@ -39,7 +39,11 @@ const build = () => { console.log('--- Building Storybooks'); for (const storybook of Object.keys(storybookAliases)) { - exec(`STORYBOOK_BASE_URL=${STORYBOOK_BASE_URL}`, `yarn storybook --site ${storybook}`); + exec( + `STORYBOOK_BASE_URL=${STORYBOOK_BASE_URL}`, + `NODE_OPTIONS=--max-old-space-size=6144`, + `yarn storybook --site ${storybook}` + ); } }; diff --git a/.eslintrc.js b/.eslintrc.js index 4f9f6f11bf8e2..c366864411d93 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1439,6 +1439,54 @@ module.exports = { 'mocha/no-skipped-tests': 'off', }, }, + { + files: [ + 'packages/kbn-scout/src/playwright/**/*.ts', + 'x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/**/*.ts', + 'src/platform/plugins/**/ui_tests/**/*.ts', + 'x-pack/platform/plugins/**/ui_tests/**/*.ts', + 'x-pack/solutions/**/plugins/**/ui_tests/**/*.ts', + ], + excludedFiles: ['packages/kbn-scout/src/playwright/**/*.test.ts'], + extends: ['plugin:playwright/recommended'], + plugins: ['playwright'], + settings: { + playwright: { + globalAliases: { + test: ['test', 'spaceTest'], + }, + }, + }, + rules: { + 'playwright/no-commented-out-tests': 'error', + 'playwright/no-conditional-expect': 'error', + 'playwright/no-conditional-in-test': 'warn', + 'playwright/no-duplicate-hooks': 'error', + 'playwright/no-focused-test': 'error', + 'playwright/no-get-by-title': 'error', + 'playwright/no-nth-methods': 'error', + 'playwright/no-page-pause': 'error', + 'playwright/no-restricted-matchers': 'error', + 'playwright/no-slowed-test': 'error', + 'playwright/no-standalone-expect': 'error', + 'playwright/no-unsafe-references': 'error', + 'playwright/no-wait-for-selector': 'warn', + 'playwright/max-nested-describe': ['error', { max: 1 }], + 'playwright/missing-playwright-await': 'error', + 'playwright/prefer-comparison-matcher': 'error', + 'playwright/prefer-equality-matcher': 'error', + 'playwright/prefer-hooks-in-order': 'error', + 'playwright/prefer-hooks-on-top': 'error', + 'playwright/prefer-strict-equal': 'error', + 'playwright/prefer-to-be': 'error', + 'playwright/prefer-to-contain': 'error', + 'playwright/prefer-to-have-count': 'error', + 'playwright/prefer-to-have-length': 'error', + 'playwright/prefer-web-first-assertions': 'error', + 'playwright/require-to-throw-message': 'error', + 'playwright/require-top-level-describe': 'error', + }, + }, { files: ['x-pack/solutions/security/plugins/lists/public/**/!(*.test).{js,mjs,ts,tsx}'], plugins: ['react-perf'], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 48b91da711023..0ebd684d3b4ac 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -102,6 +102,7 @@ packages/kbn-management/storybook/config @elastic/kibana-management packages/kbn-manifest @elastic/kibana-core packages/kbn-mock-idp-plugin @elastic/kibana-security packages/kbn-mock-idp-utils @elastic/kibana-security +packages/kbn-node-libs-browser-webpack-plugin @elastic/kibana-operations packages/kbn-openapi-bundler @elastic/security-detection-rule-management packages/kbn-openapi-generator @elastic/security-detection-rule-management packages/kbn-optimizer @elastic/kibana-operations @@ -800,7 +801,7 @@ x-pack/platform/packages/shared/ai-assistant/common @elastic/search-kibana x-pack/platform/packages/shared/ai-assistant/icon @elastic/appex-sharedux x-pack/platform/packages/shared/ai-infra/inference-common @elastic/appex-ai-infra x-pack/platform/packages/shared/ai-infra/product-doc-common @elastic/appex-ai-infra -x-pack/platform/packages/shared/alerting_rule_utils @elastic/obs-ux-management-team +x-pack/platform/packages/shared/alerting-rule-utils @elastic/obs-ux-management-team x-pack/platform/packages/shared/file-upload-common @elastic/ml-ui x-pack/platform/packages/shared/index-lifecycle-management/index_lifecycle_management_common_shared @elastic/kibana-management x-pack/platform/packages/shared/index-management/index_management_shared_types @elastic/kibana-management @@ -817,7 +818,7 @@ x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common @elastic/respon x-pack/platform/packages/shared/kbn-key-value-metadata-table @elastic/obs-ux-infra_services-team @elastic/obs-ux-logs-team x-pack/platform/packages/shared/kbn-langchain @elastic/security-generative-ai x-pack/platform/packages/shared/kbn-slo-schema @elastic/obs-ux-management-team -x-pack/platform/packages/shared/logs_overview @elastic/obs-ux-logs-team +x-pack/platform/packages/shared/logs-overview @elastic/obs-ux-logs-team x-pack/platform/packages/shared/ml/aiops_common @elastic/ml-ui x-pack/platform/packages/shared/ml/aiops_log_pattern_analysis @elastic/ml-ui x-pack/platform/packages/shared/ml/aiops_log_rate_analysis @elastic/ml-ui @@ -912,20 +913,20 @@ x-pack/platform/plugins/shared/stack_connectors @elastic/response-ops x-pack/platform/plugins/shared/task_manager @elastic/response-ops x-pack/platform/plugins/shared/timelines @elastic/security-threat-hunting-investigations x-pack/platform/plugins/shared/triggers_actions_ui @elastic/response-ops -x-pack/solutions/observability/packages/alert_details @elastic/obs-ux-management-team -x-pack/solutions/observability/packages/alerting_test_data @elastic/obs-ux-management-team -x-pack/solutions/observability/packages/get_padded_alert_time_range_util @elastic/obs-ux-management-team +x-pack/solutions/observability/packages/alert-details @elastic/obs-ux-management-team +x-pack/solutions/observability/packages/alerting-test-data @elastic/obs-ux-management-team +x-pack/solutions/observability/packages/get-padded-alert-time-range-util @elastic/obs-ux-management-team x-pack/solutions/observability/packages/kbn-alerts-grouping @elastic/response-ops x-pack/solutions/observability/packages/kbn-custom-integrations @elastic/obs-ux-logs-team x-pack/solutions/observability/packages/kbn-investigation-shared @elastic/obs-ux-management-team x-pack/solutions/observability/packages/kbn-scout-oblt @elastic/appex-qa x-pack/solutions/observability/packages/kbn-streams-schema @elastic/streams-program-team -x-pack/solutions/observability/packages/observability_ai/observability_ai_common @elastic/obs-ai-assistant -x-pack/solutions/observability/packages/observability_ai/observability_ai_server @elastic/obs-ai-assistant +x-pack/solutions/observability/packages/observability-ai/observability-ai-common @elastic/obs-ai-assistant +x-pack/solutions/observability/packages/observability-ai/observability-ai-server @elastic/obs-ai-assistant x-pack/solutions/observability/packages/synthetics_test_data @elastic/obs-ux-management-team -x-pack/solutions/observability/packages/utils_browser @elastic/observability-ui -x-pack/solutions/observability/packages/utils_common @elastic/observability-ui -x-pack/solutions/observability/packages/utils_server @elastic/observability-ui +x-pack/solutions/observability/packages/utils-browser @elastic/observability-ui +x-pack/solutions/observability/packages/utils-common @elastic/observability-ui +x-pack/solutions/observability/packages/utils-server @elastic/observability-ui x-pack/solutions/observability/plugins/apm @elastic/obs-ux-infra_services-team x-pack/solutions/observability/plugins/apm_data_access @elastic/obs-ux-infra_services-team x-pack/solutions/observability/plugins/apm/ftr_e2e @elastic/obs-ux-infra_services-team @@ -959,7 +960,7 @@ x-pack/solutions/search/packages/kbn-ipynb @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-api-keys-components @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-api-keys-server @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-index-documents @elastic/search-kibana -x-pack/solutions/search/packages/shared_ui @elastic/search-kibana +x-pack/solutions/search/packages/shared-ui @elastic/search-kibana x-pack/solutions/search/plugins/enterprise_search @elastic/search-kibana x-pack/solutions/search/plugins/search_assistant @elastic/search-kibana x-pack/solutions/search/plugins/search_connectors @elastic/search-kibana @@ -974,7 +975,7 @@ x-pack/solutions/search/plugins/serverless_search @elastic/search-kibana x-pack/solutions/security/packages/connectors @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/data_table @elastic/security-threat-hunting-investigations x-pack/solutions/security/packages/data-stream-adapter @elastic/security-threat-hunting -x-pack/solutions/security/packages/distribution_bar @elastic/kibana-cloud-security-posture +x-pack/solutions/security/packages/distribution-bar @elastic/kibana-cloud-security-posture x-pack/solutions/security/packages/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore x-pack/solutions/security/packages/expandable-flyout @elastic/security-threat-hunting-investigations x-pack/solutions/security/packages/features @elastic/security-threat-hunting-explore diff --git a/.i18nrc.json b/.i18nrc.json index 573db00934f08..1cffd1c23f767 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -21,7 +21,7 @@ "domDragDrop": "src/platform/packages/shared/kbn-dom-drag-drop", "controls": "src/platform/plugins/shared/controls", "data": "src/platform/plugins/shared/data", - "observabilityAlertDetails": "x-pack/solutions/observability/packages/alert_details", + "observabilityAlertDetails": "x-pack/solutions/observability/packages/alert-details", "dataViews": "src/platform/plugins/shared/data_views", "defaultNavigation": ["packages/default-nav", "src/platform/packages/private/default-nav"], "devTools": "src/platform/plugins/shared/dev_tools", diff --git a/config/serverless.yml b/config/serverless.yml index 3067fd0749103..8ff6baab22f2e 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -271,8 +271,5 @@ xpack.dataUsage.enabled: true # This feature is disabled in Serverless until fully tested within a Serverless environment xpack.dataUsage.enableExperimental: ['dataUsageDisabled'] -# Ensure Serverless is using the Amsterdam theme -uiSettings.experimental.defaultTheme: "amsterdam" - # This feature is disabled in Serverless until Inference Endpoint become enabled within a Serverless environment xpack.stack_connectors.enableExperimental: ['inferenceConnectorOff'] \ No newline at end of file diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 48b3da0be6be6..4d310b7197e82 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -699,10 +699,6 @@ using the CURL scripts in the scripts folder. |Exposes services to access logs data. -|{kib-repo}blob/{branch}/x-pack/solutions/observability/plugins/logs_explorer/README.md[logsExplorer] -|This plugin is home to the component and related types. It implements several of the underlying concepts that the Observability Logs Explorer app builds upon. - - |{kib-repo}blob/{branch}/x-pack/platform/plugins/shared/logs_shared/README.md[logsShared] |Exposes the shared components and APIs to access and visualize logs. diff --git a/examples/embeddable_examples/public/app/overview.tsx b/examples/embeddable_examples/public/app/overview.tsx index dd93f4c3063b0..09f972f7a666a 100644 --- a/examples/embeddable_examples/public/app/overview.tsx +++ b/examples/embeddable_examples/public/app/overview.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { css } from '@emotion/react'; import { EuiMarkdownFormat } from '@elastic/eui'; // @ts-ignore -import overviewMarkdown from '!!raw-loader!@kbn/embeddable-plugin/README.md'; +import overviewMarkdown from '@kbn/embeddable-plugin/README.md?raw'; export const Overview = () => { return ( diff --git a/examples/embeddable_examples/public/app/register_embeddable.tsx b/examples/embeddable_examples/public/app/register_embeddable.tsx index 836eaa8f06209..b15b65cb1da0c 100644 --- a/examples/embeddable_examples/public/app/register_embeddable.tsx +++ b/examples/embeddable_examples/public/app/register_embeddable.tsx @@ -10,13 +10,13 @@ import React from 'react'; import { EuiCodeBlock, EuiSpacer, EuiText } from '@elastic/eui'; // @ts-ignore -import registerSearchEmbeddableSource from '!!raw-loader!../react_embeddables/search/register_search_embeddable'; +import registerSearchEmbeddableSource from '../react_embeddables/search/register_search_embeddable?raw'; // @ts-ignore -import registerAttachActionSource from '!!raw-loader!../react_embeddables/search/register_add_search_panel_action'; +import registerAttachActionSource from '../react_embeddables/search/register_add_search_panel_action?raw'; // @ts-ignore -import registerFieldListEmbeddableSource from '!!raw-loader!../react_embeddables/field_list/register_field_list_embeddable'; +import registerFieldListEmbeddableSource from '../react_embeddables/field_list/register_field_list_embeddable?raw'; // @ts-ignore -import registerReactEmbeddableSavedObjectSource from '!!raw-loader!../react_embeddables/register_saved_object_example'; +import registerReactEmbeddableSavedObjectSource from '../react_embeddables/register_saved_object_example?raw'; export const RegisterEmbeddable = () => { return ( diff --git a/examples/field_formats_example/public/app.tsx b/examples/field_formats_example/public/app.tsx index 894a49c63098d..f378c24cec86c 100644 --- a/examples/field_formats_example/public/app.tsx +++ b/examples/field_formats_example/public/app.tsx @@ -24,15 +24,15 @@ import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import * as example1 from './examples/1_using_existing_format'; import * as example2 from './examples/2_creating_custom_formatter'; // @ts-ignore -import example1SampleCode from '!!raw-loader!./examples/1_using_existing_format'; +import example1SampleCode from './examples/1_using_existing_format?raw'; // @ts-ignore -import example2SampleCodePart1 from '!!raw-loader!../common/example_currency_format'; +import example2SampleCodePart1 from '../common/example_currency_format?raw'; // @ts-ignore -import example2SampleCodePart2 from '!!raw-loader!./examples/2_creating_custom_formatter'; +import example2SampleCodePart2 from './examples/2_creating_custom_formatter?raw'; // @ts-ignore -import example2SampleCodePart3 from '!!raw-loader!../server/examples/2_creating_custom_formatter'; +import example2SampleCodePart3 from '../server/examples/2_creating_custom_formatter?raw'; // @ts-ignore -import example3SampleCode from '!!raw-loader!./examples/3_creating_custom_format_editor'; +import example3SampleCode from './examples/3_creating_custom_format_editor?raw'; export interface Deps { fieldFormats: FieldFormatsStart; diff --git a/fleet_packages.json b/fleet_packages.json index f0dcf1efd0066..339bba0f1da71 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -24,7 +24,7 @@ [ { "name": "apm", - "version": "8.15.0-preview-1716438434", + "version": "9.0.0-preview-1738343125", "forceAlignStackVersion": true, "allowSyncToPrerelease": true }, @@ -34,7 +34,7 @@ }, { "name": "endpoint", - "version": "8.15.1" + "version": "9.0.0" }, { "name": "fleet_server", @@ -52,7 +52,7 @@ }, { "name": "synthetics", - "version": "1.2.2" + "version": "1.3.0" }, { "name": "security_detection_engine", diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index a24206d5eceaa..5ce3bec194f0e 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -44337,6 +44337,17 @@ components: query: description: An ESQL query type: string + timerange: + description: Time range to select in the time picker. + type: object + properties: + from: + type: string + to: + type: string + required: + - from + - to type: enum: - EsqlQuery diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 98735ad10c07a..af37bdad32dec 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -50914,6 +50914,17 @@ components: query: description: An ESQL query type: string + timerange: + description: Time range to select in the time picker. + type: object + properties: + from: + type: string + to: + type: string + required: + - from + - to type: enum: - EsqlQuery diff --git a/oas_docs/package-lock.json b/oas_docs/package-lock.json index d63ff3078847b..8c78a7c0453da 100644 --- a/oas_docs/package-lock.json +++ b/oas_docs/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@redocly/cli": "^1.27.2", + "@redocly/cli": "^1.28.5", "bump-cli": "^2.8.4" } }, @@ -43,23 +43,6 @@ "node": ">=6.9.0" } }, - "node_modules/@cfaester/enzyme-adapter-react-18": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cfaester/enzyme-adapter-react-18/-/enzyme-adapter-react-18-0.8.0.tgz", - "integrity": "sha512-3Z3ThTUouHwz8oIyhTYQljEMNRFtlVyc3VOOHCbxs47U6cnXs8K9ygi/c1tv49s7MBlTXeIcuN+Ttd9aPtILFQ==", - "dependencies": { - "enzyme-shallow-equal": "^1.0.0", - "function.prototype.name": "^1.1.6", - "has": "^1.0.4", - "react-is": "^18.2.0", - "react-shallow-renderer": "^16.15.0" - }, - "peerDependencies": { - "enzyme": "^3.11.0", - "react": ">=18", - "react-dom": ">=18" - } - }, "node_modules/@clack/core": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.4.tgz", @@ -515,12 +498,12 @@ } }, "node_modules/@redocly/cli": { - "version": "1.27.2", - "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-1.27.2.tgz", - "integrity": "sha512-bJi3Hb3eaTo7lnMXAJ3HQwQS45vrNXwaqNwh/nbgjkzeb4/5p7GXgB6nWkakwKUDiPVMX2rBoa8MCodNaaQ3Yg==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-1.29.0.tgz", + "integrity": "sha512-xpvcZUCFzp2sZCv3WB8ffrFTSUA7Ha2CucI6E6YJrv5d1i8jupeDIClPJ6dwWLrTfTgP/0e6c6R436pwSwzMGg==", "license": "MIT", "dependencies": { - "@redocly/openapi-core": "1.27.2", + "@redocly/openapi-core": "1.29.0", "abort-controller": "^3.0.0", "chokidar": "^3.5.1", "colorette": "^1.2.0", @@ -530,11 +513,10 @@ "glob": "^7.1.6", "handlebars": "^4.7.6", "mobx": "^6.0.4", - "node-fetch": "^2.6.1", "pluralize": "^8.0.0", - "react": "^17.0.0 || ^18.2.0", - "react-dom": "^17.0.0 || ^18.2.0", - "redoc": "~2.2.0", + "react": "^17.0.0 || ^18.2.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.2.0 || ^19.0.0", + "redoc": "2.4.0", "semver": "^7.5.2", "simple-websocket": "^9.0.0", "styled-components": "^6.0.7", @@ -545,8 +527,8 @@ "redocly": "bin/cli.js" }, "engines": { - "node": ">=14.19.0", - "npm": ">=7.0.0" + "node": ">=18.17.0", + "npm": ">=9.5.0" } }, "node_modules/@redocly/config": { @@ -556,25 +538,24 @@ "license": "MIT" }, "node_modules/@redocly/openapi-core": { - "version": "1.27.2", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.27.2.tgz", - "integrity": "sha512-qVrDc27DHpeO2NRCMeRdb4299nijKQE3BY0wrA+WUHlOLScorIi/y7JzammLk22IaTvjR9Mv9aTAdjE1aUwJnA==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.29.0.tgz", + "integrity": "sha512-Ju8POuRjYLTl6JfaSMq5exzhw4E/f1Qb7fGxgS4/PDSTzS1jzZ/UUJRBPeiQ1Ag7yuxH6JwltOr2iiltnBey1w==", "license": "MIT", "dependencies": { "@redocly/ajv": "^8.11.2", "@redocly/config": "^0.20.1", "colorette": "^1.2.0", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^7.0.5", "js-levenshtein": "^1.1.6", "js-yaml": "^4.1.0", "minimatch": "^5.0.1", - "node-fetch": "^2.6.1", "pluralize": "^8.0.0", "yaml-ast-parser": "0.0.43" }, "engines": { - "node": ">=14.19.0", - "npm": ">=7.0.0" + "node": ">=18.17.0", + "npm": ">=9.5.0" } }, "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { @@ -788,21 +769,6 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -811,65 +777,6 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.4.tgz", - "integrity": "sha512-r+mCJ7zXgXElgR4IRC+fkvNCeoaavWBs6EdCso5Tbcf+iEMKzBU/His60lt34WEZ9vlb8wDkZvQGcVI5GwkfoQ==", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-array-method-boxes-properly": "^1.0.0", - "es-object-atoms": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "peer": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -904,20 +811,6 @@ "node": ">= 4.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/axios": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", @@ -944,12 +837,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "peer": true - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -998,24 +885,6 @@ "node": ">=16.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/call-me-maybe": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", @@ -1067,48 +936,6 @@ "node": ">=8" } }, - "node_modules/cheerio": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", - "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", - "peer": true, - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "encoding-sniffer": "^0.2.0", - "htmlparser2": "^9.1.0", - "parse5": "^7.1.2", - "parse5-htmlparser2-tree-adapter": "^7.0.0", - "parse5-parser-stream": "^7.1.2", - "undici": "^6.19.5", - "whatwg-mimetype": "^4.0.0" - }, - "engines": { - "node": ">=18.17" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "peer": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1212,12 +1039,6 @@ "node": ">= 0.8" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "peer": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1259,22 +1080,6 @@ "node": ">=4" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "peer": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/css-to-react-native": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", @@ -1285,71 +1090,11 @@ "postcss-value-parser": "^4.0.2" } }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "peer": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -1376,38 +1121,6 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1435,72 +1148,11 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "peer": true - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "peer": true - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, "node_modules/dompurify": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "peer": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -1520,209 +1172,6 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/encoding-sniffer": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", - "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" - }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "peer": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/enzyme": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", - "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", - "peer": true, - "dependencies": { - "array.prototype.flat": "^1.2.3", - "cheerio": "^1.0.0-rc.3", - "enzyme-shallow-equal": "^1.0.1", - "function.prototype.name": "^1.1.2", - "has": "^1.0.3", - "html-element-map": "^1.2.0", - "is-boolean-object": "^1.0.1", - "is-callable": "^1.1.5", - "is-number-object": "^1.0.4", - "is-regex": "^1.0.5", - "is-string": "^1.0.5", - "is-subset": "^0.1.1", - "lodash.escape": "^4.0.1", - "lodash.isequal": "^4.5.0", - "object-inspect": "^1.7.0", - "object-is": "^1.0.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1", - "object.values": "^1.1.1", - "raf": "^3.4.1", - "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/enzyme-shallow-equal": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.7.tgz", - "integrity": "sha512-/um0GFqUXnpM9SvKtje+9Tjoz3f1fpBC3eXRFrNs8kpYn69JljciYP7KZTqM/YQbUY9KUjvKB4jo/q+L6WGGvg==", - "dependencies": { - "hasown": "^2.0.0", - "object-is": "^1.1.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "peer": true - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "peer": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -1916,14 +1365,6 @@ } } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, "node_modules/foreach": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", @@ -1974,63 +1415,12 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "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==", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-package-type": { @@ -2046,22 +1436,6 @@ "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", "integrity": "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==" }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2093,21 +1467,6 @@ "node": ">= 6" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2127,17 +1486,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2163,22 +1511,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2187,96 +1519,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-element-map": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", - "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", - "peer": true, - "dependencies": { - "array.prototype.filter": "^1.0.0", - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/htmlparser2": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", - "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "peer": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.1.0", - "entities": "^4.5.0" - } - }, "node_modules/http2-client": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz", @@ -2302,18 +1544,6 @@ "node": ">=4" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2345,45 +1575,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2395,60 +1586,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -2490,17 +1627,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2509,108 +1635,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", - "peer": true - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2622,11 +1646,6 @@ "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2724,24 +1743,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==", - "peer": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "peer": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "peer": true - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2902,12 +1903,6 @@ } } }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "peer": true - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2938,28 +1933,6 @@ "node": "*" } }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "peer": true, - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3011,18 +1984,6 @@ "node": ">=0.10.0" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "peer": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, "node_modules/oas-kit-common": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz", @@ -3101,40 +2062,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/object-treeify": { "version": "1.1.33", "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz", @@ -3143,54 +2070,6 @@ "node": ">= 10" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "peer": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3224,43 +2103,6 @@ "node": ">= 0.8.0" } }, - "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "peer": true, - "dependencies": { - "entities": "^4.5.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", - "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", - "peer": true, - "dependencies": { - "domhandler": "^5.0.3", - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-parser-stream": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", - "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", - "peer": true, - "dependencies": { - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/password-prompt": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/password-prompt/-/password-prompt-1.1.3.tgz", @@ -3304,12 +2146,6 @@ "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.6.tgz", "integrity": "sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==" }, - "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==", - "peer": true - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3345,14 +2181,6 @@ "node": ">=10" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/postcss": { "version": "8.4.38", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", @@ -3440,34 +2268,6 @@ } ] }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "peer": true, - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "peer": true - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "peer": true, - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3499,23 +2299,6 @@ "react": "^18.3.1" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/react-shallow-renderer": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", - "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", - "dependencies": { - "object-assign": "^4.1.1", - "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-tabs": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/react-tabs/-/react-tabs-6.0.2.tgz", @@ -3573,11 +2356,11 @@ } }, "node_modules/redoc": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.2.0.tgz", - "integrity": "sha512-52rz/xJtpUBc3Y/GAkaX03czKhQXTxoU7WnkXNzRLuGwiGb/iEO4OgwcgQqtwHWrYNaZXTyqZ4MAVXpi/e1gAg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.4.0.tgz", + "integrity": "sha512-rFlfzFVWS9XJ6aYAs/bHnLhHP5FQEhwAHDBVgwb9L2FqDQ8Hu8rQ1G84iwaWXxZfPP9UWn7JdWkxI6MXr2ZDjw==", + "license": "MIT", "dependencies": { - "@cfaester/enzyme-adapter-react-18": "^0.8.0", "@redocly/openapi-core": "^1.4.0", "classnames": "^2.3.2", "decko": "^1.2.0", @@ -3607,8 +2390,8 @@ "peerDependencies": { "core-js": "^3.1.4", "mobx": "^6.0.4", - "react": "^16.8.4 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0", + "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0", "styled-components": "^4.1.1 || ^5.1.1 || ^6.0.5" } }, @@ -3625,23 +2408,6 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3658,15 +2424,6 @@ "node": ">=0.10.0" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "peer": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3676,16 +2433,6 @@ "node": ">=0.10.0" } }, - "node_modules/rst-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", - "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", - "peer": true, - "dependencies": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3708,23 +2455,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3744,28 +2474,6 @@ } ] }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "peer": true - }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -3785,36 +2493,6 @@ "node": ">=10" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -3887,23 +2565,6 @@ "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/simple-websocket": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-9.1.0.tgz", @@ -4022,52 +2683,6 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4264,75 +2879,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", @@ -4358,34 +2904,11 @@ "node": ">=0.8.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/underscore": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" }, - "node_modules/undici": { - "version": "6.20.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz", - "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==", - "peer": true, - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -4440,27 +2963,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "peer": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "peer": true, - "engines": { - "node": ">=18" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -4484,39 +2986,6 @@ "node": ">= 8" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", diff --git a/oas_docs/package.json b/oas_docs/package.json index 4d82b1891aafe..bac6ae7f9544f 100644 --- a/oas_docs/package.json +++ b/oas_docs/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "bump-cli": "^2.8.4", - "@redocly/cli": "^1.27.2" + "@redocly/cli": "^1.28.5" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/package.json b/package.json index 820a035637fed..eaf1aa262b62f 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "serverless-security": "node scripts/kibana --dev --serverless=security", "spec_to_console": "node scripts/spec_to_console", "start": "node scripts/kibana --dev", - "storybook": "node --openssl-legacy-provider scripts/storybook", + "storybook": "node --no-deprecation scripts/storybook", "test:ftr": "node scripts/functional_tests", "test:ftr:runner": "node scripts/functional_test_runner", "test:ftr:server": "node scripts/functional_tests_server", @@ -117,8 +117,8 @@ "@elastic/ecs": "^8.11.5", "@elastic/elasticsearch": "^8.17.0", "@elastic/ems-client": "8.6.3", - "@elastic/eui": "99.1.0-borealis.0", - "@elastic/eui-theme-borealis": "0.0.9", + "@elastic/eui": "99.2.0-borealis.0", + "@elastic/eui-theme-borealis": "0.0.10", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "^1.2.3", "@elastic/numeral": "^2.5.1", @@ -174,7 +174,7 @@ "@kbn/alerting-example-plugin": "link:x-pack/examples/alerting_example", "@kbn/alerting-fixture-plugin": "link:x-pack/test/functional_with_es_ssl/plugins/alerts", "@kbn/alerting-plugin": "link:x-pack/platform/plugins/shared/alerting", - "@kbn/alerting-rule-utils": "link:x-pack/platform/packages/shared/alerting_rule_utils", + "@kbn/alerting-rule-utils": "link:x-pack/platform/packages/shared/alerting-rule-utils", "@kbn/alerting-state-types": "link:x-pack/platform/packages/private/kbn-alerting-state-types", "@kbn/alerting-types": "link:src/platform/packages/shared/kbn-alerting-types", "@kbn/alerts-as-data-utils": "link:src/platform/packages/shared/kbn-alerts-as-data-utils", @@ -629,7 +629,7 @@ "@kbn/logging-mocks": "link:src/platform/packages/shared/kbn-logging-mocks", "@kbn/logs-data-access-plugin": "link:x-pack/platform/plugins/shared/logs_data_access", "@kbn/logs-explorer-plugin": "link:x-pack/solutions/observability/plugins/logs_explorer", - "@kbn/logs-overview": "link:x-pack/platform/packages/shared/logs_overview", + "@kbn/logs-overview": "link:x-pack/platform/packages/shared/logs-overview", "@kbn/logs-shared-plugin": "link:x-pack/platform/plugins/shared/logs_shared", "@kbn/logstash-plugin": "link:x-pack/platform/plugins/private/logstash", "@kbn/managed-content-badge": "link:src/platform/packages/private/kbn-managed-content-badge", @@ -691,6 +691,7 @@ "@kbn/newsfeed-plugin": "link:src/platform/plugins/shared/newsfeed", "@kbn/newsfeed-test-plugin": "link:test/common/plugins/newsfeed", "@kbn/no-data-page-plugin": "link:src/platform/plugins/private/no_data_page", + "@kbn/node-libs-browser-webpack-plugin": "link:packages/kbn-node-libs-browser-webpack-plugin", "@kbn/notifications-plugin": "link:x-pack/platform/plugins/shared/notifications", "@kbn/object-utils": "link:src/platform/packages/shared/kbn-object-utils", "@kbn/object-versioning": "link:src/platform/packages/shared/kbn-object-versioning", @@ -698,19 +699,19 @@ "@kbn/observability-ai-assistant-app-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_app", "@kbn/observability-ai-assistant-management-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_management", "@kbn/observability-ai-assistant-plugin": "link:x-pack/platform/plugins/shared/observability_ai_assistant", - "@kbn/observability-ai-common": "link:x-pack/solutions/observability/packages/observability_ai/observability_ai_common", - "@kbn/observability-ai-server": "link:x-pack/solutions/observability/packages/observability_ai/observability_ai_server", - "@kbn/observability-alert-details": "link:x-pack/solutions/observability/packages/alert_details", - "@kbn/observability-alerting-test-data": "link:x-pack/solutions/observability/packages/alerting_test_data", + "@kbn/observability-ai-common": "link:x-pack/solutions/observability/packages/observability-ai/observability-ai-common", + "@kbn/observability-ai-server": "link:x-pack/solutions/observability/packages/observability-ai/observability-ai-server", + "@kbn/observability-alert-details": "link:x-pack/solutions/observability/packages/alert-details", + "@kbn/observability-alerting-test-data": "link:x-pack/solutions/observability/packages/alerting-test-data", "@kbn/observability-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/observability", - "@kbn/observability-get-padded-alert-time-range-util": "link:x-pack/solutions/observability/packages/get_padded_alert_time_range_util", + "@kbn/observability-get-padded-alert-time-range-util": "link:x-pack/solutions/observability/packages/get-padded-alert-time-range-util", "@kbn/observability-logs-explorer-plugin": "link:x-pack/solutions/observability/plugins/observability_logs_explorer", "@kbn/observability-onboarding-plugin": "link:x-pack/solutions/observability/plugins/observability_onboarding", "@kbn/observability-plugin": "link:x-pack/solutions/observability/plugins/observability", "@kbn/observability-shared-plugin": "link:x-pack/solutions/observability/plugins/observability_shared", - "@kbn/observability-utils-browser": "link:x-pack/solutions/observability/packages/utils_browser", - "@kbn/observability-utils-common": "link:x-pack/solutions/observability/packages/utils_common", - "@kbn/observability-utils-server": "link:x-pack/solutions/observability/packages/utils_server", + "@kbn/observability-utils-browser": "link:x-pack/solutions/observability/packages/utils-browser", + "@kbn/observability-utils-common": "link:x-pack/solutions/observability/packages/utils-common", + "@kbn/observability-utils-server": "link:x-pack/solutions/observability/packages/utils-server", "@kbn/oidc-provider-plugin": "link:x-pack/test/security_api_integration/plugins/oidc_provider", "@kbn/open-telemetry-instrumented-plugin": "link:test/common/plugins/otel_metrics", "@kbn/openapi-common": "link:src/platform/packages/shared/kbn-openapi-common", @@ -811,7 +812,7 @@ "@kbn/search-notebooks": "link:x-pack/solutions/search/plugins/search_notebooks", "@kbn/search-playground": "link:x-pack/solutions/search/plugins/search_playground", "@kbn/search-response-warnings": "link:src/platform/packages/shared/kbn-search-response-warnings", - "@kbn/search-shared-ui": "link:x-pack/solutions/search/packages/shared_ui", + "@kbn/search-shared-ui": "link:x-pack/solutions/search/packages/shared-ui", "@kbn/search-synonyms": "link:x-pack/solutions/search/plugins/search_synonyms", "@kbn/search-types": "link:src/platform/packages/shared/kbn-search-types", "@kbn/searchprofiler-plugin": "link:x-pack/platform/plugins/shared/searchprofiler", @@ -827,7 +828,7 @@ "@kbn/security-plugin-types-server": "link:x-pack/platform/packages/shared/security/plugin_types_server", "@kbn/security-role-management-model": "link:x-pack/platform/packages/private/security/role_management_model", "@kbn/security-solution-connectors": "link:x-pack/solutions/security/packages/connectors", - "@kbn/security-solution-distribution-bar": "link:x-pack/solutions/security/packages/distribution_bar", + "@kbn/security-solution-distribution-bar": "link:x-pack/solutions/security/packages/distribution-bar", "@kbn/security-solution-ess": "link:x-pack/solutions/security/plugins/security_solution_ess", "@kbn/security-solution-features": "link:x-pack/solutions/security/packages/features", "@kbn/security-solution-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/security_solution", @@ -1021,7 +1022,7 @@ "@langchain/langgraph": "0.2.19", "@langchain/openai": "^0.3.11", "@langtrase/trace-attributes": "^7.5.0", - "@launchdarkly/node-server-sdk": "^9.7.2", + "@launchdarkly/node-server-sdk": "^9.7.3", "@launchdarkly/openfeature-node-server": "^1.0.0", "@loaders.gl/core": "^3.4.7", "@loaders.gl/json": "^3.4.7", @@ -1318,7 +1319,6 @@ "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-runtime": "^7.24.7", @@ -1332,7 +1332,7 @@ "@bazel/typescript": "4.6.2", "@cypress/debugging-proxy": "2.0.1", "@cypress/grep": "^4.0.1", - "@cypress/webpack-preprocessor": "^6.0.1", + "@cypress/webpack-preprocessor": "^6.0.2", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/makelogs": "^6.1.1", "@elastic/synthetics": "^1.17.2", @@ -1545,11 +1545,13 @@ "@storybook/addon-storyshots": "^6.5.16", "@storybook/addons": "^6.5.16", "@storybook/api": "^6.5.16", + "@storybook/builder-webpack5": "^6.5.16", "@storybook/client-api": "^6.5.16", "@storybook/components": "^6.5.16", "@storybook/core": "^6.5.16", "@storybook/core-common": "^6.5.16", "@storybook/core-events": "^6.5.16", + "@storybook/manager-webpack5": "^6.5.16", "@storybook/node-logger": "^6.5.16", "@storybook/preview-web": "^6.5.16", "@storybook/react": "^6.5.16", @@ -1676,11 +1678,10 @@ "@types/vinyl": "^2.0.4", "@types/vinyl-fs": "^3.0.2", "@types/watchpack": "^1.1.5", - "@types/webpack": "^4.41.3", + "@types/webpack": "^5.28.5", "@types/webpack-bundle-analyzer": "^4.7.0", - "@types/webpack-env": "^1.15.3", - "@types/webpack-merge": "^4.1.5", - "@types/webpack-sources": "^0.1.4", + "@types/webpack-env": "^1.18.5", + "@types/webpack-sources": "^3.2.3", "@types/xml2js": "^0.4.11", "@types/yargs": "^15.0.0", "@types/yauzl": "^2.9.1", @@ -1695,26 +1696,27 @@ "autoprefixer": "^10.4.7", "axe-core": "^4.10.0", "babel-jest": "^29.7.0", - "babel-loader": "^8.2.5", + "babel-loader": "^9.1.3", "babel-plugin-add-module-exports": "^1.0.4", "babel-plugin-istanbul": "^6.1.1", "babel-plugin-require-context-hook": "^1.0.0", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", + "babel-plugin-transform-require-default": "^0.1.7", "babel-plugin-transform-typescript-metadata": "^0.3.2", - "backport": "^9.6.4", + "backport": "^9.6.6", "blob-polyfill": "^7.0.20220408", "buildkite-test-collector": "^1.7.0", "callsites": "^3.1.0", "chance": "1.0.18", "chromedriver": "^132.0.0", "clarify": "^2.2.0", - "clean-webpack-plugin": "^3.0.0", + "clean-webpack-plugin": "^4.0.0", "cli-progress": "^3.12.0", "cli-table3": "^0.6.1", "content-security-policy-parser": "^0.6.0", "cpy": "^8.1.1", - "css-loader": "^3.4.2", + "css-loader": "^7.1.2", "cssnano": "^5.1.12", "cssnano-preset-default": "^5.2.12", "cssstyle": "^4.1.0", @@ -1744,6 +1746,7 @@ "eslint-plugin-mocha": "^10.1.0", "eslint-plugin-no-unsanitized": "^4.0.2", "eslint-plugin-node": "^11.1.0", + "eslint-plugin-playwright": "^2.2.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", @@ -1752,7 +1755,7 @@ "eslint-traverse": "^1.0.0", "exit-hook": "^2.2.0", "expect": "^29.7.0", - "expose-loader": "^0.7.5", + "expose-loader": "^5.0.0", "express": "^4.21.2", "fetch-mock": "^10.1.0", "file-loader": "^4.2.0", @@ -1763,7 +1766,7 @@ "gulp-postcss": "^9.0.1", "gulp-terser": "^2.1.0", "has-ansi": "^3.0.0", - "html-loader": "^1.3.2", + "html-loader": "^5.1.0", "http-proxy": "^1.18.1", "http2-proxy": "^5.0.53", "http2-wrapper": "^2.2.1", @@ -1787,10 +1790,9 @@ "license-checker": "^25.0.1", "listr2": "^8.2.5", "lmdb": "^2.9.2", - "loader-utils": "^2.0.4", "marge": "^1.0.1", "micromatch": "^4.0.8", - "mini-css-extract-plugin": "1.1.0", + "mini-css-extract-plugin": "2.9.1", "minimist": "^1.2.8", "mocha": "^10.3.0", "mocha-junit-reporter": "^2.0.2", @@ -1803,7 +1805,7 @@ "mutation-observer": "^1.0.3", "native-hdr-histogram": "^1.0.0", "nock": "12.0.3", - "null-loader": "^3.0.0", + "node-libs-browser": "^2.2.1", "nyc": "^17.1.0", "oboe": "^2.1.7", "openapi-types": "^12.1.3", @@ -1817,12 +1819,11 @@ "playwright-chromium": "1.49.0", "pngjs": "^7.0.0", "postcss": "^8.4.31", - "postcss-loader": "^4.2.0", + "postcss-loader": "^8.1.1", "postcss-prefix-selector": "^1.16.0", "postcss-scss": "^4.0.4", "prettier": "^2.8.8", "proxy": "^2.1.1", - "raw-loader": "^3.1.0", "react-is": "~18.2.0", "react-test-renderer": "^17.0.2", "recast": "^0.23.9", @@ -1830,15 +1831,15 @@ "resolve": "^1.22.0", "rxjs-marbles": "^7.0.1", "sass-embedded": "^1.78.0", - "sass-loader": "^10.5.1", + "sass-loader": "^10.5.2", "selenium-webdriver": "^4.28.0", "sharp": "0.32.6", "simple-git": "^3.16.0", "sinon": "^7.4.2", "sort-package-json": "^1.53.1", "source-map": "^0.7.4", - "string-replace-loader": "^2.2.0", - "style-loader": "^1.1.3", + "string-replace-loader": "^3.1.0", + "style-loader": "^4.0.0", "stylelint": "^14.16.1", "stylelint-scss": "^4.3.0", "superagent": "^10.1.1", @@ -1849,25 +1850,23 @@ "table": "^6.8.2", "tape": "^5.9.0", "terser": "^5.36.0", - "terser-webpack-plugin": "^4.2.3", + "terser-webpack-plugin": "^5.3.10", "tough-cookie": "^5.0.0", "trace": "^3.2.0", "tree-kill": "^1.2.2", "ts-morph": "^15.1.0", "tsd": "^0.31.1", "typescript": "5.1.6", - "url-loader": "^2.2.0", - "val-loader": "^1.1.1", + "val-loader": "^6.0.0", "vinyl-fs": "^4.0.0", "watchpack": "^1.6.0", "web-streams-polyfill": "^4.0.0", - "webpack": "^4.41.5", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.9.3", - "webpack-merge": "^4.2.2", - "webpack-sources": "^1.4.1", - "webpack-visualizer-plugin2": "^1.1.0", + "webpack": "^5.95.0", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1", + "webpack-sources": "^3.2.3", "xml-crypto": "^6.0.0", "xmlbuilder": "15.1.1", "yargs": "^15.4.1", diff --git a/packages/kbn-ambient-ui-types/index.d.ts b/packages/kbn-ambient-ui-types/index.d.ts index 93d191900a855..9aa1876e1bc23 100644 --- a/packages/kbn-ambient-ui-types/index.d.ts +++ b/packages/kbn-ambient-ui-types/index.d.ts @@ -36,3 +36,15 @@ declare module '*.mdx' { // eslint-disable-next-line import/no-default-export export default MDXComponent; } + +declare module '*?asUrl' { + const content: string; + // eslint-disable-next-line import/no-default-export + export default string; +} + +declare module '*?raw' { + const content: string; + // eslint-disable-next-line import/no-default-export + export default string; +} diff --git a/packages/kbn-babel-preset/BUILD.bazel b/packages/kbn-babel-preset/BUILD.bazel index 37a07ed15d77f..32e642d5742d5 100644 --- a/packages/kbn-babel-preset/BUILD.bazel +++ b/packages/kbn-babel-preset/BUILD.bazel @@ -41,6 +41,7 @@ RUNTIME_DEPS = [ "@npm//babel-plugin-styled-components", "@npm//babel-plugin-transform-react-remove-prop-types", "@npm//babel-plugin-transform-typescript-metadata", + "@npm//babel-plugin-transform-require-default", ] js_library( diff --git a/packages/kbn-babel-preset/styled_components_files.js b/packages/kbn-babel-preset/styled_components_files.js index 29df6890cdbdb..d68197f46c79c 100644 --- a/packages/kbn-babel-preset/styled_components_files.js +++ b/packages/kbn-babel-preset/styled_components_files.js @@ -105,7 +105,6 @@ module.exports = { /x-pack[\/\\]platform[\/\\]plugins[\/\\]shared[\/\\]timelines[\/\\]public[\/\\]mock[\/\\]test_providers.tsx/, /x-pack[\/\\]platform[\/\\]plugins[\/\\]shared[\/\\]triggers_actions_ui[\/\\]public[\/\\]application[\/\\]sections[\/\\]actions_connectors_list[\/\\]components[\/\\]actions_connectors_list.test.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]observability[\/\\]public[\/\\]pages[\/\\]overview[\/\\]components[\/\\]news_feed[\/\\]news_feed.tsx/, - /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]observability[\/\\]public[\/\\]pages[\/\\]overview[\/\\]components[\/\\]sections[\/\\]apm[\/\\]apm_section.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]observability[\/\\]public[\/\\]pages[\/\\]overview[\/\\]components[\/\\]sections[\/\\]empty[\/\\]empty_sections.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]observability[\/\\]public[\/\\]pages[\/\\]overview[\/\\]components[\/\\]sections[\/\\]uptime[\/\\]uptime_section.tsx/, /x-pack[\/\\]solutions[\/\\]observability[\/\\]plugins[\/\\]observability[\/\\]public[\/\\]pages[\/\\]overview[\/\\]components[\/\\]sections[\/\\]ux[\/\\]core_web_vitals[\/\\]color_palette_flex_item.tsx/, @@ -180,21 +179,12 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]and_or_badge[\/\\]rounded_badge_antenna.test.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]and_or_badge[\/\\]rounded_badge_antenna.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]auto_download[\/\\]auto_download.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]barchart.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]chart_place_holder.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]common.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]donutchart.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]draggable_legend.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]draggable_legend_item.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]charts[\/\\]legend_item.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]conditions_table[\/\\]index.stories.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]conditions_table[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]draggable_wrapper.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]droppable_wrapper.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]drag_and_drop[\/\\]provider_container.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]draggables[\/\\]field_badge[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]draggables[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]empty_page[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]empty_value[\/\\]empty_value.test.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]empty_value[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]endpoint[\/\\]agents[\/\\]agent_status[\/\\]agent_status.tsx/, @@ -202,22 +192,14 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]events_viewer[\/\\]summary_view_select[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]field_selection[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]filters_global[\/\\]filters_global.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]guided_onboarding_tour[\/\\]tour_step.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_actions[\/\\]actions.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_page[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_page[\/\\]title.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_section[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]health_truncate_text[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]hover_visibility_container[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]inspect[\/\\]modal.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]item_details_card[\/\\]index.stories.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]item_details_card[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]line_clamp[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]link_icon[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]links[\/\\]helpers.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]loader[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]matrix_histogram[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]matrix_histogram[\/\\]matrix_loader.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml[\/\\]score[\/\\]anomaly_score.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml[\/\\]score[\/\\]create_description_list.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml[\/\\]tables[\/\\]basic_table.tsx/, @@ -227,16 +209,12 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml_popover[\/\\]jobs_table[\/\\]showing_count.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml_popover[\/\\]ml_popover.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]ml_popover[\/\\]upgrade_contents.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]news_feed[\/\\]post[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]no_privileges[\/\\]no_privileges.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]page[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]page_wrapper[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]panel[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]popover_items[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]progress_inline[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]selectable_text[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]subtitle[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]tables[\/\\]helpers.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]text_field_value[\/\\]index.stories.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]threat_match[\/\\]and_badge.test.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]threat_match[\/\\]and_badge.tsx/, @@ -252,13 +230,9 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]toasters[\/\\]modal_all_errors.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]toolbar[\/\\]bulk_actions[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]toolbar[\/\\]unit[\/\\]styles.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]top_n[\/\\]top_n.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]truncatable_text[\/\\]truncatable_text.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]utility_bar[\/\\]styles.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]utility_bar[\/\\]utility_bar_action.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]visualization_actions[\/\\]actions.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]visualization_actions[\/\\]lens_embeddable.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]visualization_actions[\/\\]visualization_embeddable.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]mock[\/\\]storybook_providers.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]mock[\/\\]test_providers.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detection_engine[\/\\]rule_creation[\/\\]components[\/\\]eql_query_edit[\/\\]eql_overview_link.tsx/, @@ -345,15 +319,6 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]detections[\/\\]pages[\/\\]detection_engine[\/\\]rules[\/\\]helpers.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]asset_criticality[\/\\]asset_criticality_selector.stories.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]asset_criticality_file_uploader[\/\\]asset_criticality_file_uploader.stories.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]entity_analytics_anomalies[\/\\]columns.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]entity_analytics_header[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]entity_analytics_risk_score[\/\\]columns.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]risk_details_tab_body[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]risk_information[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]risk_score_donut_chart[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]severity[\/\\]common[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]severity[\/\\]severity_bar.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]entity_analytics[\/\\]components[\/\\]styled_basic_table.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]exceptions[\/\\]components[\/\\]exceptions_list_card[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]exceptions[\/\\]components[\/\\]exceptions_utility[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]exceptions[\/\\]components[\/\\]shared_list_utilty_bar[\/\\]index.tsx/, @@ -420,20 +385,6 @@ module.exports = { /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]management[\/\\]pages[\/\\]policy[\/\\]view[\/\\]protection_updates[\/\\]protection_updates_layout.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]management[\/\\]pages[\/\\]trusted_apps[\/\\]view[\/\\]components[\/\\]condition_entry_input[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]management[\/\\]pages[\/\\]trusted_apps[\/\\]view[\/\\]components[\/\\]condition_group[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]detection_response[\/\\]alerts_by_status[\/\\]alerts_by_status.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]detection_response[\/\\]alerts_by_status[\/\\]chart_label.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]detection_response[\/\\]cases_by_status[\/\\]cases_by_status.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]detection_response[\/\\]soc_trends[\/\\]soc_trends.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]events_by_dataset[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]host_overview[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]link_panel[\/\\]inner_link_panel.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]link_panel[\/\\]link_panel.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]overview_host_stats[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]overview_network_stats[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]recent_timelines[\/\\]counts[\/\\]index.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]recent_timelines[\/\\]recent_timelines.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]stat_value.tsx/, - /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]overview[\/\\]components[\/\\]user_overview[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]resolver[\/\\]view[\/\\]controls[\/\\]styles.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]resolver[\/\\]view[\/\\]edge_line.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]resolver[\/\\]view[\/\\]panels[\/\\]cube_for_process.tsx/, diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 78a1b23232287..143026ed37bba 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -10,7 +10,12 @@ const { USES_STYLED_COMPONENTS } = require('./styled_components_files'); /** @type {import('@babel/core').ConfigFunction} */ -module.exports = (api, options = {}) => { +module.exports = ( + api, + options = { + useTransformRequireDefault: false, + } +) => { return { presets: [ [ @@ -27,6 +32,18 @@ module.exports = (api, options = {}) => { ], [require('./common_preset'), options], ], + plugins: [ + // Conditionally include babel-plugin-transform-require-default + // + // We need to include this plugin in the main worker webpack config that handles our + // non node modules code base in order to support resolving esm + // as a priority over cjs (if that's defined in the mainFields). Without that we might run into + // cases where we have a repo wide cjs code that requires an esm module (coming from the ui-shared-deps that also prioritizes esm) + // which will not be applying the .default key in the require itself. + ...(options.useTransformRequireDefault + ? [require.resolve('babel-plugin-transform-require-default')] + : []), + ], env: { production: { plugins: [ diff --git a/packages/kbn-cypress-config/index.ts b/packages/kbn-cypress-config/index.ts index a6ef563682ee2..425f9d4fced3f 100644 --- a/packages/kbn-cypress-config/index.ts +++ b/packages/kbn-cypress-config/index.ts @@ -10,6 +10,7 @@ import { v4 as uuid } from 'uuid'; import { defineConfig } from 'cypress'; import wp from '@cypress/webpack-preprocessor'; +import { NodeLibsBrowserPlugin } from '@kbn/node-libs-browser-webpack-plugin'; export function defineCypressConfig(options?: Cypress.ConfigOptions) { return defineConfig({ @@ -43,6 +44,7 @@ export function defineCypressConfig(options?: Cypress.ConfigOptions) { }, ], }, + plugins: [new NodeLibsBrowserPlugin()], }, })(file); }); diff --git a/packages/kbn-cypress-config/tsconfig.json b/packages/kbn-cypress-config/tsconfig.json index 2f9ddddbeea23..4a36f2ecdf6a5 100644 --- a/packages/kbn-cypress-config/tsconfig.json +++ b/packages/kbn-cypress-config/tsconfig.json @@ -13,5 +13,7 @@ "exclude": [ "target/**/*" ], - "kbn_references": [] + "kbn_references": [ + "@kbn/node-libs-browser-webpack-plugin", + ] } diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts index 3f426e13a6215..f5a536ababce9 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts @@ -89,8 +89,8 @@ export const NoBoundaryCrossingRule: Rule.RuleModule = { return visitAllImportStatements((req, { node, importer, type }) => { if ( req === null || - // we can ignore imports using the raw-loader, they will need to be resolved but can be managed on a case by case basis - req.startsWith('!!raw-loader') || + // we can ignore imports using the ?raw (replacing legacy raw-loader), they will need to be resolved but can be managed on a case by case basis + req.endsWith('?raw') || // type only imports can stretch across all the boundaries isTypeOnlyImport(importer) ) { diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_group_crossing_imports.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_group_crossing_imports.ts index fb262e88a02ac..518325dc1eb4f 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_group_crossing_imports.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_group_crossing_imports.ts @@ -39,8 +39,8 @@ export const NoGroupCrossingImportsRule: Rule.RuleModule = { return visitAllImportStatements((req, { node }) => { if ( req === null || - // we can ignore imports using the raw-loader, they will need to be resolved but can be managed on a case by case basis - req.startsWith('!!raw-loader') + // we can ignore imports using the ?raw (replacing legacy raw-loader), they will need to be resolved but can be managed on a case by case basis + req.endsWith('?raw') ) { return; } diff --git a/packages/kbn-import-resolver/src/import_resolver.ts b/packages/kbn-import-resolver/src/import_resolver.ts index 9ca16981b2afc..e012a7b6004aa 100644 --- a/packages/kbn-import-resolver/src/import_resolver.ts +++ b/packages/kbn-import-resolver/src/import_resolver.ts @@ -231,8 +231,8 @@ export class ImportResolver { resolve(req: string, dirname: string): ResolveResult | null { // transform webpack loader requests and focus on the actual file selected const lastExI = req.lastIndexOf('!'); - if (lastExI > -1) { - const quesI = req.lastIndexOf('?'); + const quesI = req.lastIndexOf('?'); + if (lastExI > -1 || quesI > -1) { const prefix = req.slice(0, lastExI + 1); const postfix = quesI > -1 ? req.slice(quesI) : ''; const result = this.resolve(req.slice(lastExI + 1, quesI > -1 ? quesI : undefined), dirname); diff --git a/packages/kbn-node-libs-browser-webpack-plugin/BUILD.bazel b/packages/kbn-node-libs-browser-webpack-plugin/BUILD.bazel new file mode 100644 index 0000000000000..b01c5a4c56766 --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/BUILD.bazel @@ -0,0 +1,40 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "pkg_npm", "ts_project") + +SRCS = glob( + [ + "**/*.js", + "**/*.ts", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +BUNDLER_DEPS = [ + "@npm//node-libs-browser", +] + +filegroup( + name = 'root_pkg_json', + srcs = ["//:package.json"] +) + +js_library( + name = "kbn-node-libs-browser-webpack-plugin", + package_name = "@kbn/node-libs-browser-webpack-plugin", + srcs = ["package.json"] + SRCS, + deps = BUNDLER_DEPS, + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-node-libs-browser-webpack-plugin/README.md b/packages/kbn-node-libs-browser-webpack-plugin/README.md new file mode 100644 index 0000000000000..97a3a76998a97 --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/README.md @@ -0,0 +1,3 @@ +# @kbn/node-libs-browser-webpack-plugin + +Empty package generated by @kbn/generate diff --git a/packages/kbn-node-libs-browser-webpack-plugin/index.js b/packages/kbn-node-libs-browser-webpack-plugin/index.js new file mode 100644 index 0000000000000..f55b032aeda31 --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/index.js @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +/** @typedef {import('webpack').Compiler} WebpackCompiler */ + +/* eslint-disable import/no-extraneous-dependencies */ +// @ts-expect-error +const nodeLibsBrowser = require('node-libs-browser'); + +const NodeLibsBrowserPlugin = class NodeLibsBrowserPlugin { + /** + * @param {WebpackCompiler} compiler + */ + apply(compiler) { + compiler.options.plugins.push( + new compiler.webpack.ProvidePlugin({ + Buffer: [nodeLibsBrowser.buffer, 'Buffer'], + console: nodeLibsBrowser.console, + process: nodeLibsBrowser.process, + }) + ); + + compiler.options.resolve.fallback = { + assert: nodeLibsBrowser.assert, + buffer: nodeLibsBrowser.buffer, + child_process: false, + cluster: false, + console: false, + constants: nodeLibsBrowser.constants, + crypto: nodeLibsBrowser.crypto, + dgram: false, + dns: false, + domain: nodeLibsBrowser.domain, + events: nodeLibsBrowser.events, + fs: false, + http: nodeLibsBrowser.http, + https: nodeLibsBrowser.https, + module: false, + net: false, + os: nodeLibsBrowser.os, + path: nodeLibsBrowser.path, + punycode: nodeLibsBrowser.punycode, + process: nodeLibsBrowser.process, + querystring: nodeLibsBrowser.querystring, + readline: false, + repl: false, + stream: nodeLibsBrowser.stream, + _stream_duplex: nodeLibsBrowser._stream_duplex, + _stream_passthrough: nodeLibsBrowser._stream_passthrough, + _stream_readable: nodeLibsBrowser._stream_readable, + _stream_transform: nodeLibsBrowser._stream_transform, + _stream_writable: nodeLibsBrowser._stream_writable, + string_decoder: nodeLibsBrowser.string_decoder, + sys: nodeLibsBrowser.sys, + timers: nodeLibsBrowser.timers, + tls: false, + tty: nodeLibsBrowser.tty, + url: nodeLibsBrowser.url, + util: nodeLibsBrowser.util, + vm: nodeLibsBrowser.vm, + zlib: nodeLibsBrowser.zlib, + ...compiler.options.resolve.fallback, + }; + } +}; + +module.exports = { + NodeLibsBrowserPlugin, +}; diff --git a/src/platform/plugins/shared/discover/.storybook/main.ts b/packages/kbn-node-libs-browser-webpack-plugin/jest.config.js similarity index 76% rename from src/platform/plugins/shared/discover/.storybook/main.ts rename to packages/kbn-node-libs-browser-webpack-plugin/jest.config.js index 6833e95dbd5a8..839f7a449020f 100644 --- a/src/platform/plugins/shared/discover/.storybook/main.ts +++ b/packages/kbn-node-libs-browser-webpack-plugin/jest.config.js @@ -7,6 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { discoverStorybookConfig } from './discover.webpack'; - -module.exports = discoverStorybookConfig; +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../..', + roots: ['/packages/kbn-node-libs-browser-webpack-plugin'], +}; diff --git a/packages/kbn-node-libs-browser-webpack-plugin/kibana.jsonc b/packages/kbn-node-libs-browser-webpack-plugin/kibana.jsonc new file mode 100644 index 0000000000000..69acaf05df176 --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/node-libs-browser-webpack-plugin", + "owner": "@elastic/kibana-operations" +} diff --git a/packages/kbn-node-libs-browser-webpack-plugin/package.json b/packages/kbn-node-libs-browser-webpack-plugin/package.json new file mode 100644 index 0000000000000..bee6eb1db67de --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/node-libs-browser-webpack-plugin", + "devOnly": true, + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} diff --git a/packages/kbn-node-libs-browser-webpack-plugin/tsconfig.json b/packages/kbn-node-libs-browser-webpack-plugin/tsconfig.json new file mode 100644 index 0000000000000..3bbf05e134ce1 --- /dev/null +++ b/packages/kbn-node-libs-browser-webpack-plugin/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "checkJs": true, + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "index.js", + "types.ts" + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/packages/kbn-optimizer-webpack-helpers/index.ts b/packages/kbn-optimizer-webpack-helpers/index.ts index 78e5eb9693bfe..53d78dd588044 100644 --- a/packages/kbn-optimizer-webpack-helpers/index.ts +++ b/packages/kbn-optimizer-webpack-helpers/index.ts @@ -17,6 +17,8 @@ export type { } from './src/webpack_helpers'; export { + STATS_WARNINGS_FILTER, + STATS_OPTIONS_DEFAULT_USEFUL_FILTER, isFailureStats, failedStatsToErrorMessage, getModulePath, @@ -25,4 +27,5 @@ export { isExternalModule, isIgnoredModule, isNormalModule, + isRuntimeModule, } from './src/webpack_helpers'; diff --git a/packages/kbn-optimizer-webpack-helpers/src/webpack_helpers.ts b/packages/kbn-optimizer-webpack-helpers/src/webpack_helpers.ts index 0bc96a6505e15..2f0a97c935be2 100644 --- a/packages/kbn-optimizer-webpack-helpers/src/webpack_helpers.ts +++ b/packages/kbn-optimizer-webpack-helpers/src/webpack_helpers.ts @@ -8,46 +8,31 @@ */ import webpack from 'webpack'; -// @ts-expect-error module is not typed -import Stats from 'webpack/lib/Stats'; export function isFailureStats(stats: webpack.Stats) { if (stats.hasErrors()) { return true; } - const { warnings } = stats.toJson({ all: false, warnings: true }); - - // 1 - when typescript doesn't do a full type check, as we have the ts-loader - // configured here, it does not have enough information to determine - // whether an imported name is a type or not, so when the name is then - // exported, typescript has no choice but to emit the export. Fortunately, - // the extraneous export should not be harmful, so we just suppress these warnings - // https://github.com/TypeStrong/ts-loader#transpileonly-boolean-defaultfalse - // - // 2 - Mini Css Extract plugin tracks the order for each css import we have - // through the project (and it's successive imports) since version 0.4.2. - // In case we have the same imports more than one time with different - // sequences, this plugin will throw a warning. This should not be harmful, - // but the an issue was opened and can be followed on: - // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250#issuecomment-415345126 - const filteredWarnings = Stats.filterWarnings(warnings, STATS_WARNINGS_FILTER); + const { warnings } = stats.toJson({ + all: false, + warnings: true, + }); - return filteredWarnings.length > 0; + return warnings && warnings.length > 0; } -const STATS_WARNINGS_FILTER = new RegExp( +export const STATS_WARNINGS_FILTER = new RegExp( [ - '(export .* was not found in)', + '(export .* was not found in)', // with reexportExportsPresence = false and importExportsPresence = false in the module parser this should not be necessary but looks like it affects performance '|(chunk .* \\[mini-css-extract-plugin\\]\\\nConflicting order between:)', ].join('') ); export function failedStatsToErrorMessage(stats: webpack.Stats) { const details = stats.toString({ - ...Stats.presetToOptions('minimal'), + ...stats.compilation.createStatsOptions('minimal'), colors: true, - warningsFilter: STATS_WARNINGS_FILTER, errors: true, errorDetails: true, moduleTrace: true, @@ -56,6 +41,21 @@ export function failedStatsToErrorMessage(stats: webpack.Stats) { return `Optimizations failure.\n${details.split('\n').join('\n ')}`; } +export const STATS_OPTIONS_DEFAULT_USEFUL_FILTER = { + all: false, + hash: true, + version: true, + timings: true, + assets: true, + modules: true, + reasons: true, + chunks: true, + chunkModules: true, + errorDetails: false, + entrypoints: true, + ids: true, +}; + export interface WebpackResolveData { /** compilation context */ context: string; @@ -103,7 +103,7 @@ export interface WebpackNormalModule { resource: string; buildInfo: { cacheable: boolean; - fileDependencies: Set; + buildDependencies: Set; }; dependencies: Dependency[]; } @@ -122,7 +122,7 @@ export interface WebpackIgnoredModule { } export function isIgnoredModule(module: any): module is WebpackIgnoredModule { - return module?.constructor?.name === 'RawModule' && module.identifierStr?.startsWith('ignored '); + return module?.constructor?.name === 'RawModule' && module.identifierStr?.startsWith('ignored'); } /** module replacing imports for webpack externals */ @@ -169,3 +169,7 @@ export function getModulePath(module: WebpackNormalModule) { const queryIndex = module.resource.indexOf('?'); return queryIndex === -1 ? module.resource : module.resource.slice(0, queryIndex); } + +export function isRuntimeModule(module: any): boolean { + return module instanceof webpack.RuntimeModule; +} diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index e1e4546f2aed7..08c881e2859b7 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -31,7 +31,7 @@ pageLoadAssetSize: dataUsage: 30000 dataViewEditor: 28082 dataViewFieldEditor: 42021 - dataViewManagement: 5370 + dataViewManagement: 6250 dataViews: 65000 dataVisualizer: 30000 devTools: 38637 @@ -121,8 +121,8 @@ pageLoadAssetSize: observabilityShared: 111036 osquery: 107090 painlessLab: 179748 - presentationPanel: 11468 - presentationUtil: 25000 + presentationPanel: 11550 + presentationUtil: 33905 productDocBase: 22500 profiling: 36694 remoteClusters: 51327 diff --git a/packages/kbn-optimizer/src/common/bundle_cache.ts b/packages/kbn-optimizer/src/common/bundle_cache.ts index 1eecddc6e0b4d..4947107c7d285 100644 --- a/packages/kbn-optimizer/src/common/bundle_cache.ts +++ b/packages/kbn-optimizer/src/common/bundle_cache.ts @@ -122,7 +122,7 @@ export class BundleCache { } } - public writeWebpackAsset(compilation: webpack.compilation.Compilation) { + public writeWebpackAsset(compilation: webpack.Compilation) { if (!this.path) { return; } diff --git a/packages/kbn-optimizer/src/optimizer/observe_worker.ts b/packages/kbn-optimizer/src/optimizer/observe_worker.ts index ff14af5944908..edcf8651320c9 100644 --- a/packages/kbn-optimizer/src/optimizer/observe_worker.ts +++ b/packages/kbn-optimizer/src/optimizer/observe_worker.ts @@ -62,12 +62,19 @@ function usingWorkerProc(config: OptimizerConfig, fn: (proc: ChildProcess) => const proc = fork(require.resolve('../worker/run_worker'), [], { execArgv: [ `--require=@kbn/babel-register/install`, - '--openssl-legacy-provider', ...(inspectFlag && config.inspectWorkers ? [`${inspectFlag}=${inspectPortCounter++}`] : []), ], stdio: ['ignore', 'pipe', 'pipe', 'ipc'], + env: { + // NOTE: with the default 2000 limit we get a lot of recursive watcher recreations (introduced in watchpack v2) + // which makes the experience horrible and the performance between 2.5x to 3x worse when watching. + // If that fails in other mac machines with lower defaults for maxfiles and maxfilesperproc + // or just low powerful ones we need to default to polling instead of relying in the OS events watcher system. + // That can be done in the worker/run_compilers file. + WATCHPACK_WATCHER_LIMIT: '4000', + }, }); return { diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index d69b248ac188a..0b07ea8c3e334 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -22,6 +22,36 @@ jest.mock('os', () => { cpus() { return ['foo'] as any; }, + totalmem() { + return 64000000000; + }, + freemem() { + return 20000000000; + }, + }; +}); + +jest.mock('v8', () => { + return { + ...jest.requireActual('v8'), + getHeapStatistics() { + return { + total_heap_size: 5816320, + total_heap_size_executable: 262144, + total_physical_size: 6012928, + total_available_size: 4341242192, + used_heap_size: 4930768, + heap_size_limit: 4345298944, + malloced_memory: 262320, + peak_malloced_memory: 571392, + does_zap_garbage: 0, + number_of_native_contexts: 2, + number_of_detached_contexts: 0, + total_global_handles_size: 8192, + used_global_handles_size: 3296, + external_memory: 2209666, + }; + }, }; }); diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts index fbeaf8b5014f6..bc78a3ebf82aa 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.ts @@ -26,15 +26,59 @@ export interface Limits { }; } -function pickMaxWorkerCount(dist: boolean) { - // don't break if cpus() returns nothing, or an empty array - const cpuCount = Math.max(Os.cpus()?.length, 1); - // if we're buiding the dist then we can use more of the system's resources to get things done a little quicker - const maxWorkers = dist ? cpuCount - 1 : Math.ceil(cpuCount / 3); - // ensure we always have at least two workers - return Math.max(maxWorkers, 2); +interface SystemInfo { + cpuCount: number; } +function getSystemInfo(): SystemInfo { + // collects useful system information for resource usage calculations + const cpuCount = Math.max(Os.cpus()?.length ?? 0, 1); + + return { cpuCount }; +} + +const pickMaxWorkerCount = (dist: boolean) => { + const isDist = dist; + const isCI = !!process.env.CI; + const isUseMaxAvailableResources = !!process.env.KBN_OPTIMIZER_USE_MAX_AVAILABLE_RESOURCES; + const minWorkers = 2; + const { cpuCount } = getSystemInfo(); + const maxWorkers = Math.max(cpuCount - 1, minWorkers); + + // In case we get this env var set, just use max workers and avoid any kind of + // resource balance according to memory and cpu + if (isUseMaxAvailableResources) { + return maxWorkers; + } + + // Start calculating base worker count + let workerCount; + if (isDist && isCI) { + // For CI dist builds, start with most available resources + workerCount = maxWorkers; + } else if (isDist) { + // For local dist builds, start with 80% of resources but leaving some headroom + workerCount = Math.max(Math.floor(cpuCount * 0.8), 2); + } else { + // For regular local builds, start with fewer resources of 50% + workerCount = Math.max(Math.floor(cpuCount * 0.5), 2); + } + + // Adjust by the ratio workerCount to maxWorkers. + // If it is lower or equal to 50% it adds an extra worker + // so the available resources are better used + const ratioWorkerCountToMaxWorkers = 1 - workerCount / maxWorkers; + if (ratioWorkerCountToMaxWorkers >= 0.5) { + workerCount = Math.min(workerCount + 1, cpuCount); + } + + // Make sure we respect min and max worker limits + workerCount = Math.max(workerCount, minWorkers); + workerCount = Math.min(workerCount, maxWorkers); + + return workerCount; +}; + interface Options { /** absolute path to root of the repo/build */ repoRoot: string; diff --git a/packages/kbn-optimizer/src/worker/bundle_metrics_plugin.ts b/packages/kbn-optimizer/src/worker/bundle_metrics_plugin.ts index 55eb7911a1249..4356c784f674e 100644 --- a/packages/kbn-optimizer/src/worker/bundle_metrics_plugin.ts +++ b/packages/kbn-optimizer/src/worker/bundle_metrics_plugin.ts @@ -32,82 +32,90 @@ export class BundleMetricsPlugin { const { bundle } = this; - compiler.hooks.emit.tap('BundleMetricsPlugin', (compilation) => { - const assets = Object.entries(compilation.assets) - .map( - ([name, source]: [string, any]): Asset => ({ - name, - size: source.size(), - }) - ) - .filter((asset) => { - const filename = Path.basename(asset.name); - if (filename.startsWith('.')) { - return false; - } - - const ext = Path.extname(filename); - if (IGNORED_EXTNAME.includes(ext)) { - return false; + compiler.hooks.compilation.tap('BundleMetricsPlugin', (compilation) => { + compilation.hooks.processAssets.tap( + { + name: 'BundleMetricsPlugin', + stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE, + }, + () => { + const assets = Object.entries(compilation.assets) + .map( + ([name, source]: [string, any]): Asset => ({ + name, + size: source.size(), + }) + ) + .filter((asset) => { + const filename = Path.basename(asset.name); + if (filename.startsWith('.')) { + return false; + } + + const ext = Path.extname(filename); + if (IGNORED_EXTNAME.includes(ext)) { + return false; + } + + return true; + }); + + const entryName = `${bundle.id}.${bundle.type}.js`; + const entry = assets.find((a) => a.name === entryName); + if (!entry) { + throw new Error( + `Unable to find bundle entry named [${entryName}] in [${bundle.outputDir}]` + ); } - return true; - }); - - const entryName = `${bundle.id}.${bundle.type}.js`; - const entry = assets.find((a) => a.name === entryName); - if (!entry) { - throw new Error( - `Unable to find bundle entry named [${entryName}] in [${bundle.outputDir}]` - ); - } + const chunkPrefix = `${bundle.id}.chunk.`; + const asyncChunks = assets.filter((a) => a.name.startsWith(chunkPrefix)); + const miscFiles = assets.filter((a) => a !== entry && !asyncChunks.includes(a)); - const chunkPrefix = `${bundle.id}.chunk.`; - const asyncChunks = assets.filter((a) => a.name.startsWith(chunkPrefix)); - const miscFiles = assets.filter((a) => a !== entry && !asyncChunks.includes(a)); + const sumSize = (files: Asset[]) => files.reduce((acc: number, a) => acc + a.size, 0); - const sumSize = (files: Asset[]) => files.reduce((acc: number, a) => acc + a.size, 0); - - const moduleCount = bundle.cache.getModuleCount(); - if (moduleCount === undefined) { - throw new Error(`moduleCount wasn't populated by PopulateBundleCachePlugin`); - } - - const bundleMetrics: CiStatsMetric[] = [ - { - group: `@kbn/optimizer bundle module count`, - id: bundle.id, - value: moduleCount, - }, - { - group: `page load bundle size`, - id: bundle.id, - value: entry.size, - limit: bundle.pageLoadAssetSizeLimit, - limitConfigPath: `packages/kbn-optimizer/limits.yml`, - }, - { - group: `async chunks size`, - id: bundle.id, - value: sumSize(asyncChunks), - }, - { - group: `async chunk count`, - id: bundle.id, - value: asyncChunks.length, - }, - { - group: `miscellaneous assets size`, - id: bundle.id, - value: sumSize(miscFiles), - }, - ]; - - const metricsSource = new RawSource(JSON.stringify(bundleMetrics, null, 2)); + const moduleCount = bundle.cache.getModuleCount(); + if (moduleCount === undefined) { + throw new Error(`moduleCount wasn't populated by PopulateBundleCachePlugin`); + } - // see https://github.com/jantimon/html-webpack-plugin/blob/33d69f49e6e9787796402715d1b9cd59f80b628f/index.js#L266 - // @ts-expect-error undocumented, used to add assets to the output - compilation.emitAsset('metrics.json', metricsSource); + const bundleMetrics: CiStatsMetric[] = [ + { + group: `@kbn/optimizer bundle module count`, + id: bundle.id, + value: moduleCount, + }, + { + group: `page load bundle size`, + id: bundle.id, + value: entry.size, + limit: bundle.pageLoadAssetSizeLimit, + limitConfigPath: `packages/kbn-optimizer/limits.yml`, + }, + { + group: `async chunks size`, + id: bundle.id, + value: sumSize(asyncChunks), + }, + { + group: `async chunk count`, + id: bundle.id, + value: asyncChunks.length, + }, + { + group: `miscellaneous assets size`, + id: bundle.id, + value: sumSize(miscFiles), + }, + ]; + + const metricsSource = new RawSource(JSON.stringify(bundleMetrics, null, 2)); + + // see https://github.com/jantimon/html-webpack-plugin/blob/33d69f49e6e9787796402715d1b9cd59f80b628f/index.js#L266 + // @ts-expect-error undocumented, used to add assets to the output + compilation.emitAsset('metrics.json', metricsSource); + } + ); }); } } diff --git a/packages/kbn-optimizer/src/worker/bundle_remote_module.ts b/packages/kbn-optimizer/src/worker/bundle_remote_module.ts index 7c379b7b0d897..9f879e9d4c9e2 100644 --- a/packages/kbn-optimizer/src/worker/bundle_remote_module.ts +++ b/packages/kbn-optimizer/src/worker/bundle_remote_module.ts @@ -12,6 +12,7 @@ import { KbnImportReq } from '@kbn/repo-packages'; // @ts-ignore not typed by @types/webpack import Module from 'webpack/lib/Module'; +import { RawSource } from 'webpack-sources'; import { BundleRemote } from '../common'; export class BundleRemoteModule extends Module { @@ -27,8 +28,8 @@ export class BundleRemoteModule extends Module { return this.req.full; } - chunkCondition(chunk: any) { - return chunk.hasEntryModule(); + chunkCondition(chunk: any, { chunkGraph }: any) { + return chunkGraph.getNumberOfEntryModules(chunk) > 0; } identifier() { @@ -39,19 +40,56 @@ export class BundleRemoteModule extends Module { return this.identifier(); } - needRebuild() { - return false; + needBuild(context: any, callback: any) { + return callback(null, !this.buildMeta); } build(_: any, __: any, ___: any, ____: any, callback: () => void) { - this.built = true; - this.buildMeta = {}; + this.buildMeta = { + async: false, + exportsType: undefined, + }; this.buildInfo = { + strict: false, + topLevelDeclarations: new Set(), + module: __.outputOptions.module, exportsArgument: '__webpack_exports__', }; + + // super.addDependency(new StaticExportsDependency(true, false)); callback(); } + getConcatenationBailoutReason({ moduleGraph }: any) { + return `@kbn/bundleRemote externals can't be concatenated`; + } + + codeGeneration(_: any) { + const sources = new Map(); + sources.set( + 'javascript', + new RawSource(` + __webpack_require__.r(__webpack_exports__); + var ns = __kbnBundles__.get('${this.remote.bundleType}/${this.remote.bundleId}/${this.req.target}'); + Object.defineProperties(__webpack_exports__, Object.getOwnPropertyDescriptors(ns)) + `) + ); + + const data = new Map(); + data.set('url', this.req.full); + + return { + sources, + runtimeRequirements: new Set([ + 'module', + '__webpack_exports__', + '__webpack_require__', + // '__webpack_require__.r', + ]), + data, + }; + } + source() { return ` __webpack_require__.r(__webpack_exports__); @@ -64,8 +102,8 @@ export class BundleRemoteModule extends Module { return 42; } - updateHash(hash: any) { + updateHash(hash: any, context: any) { hash.update(this.identifier()); - super.updateHash(hash); + super.updateHash(hash, context); } } diff --git a/packages/kbn-optimizer/src/worker/bundle_remote_used_exports_plugin.ts b/packages/kbn-optimizer/src/worker/bundle_remote_used_exports_plugin.ts new file mode 100644 index 0000000000000..87800586ea45d --- /dev/null +++ b/packages/kbn-optimizer/src/worker/bundle_remote_used_exports_plugin.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import NormalizePath from 'normalize-path'; +import webpack from 'webpack'; +import { Minimatch } from 'minimatch'; +import { Bundle } from '../common'; + +export class BundleRemoteUsedExportsPlugin { + constructor(private readonly bundle: Bundle) {} + apply(compiler: webpack.Compiler) { + const buildPublicDirsPatterns = () => { + const targets = this.bundle.remoteInfo.targets; + const extensions = '.{js,ts,tsx,json}'; + const builtPattern = !targets.length + ? 'public' + : targets.length === 1 + ? targets[0] + : `{${targets}}`; + return [`**/${builtPattern}/index${extensions}`, `**/${builtPattern}${extensions}`]; + }; + + const publicDirsPatterns = buildPublicDirsPatterns(); + const KbnPluginMainEntryGlob = new Minimatch(publicDirsPatterns[0]); + const KbnPluginExtraFileEntryGlob = new Minimatch(publicDirsPatterns[1]); + + compiler.hooks.compilation.tap('MarkExportsAsUsedPlugin', (compilation) => { + const moduleGraph = compilation.moduleGraph; + compilation.hooks.optimizeDependencies.tap('MarkExportsAsUsedPlugin', (modules) => { + Array.from(modules).forEach((module: any) => { + if (!module.resource) { + return; + } + + const normalizedModuleResource = NormalizePath(module.resource); + if ( + KbnPluginMainEntryGlob.match(normalizedModuleResource) || + KbnPluginExtraFileEntryGlob.match(normalizedModuleResource) + ) { + // Get all exports of the module + const exportsInfo = moduleGraph.getExportsInfo(module); + + // If the module uses export *, mark it as used in unknown way + if (module.buildMeta && module.buildMeta.exportsType === 'namespace') { + // @ts-ignore + moduleGraph.getExportsInfo(module).setAllKnownExportsUsed(); + // @ts-ignore + moduleGraph.getExportsInfo(module).setUsedInUnknownWay(); + moduleGraph.addExtraReason( + module, + `BundleRemoteUsedExportsPlugin/namespace#=>${module.resource}` + ); + } else { + Array.from(exportsInfo.exports).forEach((exportInfo) => { + if (exportInfo.name) { + moduleGraph.getExportsInfo(module).setUsedInUnknownWay(exportInfo.name); + moduleGraph.addExtraReason( + module, + `BundleRemoteUsedExportsPlugin/${exportInfo.name}#=>${module.resource}` + ); + } + }); + } + } + }); + }); + }); + } +} diff --git a/packages/kbn-optimizer/src/worker/bundle_remotes_plugin.ts b/packages/kbn-optimizer/src/worker/bundle_remotes_plugin.ts index 1a5eb8b50710d..f3e6db160fbb0 100644 --- a/packages/kbn-optimizer/src/worker/bundle_remotes_plugin.ts +++ b/packages/kbn-optimizer/src/worker/bundle_remotes_plugin.ts @@ -21,7 +21,6 @@ interface RequestData { } type Callback = (error?: any, result?: T) => void; -type ModuleFactory = (data: RequestData, callback: Callback) => void; export class BundleRemotesPlugin { private allowedBundleIds = new Set(); @@ -40,34 +39,33 @@ export class BundleRemotesPlugin { // hook into the creation of NormalModule instances in webpack, if the import // statement leading to the creation of the module is pointing to a bundleRef // entry then create a BundleRefModule instead of a NormalModule. - compilationParams.normalModuleFactory.hooks.factory.tap( - 'BundleRefsPlugin/normalModuleFactory/factory', - (wrappedFactory: ModuleFactory): ModuleFactory => - (data, callback) => { - const { request } = data.dependencies[0]; - - const cached = moduleCache.get(request); - if (cached === null) { - return wrappedFactory(data, callback); - } - if (cached !== undefined) { - return callback(null, cached); - } + compilationParams.normalModuleFactory.hooks.factorize.tapAsync( + 'BundleRefsPlugin/normalModuleFactory/factorize', + (data: RequestData, callback: Callback) => { + const { request } = data.dependencies[0]; + + const cached = moduleCache.get(request); + if (cached === null) { + return callback(); + } + if (cached !== undefined) { + return callback(null, cached); + } - this.resolve(request, (error, result) => { - if (error || result === undefined) { - return callback(error); - } + this.resolve(request, (error, result) => { + if (error || result === undefined) { + return callback(error); + } - moduleCache.set(request, result); + moduleCache.set(request, result); - if (result === null) { - return wrappedFactory(data, callback); - } + if (result === null) { + return callback(); + } - callback(null, result); - }); - } + callback(null, result); + }); + } ); }); @@ -87,7 +85,7 @@ export class BundleRemotesPlugin { compilation.hooks.finishModules.tapPromise( 'BundleRefsPlugin/finishModules', async (modules) => { - const usedBundleIds = (modules as any[]) + const usedBundleIds = (Array.from(modules) as any[]) .filter((m: any): m is BundleRemoteModule => m instanceof BundleRemoteModule) .map((m) => m.remote.bundleId); @@ -96,7 +94,7 @@ export class BundleRemotesPlugin { .join(', '); if (unusedBundleIds) { - const error = new Error( + const error = new webpack.WebpackError( `Bundle for [${this.bundle.id}] lists [${unusedBundleIds}] as a required bundle, but does not use it. Please remove it.` ); (error as any).file = manifestPath; @@ -108,7 +106,9 @@ export class BundleRemotesPlugin { } public resolve(request: string, cb: (error?: Error, bundle?: null | BundleRemoteModule) => void) { - if (request.endsWith('.json')) { + // NOTE: previously on webpack v4 ?raw files did not reach this phase and were excluded + // which is not the case anymore in webpack v5 so we need to do exclude them from being resolved + if (request.endsWith('.json') || request.endsWith('?raw')) { return cb(undefined, null); } diff --git a/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts b/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts index 69eeecdb2006f..fda5cc0fb666d 100644 --- a/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts +++ b/packages/kbn-optimizer/src/worker/emit_stats_plugin.ts @@ -11,7 +11,7 @@ import Fs from 'fs'; import Path from 'path'; import webpack from 'webpack'; - +import { STATS_OPTIONS_DEFAULT_USEFUL_FILTER } from '@kbn/optimizer-webpack-helpers'; import { Bundle } from '../common'; export class EmitStatsPlugin { @@ -27,7 +27,7 @@ export class EmitStatsPlugin { (stats) => { Fs.writeFileSync( Path.resolve(this.bundle.outputDir, 'stats.json'), - JSON.stringify(stats.toJson(), null, 2) + JSON.stringify(stats.toJson(STATS_OPTIONS_DEFAULT_USEFUL_FILTER), null, 2) ); } ); diff --git a/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts b/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts index c1b0d0f6486ca..bcd67125642f6 100644 --- a/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts +++ b/packages/kbn-optimizer/src/worker/populate_bundle_cache_plugin.ts @@ -8,7 +8,7 @@ */ import Path from 'path'; -import { inspect } from 'util'; +import { inspect, promisify } from 'util'; import webpack from 'webpack'; import { @@ -17,6 +17,7 @@ import { isIgnoredModule, isConcatenatedModule, isDelegatedModule, + isRuntimeModule, getModulePath, } from '@kbn/optimizer-webpack-helpers'; @@ -30,6 +31,14 @@ import { } from '../common'; import { BundleRemoteModule } from './bundle_remote_module'; +interface InputFileSystem { + readFile: ( + path: string, + encoding: null | undefined, + callback: (err: Error | null, stats: Buffer) => void + ) => void; +} + /** * sass-loader creates about a 40% overhead on the overall optimizer runtime, and * so this constant is used to indicate to assignBundlesToWorkers() that there is @@ -48,117 +57,157 @@ export class PopulateBundleCachePlugin { public apply(compiler: webpack.Compiler) { const { bundle, workerConfig } = this; - - compiler.hooks.emit.tap( - { - name: 'PopulateBundleCachePlugin', - before: ['BundleMetricsPlugin'], - }, - (compilation) => { - const bundleRefExportIds: string[] = []; - let moduleCount = 0; - let workUnits = compilation.fileDependencies.size; - - const paths = new Set(); - const rawHashes = new Map(); - const addReferenced = (path: string) => { - if (paths.has(path)) { - return; + const inputFs = compiler.inputFileSystem as InputFileSystem; + if (!inputFs) { + throw new Error('expected inputFs to be defined'); + } + const readFile = promisify(inputFs.readFile); + const moduleFileDepsMap = new Map(); + const allFileDepsPathSet = new Set(); + + compiler.hooks.compilation.tap('PopulateBundleCachePlugin', (compilation) => { + const hooks = webpack.NormalModule.getCompilationHooks(compilation); + + // first collect file deps for modules + hooks.beforeSnapshot.tap('PopulateBundleCachePlugin', (module: any) => { + // make sure we have file deps for this module + if (module.buildInfo.fileDependencies.size > 0) { + const realFileDeps = []; + + for (const path of module.buildInfo.fileDependencies) { + // in webpack v5 there a lot of paths collected that are not real files + // but instead folders or partial paths. + // Here we're verifying if what we have as indeed a filepath + if (Path.extname(path).length > 0) { + realFileDeps.push(path); + allFileDepsPathSet.add(path); + } } - paths.add(path); - let content: Buffer; - try { - content = compiler.inputFileSystem.readFileSync(path); - } catch { - return rawHashes.set(path, null); - } + moduleFileDepsMap.set(module.identifier(), realFileDeps); + } + }); + + // in the end process assets to calculate workUnites and references + compilation.hooks.processAssets.tapAsync( + { + name: 'PopulateBundleCachePlugin', + stage: webpack.Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING, + }, + async (_, callback) => { + const bundleRefExportIds: string[] = []; + let moduleCount = 0; + let workUnits = allFileDepsPathSet.size; + + const paths = new Set(); + const rawHashes = new Map(); + const addReferenced = async (path: string) => { + if (paths.has(path)) { + return; + } - return rawHashes.set(path, Hashes.hash(content)); - }; + paths.add(path); + let content: Buffer; + try { + content = await readFile(path, null); + } catch { + return rawHashes.set(path, null); + } - const dllRefKeys = new Set(); + return rawHashes.set(path, Hashes.hash(content)); + }; - if (bundle.manifestPath) { - addReferenced(bundle.manifestPath); - } + const dllRefKeys = new Set(); + + if (bundle.manifestPath) { + await addReferenced(bundle.manifestPath); + workUnits += 1; + } - for (const module of compilation.modules) { - if (isNormalModule(module)) { - moduleCount += 1; - const path = getModulePath(module); - const parsedPath = parseFilePath(path); + for (const module of compilation.modules) { + if (isNormalModule(module)) { + const path = getModulePath(module); + if (Path.extname(path).length === 0) { + continue; + } - // TODO: Does this need to be updated to support @kbn/ packages? - if (!parsedPath.dirs.includes('node_modules')) { - addReferenced(path); + moduleCount += 1; + const parsedPath = parseFilePath(path); - if (path.endsWith('.scss')) { - workUnits += EXTRA_SCSS_WORK_UNITS; + if (!parsedPath.dirs.includes('node_modules')) { + await addReferenced(path); - for (const depPath of module.buildInfo.fileDependencies) { - addReferenced(depPath); + if (path.endsWith('.scss')) { + workUnits += EXTRA_SCSS_WORK_UNITS; + + const dependencies = moduleFileDepsMap.get(module.identifier()); + if (dependencies) { + await Promise.all( + dependencies.map((depPath: string) => addReferenced(depPath)) + ); + } } + + continue; } + const nmIndex = parsedPath.dirs.lastIndexOf('node_modules'); + const isScoped = parsedPath.dirs[nmIndex + 1].startsWith('@'); + const pkgJsonPath = Path.join( + parsedPath.root, + ...parsedPath.dirs.slice(0, nmIndex + 1 + (isScoped ? 2 : 1)), + 'package.json' + ); + await addReferenced(pkgJsonPath); continue; } - const nmIndex = parsedPath.dirs.lastIndexOf('node_modules'); - const isScoped = parsedPath.dirs[nmIndex + 1].startsWith('@'); - const pkgJsonPath = Path.join( - parsedPath.root, - ...parsedPath.dirs.slice(0, nmIndex + 1 + (isScoped ? 2 : 1)), - 'package.json' - ); - addReferenced(pkgJsonPath); - continue; - } + if (module instanceof BundleRemoteModule) { + bundleRefExportIds.push(module.req.full); + continue; + } - if (module instanceof BundleRemoteModule) { - bundleRefExportIds.push(module.req.full); - continue; - } + if (isConcatenatedModule(module)) { + moduleCount += 1; + continue; + } - if (isConcatenatedModule(module)) { - moduleCount += module.modules.length; - continue; - } + if (isDelegatedModule(module)) { + dllRefKeys.add(module.userRequest); + continue; + } - if (isDelegatedModule(module)) { - // delegated modules are the references to the ui-shared-deps-npm dll - dllRefKeys.add(module.userRequest); - continue; - } + if (isExternalModule(module) || isIgnoredModule(module) || isRuntimeModule(module)) { + continue; + } - if (isExternalModule(module) || isIgnoredModule(module)) { - continue; + throw new Error(`Unexpected module type: ${inspect(module)}`); } - throw new Error(`Unexpected module type: ${inspect(module)}`); - } + const referencedPaths = Array.from(paths).sort(ascending((p) => p)); + const sortedDllRefKeys = Array.from(dllRefKeys).sort(ascending((p) => p)); + + bundle.cache.set({ + remoteBundleImportReqs: bundleRefExportIds.sort(ascending((p) => p)), + optimizerCacheKey: workerConfig.optimizerCacheKey, + cacheKey: bundle.createCacheKey( + referencedPaths, + new Hashes(rawHashes), + this.dllManifest, + sortedDllRefKeys + ), + moduleCount, + workUnits, + referencedPaths, + dllRefKeys: sortedDllRefKeys, + }); - const referencedPaths = Array.from(paths).sort(ascending((p) => p)); - const sortedDllRefKeys = Array.from(dllRefKeys).sort(ascending((p) => p)); + // write the cache to the compilation so that it isn't cleaned by clean-webpack-plugin + bundle.cache.writeWebpackAsset(compilation); - bundle.cache.set({ - remoteBundleImportReqs: bundleRefExportIds.sort(ascending((p) => p)), - optimizerCacheKey: workerConfig.optimizerCacheKey, - cacheKey: bundle.createCacheKey( - referencedPaths, - new Hashes(rawHashes), - this.dllManifest, - sortedDllRefKeys - ), - moduleCount, - workUnits, - referencedPaths, - dllRefKeys: sortedDllRefKeys, - }); - - // write the cache to the compilation so that it isn't cleaned by clean-webpack-plugin - bundle.cache.writeWebpackAsset(compilation); - } - ); + callback(); + } + ); + }); } } diff --git a/packages/kbn-optimizer/src/worker/run_compilers.ts b/packages/kbn-optimizer/src/worker/run_compilers.ts index c9a689edf377e..1ef138e8776ea 100644 --- a/packages/kbn-optimizer/src/worker/run_compilers.ts +++ b/packages/kbn-optimizer/src/worker/run_compilers.ts @@ -53,7 +53,6 @@ const observeCompiler = ( */ const complete$ = Rx.fromEventPattern((cb) => done.tap(PLUGIN_NAME, cb)).pipe( maybeMap((stats) => { - // @ts-expect-error not included in types, but it is real https://github.com/webpack/webpack/blob/ab4fa8ddb3f433d286653cd6af7e3aad51168649/lib/Watching.js#L58 if (stats.compilation.needAdditionalPass) { return undefined; } diff --git a/packages/kbn-optimizer/src/worker/theme_loader.ts b/packages/kbn-optimizer/src/worker/theme_loader.ts index 3bce12d94e974..97b56426c010b 100644 --- a/packages/kbn-optimizer/src/worker/theme_loader.ts +++ b/packages/kbn-optimizer/src/worker/theme_loader.ts @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { stringifyRequest, getOptions } from 'loader-utils'; import webpack from 'webpack'; import { FALLBACK_THEME_TAG, @@ -15,11 +14,17 @@ import { hasNonDefaultThemeTags, } from '@kbn/core-ui-settings-common'; +const getStringifiedRequest = (loaderContext: webpack.LoaderContext, request: string) => { + return JSON.stringify( + loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request) + ); +}; + // eslint-disable-next-line import/no-default-export -export default function (this: webpack.loader.LoaderContext) { +export default function (this: webpack.LoaderContext) { this.cacheable(true); - const options = getOptions(this); + const options = this.getOptions(); const bundleId = options.bundleId as string; const themeTags = parseThemeTags(options.themeTags); const isFallbackNeeded = hasNonDefaultThemeTags(themeTags); @@ -38,7 +43,10 @@ export default function (this: webpack.loader.LoaderContext) { defaultClause = ` default: console.error(new Error("SASS files in [${bundleId}] were not built for theme [" + window.__kbnThemeTag__ + "]. Styles were compiled using the [${FALLBACK_THEME_TAG}] theme instead to keep Kibana somewhat usable. Please adjust the advanced settings to make use of [${themeTags}] or make sure the KBN_OPTIMIZER_THEMES environment variable includes [" + window.__kbnThemeTag__ + "] in a comma-separated list of themes you want to compile. You can also set it to \'*\' to build all themes.")); - return require(${stringifyRequest(this, `${this.resourcePath}?${FALLBACK_THEME_TAG}`)});`; + return require(${getStringifiedRequest( + this, + `${this.resourcePath}?${FALLBACK_THEME_TAG}` + )});`; } return ` @@ -47,7 +55,7 @@ ${themeTags .map( (tag) => ` case '${tag}': - return require(${stringifyRequest(this, `${this.resourcePath}?${tag}`)});` + return require(${getStringifiedRequest(this, `${this.resourcePath}?${tag}`)});` ) .join('\n')} ${defaultClause} diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 98549d7ec745a..65d755b0c01c9 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -10,22 +10,24 @@ import Path from 'path'; import Fs from 'fs'; -import { stringifyRequest } from 'loader-utils'; import webpack from 'webpack'; -// @ts-expect-error import TerserPlugin from 'terser-webpack-plugin'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import UiSharedDepsNpm from '@kbn/ui-shared-deps-npm'; import * as UiSharedDepsSrc from '@kbn/ui-shared-deps-src'; import StatoscopeWebpackPlugin from '@statoscope/webpack-plugin'; -// @ts-expect-error -import VisualizerPlugin from 'webpack-visualizer-plugin2'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; +import { + STATS_WARNINGS_FILTER, + STATS_OPTIONS_DEFAULT_USEFUL_FILTER, +} from '@kbn/optimizer-webpack-helpers'; +import { NodeLibsBrowserPlugin } from '@kbn/node-libs-browser-webpack-plugin'; import { Bundle, BundleRemotes, WorkerConfig, parseDllManifest } from '../common'; import { BundleRemotesPlugin } from './bundle_remotes_plugin'; import { BundleMetricsPlugin } from './bundle_metrics_plugin'; +import { BundleRemoteUsedExportsPlugin } from './bundle_remote_used_exports_plugin'; import { EmitStatsPlugin } from './emit_stats_plugin'; import { PopulateBundleCachePlugin } from './populate_bundle_cache_plugin'; @@ -40,31 +42,34 @@ export function getWebpackConfig( const ENTRY_CREATOR = require.resolve('./entry_point_creator'); const commonConfig: webpack.Configuration = { - node: { fs: 'empty' }, context: bundle.contextDir, - cache: true, entry: { [bundle.id]: ENTRY_CREATOR, }, - devtool: worker.dist ? false : '#cheap-source-map', + devtool: worker.dist ? false : 'cheap-source-map', profile: worker.profileWebpack, + target: 'web', + output: { - hashFunction: 'sha1', + hashFunction: 'xxhash64', path: bundle.outputDir, filename: `${bundle.id}.${bundle.type}.js`, chunkFilename: `${bundle.id}.chunk.[id].js`, - devtoolModuleFilenameTemplate: (info) => + devtoolModuleFilenameTemplate: (info: any) => `/${bundle.type}:${bundle.id}/${Path.relative( bundle.sourceRoot, info.absoluteResourcePath )}${info.query}`, - jsonpFunction: `${bundle.id}_bundle_jsonpfunction`, + chunkLoadingGlobal: `${bundle.id}_bundle_jsonpfunction`, + chunkLoading: 'jsonp', }, optimization: { - noEmitOnErrors: true, + moduleIds: worker.dist ? 'deterministic' : 'natural', + chunkIds: worker.dist ? 'deterministic' : 'natural', + emitOnErrors: false, splitChunks: { maxAsyncRequests: 10, cacheGroups: { @@ -75,9 +80,13 @@ export function getWebpackConfig( }, }, - externals: UiSharedDepsSrc.externals, + externals: { + 'node:crypto': 'commonjs crypto', + ...UiSharedDepsSrc.externals, + }, plugins: [ + new NodeLibsBrowserPlugin(), new CleanWebpackPlugin(), new BundleRemotesPlugin(bundle, bundleRemotes), new PopulateBundleCachePlugin(worker, bundle, parseDllManifest(DLL_MANIFEST)), @@ -86,24 +95,22 @@ export function getWebpackConfig( context: worker.repoRoot, manifest: DLL_MANIFEST, }), - // @ts-ignore something is wrong with the StatoscopeWebpackPlugin type. - ...(worker.profileWebpack + ...((worker.profileWebpack ? [ new EmitStatsPlugin(bundle), - new StatoscopeWebpackPlugin({ - open: false, - saveReportTo: `${bundle.outputDir}/${bundle.id}.statoscope.html`, - }), - new VisualizerPlugin({ filename: `${bundle.id}.visualizer.html` }), new BundleAnalyzerPlugin({ analyzerMode: 'static', reportFilename: `${bundle.id}.analyzer.html`, openAnalyzer: false, logLevel: 'silent', }), + new StatoscopeWebpackPlugin({ + open: false, + saveReportTo: `${bundle.outputDir}/${bundle.id}.statoscope.html`, + statsOptions: STATS_OPTIONS_DEFAULT_USEFUL_FILTER, + }), ] - : []), - // @ts-ignore something is wrong with the StatoscopeWebpackPlugin type. + : []) as any), ...(bundle.banner ? [new webpack.BannerPlugin({ banner: bundle.banner, raw: true })] : []), ], @@ -199,14 +206,17 @@ export function getWebpackConfig( { loader: 'sass-loader', options: { - additionalData(content: string, loaderContext: webpack.loader.LoaderContext) { - return `@import ${stringifyRequest( - loaderContext, - Path.resolve( - worker.repoRoot, - `src/core/public/styles/core_app/_globals_${theme}.scss` + additionalData(content: string, loaderContext: webpack.LoaderContext) { + const req = JSON.stringify( + loaderContext.utils.contextify( + loaderContext.context || loaderContext.rootContext, + Path.resolve( + worker.repoRoot, + `src/core/public/styles/core_app/_globals_${theme}.scss` + ) ) - )};\n${content}`; + ); + return `@import ${req};\n${content}`; }, implementation: require('sass-embedded'), sassOptions: { @@ -228,13 +238,6 @@ export function getWebpackConfig( }, ], }, - { - test: /\.(woff|woff2|ttf|eot|svg|ico|png|jpg|gif|jpeg)(\?|$)/, - loader: 'url-loader', - options: { - limit: 8192, - }, - }, { test: /\.(js|tsx?)$/, exclude: /node_modules/, @@ -243,67 +246,47 @@ export function getWebpackConfig( options: { babelrc: false, envName: worker.dist ? 'production' : 'development', - presets: [BABEL_PRESET], + presets: [[BABEL_PRESET, { useTransformRequireDefault: true }]], }, }, }, { - test: /node_modules\/@?xstate5\/.*\.js$/, - use: { - loader: 'babel-loader', - options: { - babelrc: false, - envName: worker.dist ? 'production' : 'development', - presets: [BABEL_PRESET], - plugins: ['@babel/plugin-transform-logical-assignment-operators'], - }, - }, - }, - { - test: /\.js$/, - include: /node_modules[\\\/]@dagrejs/, - use: { - loader: 'babel-loader', - options: { - envName: worker.dist ? 'production' : 'development', - presets: ['@babel/preset-env'], // Doesn't work with BABEL_PRESET - plugins: ['@babel/plugin-proposal-class-properties'], - }, - }, + test: /\.peggy$/, + loader: require.resolve('@kbn/peggy-loader'), }, + // emits a separate file and exports the URL. Previously achievable by using file-loader. { - test: /node_modules[\/\\]@?xyflow[\/\\].*.js$/, - loaders: 'babel-loader', - options: { - envName: worker.dist ? 'production' : 'development', - presets: [BABEL_PRESET], - plugins: ['@babel/plugin-transform-logical-assignment-operators'], - }, + include: [ + require.resolve('@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js'), + require.resolve('maplibre-gl/dist/maplibre-gl-csp-worker'), + ], + type: 'asset/resource', }, + // exports the source code of the asset. Previously achievable by using raw-loader. { - test: /node_modules[\/\\]launchdarkly[^\/\\]+[\/\\].*.js$/, - loaders: 'babel-loader', - options: { - envName: worker.dist ? 'production' : 'development', - presets: [BABEL_PRESET], - }, + resourceQuery: /raw/, + type: 'asset/source', }, { test: /\.(html|md|txt|tmpl)$/, - use: { - loader: 'raw-loader', - }, + type: 'asset/source', }, + // automatically chooses between exporting a data URI and emitting a separate file. Previously achievable by using url-loader with asset size limit. { - test: /\.peggy$/, - loader: require.resolve('@kbn/peggy-loader'), + test: /\.(woff|woff2|ttf|eot|svg|ico|png|jpg|gif|jpeg)(\?|$)/, + type: 'asset', + parser: { + dataUrlCondition: { + maxSize: 8192, + }, + }, }, ], }, resolve: { extensions: ['.js', '.ts', '.tsx', '.json'], - mainFields: ['browser', 'main'], + mainFields: ['browser', 'module', 'main'], alias: { core_app_image_assets: Path.resolve( worker.repoRoot, @@ -323,16 +306,43 @@ export function getWebpackConfig( // and not for the webpack compilations performance itself hints: false, }, + + ignoreWarnings: [STATS_WARNINGS_FILTER], }; const nonDistributableConfig: webpack.Configuration = { mode: 'development', + + cache: { + type: 'memory', + cacheUnaffected: true, + }, + + experiments: { + cacheUnaffected: true, + backCompat: false, + }, + + optimization: { + sideEffects: false, + removeAvailableModules: false, + }, + + module: { + // This was default on webpack v4 + unsafeCache: true, + }, }; const distributableConfig: webpack.Configuration = { mode: 'production', plugins: [ + // NOTE: this plugin is needed to mark exports on public and extraPublicDir entry files + // as used otherwise the new webpack v5 aggressive exports analysis will mark them as unused + // and they will be removed. Without this plugin we need to run with usedExports: false which + // affects the bundle sizes by a big margin. + new BundleRemoteUsedExportsPlugin(bundle), new webpack.DefinePlugin({ 'process.env': { IS_KIBANA_DISTRIBUTABLE: `"true"`, @@ -343,8 +353,6 @@ export function getWebpackConfig( optimization: { minimizer: [ new TerserPlugin({ - cache: false, - sourceMap: false, extractComments: false, parallel: false, terserOptions: { diff --git a/packages/kbn-optimizer/tsconfig.json b/packages/kbn-optimizer/tsconfig.json index d6e79f66a561a..9bf0aab74cb53 100644 --- a/packages/kbn-optimizer/tsconfig.json +++ b/packages/kbn-optimizer/tsconfig.json @@ -30,5 +30,6 @@ "@kbn/dev-cli-runner", "@kbn/jest-serializers", "@kbn/repo-packages", + "@kbn/node-libs-browser-webpack-plugin", ] } diff --git a/packages/kbn-peggy-loader/BUILD.bazel b/packages/kbn-peggy-loader/BUILD.bazel index 13afe2c2bc2de..96c064189d69e 100644 --- a/packages/kbn-peggy-loader/BUILD.bazel +++ b/packages/kbn-peggy-loader/BUILD.bazel @@ -2,6 +2,7 @@ load("@build_bazel_rules_nodejs//:index.bzl", "js_library") SRCS = glob( [ + "**/*.js", "**/*.ts", ], exclude = [ diff --git a/packages/kbn-peggy-loader/index.ts b/packages/kbn-peggy-loader/index.js similarity index 90% rename from packages/kbn-peggy-loader/index.ts rename to packages/kbn-peggy-loader/index.js index 4829ba6f0f778..a2a2a26014967 100644 --- a/packages/kbn-peggy-loader/index.ts +++ b/packages/kbn-peggy-loader/index.js @@ -8,10 +8,12 @@ */ import { getJsSource } from '@kbn/peggy'; -import webpack from 'webpack'; // eslint-disable-next-line import/no-default-export -export default function (this: webpack.loader.LoaderContext) { +/** + * @this {import('webpack').LoaderContext} + */ +export default function () { this.cacheable(true); const callback = this.async(); diff --git a/packages/kbn-peggy-loader/tsconfig.json b/packages/kbn-peggy-loader/tsconfig.json index 3e412325cfa91..34ee5a02ff506 100644 --- a/packages/kbn-peggy-loader/tsconfig.json +++ b/packages/kbn-peggy-loader/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { + "checkJs": true, "outDir": "target/types", "types": [ "jest", @@ -9,11 +10,12 @@ }, "include": [ "**/*.ts", - ], - "kbn_references": [ - "@kbn/peggy" + "**/*.js" ], "exclude": [ "target/**/*", + ], + "kbn_references": [ + "@kbn/peggy", ] } diff --git a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts index d391ec22d0226..5133297f95f64 100644 --- a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts @@ -40,9 +40,6 @@ it('builds a generated plugin into a viable archive', async () => { process.execPath, ['scripts/generate_plugin', '-y', '--name', 'fooTestPlugin'], { - env: { - NODE_OPTIONS: '--openssl-legacy-provider', - }, cwd: REPO_ROOT, all: true, } @@ -55,8 +52,7 @@ it('builds a generated plugin into a viable archive', async () => { }; expect(filterLogs(generateProc.all)).toMatchInlineSnapshot(` - "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/9.0/production.html#openssl-legacy-provider - succ 🎉 + " succ 🎉 Your plugin has been created in plugins/foo_test_plugin " @@ -66,17 +62,13 @@ it('builds a generated plugin into a viable archive', async () => { process.execPath, ['../../scripts/plugin_helpers', 'build', '--kibana-version', '7.5.0'], { - env: { - NODE_OPTIONS: '--openssl-legacy-provider', - }, cwd: PLUGIN_DIR, all: true, } ); expect(filterLogs(buildProc.all)).toMatchInlineSnapshot(` - "Kibana is currently running with legacy OpenSSL providers enabled! For details and instructions on how to disable see https://www.elastic.co/guide/en/kibana/9.0/production.html#openssl-legacy-provider - info deleting the build and target directories + " info deleting the build and target directories info run bazel and build required artifacts for the optimizer succ bazel run successfully and artifacts were created info running @kbn/optimizer @@ -106,8 +98,8 @@ it('builds a generated plugin into a viable archive', async () => { "kibana/fooTestPlugin/server/plugin.js", "kibana/fooTestPlugin/server/routes/index.js", "kibana/fooTestPlugin/server/types.js", - "kibana/fooTestPlugin/target/public/fooTestPlugin.chunk.1.js", - "kibana/fooTestPlugin/target/public/fooTestPlugin.chunk.1.js.br", + "kibana/fooTestPlugin/target/public/fooTestPlugin.chunk.998.js", + "kibana/fooTestPlugin/target/public/fooTestPlugin.chunk.998.js.br", "kibana/fooTestPlugin/target/public/fooTestPlugin.plugin.js", "kibana/fooTestPlugin/target/public/fooTestPlugin.plugin.js.br", "kibana/fooTestPlugin/translations/ja-JP.json", diff --git a/packages/kbn-plugin-helpers/src/tasks/optimize.ts b/packages/kbn-plugin-helpers/src/tasks/optimize.ts index 1ef238665879f..cdb622438be08 100644 --- a/packages/kbn-plugin-helpers/src/tasks/optimize.ts +++ b/packages/kbn-plugin-helpers/src/tasks/optimize.ts @@ -64,7 +64,7 @@ export async function optimize({ const proc = fork(require.resolve('./optimize_worker'), { cwd: REPO_ROOT, - execArgv: ['--require=@kbn/babel-register/install', '--openssl-legacy-provider'], + execArgv: ['--require=@kbn/babel-register/install'], stdio: ['ignore', 'pipe', 'pipe', 'ipc'], }); diff --git a/packages/kbn-plugin-helpers/src/tasks/optimize_worker.ts b/packages/kbn-plugin-helpers/src/tasks/optimize_worker.ts index 823da79c934c9..d05c10ee69eb1 100644 --- a/packages/kbn-plugin-helpers/src/tasks/optimize_worker.ts +++ b/packages/kbn-plugin-helpers/src/tasks/optimize_worker.ts @@ -42,7 +42,7 @@ process.on('message', (msg: any) => { return; } - if (stats.hasErrors()) { + if (stats?.hasErrors()) { send.call(process, { success: false, error: `Failed to compile with webpack:\n${stats.toString()}`, @@ -52,7 +52,7 @@ process.on('message', (msg: any) => { send.call(process, { success: true, - warnings: stats.hasWarnings() ? stats.toString() : '', + warnings: stats?.hasWarnings() ? stats.toString() : '', }); } ); diff --git a/packages/kbn-repo-source-classifier/README.mdx b/packages/kbn-repo-source-classifier/README.mdx index 2f197aa83a0c8..8e05d53808be4 100644 --- a/packages/kbn-repo-source-classifier/README.mdx +++ b/packages/kbn-repo-source-classifier/README.mdx @@ -13,7 +13,7 @@ This package exposes a class which can be used to efficiently classify all of th - `browser package`: plugin code in the root `public/` directory (and a few others in specific plugins), eventually this will include packages of type `browser-plugin` or `browser-shared` - `common packages`: includes any existing package, plugin code in root `common/` directories, (and a few others in specific plugins), Eventually this will include `common-shared` packages - `tests or mocks`: code that is loaded by jest/storybook, and mocks/helpers intended for use by that code. These files usually live along side package code but will have a separate dependency tree and are pieces of code which should never end up in the product. - - `static`: static files, currently any .json file or things loaded via `raw-loader` in browser code + - `static`: static files, currently any .json file or things loaded via `?raw` or `?asUrl` in browser code - `tooling`: scripts, config files for tools like eslint, webpack, etc. - `non-package`: code that lives outside of packages/plugins or doesn't fit into other more specific categories. Once the package project is complete this category should be limited to just `@kbn/pm` diff --git a/packages/kbn-scout/index.ts b/packages/kbn-scout/index.ts index 0b8fdad7e09c1..ed0d18bd17ef8 100644 --- a/packages/kbn-scout/index.ts +++ b/packages/kbn-scout/index.ts @@ -16,6 +16,7 @@ export { createPlaywrightConfig, createLazyPageObject, ingestTestDataHook, + ingestSynthtraceDataHook, } from './src/playwright'; export type { ScoutPlaywrightOptions, diff --git a/packages/kbn-scout/src/common/services/clients.ts b/packages/kbn-scout/src/common/services/clients.ts index eb241adac18cf..ed5efd8e77786 100644 --- a/packages/kbn-scout/src/common/services/clients.ts +++ b/packages/kbn-scout/src/common/services/clients.ts @@ -8,6 +8,7 @@ */ import { createEsClientForTesting, KbnClient } from '@kbn/test'; +import { ToolingLog } from '@kbn/tooling-log'; import { ScoutLogger } from './logger'; import { ScoutTestConfig, EsClient } from '../../types'; @@ -16,7 +17,7 @@ interface ClientOptions { url: string; username: string; password: string; - log: ScoutLogger; + log: ScoutLogger | ToolingLog; } function createClientUrlWithAuth({ serviceName, url, username, password, log }: ClientOptions) { @@ -24,14 +25,17 @@ function createClientUrlWithAuth({ serviceName, url, username, password, log }: clientUrl.username = username; clientUrl.password = password; - log.serviceLoaded(`${serviceName}Client`); + if (log instanceof ScoutLogger) { + log.serviceLoaded(`${serviceName}Client`); + } + return clientUrl.toString(); } let esClientInstance: EsClient | null = null; let kbnClientInstance: KbnClient | null = null; -export function getEsClient(config: ScoutTestConfig, log: ScoutLogger) { +export function getEsClient(config: ScoutTestConfig, log: ScoutLogger | ToolingLog) { if (!esClientInstance) { const { username, password } = config.auth; const elasticsearchUrl = createClientUrlWithAuth({ diff --git a/packages/kbn-scout/src/common/services/synthtrace.ts b/packages/kbn-scout/src/common/services/synthtrace.ts new file mode 100644 index 0000000000000..02510f77bc923 --- /dev/null +++ b/packages/kbn-scout/src/common/services/synthtrace.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { + ApmSynthtraceEsClient, + ApmSynthtraceKibanaClient, + InfraSynthtraceEsClient, + InfraSynthtraceKibanaClient, + LogLevel, + OtelSynthtraceEsClient, + createLogger, +} from '@kbn/apm-synthtrace'; +import { ScoutLogger } from './logger'; +import { EsClient } from '../../types'; + +let apmSynthtraceEsClientInstance: ApmSynthtraceEsClient | undefined; +let infraSynthtraceEsClientInstance: InfraSynthtraceEsClient | undefined; +let otelSynthtraceEsClientInstance: OtelSynthtraceEsClient | undefined; +const logger = createLogger(LogLevel.info); + +export async function getApmSynthtraceEsClient( + esClient: EsClient, + target: string, + log: ScoutLogger +) { + if (!apmSynthtraceEsClientInstance) { + const apmSynthtraceKibanaClient = new ApmSynthtraceKibanaClient({ + logger, + target, + }); + + const version = await apmSynthtraceKibanaClient.fetchLatestApmPackageVersion(); + await apmSynthtraceKibanaClient.installApmPackage(version); + apmSynthtraceEsClientInstance = new ApmSynthtraceEsClient({ + client: esClient, + logger, + refreshAfterIndex: true, + version, + }); + + apmSynthtraceEsClientInstance.pipeline( + apmSynthtraceEsClientInstance.getDefaultPipeline({ includeSerialization: false }) + ); + + log.serviceLoaded('apmSynthtraceClient'); + } + + return apmSynthtraceEsClientInstance; +} + +export async function getInfraSynthtraceEsClient( + esClient: EsClient, + kbnUrl: string, + auth: { username: string; password: string }, + log: ScoutLogger +) { + if (!infraSynthtraceEsClientInstance) { + const infraSynthtraceKibanaClient = new InfraSynthtraceKibanaClient({ + logger, + target: kbnUrl, + username: auth.username, + password: auth.password, + }); + + const version = await infraSynthtraceKibanaClient.fetchLatestSystemPackageVersion(); + await infraSynthtraceKibanaClient.installSystemPackage(version); + infraSynthtraceEsClientInstance = new InfraSynthtraceEsClient({ + client: esClient, + logger, + refreshAfterIndex: true, + }); + + infraSynthtraceEsClientInstance.pipeline( + infraSynthtraceEsClientInstance.getDefaultPipeline({ includeSerialization: false }) + ); + + log.serviceLoaded('infraSynthtraceClient'); + } + + return infraSynthtraceEsClientInstance; +} + +export function getOtelSynthtraceEsClient(esClient: EsClient, log: ScoutLogger) { + if (!otelSynthtraceEsClientInstance) { + otelSynthtraceEsClientInstance = new OtelSynthtraceEsClient({ + client: esClient, + logger, + refreshAfterIndex: true, + }); + + otelSynthtraceEsClientInstance.pipeline( + otelSynthtraceEsClientInstance.getDefaultPipeline({ includeSerialization: false }) + ); + + log.serviceLoaded('otelSynthtraceClient'); + } + + return otelSynthtraceEsClientInstance; +} diff --git a/packages/kbn-scout/src/playwright/fixtures/single_thread_fixtures.ts b/packages/kbn-scout/src/playwright/fixtures/single_thread_fixtures.ts index 931f6e6f4d7c5..fccf1fe5d9e4d 100644 --- a/packages/kbn-scout/src/playwright/fixtures/single_thread_fixtures.ts +++ b/packages/kbn-scout/src/playwright/fixtures/single_thread_fixtures.ts @@ -14,6 +14,7 @@ import { coreWorkerFixtures, esArchiverFixture, uiSettingsFixture, + synthtraceFixture, } from './worker'; import type { EsArchiverFixture, @@ -23,23 +24,23 @@ import type { ScoutLogger, ScoutTestConfig, UiSettingsFixture, + SynthtraceFixture, } from './worker'; import { scoutPageFixture, browserAuthFixture, pageObjectsFixture, validateTagsFixture, - BrowserAuthFixture, - ScoutPage, - PageObjects, } from './test'; -export type { PageObjects, ScoutPage } from './test'; +import type { BrowserAuthFixture, ScoutPage, PageObjects } from './test'; +export type { ScoutPage, PageObjects } from './test'; export const scoutFixtures = mergeTests( // worker scope fixtures coreWorkerFixtures, esArchiverFixture, uiSettingsFixture, + synthtraceFixture, // api fixtures apiFixtures, // test scope fixtures @@ -63,4 +64,7 @@ export interface ScoutWorkerFixtures extends ApiFixtures { esClient: EsClient; esArchiver: EsArchiverFixture; uiSettings: UiSettingsFixture; + apmSynthtraceEsClient: SynthtraceFixture['apmSynthtraceEsClient']; + infraSynthtraceEsClient: SynthtraceFixture['infraSynthtraceEsClient']; + otelSynthtraceEsClient: SynthtraceFixture['otelSynthtraceEsClient']; } diff --git a/packages/kbn-scout/src/playwright/fixtures/test/scout_page/single_thread.ts b/packages/kbn-scout/src/playwright/fixtures/test/scout_page/single_thread.ts index 12a50ee925815..0ff8af76a37dc 100644 --- a/packages/kbn-scout/src/playwright/fixtures/test/scout_page/single_thread.ts +++ b/packages/kbn-scout/src/playwright/fixtures/test/scout_page/single_thread.ts @@ -59,6 +59,8 @@ function extendPageWithTestSubject(page: Page): ScoutPage['testSubj'] { await page.locator(testSubjSelector).click(); for (const char of text) { await page.keyboard.insertText(char); + // it is important to delay characters input to avoid flakiness, default is 25 ms + // eslint-disable-next-line playwright/no-wait-for-timeout await page.waitForTimeout(delay); } }; diff --git a/packages/kbn-scout/src/playwright/fixtures/worker/index.ts b/packages/kbn-scout/src/playwright/fixtures/worker/index.ts index ab4a966ee9199..72b85770b7bbd 100644 --- a/packages/kbn-scout/src/playwright/fixtures/worker/index.ts +++ b/packages/kbn-scout/src/playwright/fixtures/worker/index.ts @@ -28,3 +28,6 @@ export type { ScoutSpaceParallelFixture } from './scout_space'; export { apiFixtures } from './apis'; export type { ApiFixtures, ApiParallelWorkerFixtures } from './apis'; + +export { synthtraceFixture } from './synthtrace'; +export type { SynthtraceFixture } from './synthtrace'; diff --git a/packages/kbn-scout/src/playwright/fixtures/worker/synthtrace.ts b/packages/kbn-scout/src/playwright/fixtures/worker/synthtrace.ts new file mode 100644 index 0000000000000..f82cd962fb7de --- /dev/null +++ b/packages/kbn-scout/src/playwright/fixtures/worker/synthtrace.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { Readable } from 'stream'; +import type { ApmFields, Fields, InfraDocument, OtelDocument } from '@kbn/apm-synthtrace-client'; +import Url from 'url'; +import type { SynthtraceEsClient } from '@kbn/apm-synthtrace/src/lib/shared/base_client'; +import { + getApmSynthtraceEsClient, + getInfraSynthtraceEsClient, + getOtelSynthtraceEsClient, +} from '../../../common/services/synthtrace'; +import { coreWorkerFixtures } from './core_fixtures'; +import type { SynthtraceEvents } from '../../global_hooks/synthtrace_ingestion'; + +interface SynthtraceFixtureEsClient { + index: (events: SynthtraceEvents) => Promise; + clean: SynthtraceEsClient['clean']; +} + +export interface SynthtraceFixture { + apmSynthtraceEsClient: SynthtraceFixtureEsClient; + infraSynthtraceEsClient: SynthtraceFixtureEsClient; + otelSynthtraceEsClient: SynthtraceFixtureEsClient; +} + +const useSynthtraceClient = async ( + client: SynthtraceEsClient, + use: (client: SynthtraceFixtureEsClient) => Promise +) => { + const index = async (events: SynthtraceEvents) => + await client.index(Readable.from(Array.from(events).flatMap((event) => event.serialize()))); + + const clean = async () => await client.clean(); + + await use({ index, clean }); + + // cleanup function after all tests have ran + await client.clean(); +}; + +export const synthtraceFixture = coreWorkerFixtures.extend<{}, SynthtraceFixture>({ + apmSynthtraceEsClient: [ + async ({ esClient, config, kbnUrl, log }, use) => { + const { username, password } = config.auth; + const kibanaUrl = new URL(kbnUrl.get()); + const kibanaUrlWithAuth = Url.format({ + protocol: kibanaUrl.protocol, + hostname: kibanaUrl.hostname, + port: kibanaUrl.port, + auth: `${username}:${password}`, + }); + + const apmSynthtraceEsClient = await getApmSynthtraceEsClient( + esClient, + kibanaUrlWithAuth, + log + ); + + await useSynthtraceClient(apmSynthtraceEsClient, use); + }, + { scope: 'worker' }, + ], + infraSynthtraceEsClient: [ + async ({ esClient, config, kbnUrl, log }, use) => { + const infraSynthtraceEsClient = await getInfraSynthtraceEsClient( + esClient, + kbnUrl.get(), + config.auth, + log + ); + + await useSynthtraceClient(infraSynthtraceEsClient, use); + }, + { scope: 'worker' }, + ], + otelSynthtraceEsClient: [ + async ({ esClient, log }, use) => { + const otelSynthtraceEsClient = await getOtelSynthtraceEsClient(esClient, log); + + await useSynthtraceClient(otelSynthtraceEsClient, use); + }, + { scope: 'worker' }, + ], +}); diff --git a/packages/kbn-scout/src/playwright/global_hooks/index.ts b/packages/kbn-scout/src/playwright/global_hooks/index.ts index 2e2bcf6e8004c..3c72ba5f7b6bf 100644 --- a/packages/kbn-scout/src/playwright/global_hooks/index.ts +++ b/packages/kbn-scout/src/playwright/global_hooks/index.ts @@ -8,3 +8,4 @@ */ export { ingestTestDataHook } from './data_ingestion'; +export { ingestSynthtraceDataHook } from './synthtrace_ingestion'; diff --git a/packages/kbn-scout/src/playwright/global_hooks/synthtrace_ingestion.ts b/packages/kbn-scout/src/playwright/global_hooks/synthtrace_ingestion.ts new file mode 100644 index 0000000000000..7af809f66801b --- /dev/null +++ b/packages/kbn-scout/src/playwright/global_hooks/synthtrace_ingestion.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { FullConfig } from 'playwright/test'; +import Url from 'url'; +import { Readable } from 'node:stream'; +import type { + ApmFields, + Fields, + InfraDocument, + OtelDocument, + Serializable, + SynthtraceGenerator, +} from '@kbn/apm-synthtrace-client'; +import { + getLogger, + createScoutConfig, + measurePerformanceAsync, + getEsClient, + ScoutLogger, + EsClient, +} from '../../common'; +import { ScoutTestOptions } from '../types'; +import { + getApmSynthtraceEsClient, + getInfraSynthtraceEsClient, + getOtelSynthtraceEsClient, +} from '../../common/services/synthtrace'; + +export type SynthtraceEvents = SynthtraceGenerator | Array>; + +interface SynthtraceIngestionData { + apm: Array>; + infra: Array>; + otel: Array>; +} + +const getSynthtraceClient = ( + key: keyof SynthtraceIngestionData, + esClient: EsClient, + kbnUrl: string, + auth: { username: string; password: string }, + log: ScoutLogger +) => { + switch (key) { + case 'apm': + const kibanaUrl = new URL(kbnUrl); + const kibanaUrlWithAuth = Url.format({ + protocol: kibanaUrl.protocol, + hostname: kibanaUrl.hostname, + port: kibanaUrl.port, + auth: `${auth.username}:${auth.password}`, + }); + return getApmSynthtraceEsClient(esClient, kibanaUrlWithAuth, log); + case 'infra': + return getInfraSynthtraceEsClient(esClient, kbnUrl, auth, log); + case 'otel': + return getOtelSynthtraceEsClient(esClient, log); + } +}; + +export async function ingestSynthtraceDataHook(config: FullConfig, data: SynthtraceIngestionData) { + const log = getLogger(); + + const { apm, infra, otel } = data; + const hasApmData = apm.length > 0; + const hasInfraData = infra.length > 0; + const hasOtelData = otel.length > 0; + const hasAnyData = hasApmData || hasInfraData || hasOtelData; + + if (!hasAnyData) { + log.debug('[setup] no synthtrace data to ingest'); + return; + } + + return measurePerformanceAsync(log, '[setup]: ingestSynthtraceDataHook', async () => { + // TODO: This should be configurable local vs cloud + + const configName = 'local'; + const projectUse = config.projects[0].use as ScoutTestOptions; + const serversConfigDir = projectUse.serversConfigDir; + const scoutConfig = createScoutConfig(serversConfigDir, configName, log); + const esClient = getEsClient(scoutConfig, log); + const kbnUrl = scoutConfig.hosts.kibana; + + for (const key of Object.keys(data)) { + const typedKey = key as keyof SynthtraceIngestionData; + if (data[typedKey].length > 0) { + const client = await getSynthtraceClient(typedKey, esClient, kbnUrl, scoutConfig.auth, log); + + log.debug(`[setup] ingesting ${key} synthtrace data`); + + try { + await Promise.all( + data[typedKey].map((event) => { + return client.index(Readable.from(Array.from(event).flatMap((e) => e.serialize()))); + }) + ); + } catch (e) { + log.debug(`[setup] error ingesting ${key} synthtrace data`, e); + } + + log.debug(`[setup] ${key} synthtrace data ingested successfully`); + } else { + log.debug(`[setup] no synthtrace data to ingest for ${key}`); + } + } + }); +} diff --git a/packages/kbn-scout/src/playwright/index.ts b/packages/kbn-scout/src/playwright/index.ts index b5c0f125b8165..0f6d62a176c35 100644 --- a/packages/kbn-scout/src/playwright/index.ts +++ b/packages/kbn-scout/src/playwright/index.ts @@ -32,4 +32,4 @@ export type { // use to tag tests export { tags } from './tags'; -export { ingestTestDataHook } from './global_hooks'; +export { ingestTestDataHook, ingestSynthtraceDataHook } from './global_hooks'; diff --git a/packages/kbn-scout/src/playwright/page_objects/maps_page.ts b/packages/kbn-scout/src/playwright/page_objects/maps_page.ts index bff713088b45c..94eb713368f8c 100644 --- a/packages/kbn-scout/src/playwright/page_objects/maps_page.ts +++ b/packages/kbn-scout/src/playwright/page_objects/maps_page.ts @@ -9,10 +9,21 @@ import { ScoutPage } from '..'; +const DEFAULT_MAP_LOADING_TIMEOUT = 10_000; + export class MapsPage { constructor(private readonly page: ScoutPage) {} async gotoNewMap() { - await this.page.gotoApp('maps/map'); + return this.page.gotoApp('maps/map'); + } + + async waitForRenderComplete() { + // first wait for the top level container to be present + await this.page.locator('div#maps-plugin').waitFor({ timeout: DEFAULT_MAP_LOADING_TIMEOUT }); + // then wait for the map to be fully rendered + return this.page + .locator('div[data-dom-id][data-render-complete="true"]') + .waitFor({ timeout: DEFAULT_MAP_LOADING_TIMEOUT }); } } diff --git a/packages/kbn-scout/src/servers/start_servers.ts b/packages/kbn-scout/src/servers/start_servers.ts index 32eb2030c978d..876f60f18f02e 100644 --- a/packages/kbn-scout/src/servers/start_servers.ts +++ b/packages/kbn-scout/src/servers/start_servers.ts @@ -16,7 +16,7 @@ import { runElasticsearch } from './run_elasticsearch'; import { getExtraKbnOpts, runKibanaServer } from './run_kibana_server'; import { StartServerOptions } from './flags'; import { loadServersConfig } from '../config'; -import { silence } from '../common'; +import { getEsClient, silence } from '../common'; export async function startServers(log: ToolingLog, options: StartServerOptions) { const runStartTime = Date.now(); @@ -32,6 +32,14 @@ export async function startServers(log: ToolingLog, options: StartServerOptions) logsDir: options.logsDir, }); + log.info('Enable authc debug logs for ES'); + const client = getEsClient(config.getScoutTestConfig(), log); + await client.cluster.putSettings({ + persistent: { + 'logger.org.elasticsearch.xpack.security.authc': 'debug', + }, + }); + await runKibanaServer({ procs, config, diff --git a/packages/kbn-scout/tsconfig.json b/packages/kbn-scout/tsconfig.json index 4be0277f18930..fcb8f35423070 100644 --- a/packages/kbn-scout/tsconfig.json +++ b/packages/kbn-scout/tsconfig.json @@ -28,5 +28,7 @@ "@kbn/test-subj-selector", "@kbn/scout-info", "@kbn/scout-reporting", + "@kbn/apm-synthtrace", + "@kbn/apm-synthtrace-client", ] } diff --git a/packages/kbn-storybook/src/ignore_not_found_export_plugin.ts b/packages/kbn-storybook/src/ignore_not_found_export_plugin.ts index bbb9177c68023..6ef9ace877702 100644 --- a/packages/kbn-storybook/src/ignore_not_found_export_plugin.ts +++ b/packages/kbn-storybook/src/ignore_not_found_export_plugin.ts @@ -12,26 +12,17 @@ // This plugin suppresses the irritating TS-related warnings in Storybook HMR. import { Compiler, Stats } from 'webpack'; -// @ts-expect-error -import ModuleDependencyWarning from 'webpack/lib/ModuleDependencyWarning'; export class IgnoreNotFoundExportPlugin { apply(compiler: Compiler) { const messageRegExp = /export '.*'( \(reexported as '.*'\))? was not found in/; + const doneHook = (stats: Stats) => + (stats.compilation.warnings = stats.compilation.warnings.filter( + (warn: any) => + // Unfortunately webpack is not exporting ModuleDependencyWarning type, so I'm using constructor.name instead + warn.constructor.name === 'ModuleDependencyWarning' && !messageRegExp.test(warn.message) + )); - function doneHook(stats: Stats) { - stats.compilation.warnings = stats.compilation.warnings.filter(function (warn) { - if (warn instanceof ModuleDependencyWarning && messageRegExp.test(warn.message)) { - return false; - } - return true; - }); - } - - if (compiler.hooks) { - compiler.hooks.done.tap('IgnoreNotFoundExportPlugin', doneHook); - } else { - compiler.plugin('done', doneHook); - } + compiler.hooks.done.tap('IgnoreNotFoundExportPlugin', doneHook); } } diff --git a/packages/kbn-storybook/src/lib/default_config.ts b/packages/kbn-storybook/src/lib/default_config.ts index 1a2fc7924b6d9..1c6ff42264a00 100644 --- a/packages/kbn-storybook/src/lib/default_config.ts +++ b/packages/kbn-storybook/src/lib/default_config.ts @@ -11,7 +11,7 @@ import * as path from 'path'; import fs from 'fs'; import type { StorybookConfig } from '@storybook/core-common'; import webpack, { Configuration } from 'webpack'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { REPO_ROOT } from './constants'; import { default as WebpackConfig } from '../webpack.config'; @@ -24,11 +24,18 @@ const toPath = (_path: string) => path.join(REPO_ROOT, _path); // This ignore pattern excludes all of node_modules EXCEPT for `@kbn`. This allows for // changes to packages to cause a refresh in Storybook. -const IGNORE_PATTERN = - /[/\\]node_modules[/\\](?!@kbn[/\\][^/\\]+[/\\](?!node_modules)([^/\\]+))([^/\\]+[/\\][^/\\]+)/; +const IGNORE_GLOBS = [ + '**/node_modules/**', + '!**/node_modules/@kbn/**', + '!**/node_modules/@kbn/*/**', + '!**/node_modules/@kbn/*/!(node_modules)/**', +]; export const defaultConfig: StorybookConfig = { addons: ['@kbn/storybook/preset', '@storybook/addon-a11y', '@storybook/addon-essentials'], + core: { + builder: 'webpack5', + }, stories: ['../**/*.stories.tsx', '../**/*.stories.mdx'], typescript: { reactDocgen: false, @@ -99,11 +106,17 @@ export const defaultConfig: StorybookConfig = { }) ); - config.node = { fs: 'empty' }; + config.resolve = { + ...config.resolve, + fallback: { + ...config?.resolve?.fallback, + fs: false, + }, + }; config.watch = true; config.watchOptions = { ...config.watchOptions, - ignored: [IGNORE_PATTERN], + ignored: IGNORE_GLOBS, }; // Remove when @storybook has moved to @emotion v11 diff --git a/packages/kbn-storybook/src/webpack.config.ts b/packages/kbn-storybook/src/webpack.config.ts index f2c17e2313d99..c085c4237183c 100644 --- a/packages/kbn-storybook/src/webpack.config.ts +++ b/packages/kbn-storybook/src/webpack.config.ts @@ -7,25 +7,18 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +/* eslint-disable import/no-default-export */ import { externals } from '@kbn/ui-shared-deps-src'; -import { stringifyRequest } from 'loader-utils'; import { resolve } from 'path'; -import webpack, { Configuration, Stats } from 'webpack'; -import webpackMerge from 'webpack-merge'; +import webpack, { Configuration } from 'webpack'; +import { merge as webpackMerge } from 'webpack-merge'; +import { NodeLibsBrowserPlugin } from '@kbn/node-libs-browser-webpack-plugin'; import { REPO_ROOT } from './lib/constants'; import { IgnoreNotFoundExportPlugin } from './ignore_not_found_export_plugin'; import 'webpack-dev-server'; // Extends webpack configuration with `devServer` property type Preset = string | [string, Record] | Record; -const stats = { - ...Stats.presetToOptions('minimal'), - colors: true, - errorDetails: true, - errors: true, - moduleTrace: true, -}; - function isProgressPlugin(plugin: any) { return 'handler' in plugin && plugin.showActiveModules && plugin.showModules; } @@ -35,7 +28,10 @@ function isHtmlPlugin(plugin: any): plugin is { options: { template: string } } } interface BabelLoaderRule extends webpack.RuleSetRule { - use: webpack.RuleSetLoader[]; + use: Array<{ + loader: 'babel-loader'; + [key: string]: unknown; + }>; } function isBabelLoaderRule(rule: webpack.RuleSetRule): rule is BabelLoaderRule { @@ -44,7 +40,7 @@ function isBabelLoaderRule(rule: webpack.RuleSetRule): rule is BabelLoaderRule { Array.isArray(rule.use) && rule.use.some( (l) => - typeof l === 'object' && typeof l.loader === 'string' && l.loader.includes('babel-loader') + typeof l === 'object' && typeof l?.loader === 'string' && l?.loader.includes('babel-loader') ) ); } @@ -69,12 +65,14 @@ function isDesiredPreset(preset: Preset) { } // Extend the Storybook Webpack config with some customizations -/* eslint-disable import/no-default-export */ +/** + * @returns {import('webpack').Configuration} + */ export default ({ config: storybookConfig }: { config: Configuration }) => { const config: Configuration = { devServer: { devMiddleware: { - stats, + stats: 'errors-only', }, }, externals, @@ -91,9 +89,7 @@ export default ({ config: storybookConfig }: { config: Configuration }) => { }, { test: /\.(html|md|txt|tmpl)$/, - use: { - loader: 'raw-loader', - }, + type: 'asset/source', }, { test: /\.peggy$/, @@ -119,10 +115,13 @@ export default ({ config: storybookConfig }: { config: Configuration }) => { loader: 'sass-loader', options: { additionalData(content: string, loaderContext: any) { - return `@import ${stringifyRequest( - loaderContext, - resolve(REPO_ROOT, 'src/core/public/styles/core_app/_globals_v8light.scss') - )};\n${content}`; + const req = JSON.stringify( + loaderContext.utils.contextify( + loaderContext.context || loaderContext.rootContext, + resolve(REPO_ROOT, 'src/core/public/styles/core_app/_globals_v8light.scss') + ) + ); + return `@import ${req};\n${content}`; }, implementation: require('sass-embedded'), sassOptions: { @@ -133,39 +132,9 @@ export default ({ config: storybookConfig }: { config: Configuration }) => { }, ], }, - { - test: /node_modules\/@?xstate5\/.*\.js$/, - use: { - loader: 'babel-loader', - options: { - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/webpack_preset')], - plugins: ['@babel/plugin-transform-logical-assignment-operators'], - }, - }, - }, - { - test: /\.js$/, - include: /node_modules[\\\/]@dagrejs/, - use: { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env'], // Doesn't work with @kbn/babel-preset/webpack_preset - plugins: ['@babel/plugin-proposal-class-properties'], - }, - }, - }, - { - test: /node_modules[\/\\]@?xyflow[\/\\].*.js$/, - loaders: 'babel-loader', - options: { - presets: [require.resolve('@kbn/babel-preset/webpack_preset')], - plugins: ['@babel/plugin-transform-logical-assignment-operators'], - }, - }, ], }, - plugins: [new IgnoreNotFoundExportPlugin()], + plugins: [new NodeLibsBrowserPlugin(), new IgnoreNotFoundExportPlugin()], resolve: { extensions: ['.js', '.mjs', '.ts', '.tsx', '.json', '.mdx'], mainFields: ['browser', 'main'], @@ -175,16 +144,16 @@ export default ({ config: storybookConfig }: { config: Configuration }) => { vega: resolve(REPO_ROOT, 'node_modules/vega/build-es5/vega.js'), }, }, - stats, + stats: 'errors-only', }; // Override storybookConfig mainFields instead of merging with config delete storybookConfig.resolve?.mainFields; - const updatedModuleRules = []; + const updatedModuleRules: webpack.RuleSetRule[] = []; // clone and modify the module.rules config provided by storybook so that the default babel plugins run after the typescript preset for (const originalRule of storybookConfig.module?.rules ?? []) { - const rule = { ...originalRule }; + const rule = typeof originalRule !== 'string' ? { ...originalRule } : {}; updatedModuleRules.push(rule); if (isBabelLoaderRule(rule)) { @@ -237,7 +206,7 @@ export default ({ config: storybookConfig }: { config: Configuration }) => { filteredStorybookPlugins.push(plugin); } - return webpackMerge( + return webpackMerge( { ...storybookConfig, plugins: filteredStorybookPlugins, diff --git a/packages/kbn-storybook/tsconfig.json b/packages/kbn-storybook/tsconfig.json index ab513c1d02c0c..8f120043dc5d7 100644 --- a/packages/kbn-storybook/tsconfig.json +++ b/packages/kbn-storybook/tsconfig.json @@ -22,6 +22,7 @@ "@kbn/core-i18n-browser", "@kbn/react-kibana-context-root", "@kbn/core-analytics-browser", + "@kbn/node-libs-browser-webpack-plugin", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-test/src/jest/resolver.js b/packages/kbn-test/src/jest/resolver.js index 8698e72a2e917..24a6b0f4d245a 100644 --- a/packages/kbn-test/src/jest/resolver.js +++ b/packages/kbn-test/src/jest/resolver.js @@ -32,6 +32,18 @@ const STATIC_FILE_EXT = const IS_REACT_18 = process.env.REACT_18 === 'true'; +/** + * @param {string} str + * @returns + */ +function parseRequestOrExtSuffix(str) { + const rawSuffix = '?raw'; + if (str.endsWith(rawSuffix)) { + return str.slice(0, -rawSuffix.length); + } + return str; +} + /** * @param {string} request * @param {import('resolve').SyncOpts} options @@ -85,25 +97,27 @@ module.exports = (request, options) => { const reqExt = Path.extname(request); if (reqExt) { - const reqBasename = Path.basename(request, reqExt); - if ((reqExt === '.css' || reqExt === '.scss') && reqBasename.endsWith('.module')) { + const pRequest = parseRequestOrExtSuffix(request); + const pReqExt = parseRequestOrExtSuffix(reqExt); + const reqBasename = Path.basename(pRequest, pReqExt); + if ((pReqExt === '.css' || pReqExt === '.scss') && reqBasename.endsWith('.module')) { return CSS_MODULE_MOCK; } - if (reqExt === '.css' || reqExt === '.less' || reqExt === '.scss') { + if (pReqExt === '.css' || pReqExt === '.less' || pReqExt === '.scss') { return STYLE_MOCK; } - if (STATIC_FILE_EXT.includes(reqExt)) { + if (STATIC_FILE_EXT.includes(pReqExt)) { return FILE_MOCK; } - if (reqExt === '.worker' && reqBasename.endsWith('.editor')) { + if (pReqExt === '.worker' && reqBasename.endsWith('.editor')) { return WORKER_MOCK; } } - if (request.startsWith('file-loader!') || request.startsWith('!!file-loader!')) { + if (request.endsWith('?asUrl')) { return FILE_MOCK; } diff --git a/renovate.json b/renovate.json index 7e96fed5facaa..7f7b15d764d82 100644 --- a/renovate.json +++ b/renovate.json @@ -40,6 +40,15 @@ ], "enabled": false }, + { + "groupName": "webpack", + "matchDepNames": ["webpack", "@types/webpack", "webpack-cli", "webpack-dev-server", "webpack-merge"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "backport:all-open", "release_note:skip", "ci:build-webpack-bundle-analyzer"], + "minimumReleaseAge": "60 days", + "enabled": true + }, { "groupName": "devcontainer", "reviewers": [ @@ -1420,6 +1429,7 @@ "eslint-plugin-mocha", "eslint-plugin-no-unsanitized", "eslint-plugin-node", + "eslint-plugin-playwright", "eslint-plugin-react", "eslint-plugin-react-hooks", "eslint-plugin-react-perf", @@ -4322,6 +4332,25 @@ "Feature:Console" ], "enabled": true + }, + { + "groupName": "node-libs-browser", + "matchDepNames": [ + "node-libs-browser" + ], + "reviewers": [ + "team:kibana-operations" + ], + "matchBaseBranches": [ + "main" + ], + "labels": [ + "Team:Operations", + "backport:prev-minor", + "release_note:skip" + ], + "minimumReleaseAge": "7 days", + "enabled": true } ], "customManagers": [ diff --git a/src/core/packages/integrations/browser-internal/src/styles/styles_service.test.ts b/src/core/packages/integrations/browser-internal/src/styles/styles_service.test.ts index e3e49bfe8e7aa..0a7d6d9898d61 100644 --- a/src/core/packages/integrations/browser-internal/src/styles/styles_service.test.ts +++ b/src/core/packages/integrations/browser-internal/src/styles/styles_service.test.ts @@ -9,7 +9,7 @@ import { BehaviorSubject } from 'rxjs'; -jest.mock('!!raw-loader!./disable_animations.css', () => 'MOCK DISABLE ANIMATIONS CSS'); +jest.mock('./disable_animations.css?raw', () => 'MOCK DISABLE ANIMATIONS CSS'); import { StylesService } from './styles_service'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; diff --git a/src/core/packages/integrations/browser-internal/src/styles/styles_service.ts b/src/core/packages/integrations/browser-internal/src/styles/styles_service.ts index 71132085ec1fa..7b04e0dd72191 100644 --- a/src/core/packages/integrations/browser-internal/src/styles/styles_service.ts +++ b/src/core/packages/integrations/browser-internal/src/styles/styles_service.ts @@ -12,7 +12,7 @@ import { Subscription } from 'rxjs'; import type { CoreService } from '@kbn/core-base-browser-internal'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; // @ts-expect-error -import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; +import disableAnimationsCss from './disable_animations.css?raw'; interface StartDeps { uiSettings: IUiSettingsClient; diff --git a/src/core/packages/rendering/server-internal/src/__snapshots__/rendering_service.test.ts.snap b/src/core/packages/rendering/server-internal/src/__snapshots__/rendering_service.test.ts.snap index 8b1dc7ef53e15..79740bdef49bd 100644 --- a/src/core/packages/rendering/server-internal/src/__snapshots__/rendering_service.test.ts.snap +++ b/src/core/packages/rendering/server-internal/src/__snapshots__/rendering_service.test.ts.snap @@ -68,7 +68,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -150,7 +150,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -236,7 +236,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -318,7 +318,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -400,7 +400,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -486,7 +486,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -568,7 +568,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -650,7 +650,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -732,7 +732,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -823,7 +823,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -905,7 +905,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -996,7 +996,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1083,7 +1083,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1165,7 +1165,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1256,7 +1256,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1343,7 +1343,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1430,7 +1430,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", @@ -1519,7 +1519,7 @@ Object { "serverBasePath": "/mock-server-basepath", "theme": Object { "darkMode": "theme:darkMode", - "name": "theme:name", + "name": "borealis", "stylesheetPaths": Object { "dark": Array [ "/style-1.css", diff --git a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts index 8576d075c1fbc..c6e90dfe0d72f 100644 --- a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts +++ b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.test.ts @@ -14,6 +14,7 @@ import { getJsDependencyPathsMock, } from './bootstrap_renderer.test.mocks'; +import { BehaviorSubject } from 'rxjs'; import { PackageInfo } from '@kbn/config'; import { AuthStatus } from '@kbn/core-http-server'; import type { UiPlugins } from '@kbn/core-plugins-base-server-internal'; @@ -21,6 +22,7 @@ import { httpServiceMock, httpServerMock } from '@kbn/core-http-server-mocks'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-server-mocks'; import { bootstrapRendererFactory, BootstrapRenderer } from './bootstrap_renderer'; import { userSettingsServiceMock } from '@kbn/core-user-settings-server-mocks'; +import { DEFAULT_THEME_NAME, ThemeName } from '@kbn/core-ui-settings-common'; const createPackageInfo = (parts: Partial = {}): PackageInfo => ({ branch: 'master', @@ -37,12 +39,10 @@ const createPackageInfo = (parts: Partial = {}): PackageInfo => ({ const getClientGetMockImplementation = ({ darkMode, name }: { darkMode?: boolean | string; name?: string } = {}) => (key: string) => { - switch (key) { - case 'theme:darkMode': - return Promise.resolve(darkMode ?? false); - case 'theme:name': - return Promise.resolve(name ?? 'borealis'); + if (key === 'theme:darkMode') { + return Promise.resolve(darkMode ?? false); } + return Promise.resolve(); }; @@ -59,6 +59,7 @@ describe('bootstrapRenderer', () => { let uiPlugins: UiPlugins; let packageInfo: PackageInfo; let userSettingsService: ReturnType; + const themeName$ = new BehaviorSubject(DEFAULT_THEME_NAME); beforeEach(() => { auth = httpServiceMock.createAuth(); @@ -78,6 +79,7 @@ describe('bootstrapRenderer', () => { packageInfo, uiPlugins, baseHref: `/base-path/${packageInfo.buildShaShort}`, // the base href as provided by static assets module + themeName$, }); }); @@ -104,9 +106,8 @@ describe('bootstrapRenderer', () => { uiSettingsClient, }); - expect(uiSettingsClient.get).toHaveBeenCalledTimes(2); + expect(uiSettingsClient.get).toHaveBeenCalledTimes(1); expect(uiSettingsClient.get).toHaveBeenCalledWith('theme:darkMode'); - expect(uiSettingsClient.get).toHaveBeenCalledWith('theme:name'); }); it('calls getThemeTag with the values from the UiSettingsClient (true/dark) when the UserSettingsService is not provided', async () => { @@ -155,6 +156,7 @@ describe('bootstrapRenderer', () => { uiPlugins, baseHref: '/base-path', userSettingsService, + themeName$, }); uiSettingsClient.get.mockResolvedValue(false); @@ -181,6 +183,7 @@ describe('bootstrapRenderer', () => { uiPlugins, baseHref: '/base-path', userSettingsService, + themeName$, }); const request = httpServerMock.createKibanaRequest(); @@ -206,6 +209,7 @@ describe('bootstrapRenderer', () => { uiPlugins, baseHref: '/base-path', userSettingsService, + themeName$, }); const request = httpServerMock.createKibanaRequest(); @@ -231,6 +235,7 @@ describe('bootstrapRenderer', () => { uiPlugins, baseHref: '/base-path', userSettingsService, + themeName$, }); uiSettingsClient.get.mockImplementation( @@ -269,9 +274,8 @@ describe('bootstrapRenderer', () => { uiSettingsClient, }); - expect(uiSettingsClient.get).toHaveBeenCalledTimes(2); + expect(uiSettingsClient.get).toHaveBeenCalledTimes(1); expect(uiSettingsClient.get).toHaveBeenCalledWith('theme:darkMode'); - expect(uiSettingsClient.get).toHaveBeenCalledWith('theme:name'); }); it('calls getThemeTag with the correct parameters', async () => { @@ -350,31 +354,40 @@ describe('bootstrapRenderer', () => { darkMode: false, }); }); + }); - it('calls getThemeTag with `v8` theme name when buildFlavor is `serverless`', async () => { - renderer = bootstrapRendererFactory({ - auth, - packageInfo: { - ...packageInfo, - buildFlavor: 'serverless', - }, - uiPlugins, - baseHref: `/base-path/${packageInfo.buildShaShort}`, // the base href as provided by static assets module - }); + it('calls getThemeTag with the correct theme name', async () => { + uiSettingsClient.get.mockImplementation( + getClientGetMockImplementation({ + darkMode: true, + }) + ); + const request = httpServerMock.createKibanaRequest(); - const request = httpServerMock.createKibanaRequest(); + await renderer({ + request, + uiSettingsClient, + }); - await renderer({ - request, - uiSettingsClient, - }); + expect(getThemeTagMock).toHaveBeenCalledTimes(1); + expect(getThemeTagMock).toHaveBeenCalledWith( + expect.objectContaining({ + name: themeName$.getValue(), + }) + ); - expect(getThemeTagMock).toHaveBeenCalledTimes(1); - expect(getThemeTagMock).toHaveBeenCalledWith({ - name: 'borealis', - darkMode: false, - }); + themeName$.next('amsterdam'); + await renderer({ + request, + uiSettingsClient, }); + + expect(getThemeTagMock).toHaveBeenLastCalledWith( + expect.objectContaining({ + // 'amsterdam' is mapped to 'v8' for backwards compatibility + name: 'v8', + }) + ); }); [false, true].forEach((isAnonymousPage) => { diff --git a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts index 5b1cfc7c0c368..d55c591c60a17 100644 --- a/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts +++ b/src/core/packages/rendering/server-internal/src/bootstrap/bootstrap_renderer.ts @@ -8,14 +8,13 @@ */ import { createHash } from 'crypto'; +import { BehaviorSubject } from 'rxjs'; import { PackageInfo } from '@kbn/config'; import type { KibanaRequest, HttpAuth } from '@kbn/core-http-server'; import { type DarkModeValue, type ThemeName, - DEFAULT_THEME_NAME, parseDarkModeValue, - parseThemeNameValue, } from '@kbn/core-ui-settings-common'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-server'; import type { UiPlugins } from '@kbn/core-plugins-base-server-internal'; @@ -36,6 +35,7 @@ interface FactoryOptions { uiPlugins: UiPlugins; auth: HttpAuth; userSettingsService?: InternalUserSettingsServiceSetup; + themeName$: BehaviorSubject; } interface RenderedOptions { @@ -55,6 +55,7 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ uiPlugins, auth, userSettingsService, + themeName$, }) => { const isAuthenticated = (request: KibanaRequest) => { const { status: authStatus } = auth.get(request); @@ -64,11 +65,9 @@ export const bootstrapRendererFactory: BootstrapRendererFactory = ({ return async function bootstrapRenderer({ uiSettingsClient, request, isAnonymousPage = false }) { let darkMode: DarkModeValue = false; - let themeName: ThemeName = DEFAULT_THEME_NAME; + const themeName = themeName$.getValue(); try { - themeName = parseThemeNameValue(await uiSettingsClient.get('theme:name')); - const authenticated = isAuthenticated(request); if (authenticated) { diff --git a/src/core/packages/rendering/server-internal/src/rendering_service.test.ts b/src/core/packages/rendering/server-internal/src/rendering_service.test.ts index 7f7f2f504411d..8beba0eceab8d 100644 --- a/src/core/packages/rendering/server-internal/src/rendering_service.test.ts +++ b/src/core/packages/rendering/server-internal/src/rendering_service.test.ts @@ -27,10 +27,13 @@ import { mockRenderingServiceParams, mockRenderingPrebootDeps, mockRenderingSetupDeps, + mockRenderingStartDeps, } from './test_helpers/params'; import { InternalRenderingServicePreboot, InternalRenderingServiceSetup } from './types'; -import { RenderingService } from './rendering_service'; +import { RenderingService, DEFAULT_THEME_NAME_FEATURE_FLAG } from './rendering_service'; import { AuthStatus } from '@kbn/core-http-server'; +import { DEFAULT_THEME_NAME, ThemeName } from '@kbn/core-ui-settings-common'; +import { BehaviorSubject } from 'rxjs'; const BUILD_DATE = '2023-05-15T23:12:09+0000'; const INJECTED_METADATA = { @@ -584,4 +587,40 @@ describe('RenderingService', () => { return [(await service.setup(mockRenderingSetupDeps)).render, mockRenderingSetupDeps]; }); }); + + describe('start()', () => { + it('subscribes to the featureFlags.setStringValue$ observable and updates theme name accordingly', async () => { + // setup and render added to assert the current theme name + const { render } = await service.setup(mockRenderingSetupDeps); + const themeName$ = new BehaviorSubject(DEFAULT_THEME_NAME); + const getStringValue$ = jest + .fn() + .mockImplementation((_, fallback) => themeName$.asObservable()); + service.start({ + ...mockRenderingStartDeps, + featureFlags: { + ...mockRenderingStartDeps.featureFlags, + getStringValue$, + }, + }); + + expect(getStringValue$).toHaveBeenCalledTimes(1); + expect(getStringValue$).toHaveBeenCalledWith( + DEFAULT_THEME_NAME_FEATURE_FLAG, + DEFAULT_THEME_NAME + ); + + const uiSettings = { + client: uiSettingsServiceMock.createClient(), + globalClient: uiSettingsServiceMock.createClient(), + }; + + let renderResult = await render(createKibanaRequest(), uiSettings); + expect(renderResult).toContain(',"name":"borealis"'); + + themeName$.next('amsterdam'); + renderResult = await render(createKibanaRequest(), uiSettings); + expect(renderResult).toContain(',"name":"amsterdam"'); + }); + }); }); diff --git a/src/core/packages/rendering/server-internal/src/rendering_service.tsx b/src/core/packages/rendering/server-internal/src/rendering_service.tsx index 7ed024e88c211..44e17403bfbaa 100644 --- a/src/core/packages/rendering/server-internal/src/rendering_service.tsx +++ b/src/core/packages/rendering/server-internal/src/rendering_service.tsx @@ -9,8 +9,7 @@ import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; -import { firstValueFrom, of } from 'rxjs'; -import { catchError, take, timeout } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, of, map, catchError, take, timeout } from 'rxjs'; import { i18n as i18nLib } from '@kbn/i18n'; import type { ThemeVersion } from '@kbn/ui-shared-deps-npm'; @@ -26,6 +25,7 @@ import { parseThemeNameValue, type UiSettingsParams, type UserProvidedValues, + DEFAULT_THEME_NAME, } from '@kbn/core-ui-settings-common'; import { Template } from './views'; import { @@ -35,6 +35,7 @@ import { InternalRenderingServicePreboot, InternalRenderingServiceSetup, RenderingMetadata, + RenderingStartDeps, } from './types'; import { registerBootstrapRoute, bootstrapRendererFactory } from './bootstrap'; import { @@ -60,8 +61,14 @@ type RenderOptions = const themeVersion: ThemeVersion = 'v8'; +// TODO: Remove the temporary feature flag and supporting code when Borealis is live in Serverless +// https://github.com/elastic/eui-private/issues/192 +export const DEFAULT_THEME_NAME_FEATURE_FLAG = 'coreRendering.defaultThemeName'; + /** @internal */ export class RenderingService { + private readonly themeName$ = new BehaviorSubject(DEFAULT_THEME_NAME); + constructor(private readonly coreContext: CoreContext) {} public async preboot({ @@ -77,6 +84,7 @@ export class RenderingService { baseHref: http.staticAssets.getHrefBase(), packageInfo: this.coreContext.env.packageInfo, auth: http.auth, + themeName$: this.themeName$, }), }); }); @@ -103,6 +111,7 @@ export class RenderingService { baseHref: http.staticAssets.getHrefBase(), packageInfo: this.coreContext.env.packageInfo, auth: http.auth, + themeName$: this.themeName$, userSettingsService: userSettings, }), }); @@ -121,6 +130,14 @@ export class RenderingService { }; } + public start({ featureFlags }: RenderingStartDeps) { + featureFlags + .getStringValue$(DEFAULT_THEME_NAME_FEATURE_FLAG, DEFAULT_THEME_NAME) + // Parse the input feature flag value to ensure it's of type ThemeName + .pipe(map((value) => parseThemeNameValue(value))) + .subscribe(this.themeName$); + } + private async render( renderOptions: RenderOptions, request: KibanaRequest, @@ -213,8 +230,6 @@ export class RenderingService { darkMode = getSettingValue('theme:darkMode', settings, parseDarkModeValue); } - const themeName = getSettingValue('theme:name', settings, parseThemeNameValue); - const themeStylesheetPaths = (mode: boolean) => getThemeStylesheetPaths({ darkMode: mode, @@ -279,7 +294,7 @@ export class RenderingService { }, theme: { darkMode, - name: themeName, + name: this.themeName$.getValue(), version: themeVersion, stylesheetPaths: { default: themeStylesheetPaths(false), diff --git a/src/core/packages/rendering/server-internal/src/test_helpers/params.ts b/src/core/packages/rendering/server-internal/src/test_helpers/params.ts index 735358f5aa92f..376d7df88c17c 100644 --- a/src/core/packages/rendering/server-internal/src/test_helpers/params.ts +++ b/src/core/packages/rendering/server-internal/src/test_helpers/params.ts @@ -48,3 +48,6 @@ export const mockRenderingSetupDeps = { userSettings, i18n: i18nServiceMock.createSetupContract(), }; +export const mockRenderingStartDeps = { + featureFlags: coreFeatureFlagsMock.createStart(), +}; diff --git a/src/core/packages/rendering/server-internal/src/test_helpers/rendering_service.ts b/src/core/packages/rendering/server-internal/src/test_helpers/rendering_service.ts index 1deef9eb79dc1..88872b2d7ddb8 100644 --- a/src/core/packages/rendering/server-internal/src/test_helpers/rendering_service.ts +++ b/src/core/packages/rendering/server-internal/src/test_helpers/rendering_service.ts @@ -22,10 +22,12 @@ export const setupMock: jest.Mocked = { }; export const mockPreboot = jest.fn().mockResolvedValue(prebootMock); export const mockSetup = jest.fn().mockResolvedValue(setupMock); +export const mockStart = jest.fn(); export const mockStop = jest.fn(); export const mockRenderingService: jest.Mocked = { preboot: mockPreboot, setup: mockSetup, + start: mockStart, stop: mockStop, }; export const RenderingService = jest.fn( diff --git a/src/core/packages/rendering/server-internal/src/types.ts b/src/core/packages/rendering/server-internal/src/types.ts index 35bd9d9d21ff5..57457e6bf79b1 100644 --- a/src/core/packages/rendering/server-internal/src/types.ts +++ b/src/core/packages/rendering/server-internal/src/types.ts @@ -25,6 +25,7 @@ import type { InternalUserSettingsServiceSetup } from '@kbn/core-user-settings-s import type { I18nServiceSetup } from '@kbn/core-i18n-server'; import type { InternalI18nServicePreboot } from '@kbn/core-i18n-server-internal'; import type { InternalFeatureFlagsSetup } from '@kbn/core-feature-flags-server-internal'; +import type { FeatureFlagsStart } from '@kbn/core-feature-flags-server'; /** @internal */ export interface RenderingMetadata { @@ -60,6 +61,11 @@ export interface RenderingSetupDeps { i18n: I18nServiceSetup; } +/** @internal */ +export interface RenderingStartDeps { + featureFlags: FeatureFlagsStart; +} + /** @internal */ export interface IRenderOptions { /** diff --git a/src/core/packages/rendering/server-internal/tsconfig.json b/src/core/packages/rendering/server-internal/tsconfig.json index aca7d8f632031..c8e9829e6758a 100644 --- a/src/core/packages/rendering/server-internal/tsconfig.json +++ b/src/core/packages/rendering/server-internal/tsconfig.json @@ -47,6 +47,7 @@ "@kbn/apm-config-loader", "@kbn/core-feature-flags-server-internal", "@kbn/core-feature-flags-server-mocks", + "@kbn/core-feature-flags-server", ], "exclude": [ "target/**/*", diff --git a/src/core/packages/rendering/server-mocks/src/rendering_service.mock.ts b/src/core/packages/rendering/server-mocks/src/rendering_service.mock.ts index 869afcab90632..b90b4c72c1836 100644 --- a/src/core/packages/rendering/server-mocks/src/rendering_service.mock.ts +++ b/src/core/packages/rendering/server-mocks/src/rendering_service.mock.ts @@ -34,6 +34,7 @@ function createRenderingService() { const mock: RenderingServiceMock = { preboot: jest.fn(), setup: jest.fn(), + start: jest.fn(), stop: jest.fn(), }; diff --git a/src/core/packages/root/server-internal/src/server.ts b/src/core/packages/root/server-internal/src/server.ts index 60e5f4be10085..432a75535088a 100644 --- a/src/core/packages/root/server-internal/src/server.ts +++ b/src/core/packages/root/server-internal/src/server.ts @@ -454,6 +454,10 @@ export class Server { this.httpRateLimiter.start(); this.status.start(); + this.rendering.start({ + featureFlags: featureFlagsStart, + }); + this.coreStart = { analytics: analyticsStart, capabilities: capabilitiesStart, diff --git a/src/core/packages/ui-settings/common/src/theme.ts b/src/core/packages/ui-settings/common/src/theme.ts index 33d613e19ad56..cabd20d17ccf1 100644 --- a/src/core/packages/ui-settings/common/src/theme.ts +++ b/src/core/packages/ui-settings/common/src/theme.ts @@ -47,12 +47,6 @@ export function parseThemeTags(input?: unknown): ThemeTags { return DEFAULT_THEME_TAGS; } - // TODO: remove when Borealis is in public beta - // This is left here for backwards compatibility during Borealis testing. - if (input === 'experimental') { - return DEFAULT_THEME_TAGS; - } - let rawTags: string[]; if (typeof input === 'string') { rawTags = input.split(',').map((tag) => tag.trim()); diff --git a/src/core/packages/usage-data/server-internal/src/core_usage_data_service.test.ts b/src/core/packages/usage-data/server-internal/src/core_usage_data_service.test.ts index f72664ff0c1fa..bc5ad516bb83c 100644 --- a/src/core/packages/usage-data/server-internal/src/core_usage_data_service.test.ts +++ b/src/core/packages/usage-data/server-internal/src/core_usage_data_service.test.ts @@ -307,6 +307,7 @@ describe('CoreUsageDataService', () => { }, "keepaliveTimeout": 120000, "maxPayloadInBytes": 1048576, + "protocol": "http1", "requestId": Object { "allowFromAnyIp": false, "ipAllowlistConfigured": false, diff --git a/src/core/packages/usage-data/server-internal/src/core_usage_data_service.ts b/src/core/packages/usage-data/server-internal/src/core_usage_data_service.ts index c970bd4abfa6d..dec6b7fa5efd2 100644 --- a/src/core/packages/usage-data/server-internal/src/core_usage_data_service.ts +++ b/src/core/packages/usage-data/server-internal/src/core_usage_data_service.ts @@ -280,6 +280,7 @@ export class CoreUsageDataService rewriteBasePath: http.rewriteBasePath, keepaliveTimeout: http.keepaliveTimeout, socketTimeout: http.socketTimeout, + protocol: http.protocol, compression: { enabled: http.compression.enabled, referrerWhitelistConfigured: isConfigured.array(http.compression.referrerWhitelist), diff --git a/src/core/packages/usage-data/server-mocks/src/core_usage_data_service.mock.ts b/src/core/packages/usage-data/server-mocks/src/core_usage_data_service.mock.ts index 57628901c1a60..bc14931fd31e9 100644 --- a/src/core/packages/usage-data/server-mocks/src/core_usage_data_service.mock.ts +++ b/src/core/packages/usage-data/server-mocks/src/core_usage_data_service.mock.ts @@ -62,6 +62,7 @@ const createStartContractMock = () => { }, keepaliveTimeout: 120000, maxPayloadInBytes: 1048576, + protocol: 'http1', requestId: { allowFromAnyIp: false, ipAllowlistConfigured: false, diff --git a/src/core/packages/usage-data/server/src/core_usage_data.ts b/src/core/packages/usage-data/server/src/core_usage_data.ts index 24849db2de255..8824d75ea4bc5 100644 --- a/src/core/packages/usage-data/server/src/core_usage_data.ts +++ b/src/core/packages/usage-data/server/src/core_usage_data.ts @@ -91,6 +91,7 @@ export interface CoreConfigUsageData { rewriteBasePath: boolean; keepaliveTimeout: number; socketTimeout: number; + protocol: 'http1' | 'http2'; compression: { enabled: boolean; referrerWhitelistConfigured: boolean; diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts index afd3f49900110..50837a4699994 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts @@ -51,7 +51,7 @@ export async function runDockerGenerator( */ if (flags.baseImage === 'wolfi') baseImageName = - 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:8df3ca6e1468dfda09359c47162bff2df9f9b48986037e8324b63e9347a3ce17'; + 'docker.elastic.co/wolfi/chainguard-base:latest@sha256:d74b1fda6b7fee2c90b410df258e005c049e0672fe16d79d00e58f14fb69f90b'; let imageFlavor = ''; if (flags.baseImage === 'ubi') imageFlavor += `-ubi`; diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index cfe33e30e8705..d648755d6ee4c 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -87,8 +87,8 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.6.3': ['Elastic License 2.0'], - '@elastic/eui@99.1.0-borealis.0': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'], - '@elastic/eui-theme-borealis@0.0.9': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'], + '@elastic/eui@99.2.0-borealis.0': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'], + '@elastic/eui-theme-borealis@0.0.10': ['Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry 'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary '@bufbuild/protobuf@1.2.1': ['Apache-2.0'], // license (Apache-2.0 AND BSD-3-Clause) diff --git a/src/dev/storybook/run_storybook_cli.ts b/src/dev/storybook/run_storybook_cli.ts index 26369b6646196..dd9855bdbfdd9 100644 --- a/src/dev/storybook/run_storybook_cli.ts +++ b/src/dev/storybook/run_storybook_cli.ts @@ -41,6 +41,7 @@ run( log.verbose('Loading Storybook:', configDir); + // TODO: once storybook is upgraded into a newer version, --no-deprecation flag could be removed when invoking it through the package.json script runStorybookCli({ configDir, name: alias }); }, { diff --git a/src/platform/packages/private/kbn-mapbox-gl/index.ts b/src/platform/packages/private/kbn-mapbox-gl/index.ts index dfc5a876ec262..7721b98cfa3b4 100644 --- a/src/platform/packages/private/kbn-mapbox-gl/index.ts +++ b/src/platform/packages/private/kbn-mapbox-gl/index.ts @@ -33,10 +33,8 @@ import type { // @ts-expect-error import maplibreglDist from 'maplibre-gl/dist/maplibre-gl-csp'; -// @ts-expect-error -import mbRtlPlugin from '!!file-loader!@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js'; -// @ts-expect-error -import mbWorkerUrl from '!!file-loader!maplibre-gl/dist/maplibre-gl-csp-worker'; +import mbRtlPlugin from '@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js?asUrl'; +import mbWorkerUrl from 'maplibre-gl/dist/maplibre-gl-csp-worker?asUrl'; import 'maplibre-gl/dist/maplibre-gl.css'; const maplibregl: any = maplibreglDist; diff --git a/src/platform/packages/private/kbn-mapbox-gl/tsconfig.json b/src/platform/packages/private/kbn-mapbox-gl/tsconfig.json index 9a47088cfbaa3..4ca45c90ec152 100644 --- a/src/platform/packages/private/kbn-mapbox-gl/tsconfig.json +++ b/src/platform/packages/private/kbn-mapbox-gl/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", - "types": [] + "types": ["@kbn/ambient-ui-types"] }, "include": [ "**/*.ts", diff --git a/src/platform/packages/private/kbn-ui-shared-deps-npm/BUILD.bazel b/src/platform/packages/private/kbn-ui-shared-deps-npm/BUILD.bazel index 1e54524fdf55e..19225c0eefe06 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-npm/BUILD.bazel +++ b/src/platform/packages/private/kbn-ui-shared-deps-npm/BUILD.bazel @@ -26,8 +26,8 @@ SRCS = glob( RUNTIME_DEPS = [ "@npm//babel-loader", "@npm//@babel/plugin-proposal-optional-chaining", - "@npm//loader-utils", "@npm//val-loader", + "//packages/kbn-node-libs-browser-webpack-plugin", "//src/platform/packages/shared/kbn-repo-info", # deps in the dll need to be included in the sandbox for consumers # of this DLL (ui-shared-deps-src) because webpack won't actually @@ -53,6 +53,7 @@ RUNTIME_DEPS = [ "@npm//jquery", "@npm//lodash", "@npm//moment-timezone", + "@npm//node-libs-browser", "@npm//react-dom", "@npm//react-dom-18", "@npm//react-router-dom", @@ -96,11 +97,9 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", - "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", - "NODE_OPTIONS": "--openssl-legacy-provider", "REACT_18": "$(REACT_18)", }, }) diff --git a/src/platform/packages/private/kbn-ui-shared-deps-npm/src/public_path_loader.js b/src/platform/packages/private/kbn-ui-shared-deps-npm/src/public_path_loader.js index bc0e90a8031f3..6e2f0d7e1ee94 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-npm/src/public_path_loader.js +++ b/src/platform/packages/private/kbn-ui-shared-deps-npm/src/public_path_loader.js @@ -7,19 +7,21 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -// eslint-disable-next-line import/no-extraneous-dependencies -const { stringifyRequest } = require('loader-utils'); - const VAL_LOADER = require.resolve('val-loader'); const MODULE_CREATOR = require.resolve('./public_path_module_creator'); /** - * @this {any} this + * @this {import('webpack').LoaderContext} * @param {string} source */ module.exports = function (source) { const options = this.query; const valOpts = new URLSearchParams({ key: options.key }).toString(); - const req = `${VAL_LOADER}?${valOpts}!${MODULE_CREATOR}`; - return `require(${stringifyRequest(this, req)});${source}`; + const req = JSON.stringify( + this.utils.contextify( + this.context || this.rootContext, + `${VAL_LOADER}?${valOpts}!${MODULE_CREATOR}` + ) + ); + return `require(${req});${source}`; }; diff --git a/src/platform/packages/private/kbn-ui-shared-deps-npm/webpack.config.js b/src/platform/packages/private/kbn-ui-shared-deps-npm/webpack.config.js index 08efd5863c147..eae896c6045e8 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-npm/webpack.config.js +++ b/src/platform/packages/private/kbn-ui-shared-deps-npm/webpack.config.js @@ -9,6 +9,7 @@ const Path = require('path'); const webpack = require('webpack'); +const { NodeLibsBrowserPlugin } = require('@kbn/node-libs-browser-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); @@ -19,14 +20,11 @@ const WEBPACK_SRC = require.resolve('webpack'); const REPO_ROOT = Path.resolve(__dirname, '..', '..', '..', '..', '..'); +/** @returns {import('webpack').Configuration} */ module.exports = (_, argv) => { const outputPath = argv.outputPath ? Path.resolve(argv.outputPath) : UiSharedDepsNpm.distDir; return { - node: { - child_process: 'empty', - fs: 'empty', - }, externals: { module: 'module', }, @@ -63,12 +61,12 @@ module.exports = (_, argv) => { '@elastic/charts', '@elastic/eui', '@elastic/eui/optimize/es/components/provider/nested', - '@elastic/eui/optimize/es/services', - '@elastic/eui/optimize/es/services/format', + '@elastic/eui/optimize/es/services/theme/warning', '@elastic/eui/dist/eui_theme_amsterdam_light.json', '@elastic/eui/dist/eui_theme_amsterdam_dark.json', '@elastic/eui/dist/eui_theme_borealis_light.json', '@elastic/eui/dist/eui_theme_borealis_dark.json', + '@elastic/eui-theme-borealis', '@elastic/numeral', '@emotion/cache', '@emotion/react', @@ -105,6 +103,7 @@ module.exports = (_, argv) => { }, context: __dirname, devtool: 'cheap-source-map', + target: 'web', output: { path: outputPath, filename: '[name].dll.js', @@ -112,7 +111,6 @@ module.exports = (_, argv) => { devtoolModuleFilenameTemplate: (info) => `kbn-ui-shared-deps-npm/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`, library: '__kbnSharedDeps_npm__', - futureEmitAssets: true, }, module: { @@ -148,11 +146,15 @@ module.exports = (_, argv) => { react: process.env.REACT_18 === 'true' ? 'react-18' : 'react', }, extensions: ['.js', '.ts'], + mainFields: ['browser', 'module', 'main'], + conditionNames: ['browser', 'module', 'import', 'require', 'default'], }, optimization: { + moduleIds: process.env.NODE_ENV === 'production' ? 'deterministic' : 'natural', + chunkIds: process.env.NODE_ENV === 'production' ? 'deterministic' : 'natural', minimize: false, - noEmitOnErrors: true, + emitOnErrors: false, }, performance: { @@ -163,6 +165,7 @@ module.exports = (_, argv) => { }, plugins: [ + new NodeLibsBrowserPlugin(), new CleanWebpackPlugin({ protectWebpackAssets: false, cleanAfterEveryBuildPatterns: [ @@ -175,6 +178,7 @@ module.exports = (_, argv) => { }), new webpack.DllPlugin({ context: REPO_ROOT, + entryOnly: false, path: Path.resolve(outputPath, '[name]-manifest.json'), name: '__kbnSharedDeps_npm__', }), diff --git a/src/platform/packages/private/kbn-ui-shared-deps-src/BUILD.bazel b/src/platform/packages/private/kbn-ui-shared-deps-src/BUILD.bazel index 7d84db05f99d5..c8ee5c950a131 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-src/BUILD.bazel +++ b/src/platform/packages/private/kbn-ui-shared-deps-src/BUILD.bazel @@ -15,7 +15,6 @@ webpack_cli( "@npm//moment", "@npm//babel-loader", "@npm//css-loader", - "@npm//url-loader", "@npm//@babel/plugin-transform-numeric-separator", "//src/platform/packages/private/kbn-ui-shared-deps-npm", "//packages/kbn-babel-register", @@ -57,11 +56,9 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", - "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", - "NODE_OPTIONS": "--openssl-legacy-provider", "REACT_18": "$(REACT_18)", }, }), diff --git a/src/platform/packages/private/kbn-ui-shared-deps-src/src/definitions.js b/src/platform/packages/private/kbn-ui-shared-deps-src/src/definitions.js index 4c6a66de525c3..109c376cb6cd3 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-src/src/definitions.js +++ b/src/platform/packages/private/kbn-ui-shared-deps-src/src/definitions.js @@ -75,8 +75,7 @@ const externals = { '@elastic/eui': '__kbnSharedDeps__.ElasticEui', '@elastic/eui/lib/components/provider/nested': '__kbnSharedDeps__.ElasticEuiLibComponentsUseIsNestedEuiProvider', - '@elastic/eui/lib/services': '__kbnSharedDeps__.ElasticEuiLibServices', - '@elastic/eui/lib/services/format': '__kbnSharedDeps__.ElasticEuiLibServicesFormat', + '@elastic/eui/lib/services/theme/warning': '__kbnSharedDeps__.ElasticEuiLibServicesThemeWarning', '@elastic/eui-theme-borealis': '__kbnSharedDeps__.ElasticEuiThemeBorealis', // transient dep of eui diff --git a/src/platform/packages/private/kbn-ui-shared-deps-src/src/entry.js b/src/platform/packages/private/kbn-ui-shared-deps-src/src/entry.js index c76d3bb433589..71f47f31abfcb 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-src/src/entry.js +++ b/src/platform/packages/private/kbn-ui-shared-deps-src/src/entry.js @@ -51,10 +51,9 @@ export const Rxjs = require('rxjs'); export const ElasticNumeral = require('@elastic/numeral'); export const ElasticCharts = require('@elastic/charts'); export const ElasticEui = require('@elastic/eui'); -export const ElasticEuiThemeBorealis = require('@elastic/eui-theme-borealis'); export const ElasticEuiLibComponentsUseIsNestedEuiProvider = require('@elastic/eui/optimize/es/components/provider/nested'); -export const ElasticEuiLibServices = require('@elastic/eui/optimize/es/services'); -export const ElasticEuiLibServicesFormat = require('@elastic/eui/optimize/es/services/format'); +export const ElasticEuiLibServicesThemeWarning = require('@elastic/eui/optimize/es/services/theme/warning'); +export const ElasticEuiThemeBorealis = require('@elastic/eui-theme-borealis'); export const KbnDatemath = require('@kbn/datemath'); export const HelloPangeaDnd = require('@hello-pangea/dnd/dist/dnd'); export const ReduxjsToolkit = require('@reduxjs/toolkit'); diff --git a/src/platform/packages/private/kbn-ui-shared-deps-src/webpack.config.js b/src/platform/packages/private/kbn-ui-shared-deps-src/webpack.config.js index 2c01d209b7315..cb65a782e6ba9 100644 --- a/src/platform/packages/private/kbn-ui-shared-deps-src/webpack.config.js +++ b/src/platform/packages/private/kbn-ui-shared-deps-src/webpack.config.js @@ -13,6 +13,7 @@ require('@kbn/babel-register').install(); const Path = require('path'); const webpack = require('webpack'); +const { NodeLibsBrowserPlugin } = require('@kbn/node-libs-browser-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const UiSharedDepsNpm = require('@kbn/ui-shared-deps-npm'); @@ -22,11 +23,8 @@ const MOMENT_SRC = require.resolve('moment/min/moment-with-locales.js'); const REPO_ROOT = Path.resolve(__dirname, '..', '..', '..', '..', '..'); +/** @returns {import('webpack').Configuration} */ module.exports = { - node: { - child_process: 'empty', - fs: 'empty', - }, externals: { module: 'module', }, @@ -36,6 +34,7 @@ module.exports = { }, context: __dirname, devtool: 'cheap-source-map', + target: 'web', output: { path: UiSharedDepsSrcDistDir, filename: '[name].js', @@ -44,7 +43,6 @@ module.exports = { devtoolModuleFilenameTemplate: (info) => `kbn-ui-shared-deps-src/${Path.relative(REPO_ROOT, info.absoluteResourcePath)}`, library: '__kbnSharedDeps__', - futureEmitAssets: true, }, module: { @@ -68,13 +66,6 @@ module.exports = { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'], }, - { - test: /\.(ttf)(\?|$)/, - loader: 'url-loader', - options: { - limit: 8192, - }, - }, { test: /\.(js|tsx?)$/, exclude: /[\/\\]node_modules[\/\\](?!@kbn)([^\/\\]+)[\/\\]/, @@ -102,13 +93,28 @@ module.exports = { }, }, }, + // automatically chooses between exporting a data URI and emitting a separate file. Previously achievable by using url-loader with asset size limit. + { + test: /\.(ttf)(\?|$)/, + type: 'asset', + parser: { + dataUrlCondition: { + maxSize: 8192, + }, + }, + }, ], }, resolve: { extensions: ['.js', '.ts', '.tsx'], + mainFields: ['browser', 'module', 'main'], + conditionNames: ['browser', 'module', 'import', 'require', 'default'], alias: { '@elastic/eui$': '@elastic/eui/optimize/es', + '@elastic/eui/lib/components/provider/nested$': + '@elastic/eui/optimize/es/components/provider/nested', + '@elastic/eui/lib/services/theme/warning$': '@elastic/eui/optimize/es/services/theme/warning', moment: MOMENT_SRC, // NOTE: Used to include react profiling on bundles // https://gist.github.com/bvaughn/25e6233aeb1b4f0cdb8d8366e54a3977#webpack-4 @@ -120,8 +126,10 @@ module.exports = { }, optimization: { + moduleIds: process.env.NODE_ENV === 'production' ? 'deterministic' : 'natural', + chunkIds: process.env.NODE_ENV === 'production' ? 'deterministic' : 'natural', minimize: false, - noEmitOnErrors: true, + emitOnErrors: false, }, performance: { @@ -132,6 +140,7 @@ module.exports = { }, plugins: [ + new NodeLibsBrowserPlugin(), new MiniCssExtractPlugin({ filename: '[name].css', }), diff --git a/src/platform/packages/private/kbn-unsaved-changes-badge/src/components/unsaved_changes_badge/__snapshots__/unsaved_changes_badge.test.tsx.snap b/src/platform/packages/private/kbn-unsaved-changes-badge/src/components/unsaved_changes_badge/__snapshots__/unsaved_changes_badge.test.tsx.snap index 9103b94e19379..3c840fdd7afc9 100644 --- a/src/platform/packages/private/kbn-unsaved-changes-badge/src/components/unsaved_changes_badge/__snapshots__/unsaved_changes_badge.test.tsx.snap +++ b/src/platform/packages/private/kbn-unsaved-changes-badge/src/components/unsaved_changes_badge/__snapshots__/unsaved_changes_badge.test.tsx.snap @@ -10,7 +10,7 @@ exports[` should show all menu items 1`] = ` aria-label="View available actions" class="euiBadge emotion-euiBadge-clickable" data-test-subj="unsavedChangesBadge" - style="--euiBadgeBackgroundColor: #F6E58D; --euiBadgeTextColor: #000000;" + style="--euiBadgeBackgroundColor: #F6E58D; --euiBadgeTextColor: #07101F;" title="test" > { } as RenderCellValuePropsWithInTableSearch) ).toMatchInlineSnapshot(` { expect(badge).toBeInTheDocument(); expect(badge).toHaveTextContent('info'); expect(getComputedStyle(badge).getPropertyValue('--euiBadgeBackgroundColor')).toEqual( - '#90b0d1' + '#90bdff' ); }); diff --git a/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/utils/get_log_level_color.test.ts b/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/utils/get_log_level_color.test.ts index fcbf7848603a9..fbd18ea82bf58 100644 --- a/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/utils/get_log_level_color.test.ts +++ b/src/platform/packages/shared/kbn-discover-utils/src/data_types/logs/utils/get_log_level_color.test.ts @@ -20,28 +20,28 @@ const euiTheme = { describe('getLogLevelColor', () => { test('should work correctly', () => { expect(getLogLevelColor(LogLevelCoalescedValue.debug, euiTheme as EuiThemeComputed)).toBe( - '#becfe3' + '#bdd7ff' ); expect(getLogLevelColor(LogLevelCoalescedValue.info, euiTheme as EuiThemeComputed)).toBe( - '#90b0d1' + '#90bdff' ); expect(getLogLevelColor(LogLevelCoalescedValue.notice, euiTheme as EuiThemeComputed)).toBe( - '#6092c0' + '#61a2ff' ); expect(getLogLevelColor(LogLevelCoalescedValue.warning, euiTheme as EuiThemeComputed)).toBe( - '#d6bf57' + '#fcd883' ); expect(getLogLevelColor(LogLevelCoalescedValue.error, euiTheme as EuiThemeComputed)).toBe( - '#e18774' + '#fc9a92' ); expect(getLogLevelColor(LogLevelCoalescedValue.critical, euiTheme as EuiThemeComputed)).toBe( - '#dd7b67' + '#fb9188' ); expect(getLogLevelColor(LogLevelCoalescedValue.alert, euiTheme as EuiThemeComputed)).toBe( - '#d76f5b' + '#fa877e' ); expect(getLogLevelColor(LogLevelCoalescedValue.emergency, euiTheme as EuiThemeComputed)).toBe( - '#d2634e' + '#f87c74' ); // other expect(getLogLevelColor(LogLevelCoalescedValue.trace, euiTheme as EuiThemeComputed)).toBe( diff --git a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts index b710c7f7cf0e0..e30a6200e07c4 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts @@ -299,6 +299,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D overview: `${KIBANA_DOCS}upgrade-assistant.html`, batchReindex: `${KIBANA_DOCS}batch-start-resume-reindex.html`, remoteReindex: `${ELASTICSEARCH_DOCS}docs-reindex.html#reindex-from-remote`, + unfreezeApi: `${ELASTICSEARCH_DOCS}unfreeze-index-api.html`, reindexWithPipeline: `${ELASTICSEARCH_DOCS}docs-reindex.html#reindex-with-an-ingest-pipeline`, }, rollupJobs: `${KIBANA_DOCS}data-rollups.html`, @@ -454,7 +455,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D aiAssistant: `${SECURITY_SOLUTION_DOCS}security-assistant.html`, signalsMigrationApi: `${SECURITY_SOLUTION_DOCS}signals-migration-api.html`, legacyEndpointManagementApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-199598`, - legacyBulkApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-207091`, + legacyRuleManagementBulkApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-207091`, }, query: { eql: `${ELASTICSEARCH_DOCS}eql.html`, diff --git a/src/platform/packages/shared/kbn-doc-links/src/types.ts b/src/platform/packages/shared/kbn-doc-links/src/types.ts index eb3287f86e99e..0fff5c2a92125 100644 --- a/src/platform/packages/shared/kbn-doc-links/src/types.ts +++ b/src/platform/packages/shared/kbn-doc-links/src/types.ts @@ -260,6 +260,7 @@ export interface DocLinks { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; + readonly unfreezeApi: string; readonly reindexWithPipeline: string; }; readonly rollupJobs: string; @@ -319,7 +320,7 @@ export interface DocLinks { readonly detectionEngineOverview: string; readonly signalsMigrationApi: string; readonly legacyEndpointManagementApiDeprecations: string; - readonly legacyBulkApiDeprecations: string; + readonly legacyRuleManagementBulkApiDeprecations: string; }; readonly query: { readonly eql: string; diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts index bb50d88705697..658733aa31005 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts @@ -136,6 +136,24 @@ describe('WHERE ', () => { } }); + test('filters suggestions based on previous commands', async () => { + const { assertSuggestions } = await setup(); + + await assertSuggestions('from a | where / | limit 3', [ + ...getFieldNamesByType('any') + .map((field) => `${field} `) + .map(attachTriggerCommand), + ...allEvalFns, + ]); + + await assertSuggestions('from a | limit 3 | where / ', [ + ...getFieldNamesByType('any') + .map((field) => `${field} `) + .map(attachTriggerCommand), + ...allEvalFns.filter((fn) => fn.label !== 'QSTR' && fn.label !== 'MATCH'), + ]); + }); + test('suggests operators after a field name', async () => { const { assertSuggestions } = await setup(); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/helpers.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/helpers.ts index 0d62b5040c034..56474adac67ee 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/helpers.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/helpers.ts @@ -115,7 +115,7 @@ export const policies = [ /** * Utility to filter down the function list for the given type * It is mainly driven by the return type, but it can be filtered upon with the last optional argument "paramsTypes" - * jsut make sure to pass the arguments in the right order + * just make sure to pass the arguments in the right order * @param command current command context * @param expectedReturnType the expected type returned by the function * @param functionCategories diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index 454c0b135ae6f..15e244e542896 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -10,7 +10,6 @@ import { uniq, uniqBy } from 'lodash'; import type { AstProviderFn, - ESQLAst, ESQLAstItem, ESQLCommand, ESQLCommandOption, @@ -163,10 +162,6 @@ export async function suggest( const { ast } = await astProvider(correctedQuery); const astContext = getAstContext(innerText, ast, offset); - // But we also need the full ast for the full query - const correctedFullQuery = correctQuerySyntax(fullText, context); - const { ast: fullAst } = await astProvider(correctedFullQuery); - if (astContext.type === 'comment') { return []; } @@ -230,7 +225,6 @@ export async function suggest( getPolicies, getPolicyMetadata, resourceRetriever?.getPreferences, - fullAst, resourceRetriever ); } @@ -417,7 +411,6 @@ async function getSuggestionsWithinCommandExpression( getPolicies: GetPoliciesFn, getPolicyMetadata: GetPolicyMetadataFn, getPreferences?: () => Promise<{ histogramBarTarget: number } | undefined>, - fullAst?: ESQLAst, callbacks?: ESQLCallbacks ) { const commandDef = getCommandDefinition(command.name); @@ -438,7 +431,7 @@ async function getSuggestionsWithinCommandExpression( (expression: ESQLAstItem | undefined) => getExpressionType(expression, references.fields, references.variables), getPreferences, - fullAst, + commands, commandDef, callbacks ); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/join/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/join/index.ts index 70314bea364f3..c4d4664ccf24a 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/join/index.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/join/index.ts @@ -8,8 +8,7 @@ */ import { i18n } from '@kbn/i18n'; -import { type ESQLAstItem, ESQLAst } from '@kbn/esql-ast'; -import { ESQLCommand } from '@kbn/esql-ast/src/types'; +import { type ESQLAstItem, type ESQLCommand } from '@kbn/esql-ast'; import type { ESQLCallbacks } from '../../../shared/types'; import { CommandBaseDefinition, @@ -45,7 +44,7 @@ export const suggest: CommandBaseDefinition<'join'>['suggest'] = async ( getSuggestedVariableName: () => string, getExpressionType: (expression: ESQLAstItem | undefined) => SupportedDataType | 'unknown', getPreferences?: () => Promise<{ histogramBarTarget: number } | undefined>, - fullTextAst?: ESQLAst, + previousCommands?: ESQLCommand[], definition?: CommandDefinition<'join'>, callbacks?: ESQLCallbacks ): Promise => { diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/where/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/where/index.ts index d47c08722f798..68bbd19bc1967 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/where/index.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/commands/where/index.ts @@ -13,7 +13,6 @@ import { type ESQLCommand, type ESQLSingleAstItem, type ESQLFunction, - ESQLAst, } from '@kbn/esql-ast'; import { logicalOperators } from '../../../definitions/builtin'; import { isParameterType, type SupportedDataType } from '../../../definitions/types'; @@ -42,7 +41,7 @@ export async function suggest( _getSuggestedVariableName: () => string, getExpressionType: (expression: ESQLAstItem | undefined) => SupportedDataType | 'unknown', _getPreferences?: () => Promise<{ histogramBarTarget: number } | undefined>, - fullTextAst?: ESQLAst + previousCommands?: ESQLCommand[] ): Promise { const suggestions: SuggestionRawDefinition[] = []; @@ -163,7 +162,7 @@ export async function suggest( case 'empty_expression': // Don't suggest MATCH or QSTR after unsupported commands - const priorCommands = fullTextAst?.map((a) => a.name) ?? []; + const priorCommands = previousCommands?.map((a) => a.name) ?? []; const ignored = []; if (priorCommands.some((c) => UNSUPPORTED_COMMANDS_BEFORE_MATCH.has(c))) { ignored.push('match'); @@ -171,7 +170,7 @@ export async function suggest( if (priorCommands.some((c) => UNSUPPORTED_COMMANDS_BEFORE_QSTR.has(c))) { ignored.push('qstr'); } - const last = fullTextAst?.[fullTextAst.length - 1]; + const last = previousCommands?.[previousCommands.length - 1]; let columnSuggestions: SuggestionRawDefinition[] = []; if (!last?.text?.endsWith(`:${EDITOR_MARKER}`)) { columnSuggestions = await getColumnsByType('any', [], { diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/types.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/types.ts index 9d53b7fd250a0..481f39daf041b 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/types.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/types.ts @@ -8,7 +8,6 @@ */ import type { - ESQLAst, ESQLAstItem, ESQLCommand, ESQLCommandOption, @@ -210,7 +209,7 @@ export interface CommandBaseDefinition { getSuggestedVariableName: () => string, getExpressionType: (expression: ESQLAstItem | undefined) => SupportedDataType | 'unknown', getPreferences?: () => Promise<{ histogramBarTarget: number } | undefined>, - fullTextAst?: ESQLAst, + previousCommands?: ESQLCommand[], definition?: CommandDefinition, callbacks?: ESQLCallbacks ) => Promise; diff --git a/src/platform/packages/shared/kbn-monaco/BUILD.bazel b/src/platform/packages/shared/kbn-monaco/BUILD.bazel index e552cf0822a83..de340d159e365 100644 --- a/src/platform/packages/shared/kbn-monaco/BUILD.bazel +++ b/src/platform/packages/shared/kbn-monaco/BUILD.bazel @@ -28,6 +28,7 @@ SHARED_DEPS = [ "//src/platform/packages/shared/kbn-ui-theme", "//src/platform/packages/shared/kbn-esql-validation-autocomplete", "//src/platform/packages/shared/kbn-esql-ast", + "//packages/kbn-node-libs-browser-webpack-plugin", "@npm//antlr4", "@npm//monaco-editor", "@npm//monaco-yaml", @@ -41,7 +42,6 @@ webpack_cli( "@npm//terser-webpack-plugin", "@npm//@babel/runtime", "@npm//babel-loader", - "@npm//raw-loader", "@npm//rxjs", "webpack.config.js", @@ -59,11 +59,9 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", - "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", - "NODE_OPTIONS": "--openssl-legacy-provider", }, }), visibility = ["//visibility:public"], diff --git a/src/platform/packages/shared/kbn-monaco/webpack.config.js b/src/platform/packages/shared/kbn-monaco/webpack.config.js index 4f558834d8059..ddd21c9c7e029 100644 --- a/src/platform/packages/shared/kbn-monaco/webpack.config.js +++ b/src/platform/packages/shared/kbn-monaco/webpack.config.js @@ -8,6 +8,7 @@ */ const path = require('path'); +const { NodeLibsBrowserPlugin } = require('@kbn/node-libs-browser-webpack-plugin'); const getWorkerEntry = (language) => { switch (language) { @@ -30,7 +31,8 @@ const workerConfig = (languages) => ({ entries[language] = getWorkerEntry(language); return entries; }, {}), - devtool: process.env.NODE_ENV === 'production' ? false : '#cheap-source-map', + devtool: process.env.NODE_ENV === 'production' ? false : 'cheap-source-map', + target: 'web', output: { path: path.resolve(__dirname, 'target_workers'), filename: ({ chunk }) => `${chunk.name}.editor.worker.js`, @@ -42,6 +44,7 @@ const workerConfig = (languages) => ({ 'vscode-uri$': require.resolve('vscode-uri').replace(/\/umd\/index.js/, '/esm/index.mjs'), }, }, + plugins: [new NodeLibsBrowserPlugin()], stats: 'errors-only', module: { rules: [ diff --git a/src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/__snapshots__/use_comparison_cell_value.test.tsx.snap b/src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/__snapshots__/use_comparison_cell_value.test.tsx.snap index bb53364085039..b7825414088b3 100644 --- a/src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/__snapshots__/use_comparison_cell_value.test.tsx.snap +++ b/src/platform/packages/shared/kbn-unified-data-table/src/components/compare_documents/hooks/__snapshots__/use_comparison_cell_value.test.tsx.snap @@ -11,7 +11,7 @@ exports[`useComparisonCellValue should render a tooltip when the field is derive class="euiFlexItem emotion-euiFlexItem-growZero" > ); expect(component.html()).toMatchInlineSnapshot( - `"
extension
.gz
_index
test
_score
1
"` + `"
extension
.gz
_index
test
_score
1
"` ); }); }); diff --git a/src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx b/src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx index 960a576f8342f..8f615c07ddb8a 100644 --- a/src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx +++ b/src/platform/packages/shared/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx @@ -157,7 +157,7 @@ describe('Unified data table cell rendering', function () { /> ); expect(component.html()).toMatchInlineSnapshot( - `"
100
"` + `"
100
"` ); }); @@ -184,7 +184,7 @@ describe('Unified data table cell rendering', function () { /> ); expect(component.html()).toMatchInlineSnapshot( - `"
100
"` + `"
100
"` ); findTestSubject(component, 'docTableClosePopover').simulate('click'); expect(closePopoverMockFn).toHaveBeenCalledTimes(1); diff --git a/src/platform/packages/shared/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap b/src/platform/packages/shared/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap index cf9ddb38bbe69..bf6a40469476a 100644 --- a/src/platform/packages/shared/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap +++ b/src/platform/packages/shared/kbn-unified-doc-viewer/src/components/field_name/__snapshots__/field_name.test.tsx.snap @@ -14,7 +14,7 @@ exports[`FieldName renders a custom description icon 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" > { ); expect(wrapper).toMatchInlineSnapshot(` { const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` diff --git a/src/platform/packages/shared/kbn-visualization-ui-components/components/drag_drop_bucket/buckets.test.tsx b/src/platform/packages/shared/kbn-visualization-ui-components/components/drag_drop_bucket/buckets.test.tsx index e3abee643eeaa..0d96c558b0c54 100644 --- a/src/platform/packages/shared/kbn-visualization-ui-components/components/drag_drop_bucket/buckets.test.tsx +++ b/src/platform/packages/shared/kbn-visualization-ui-components/components/drag_drop_bucket/buckets.test.tsx @@ -65,7 +65,7 @@ describe('buckets shared components', () => { it('should render invalid component', () => { const instance = mount(); const iconProps = instance.find(EuiIcon).first().props(); - expect(iconProps.color.toUpperCase()).toEqual('#BD271E'); + expect(iconProps.color.toUpperCase()).toEqual('#A71627'); expect(iconProps.type).toEqual('warning'); }); it('should call onRemoveClick when remove icon is clicked', () => { diff --git a/src/platform/packages/shared/shared-ux/button_toolbar/src/popover/popover.test.tsx b/src/platform/packages/shared/shared-ux/button_toolbar/src/popover/popover.test.tsx index d4cd612a2d1c9..c77e311077dcd 100644 --- a/src/platform/packages/shared/shared-ux/button_toolbar/src/popover/popover.test.tsx +++ b/src/platform/packages/shared/shared-ux/button_toolbar/src/popover/popover.test.tsx @@ -38,8 +38,8 @@ describe('', () => { expect(button.prop('color')).toBe('text'); expect(button.prop('css')).toMatchObject({ backgroundColor: '#FFFFFF', - border: '1px solid #D3DAE6', - color: '#343741', + border: '1px solid #E3E8F2', + color: '#1D2A3E', }); }); diff --git a/src/platform/plugins/private/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/platform/plugins/private/kibana_usage_collection/server/collectors/core/core_usage_collector.ts index 41e7bf9fd7402..c61e81c3339a3 100644 --- a/src/platform/plugins/private/kibana_usage_collection/server/collectors/core/core_usage_collector.ts +++ b/src/platform/plugins/private/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -151,6 +151,10 @@ export function getCoreUsageCollector( type: 'long', _meta: { description: 'Maximum payload size in bytes that is allowed.' }, }, + protocol: { + type: 'keyword', + _meta: { description: 'Protocol to serve the requests ("http1" | "http2")' }, + }, rewriteBasePath: { type: 'boolean', _meta: { description: 'Indicates if the base path should be rewritten.' }, diff --git a/src/platform/plugins/private/vis_types/vega/public/default_spec.ts b/src/platform/plugins/private/vis_types/vega/public/default_spec.ts index fd4d54a26eab7..fc68b8566b45f 100644 --- a/src/platform/plugins/private/vis_types/vega/public/default_spec.ts +++ b/src/platform/plugins/private/vis_types/vega/public/default_spec.ts @@ -8,6 +8,6 @@ */ // @ts-ignore -import defaultSpec from '!!raw-loader!./default.spec.hjson'; +import defaultSpec from './default.spec.hjson?raw'; export const getDefaultSpec = () => defaultSpec; diff --git a/src/platform/plugins/private/vis_types/vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap b/src/platform/plugins/private/vis_types/vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap index c9a3c41edca93..a6910fbc2f7c8 100644 --- a/src/platform/plugins/private/vis_types/vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap +++ b/src/platform/plugins/private/vis_types/vislib/public/vislib/components/legend/__snapshots__/legend.test.tsx.snap @@ -2,4 +2,4 @@ exports[`VisLegend Component Legend closed should match the snapshot 1`] = `"
"`; -exports[`VisLegend Component Legend open should match the snapshot 1`] = `"
"`; +exports[`VisLegend Component Legend open should match the snapshot 1`] = `"
"`; diff --git a/src/platform/plugins/shared/chart_expressions/expression_gauge/public/components/__snapshots__/gauge_component.test.tsx.snap b/src/platform/plugins/shared/chart_expressions/expression_gauge/public/components/__snapshots__/gauge_component.test.tsx.snap index 501b6844c2fcf..ea4cb22cdf203 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_gauge/public/components/__snapshots__/gauge_component.test.tsx.snap +++ b/src/platform/plugins/shared/chart_expressions/expression_gauge/public/components/__snapshots__/gauge_component.test.tsx.snap @@ -568,8 +568,8 @@ exports[`GaugeComponent renders the chart 1`] = ` ('data')[0]?.[0]; expect((datum?.ticks as () => number[])?.()).toEqual([0, 1, 2, 3, 4, 10]); const colorBands = bullet.prop('colorBands'); - expect(colorBands).toEqual(['#D3DAE6', '#D3DAE6']); + expect(colorBands).toEqual(['#CAD3E2', '#CAD3E2']); }); it('sets proper color bands if palette steps are smaller than minimum', () => { const palette = { @@ -268,7 +268,7 @@ describe('GaugeComponent', function () { } as GaugeRenderProps; const bullet = shallowWithIntl().find(Bullet); const colorBands = bullet.prop('colorBands'); - expect(colorBands).toEqual(['#D3DAE6', '#D3DAE6']); + expect(colorBands).toEqual(['#CAD3E2', '#CAD3E2']); }); it('sets proper color bands if percent palette steps are smaller than 0', () => { const palette = { @@ -296,7 +296,7 @@ describe('GaugeComponent', function () { } as GaugeRenderProps; const bullet = shallowWithIntl().find(Bullet); const colorBands = bullet.prop('colorBands'); - expect(colorBands).toEqual(['#D3DAE6', '#D3DAE6']); + expect(colorBands).toEqual(['#CAD3E2', '#CAD3E2']); }); it('doesnt set bands for values differing <10%', () => { const palette = { @@ -324,7 +324,7 @@ describe('GaugeComponent', function () { } as GaugeRenderProps; const bullet = shallowWithIntl().find(Bullet); const colorBands = bullet.prop('colorBands'); - expect(colorBands).toEqual(['#D3DAE6', '#D3DAE6']); + expect(colorBands).toEqual(['#CAD3E2', '#CAD3E2']); }); it('sets proper color bands for values greater than maximum', () => { const palette = { @@ -352,7 +352,7 @@ describe('GaugeComponent', function () { } as GaugeRenderProps; const bullet = shallowWithIntl().find(Bullet); const colorBands = bullet.prop('colorBands'); - expect(colorBands).toEqual(['#D3DAE6', '#D3DAE6']); + expect(colorBands).toEqual(['#CAD3E2', '#CAD3E2']); }); it('passes number bands from color palette with no stops defined', () => { const palette = { diff --git a/src/platform/plugins/shared/chart_expressions/expression_legacy_metric/.storybook/main.js b/src/platform/plugins/shared/chart_expressions/expression_legacy_metric/.storybook/main.js index 18faa0335df0d..ee807948934b7 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_legacy_metric/.storybook/main.js +++ b/src/platform/plugins/shared/chart_expressions/expression_legacy_metric/.storybook/main.js @@ -8,7 +8,7 @@ */ import { defaultConfig } from '@kbn/storybook'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { resolve } from 'path'; const mockConfig = { diff --git a/src/platform/plugins/shared/chart_expressions/expression_metric/.storybook/main.js b/src/platform/plugins/shared/chart_expressions/expression_metric/.storybook/main.js index b12d2e91b8540..5b8471849cda8 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_metric/.storybook/main.js +++ b/src/platform/plugins/shared/chart_expressions/expression_metric/.storybook/main.js @@ -8,7 +8,7 @@ */ import { defaultConfig } from '@kbn/storybook'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { resolve } from 'path'; const mockConfig = { diff --git a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/.storybook/main.js b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/.storybook/main.js index 65c802d71b989..206604f1ff758 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/.storybook/main.js +++ b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/.storybook/main.js @@ -8,7 +8,7 @@ */ import { defaultConfig } from '@kbn/storybook'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { resolve } from 'path'; const mockConfig = { diff --git a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tag_cloud.scss b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tag_cloud.scss deleted file mode 100644 index 8a017150fe195..0000000000000 --- a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tag_cloud.scss +++ /dev/null @@ -1,28 +0,0 @@ -// Prefix all styles with "tgc" to avoid conflicts. -// Examples -// tgcChart -// tgcChart__legend -// tgcChart__legend--small -// tgcChart__legend-isLoading - -.tgcChart__wrapper { - flex: 1 1 0; - display: flex; - flex-direction: column; - // it is used for rendering at `Canvas`. - height: 100%; -} - -.tgcChart__wrapper text { - cursor: pointer; -} - -.tgcChart__label { - width: 100%; - text-align: center; - font-weight: $euiFontWeightBold; -} - -.tgcChart__warning { - width: $euiSize; -} diff --git a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx index 46064ebd6b6e2..aa196eecf3812 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx +++ b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/public/components/tagcloud_component.tsx @@ -11,7 +11,7 @@ import React, { useCallback, useEffect, useState, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { throttle } from 'lodash'; -import { EuiIconTip, EuiResizeObserver } from '@elastic/eui'; +import { EuiIconTip, EuiResizeObserver, UseEuiTheme } from '@elastic/eui'; import { IconChartTagcloud } from '@kbn/chart-icons'; import { Chart, @@ -30,12 +30,11 @@ import type { AllowedSettingsOverrides, AllowedChartOverrides } from '@kbn/chart import { getColumnByAccessor, getFormatByAccessor } from '@kbn/visualizations-plugin/common/utils'; import { isMultiFieldKey } from '@kbn/data-plugin/common'; import { KbnPalettes, useKbnPalettes } from '@kbn/palettes'; +import { css } from '@emotion/react'; import { getFormatService } from '../format_service'; import { TagcloudRendererConfig } from '../../common/types'; import { ScaleOptions, Orientation } from '../../common/constants'; -import './tag_cloud.scss'; - const MAX_TAG_COUNT = 200; export type TagCloudChartProps = TagcloudRendererConfig & { @@ -237,7 +236,7 @@ export const TagCloudChart = ({ return ( {(resizeRef) => ( -
+
{label && showLabel && ( -
+
{label}
)} {!visParams.isPreview && warning && ( -
+
)} {!visParams.isPreview && tagCloudData.length > MAX_TAG_COUNT && ( -
+
+ css({ + width: '100%', + textAlign: 'center', + fontWeight: euiTheme.font.weight.bold, + }), + warning: ({ euiTheme }: UseEuiTheme) => + css({ + width: euiTheme.size.base, + }), +}; diff --git a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/tsconfig.json b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/tsconfig.json index e9fafe7144774..dedd498f7b39b 100644 --- a/src/platform/plugins/shared/chart_expressions/expression_tagcloud/tsconfig.json +++ b/src/platform/plugins/shared/chart_expressions/expression_tagcloud/tsconfig.json @@ -8,6 +8,7 @@ "common/**/*", "public/**/*", "server/**/*", + "../../../../../../typings/emotion.d.ts" ], "kbn_references": [ { "path": "../tsconfig.json" }, diff --git a/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.test.ts b/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.test.ts index f7c6bd3b32054..7110496e407cb 100644 --- a/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.test.ts +++ b/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.test.ts @@ -11,6 +11,7 @@ * Mock the function "populateContext" that accesses the autocomplete definitions */ import { monaco } from '@kbn/monaco'; +import { MonacoEditorActionsProvider } from '../monaco_editor_actions_provider'; const mockPopulateContext = jest.fn(); @@ -26,6 +27,7 @@ import { getDocumentationLinkFromAutocomplete, getUrlPathCompletionItems, shouldTriggerSuggestions, + getBodyCompletionItems, } from './autocomplete_utils'; describe('autocomplete_utils', () => { @@ -216,4 +218,80 @@ describe('autocomplete_utils', () => { expect(items.length).toBe(5); }); }); + + describe('inline JSON body completion', () => { + it('completes "term" inside {"query": {te}} without extra quotes or missing template', async () => { + // 1) Set up a mock monaco model with two lines of text + // - Line 1: GET index/_search + // - Line 2: {"query": {te}} + // In a real editor, requestStartLineNumber = 1 (0-based vs 1-based might differ), + // so we adjust accordingly in the test. + const mockModel = { + getLineContent: (lineNumber: number) => { + if (lineNumber === 1) { + // request line + return 'GET index/_search'; + } else if (lineNumber === 2) { + // inline JSON with partial property 'te' + return '{"query": {te}}'; + } + return ''; + }, + // getValueInRange will return everything from line 2 up to our position + getValueInRange: ({ startLineNumber, endLineNumber }: monaco.IRange) => { + if (startLineNumber === 2 && endLineNumber === 2) { + // partial body up to cursor (we can just return the entire line for simplicity) + return '{"query": {te}}'; + } + return ''; + }, + getWordUntilPosition: () => ({ + startColumn: 13, // approximate "te" start + endColumn: 15, + word: 'te', + }), + getLineMaxColumn: () => 999, // large max + } as unknown as monaco.editor.ITextModel; + + // 2) The user is on line 2, at column ~15 (after 'te'). + const mockPosition = { + lineNumber: 2, + column: 15, + } as monaco.Position; + + mockPopulateContext.mockImplementation((...args) => { + const context = args[0][1]; + context.autoCompleteSet = [ + { + name: 'term', + }, + ]; + }); + + // 4) We call getBodyCompletionItems, passing requestStartLineNumber = 1 + // because line 1 has "GET index/_search", so line 2 is the body. + const mockEditor = {} as MonacoEditorActionsProvider; + const suggestions = await getBodyCompletionItems( + mockModel, + mockPosition, + 1, // the line number where the request method/URL is + mockEditor + ); + + // 5) We should get 1 suggestion for "term" + expect(suggestions).toHaveLength(1); + const termSuggestion = suggestions[0]; + + // 6) Check the snippet text. For example, if your final snippet logic + // inserts `"term": $0`, we ensure there's no extra quote like ""term" + // and if you have a template for "term", we can check that too. + const insertText = termSuggestion.insertText; + + // No double quotes at the start: + expect(insertText).not.toContain('""term"'); + // Valid JSON snippet + expect(insertText).toContain('"term"'); + expect(insertText).toContain('$0'); + }); + }); }); diff --git a/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.ts b/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.ts index c36542b43e75e..71e231f54a796 100644 --- a/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.ts +++ b/src/platform/plugins/shared/console/public/application/containers/editor/utils/autocomplete_utils.ts @@ -348,33 +348,19 @@ const getInsertText = ( if (name === undefined) { return ''; } - let insertText = ''; - if (typeof name === 'string') { - const bodyContentLines = bodyContent.split('\n'); - const currentContentLine = bodyContentLines[bodyContentLines.length - 1]; - const incompleteFieldRegex = /.*"[^"]*$/; - if (incompleteFieldRegex.test(currentContentLine)) { - // The cursor is after an unmatched quote (e.g. '..."abc', '..."') - insertText = ''; - } else { - // The cursor is at the beginning of a field so the insert text should start with a quote - insertText = '"'; - } - if (insertValue && insertValue !== '{' && insertValue !== '[') { - insertText += `${insertValue}"`; - } else { - insertText += `${name}"`; - } - } else { - insertText = name + ''; - } + + // Always create the insert text with the name first, check the end of the body content + // to decide if we need to add a double quote after the name. + // This is done to avoid adding a double quote if the user is typing a value after the name. + let insertText = bodyContent.trim().endsWith('"') ? `${name}"` : `"${name}"`; // check if there is template to add const conditionalTemplate = getConditionalTemplate(name, bodyContent, context.endpoint); if (conditionalTemplate) { template = conditionalTemplate; } - if (template !== undefined && context.addTemplate) { + + if (template) { let templateLines; const { __raw, value: templateValue } = template; if (__raw && templateValue) { @@ -384,10 +370,16 @@ const getInsertText = ( } insertText += ': ' + templateLines.join('\n'); } else if (value === '{') { - insertText += '{}'; + insertText += ': {$0}'; } else if (value === '[') { - insertText += '[]'; + insertText += ': [$0]'; + } else if (insertValue && insertValue !== '{' && insertValue !== '[') { + insertText = `"${insertValue}"`; + insertText += ': $0'; + } else { + insertText += ': $0'; } + // the string $0 is used to move the cursor between empty curly/square brackets if (insertText.endsWith('{}')) { insertText = insertText.substring(0, insertText.length - 2) + '{$0}'; diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_app/_dashboard_app.scss b/src/platform/plugins/shared/dashboard/public/dashboard_app/_dashboard_app.scss index c89337d29e720..dfef1bf0c4ec9 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_app/_dashboard_app.scss +++ b/src/platform/plugins/shared/dashboard/public/dashboard_app/_dashboard_app.scss @@ -1,4 +1,4 @@ -@import 'src/core/public/mixins'; +@import '../../../../../../../src/core/public/mixins'; .dshUnsavedListingItem { margin-top: $euiSizeM; diff --git a/src/platform/plugins/shared/discover/.storybook/discover.webpack.ts b/src/platform/plugins/shared/discover/.storybook/main.js similarity index 81% rename from src/platform/plugins/shared/discover/.storybook/discover.webpack.ts rename to src/platform/plugins/shared/discover/.storybook/main.js index 91c2a37df3942..aa82846a1c085 100644 --- a/src/platform/plugins/shared/discover/.storybook/discover.webpack.ts +++ b/src/platform/plugins/shared/discover/.storybook/main.js @@ -7,9 +7,9 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { defaultConfig, StorybookConfig } from '@kbn/storybook'; +import { defaultConfig } from '@kbn/storybook'; -export const discoverStorybookConfig: StorybookConfig = { +module.exports = { ...defaultConfig, stories: ['../**/*.stories.tsx'], }; diff --git a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts index 1e84012942c16..1c5731ce6d81e 100644 --- a/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts +++ b/src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/logs_data_source_profile/profile.test.ts @@ -172,7 +172,7 @@ describe('logsDataSourceProfileProvider', () => { }); expect(getRowIndicator).toBeDefined(); - expect(getRowIndicator?.(row, euiTheme)).toEqual({ color: '#90b0d1', label: 'Info' }); + expect(getRowIndicator?.(row, euiTheme)).toEqual({ color: '#90bdff', label: 'Info' }); }); it('should not return a color for a missing log level in the document', () => { diff --git a/src/platform/plugins/shared/telemetry/schema/oss_platform.json b/src/platform/plugins/shared/telemetry/schema/oss_platform.json index 7dd943ba7557b..487f404ab135f 100644 --- a/src/platform/plugins/shared/telemetry/schema/oss_platform.json +++ b/src/platform/plugins/shared/telemetry/schema/oss_platform.json @@ -8562,6 +8562,12 @@ "description": "Maximum payload size in bytes that is allowed." } }, + "protocol": { + "type": "keyword", + "_meta": { + "description": "Protocol to serve the requests (\"http1\" | \"http2\")" + } + }, "rewriteBasePath": { "type": "boolean", "_meta": { diff --git a/src/platform/plugins/shared/unified_search/.storybook/main.js b/src/platform/plugins/shared/unified_search/.storybook/main.js index 86528a888e70e..6eb26edfec43e 100644 --- a/src/platform/plugins/shared/unified_search/.storybook/main.js +++ b/src/platform/plugins/shared/unified_search/.storybook/main.js @@ -8,7 +8,7 @@ */ import { defaultConfig } from '@kbn/storybook'; -import webpackMerge from 'webpack-merge'; +import { merge as webpackMerge } from 'webpack-merge'; import { resolve } from 'path'; const mockConfig = { diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/state.ts b/src/platform/plugins/shared/visualizations/public/embeddable/state.ts index 2b1baea47c829..1965865371310 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/state.ts +++ b/src/platform/plugins/shared/visualizations/public/embeddable/state.ts @@ -30,13 +30,11 @@ import { import { getSavedVisualization } from '../utils/saved_visualize_utils'; import type { SerializedVis } from '../vis'; import { - isVisualizeSavedObjectState, VisualizeSavedObjectInputState, VisualizeSerializedState, VisualizeRuntimeState, VisualizeSavedVisInputState, ExtraSavedObjectProperties, - isVisualizeRuntimeState, } from './types'; export const deserializeState = async ( @@ -49,15 +47,24 @@ export const deserializeState = async ( }, } as VisualizeRuntimeState; let serializedState = cloneDeep(state.rawState); - if (isVisualizeSavedObjectState(serializedState)) { - serializedState = await deserializeSavedObjectState(serializedState); - } else if (isVisualizeRuntimeState(serializedState)) { + if ((serializedState as VisualizeSavedObjectInputState).savedObjectId) { + serializedState = await deserializeSavedObjectState( + serializedState as VisualizeSavedObjectInputState + ); + } else if ((serializedState as VisualizeRuntimeState).serializedVis) { + // TODO remove once embeddable only exposes SerializedState + // Canvas passes incoming embeddable state in getSerializedStateForChild + // without this early return, serializedVis gets replaced in deserializeSavedVisState + // and breaks adding a new by-value embeddable in Canvas return serializedState as VisualizeRuntimeState; } const references: Reference[] = state.references ?? []; - const deserializedSavedVis = deserializeSavedVisState(serializedState, references); + const deserializedSavedVis = deserializeSavedVisState( + serializedState as VisualizeSavedVisInputState, + references + ); return { ...serializedState, diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/types.ts b/src/platform/plugins/shared/visualizations/public/embeddable/types.ts index ad7a7c86dde58..84b5c84e5d60e 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/types.ts +++ b/src/platform/plugins/shared/visualizations/public/embeddable/types.ts @@ -71,26 +71,6 @@ export type VisualizeOutputState = VisualizeSavedVisInputState & Required> & ExtraSavedObjectProperties; -export const isVisualizeSavedObjectState = ( - state: unknown -): state is VisualizeSavedObjectInputState => { - return ( - typeof state !== 'undefined' && - (state as VisualizeSavedObjectInputState).savedObjectId !== undefined && - !!(state as VisualizeSavedObjectInputState).savedObjectId && - !('savedVis' in (state as VisualizeSavedObjectInputState)) && - !('serializedVis' in (state as VisualizeSavedObjectInputState)) - ); -}; - -export const isVisualizeRuntimeState = (state: unknown): state is VisualizeRuntimeState => { - return ( - !isVisualizeSavedObjectState(state) && - !('savedVis' in (state as VisualizeRuntimeState)) && - (state as VisualizeRuntimeState).serializedVis !== undefined - ); -}; - export type VisualizeApi = Partial & PublishesDataViews & PublishesDataLoading & diff --git a/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx b/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx index 873e030fdfb9f..57c95cfc60700 100644 --- a/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/platform/plugins/shared/visualizations/public/embeddable/visualize_embeddable.tsx @@ -54,7 +54,6 @@ import { VisualizeOutputState, VisualizeRuntimeState, VisualizeSerializedState, - isVisualizeSavedObjectState, } from './types'; import { initializeEditApi } from './initialize_edit_api'; @@ -67,15 +66,11 @@ export const getVisualizeEmbeddableFactory: (deps: { }) => ({ type: VISUALIZE_EMBEDDABLE_TYPE, deserializeState, - buildEmbeddable: async (initialState: unknown, buildApi, uuid, parentApi) => { - // Handle state transfer from legacy visualize editor, which uses the legacy visualize embeddable and doesn't - // produce a snapshot state. If buildEmbeddable is passed only a savedObjectId in the state, this means deserializeState - // was never run, and it needs to be invoked manually - const state = isVisualizeSavedObjectState(initialState) - ? await deserializeState({ - rawState: initialState, - }) - : (initialState as VisualizeRuntimeState); + buildEmbeddable: async (initialState, buildApi, uuid, parentApi) => { + const state = { + ...initialState, + linkedToLibrary: Boolean(initialState.savedObjectId), + }; // Initialize dynamic actions const dynamicActionsApi = embeddableEnhancedStart?.initializeReactEmbeddableDynamicActions( diff --git a/src/platform/plugins/shared/visualizations/public/plugin.ts b/src/platform/plugins/shared/visualizations/public/plugin.ts index 38f0b4d209bf9..56395bc4d1612 100644 --- a/src/platform/plugins/shared/visualizations/public/plugin.ts +++ b/src/platform/plugins/shared/visualizations/public/plugin.ts @@ -406,10 +406,15 @@ export class VisualizationsPlugin return getVisualizeEmbeddableFactory({ embeddableStart, embeddableEnhancedStart }); }); embeddable.registerAddFromLibraryType({ - onAdd: (container, savedObject) => { + onAdd: async (container, savedObject) => { + const { deserializeState } = await import('./embeddable/state'); + const initialState = await deserializeState({ + rawState: { savedObjectId: savedObject.id }, + references: savedObject.references, + }); container.addNewPanel({ panelType: VISUALIZE_EMBEDDABLE_TYPE, - initialState: { savedObjectId: savedObject.id }, + initialState, }); }, savedObjectType: VISUALIZE_EMBEDDABLE_TYPE, diff --git a/src/platform/plugins/shared/visualizations/public/visualize_app/utils/get_top_nav_config.tsx b/src/platform/plugins/shared/visualizations/public/visualize_app/utils/get_top_nav_config.tsx index 32b223a58c9c1..10adf085fdf8c 100644 --- a/src/platform/plugins/shared/visualizations/public/visualize_app/utils/get_top_nav_config.tsx +++ b/src/platform/plugins/shared/visualizations/public/visualize_app/utils/get_top_nav_config.tsx @@ -186,7 +186,10 @@ export const getTopNavConfig = ( stateTransfer.navigateToWithEmbeddablePackage(app, { state: { type: VISUALIZE_EMBEDDABLE_TYPE, - input: { savedObjectId: id }, + input: { + serializedVis: vis.serialize(), + savedObjectId: id, + }, embeddableId: saveOptions.copyOnSave ? undefined : embeddableId, searchSessionId: data.search.session.getSessionId(), }, diff --git a/test/functional/apps/console/_autocomplete.ts b/test/functional/apps/console/_autocomplete.ts index 2f771a2f70097..50f3de7de605a 100644 --- a/test/functional/apps/console/_autocomplete.ts +++ b/test/functional/apps/console/_autocomplete.ts @@ -59,6 +59,33 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(PageObjects.console.isAutocompleteVisible()).to.be.eql(true); }); + it('correctly autocompletes inline JSON', async () => { + // 1) Type the request line + inline body (two lines total). + await PageObjects.console.enterText('GET index/_search\n{"query": {t'); + + // 2) Trigger autocomplete + await PageObjects.console.sleepForDebouncePeriod(); + await PageObjects.console.promptAutocomplete('e'); + + // 3) Wait for the autocomplete suggestions to appear + await retry.waitFor('autocomplete to be visible', () => + PageObjects.console.isAutocompleteVisible() + ); + + // 4) Press Enter to accept the first suggestion (likely "term") + await PageObjects.console.pressEnter(); + + // 5) Now check the text in the editor + await retry.try(async () => { + const text = await PageObjects.console.getEditorText(); + // Assert we do NOT invalid autocompletions such as `""term"` or `{term"` + expect(text).not.to.contain('""term"'); + expect(text).not.to.contain('{term"'); + // and that "term" was inserted + expect(text).to.contain('"term"'); + }); + }); + it('should not show duplicate suggestions', async () => { await PageObjects.console.enterText(`POST _ingest/pipeline/_simulate { diff --git a/tsconfig.base.json b/tsconfig.base.json index a070ce01350b0..5219ba8e47f26 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -48,8 +48,8 @@ "@kbn/alerting-fixture-plugin/*": ["x-pack/test/functional_with_es_ssl/plugins/alerts/*"], "@kbn/alerting-plugin": ["x-pack/platform/plugins/shared/alerting"], "@kbn/alerting-plugin/*": ["x-pack/platform/plugins/shared/alerting/*"], - "@kbn/alerting-rule-utils": ["x-pack/platform/packages/shared/alerting_rule_utils"], - "@kbn/alerting-rule-utils/*": ["x-pack/platform/packages/shared/alerting_rule_utils/*"], + "@kbn/alerting-rule-utils": ["x-pack/platform/packages/shared/alerting-rule-utils"], + "@kbn/alerting-rule-utils/*": ["x-pack/platform/packages/shared/alerting-rule-utils/*"], "@kbn/alerting-state-types": ["x-pack/platform/packages/private/kbn-alerting-state-types"], "@kbn/alerting-state-types/*": ["x-pack/platform/packages/private/kbn-alerting-state-types/*"], "@kbn/alerting-types": ["src/platform/packages/shared/kbn-alerting-types"], @@ -1188,8 +1188,8 @@ "@kbn/logs-data-access-plugin/*": ["x-pack/platform/plugins/shared/logs_data_access/*"], "@kbn/logs-explorer-plugin": ["x-pack/solutions/observability/plugins/logs_explorer"], "@kbn/logs-explorer-plugin/*": ["x-pack/solutions/observability/plugins/logs_explorer/*"], - "@kbn/logs-overview": ["x-pack/platform/packages/shared/logs_overview"], - "@kbn/logs-overview/*": ["x-pack/platform/packages/shared/logs_overview/*"], + "@kbn/logs-overview": ["x-pack/platform/packages/shared/logs-overview"], + "@kbn/logs-overview/*": ["x-pack/platform/packages/shared/logs-overview/*"], "@kbn/logs-shared-plugin": ["x-pack/platform/plugins/shared/logs_shared"], "@kbn/logs-shared-plugin/*": ["x-pack/platform/plugins/shared/logs_shared/*"], "@kbn/logstash-plugin": ["x-pack/platform/plugins/private/logstash"], @@ -1324,6 +1324,8 @@ "@kbn/newsfeed-test-plugin/*": ["test/common/plugins/newsfeed/*"], "@kbn/no-data-page-plugin": ["src/platform/plugins/private/no_data_page"], "@kbn/no-data-page-plugin/*": ["src/platform/plugins/private/no_data_page/*"], + "@kbn/node-libs-browser-webpack-plugin": ["packages/kbn-node-libs-browser-webpack-plugin"], + "@kbn/node-libs-browser-webpack-plugin/*": ["packages/kbn-node-libs-browser-webpack-plugin/*"], "@kbn/notifications-plugin": ["x-pack/platform/plugins/shared/notifications"], "@kbn/notifications-plugin/*": ["x-pack/platform/plugins/shared/notifications/*"], "@kbn/object-utils": ["src/platform/packages/shared/kbn-object-utils"], @@ -1338,18 +1340,18 @@ "@kbn/observability-ai-assistant-management-plugin/*": ["x-pack/solutions/observability/plugins/observability_ai_assistant_management/*"], "@kbn/observability-ai-assistant-plugin": ["x-pack/platform/plugins/shared/observability_ai_assistant"], "@kbn/observability-ai-assistant-plugin/*": ["x-pack/platform/plugins/shared/observability_ai_assistant/*"], - "@kbn/observability-ai-common": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_common"], - "@kbn/observability-ai-common/*": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_common/*"], - "@kbn/observability-ai-server": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_server"], - "@kbn/observability-ai-server/*": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_server/*"], - "@kbn/observability-alert-details": ["x-pack/solutions/observability/packages/alert_details"], - "@kbn/observability-alert-details/*": ["x-pack/solutions/observability/packages/alert_details/*"], - "@kbn/observability-alerting-test-data": ["x-pack/solutions/observability/packages/alerting_test_data"], - "@kbn/observability-alerting-test-data/*": ["x-pack/solutions/observability/packages/alerting_test_data/*"], + "@kbn/observability-ai-common": ["x-pack/solutions/observability/packages/observability-ai/observability-ai-common"], + "@kbn/observability-ai-common/*": ["x-pack/solutions/observability/packages/observability-ai/observability-ai-common/*"], + "@kbn/observability-ai-server": ["x-pack/solutions/observability/packages/observability-ai/observability-ai-server"], + "@kbn/observability-ai-server/*": ["x-pack/solutions/observability/packages/observability-ai/observability-ai-server/*"], + "@kbn/observability-alert-details": ["x-pack/solutions/observability/packages/alert-details"], + "@kbn/observability-alert-details/*": ["x-pack/solutions/observability/packages/alert-details/*"], + "@kbn/observability-alerting-test-data": ["x-pack/solutions/observability/packages/alerting-test-data"], + "@kbn/observability-alerting-test-data/*": ["x-pack/solutions/observability/packages/alerting-test-data/*"], "@kbn/observability-fixtures-plugin": ["x-pack/test/cases_api_integration/common/plugins/observability"], "@kbn/observability-fixtures-plugin/*": ["x-pack/test/cases_api_integration/common/plugins/observability/*"], - "@kbn/observability-get-padded-alert-time-range-util": ["x-pack/solutions/observability/packages/get_padded_alert_time_range_util"], - "@kbn/observability-get-padded-alert-time-range-util/*": ["x-pack/solutions/observability/packages/get_padded_alert_time_range_util/*"], + "@kbn/observability-get-padded-alert-time-range-util": ["x-pack/solutions/observability/packages/get-padded-alert-time-range-util"], + "@kbn/observability-get-padded-alert-time-range-util/*": ["x-pack/solutions/observability/packages/get-padded-alert-time-range-util/*"], "@kbn/observability-logs-explorer-plugin": ["x-pack/solutions/observability/plugins/observability_logs_explorer"], "@kbn/observability-logs-explorer-plugin/*": ["x-pack/solutions/observability/plugins/observability_logs_explorer/*"], "@kbn/observability-onboarding-plugin": ["x-pack/solutions/observability/plugins/observability_onboarding"], @@ -1360,12 +1362,12 @@ "@kbn/observability-shared-plugin/*": ["x-pack/solutions/observability/plugins/observability_shared/*"], "@kbn/observability-synthetics-test-data": ["x-pack/solutions/observability/packages/synthetics_test_data"], "@kbn/observability-synthetics-test-data/*": ["x-pack/solutions/observability/packages/synthetics_test_data/*"], - "@kbn/observability-utils-browser": ["x-pack/solutions/observability/packages/utils_browser"], - "@kbn/observability-utils-browser/*": ["x-pack/solutions/observability/packages/utils_browser/*"], - "@kbn/observability-utils-common": ["x-pack/solutions/observability/packages/utils_common"], - "@kbn/observability-utils-common/*": ["x-pack/solutions/observability/packages/utils_common/*"], - "@kbn/observability-utils-server": ["x-pack/solutions/observability/packages/utils_server"], - "@kbn/observability-utils-server/*": ["x-pack/solutions/observability/packages/utils_server/*"], + "@kbn/observability-utils-browser": ["x-pack/solutions/observability/packages/utils-browser"], + "@kbn/observability-utils-browser/*": ["x-pack/solutions/observability/packages/utils-browser/*"], + "@kbn/observability-utils-common": ["x-pack/solutions/observability/packages/utils-common"], + "@kbn/observability-utils-common/*": ["x-pack/solutions/observability/packages/utils-common/*"], + "@kbn/observability-utils-server": ["x-pack/solutions/observability/packages/utils-server"], + "@kbn/observability-utils-server/*": ["x-pack/solutions/observability/packages/utils-server/*"], "@kbn/oidc-provider-plugin": ["x-pack/test/security_api_integration/plugins/oidc_provider"], "@kbn/oidc-provider-plugin/*": ["x-pack/test/security_api_integration/plugins/oidc_provider/*"], "@kbn/open-telemetry-instrumented-plugin": ["test/common/plugins/otel_metrics"], @@ -1612,8 +1614,8 @@ "@kbn/search-playground/*": ["x-pack/solutions/search/plugins/search_playground/*"], "@kbn/search-response-warnings": ["src/platform/packages/shared/kbn-search-response-warnings"], "@kbn/search-response-warnings/*": ["src/platform/packages/shared/kbn-search-response-warnings/*"], - "@kbn/search-shared-ui": ["x-pack/solutions/search/packages/shared_ui"], - "@kbn/search-shared-ui/*": ["x-pack/solutions/search/packages/shared_ui/*"], + "@kbn/search-shared-ui": ["x-pack/solutions/search/packages/shared-ui"], + "@kbn/search-shared-ui/*": ["x-pack/solutions/search/packages/shared-ui/*"], "@kbn/search-synonyms": ["x-pack/solutions/search/plugins/search_synonyms"], "@kbn/search-synonyms/*": ["x-pack/solutions/search/plugins/search_synonyms/*"], "@kbn/search-types": ["src/platform/packages/shared/kbn-search-types"], @@ -1646,8 +1648,8 @@ "@kbn/security-role-management-model/*": ["x-pack/platform/packages/private/security/role_management_model/*"], "@kbn/security-solution-connectors": ["x-pack/solutions/security/packages/connectors"], "@kbn/security-solution-connectors/*": ["x-pack/solutions/security/packages/connectors/*"], - "@kbn/security-solution-distribution-bar": ["x-pack/solutions/security/packages/distribution_bar"], - "@kbn/security-solution-distribution-bar/*": ["x-pack/solutions/security/packages/distribution_bar/*"], + "@kbn/security-solution-distribution-bar": ["x-pack/solutions/security/packages/distribution-bar"], + "@kbn/security-solution-distribution-bar/*": ["x-pack/solutions/security/packages/distribution-bar/*"], "@kbn/security-solution-ess": ["x-pack/solutions/security/plugins/security_solution_ess"], "@kbn/security-solution-ess/*": ["x-pack/solutions/security/plugins/security_solution_ess/*"], "@kbn/security-solution-features": ["x-pack/solutions/security/packages/features"], diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index d617094720c84..63da67bd90806 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -111,7 +111,7 @@ "xpack.observability_onboarding": "solutions/observability/plugins/observability_onboarding", "xpack.observabilityShared": "solutions/observability/plugins/observability_shared", "xpack.observabilityLogsOverview": [ - "platform/packages/shared/logs_overview/src/components" + "platform/packages/shared/logs-overview/src/components" ], "xpack.osquery": [ "platform/plugins/shared/osquery" @@ -130,7 +130,7 @@ ], "xpack.runtimeFields": "platform/plugins/private/runtime_fields", "xpack.screenshotting": "platform/plugins/shared/screenshotting", - "xpack.searchSharedUI": "solutions/search/packages/shared_ui", + "xpack.searchSharedUI": "solutions/search/packages/shared-ui", "xpack.searchHomepage": "solutions/search/plugins/search_homepage", "xpack.searchIndices": "solutions/search/plugins/search_indices", "xpack.searchNavigation": "solutions/search/plugins/search_solution/search_navigation", diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/README.md b/x-pack/platform/packages/shared/alerting-rule-utils/README.md similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/README.md rename to x-pack/platform/packages/shared/alerting-rule-utils/README.md diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/index.ts b/x-pack/platform/packages/shared/alerting-rule-utils/index.ts similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/index.ts rename to x-pack/platform/packages/shared/alerting-rule-utils/index.ts diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/jest.config.js b/x-pack/platform/packages/shared/alerting-rule-utils/jest.config.js similarity index 81% rename from x-pack/platform/packages/shared/alerting_rule_utils/jest.config.js rename to x-pack/platform/packages/shared/alerting-rule-utils/jest.config.js index 120294e177a35..2abb1a27e80a6 100644 --- a/x-pack/platform/packages/shared/alerting_rule_utils/jest.config.js +++ b/x-pack/platform/packages/shared/alerting-rule-utils/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/platform/packages/shared/alerting_rule_utils'], + roots: ['/x-pack/platform/packages/shared/alerting-rule-utils'], }; diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/kibana.jsonc b/x-pack/platform/packages/shared/alerting-rule-utils/kibana.jsonc similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/kibana.jsonc rename to x-pack/platform/packages/shared/alerting-rule-utils/kibana.jsonc diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/package.json b/x-pack/platform/packages/shared/alerting-rule-utils/package.json similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/package.json rename to x-pack/platform/packages/shared/alerting-rule-utils/package.json diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/src/get_ecs_groups.test.ts b/x-pack/platform/packages/shared/alerting-rule-utils/src/get_ecs_groups.test.ts similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/src/get_ecs_groups.test.ts rename to x-pack/platform/packages/shared/alerting-rule-utils/src/get_ecs_groups.test.ts diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/src/get_ecs_groups.ts b/x-pack/platform/packages/shared/alerting-rule-utils/src/get_ecs_groups.ts similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/src/get_ecs_groups.ts rename to x-pack/platform/packages/shared/alerting-rule-utils/src/get_ecs_groups.ts diff --git a/x-pack/platform/packages/shared/alerting_rule_utils/tsconfig.json b/x-pack/platform/packages/shared/alerting-rule-utils/tsconfig.json similarity index 100% rename from x-pack/platform/packages/shared/alerting_rule_utils/tsconfig.json rename to x-pack/platform/packages/shared/alerting-rule-utils/tsconfig.json diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx index 143cd3367a804..fa75e2dc475d8 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/chat/chat_body.tsx @@ -374,7 +374,7 @@ export function ChatBody({ paddingSize="m" className={animClassName(euiTheme)} > - {connectors.connectors?.length === 0 || messages.length === 1 ? ( + {connectors.connectors?.length === 0 || messages.length === 0 ? ( ; - case MessageRole.System: - return ; - default: return null; } diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/hooks/use_conversation.test.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/hooks/use_conversation.test.tsx index 196553ce55066..ac65d22eff6eb 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/hooks/use_conversation.test.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/hooks/use_conversation.test.tsx @@ -116,16 +116,8 @@ describe('useConversation', () => { }); }); - it('returns only the system message', () => { - expect(hookResult.result.current.messages).toEqual([ - { - '@timestamp': expect.any(String), - message: { - content: '', - role: MessageRole.System, - }, - }, - ]); + it('returns empty messages', () => { + expect(hookResult.result.current.messages).toEqual([]); }); it('returns a ready state', () => { @@ -157,15 +149,8 @@ describe('useConversation', () => { }); }); - it('returns the system message and the initial messages', () => { + it('returns the initial messages', () => { expect(hookResult.result.current.messages).toEqual([ - { - '@timestamp': expect.any(String), - message: { - content: '', - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -183,14 +168,8 @@ describe('useConversation', () => { conversation: { id: 'my-conversation-id', }, + systemMessage: 'System', messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -218,14 +197,8 @@ describe('useConversation', () => { conversation: { id: 'my-conversation-id', }, + systemMessage: 'System', messages: [ - { - '@timestamp': expect.any(String), - message: { - content: 'System', - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -239,13 +212,6 @@ describe('useConversation', () => { it('sets messages to the messages of the conversation', () => { expect(hookResult.result.current.messages).toEqual([ - { - '@timestamp': expect.any(String), - message: { - content: expect.any(String), - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -255,10 +221,6 @@ describe('useConversation', () => { }, ]); }); - - it('overrides the system message', () => { - expect(hookResult.result.current.messages[0].message.content).toBe(''); - }); }); describe('with a conversation id that fails to load', () => { @@ -282,7 +244,7 @@ describe('useConversation', () => { }); it('resets the messages', () => { - expect(hookResult.result.current.messages.length).toBe(1); + expect(hookResult.result.current.messages.length).toBe(0); }); }); @@ -290,13 +252,6 @@ describe('useConversation', () => { const subject: Subject = new Subject(); let onConversationUpdate: jest.Mock; const expectedMessages = [ - { - '@timestamp': expect.any(String), - message: { - role: MessageRole.System, - content: '', - }, - }, { '@timestamp': expect.any(String), message: { @@ -333,6 +288,7 @@ describe('useConversation', () => { conversation: { id: 'my-conversation-id', }, + systemMessage: '', messages: expectedMessages, }, (request as any).params.body diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/builders.ts b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/builders.ts index 0f614f37642f1..219d243b98993 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/builders.ts +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/builders.ts @@ -32,19 +32,6 @@ export function buildMessage(params: BuildMessageProps): Message { ); } -export function buildSystemMessage( - params?: Omit & { - message: DeepPartial>; - } -) { - return buildMessage( - // @ts-expect-error upgrade typescript v5.1.6 - merge({}, params, { - message: { role: MessageRole.System }, - }) - ); -} - export function buildUserMessage( params?: Omit & { message?: DeepPartial>; @@ -117,7 +104,8 @@ export function buildConversation(params?: Partial): Conversation title: '', last_updated: '', }, - messages: [buildSystemMessage()], + systemMessage: '', + messages: [], labels: {}, numeric_labels: {}, namespace: '', diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/create_mock_chat_service.ts b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/create_mock_chat_service.ts index 7913b3ce78957..2256c8ad14944 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/create_mock_chat_service.ts +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/create_mock_chat_service.ts @@ -8,7 +8,6 @@ import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { FunctionDefinition, - MessageRole, ObservabilityAIAssistantChatService, } from '@kbn/observability-ai-assistant-plugin/public'; import { BehaviorSubject } from 'rxjs'; @@ -25,13 +24,7 @@ export const createMockChatService = (): MockedChatService => { hasFunction: jest.fn().mockReturnValue(false), hasRenderFunction: jest.fn().mockReturnValue(true), renderFunction: jest.fn(), - getSystemMessage: jest.fn().mockReturnValue({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: '', - }, - }), + getSystemMessage: jest.fn().mockReturnValue('system message'), getScopes: jest.fn(), }; return mockChatService; diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_role_translation.ts b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_role_translation.ts index 95421a089dea0..6e07ae9224091 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_role_translation.ts +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_role_translation.ts @@ -15,12 +15,6 @@ export function getRoleTranslation(role: MessageRole) { }); } - if (role === MessageRole.System) { - return i18n.translate('xpack.aiAssistant.chatTimeline.messages.system.label', { - defaultMessage: 'System', - }); - } - return i18n.translate('xpack.aiAssistant.chatTimeline.messages.elasticAssistant.label', { defaultMessage: 'Elastic Assistant', }); diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx index 7dcf9cadb6bbf..5f43204cbb398 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.test.tsx @@ -59,13 +59,6 @@ describe('getTimelineItemsFromConversation', () => { }, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -77,7 +70,7 @@ describe('getTimelineItemsFromConversation', () => { onActionClick: jest.fn(), }); }); - it('excludes the system message', () => { + it('includes the opening message and the user message', () => { expect(items.length).toBe(2); expect(items[0].title).toBe('started a conversation'); }); @@ -113,13 +106,6 @@ describe('getTimelineItemsFromConversation', () => { hasConnector: true, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -204,13 +190,6 @@ describe('getTimelineItemsFromConversation', () => { hasConnector: true, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -282,13 +261,6 @@ describe('getTimelineItemsFromConversation', () => { hasConnector: true, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -364,13 +336,6 @@ describe('getTimelineItemsFromConversation', () => { }, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -415,13 +380,6 @@ describe('getTimelineItemsFromConversation', () => { hasConnector: true, chatState: ChatState.Ready, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -491,13 +449,6 @@ describe('getTimelineItemsFromConversation', () => { hasConnector: true, chatState: ChatState.Loading, messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }, { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.tsx b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.tsx index 5160e8b636b6c..dcd1242ee535b 100644 --- a/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.tsx +++ b/x-pack/platform/packages/shared/kbn-ai-assistant/src/utils/get_timeline_items_from_conversation.tsx @@ -80,10 +80,6 @@ export function getTimelineItemsfromConversation({ payload: ChatActionClickPayload; }) => void; }): ChatTimelineItem[] { - const messagesWithoutSystem = messages.filter( - (message) => message.message.role !== MessageRole.System - ); - const items: ChatTimelineItem[] = [ { id: v4(), @@ -100,7 +96,7 @@ export function getTimelineItemsfromConversation({ }), role: MessageRole.User, }, - ...messagesWithoutSystem.map((message, index) => { + ...messages.map((message, index) => { const id = v4(); let title: React.ReactNode = ''; @@ -108,10 +104,8 @@ export function getTimelineItemsfromConversation({ let element: React.ReactNode | undefined; const prevFunctionCall = - message.message.name && - messagesWithoutSystem[index - 1] && - messagesWithoutSystem[index - 1].message.function_call - ? messagesWithoutSystem[index - 1].message.function_call + message.message.name && messages[index - 1] && messages[index - 1].message.function_call + ? messages[index - 1].message.function_call : undefined; let role = message.message.function_call?.trigger || message.message.role; diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/ess/elastic_assistant_api_2023_10_31.bundled.schema.yaml b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/ess/elastic_assistant_api_2023_10_31.bundled.schema.yaml index 2fa07930c01a5..763a7f0efb081 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/ess/elastic_assistant_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/ess/elastic_assistant_api_2023_10_31.bundled.schema.yaml @@ -1410,6 +1410,17 @@ components: query: description: An ESQL query type: string + timerange: + description: Time range to select in the time picker. + type: object + properties: + from: + type: string + to: + type: string + required: + - from + - to type: enum: - EsqlQuery diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/serverless/elastic_assistant_api_2023_10_31.bundled.schema.yaml b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/serverless/elastic_assistant_api_2023_10_31.bundled.schema.yaml index 3527628edf5ae..b4c3e59a17a71 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/serverless/elastic_assistant_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/docs/openapi/serverless/elastic_assistant_api_2023_10_31.bundled.schema.yaml @@ -1410,6 +1410,17 @@ components: query: description: An ESQL query type: string + timerange: + description: Time range to select in the time picker. + type: object + properties: + from: + type: string + to: + type: string + required: + - from + - to type: enum: - EsqlQuery diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/content_references/references/index.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/content_references/references/index.ts index d44d33fdc28e6..b2ccc6ce022c2 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/content_references/references/index.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/content_references/references/index.ts @@ -71,15 +71,11 @@ export const knowledgeBaseReference = ( * @returns KnowledgeBaseReference */ export const esqlQueryReference = ( - id: ContentReferenceId, - query: string, - label: string + params: Omit ): EsqlContentReference => { return { type: 'EsqlQuery', - id, - label, - query, + ...params, }; }; diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts index 82a76f850e3bb..b41211aca8eb2 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts @@ -81,6 +81,15 @@ export const EsqlContentReference = BaseContentReference.merge( * Label of the query */ label: z.string(), + /** + * Time range to select in the time picker. + */ + timerange: z + .object({ + from: z.string(), + to: z.string(), + }) + .optional(), }) ); diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml index b651ddd3ca660..6df8ee8a19f3a 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml @@ -71,6 +71,17 @@ components: label: description: Label of the query type: string + timerange: + description: Time range to select in the time picker. + type: object + required: + - 'from' + - 'to' + properties: + from: + type: string + to: + type: string SecurityAlertContentReference: description: References a security alert diff --git a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/assistant_nav_link.test.tsx b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/assistant_nav_link.test.tsx index 3637bc6387d0a..869e6b66e4a8c 100644 --- a/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/assistant_nav_link.test.tsx +++ b/x-pack/platform/packages/shared/kbn-elastic-assistant/impl/assistant_context/assistant_nav_link.test.tsx @@ -91,7 +91,7 @@ describe('AssistantNavLink', () => { ); - expect(queryByTestId('assistantNavLink')).toHaveStyle('background-color: rgb(204, 228, 245)'); + expect(queryByTestId('assistantNavLink')).toHaveStyle('background-color: rgb(217, 232, 255)'); }); it('should render the header link text', () => { diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.test.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.test.tsx index ef4170b7730b9..7379185b6004c 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.test.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.test.tsx @@ -37,7 +37,7 @@ describe('ConfigurationFormItems', () => { it('renders link when isInternalProvider is true and key is model_id', () => { render(); - const link = screen.getByRole('link', { name: /looking for elasticsearch model ids/i }); + const link = screen.getByRole('link', { name: /Learn more./i }); expect(link).toBeInTheDocument(); expect(link).toHaveAttribute( 'href', diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx index 3b6bcbd6169aa..21811410aabbf 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/configuration/configuration_form_items.tsx @@ -66,7 +66,7 @@ export const ConfigurationFormItems: React.FC = ({ external target="_blank" > - {LABELS.ES_MODELS_LINK_TEXT} + {LABELS.LEARN_MORE} ) : ( diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/translations.ts b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/translations.ts index 13e15330705ae..9b5b5ea774ed1 100644 --- a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/translations.ts +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/translations.ts @@ -120,10 +120,10 @@ export const OPTIONALTEXT = i18n.translate( } ); -export const ES_MODELS_LINK_TEXT = i18n.translate( - 'xpack.inferenceEndpointUICommon.components.esModelsLinkText', +export const LEARN_MORE = i18n.translate( + 'xpack.inferenceEndpointUICommon.components.learnMoreText', { - defaultMessage: 'Looking for Elasticsearch model Ids', + defaultMessage: 'Learn more.', } ); diff --git a/x-pack/platform/packages/shared/logs_overview/README.md b/x-pack/platform/packages/shared/logs-overview/README.md similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/README.md rename to x-pack/platform/packages/shared/logs-overview/README.md diff --git a/x-pack/platform/packages/shared/logs_overview/index.ts b/x-pack/platform/packages/shared/logs-overview/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/index.ts rename to x-pack/platform/packages/shared/logs-overview/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/jest.config.js b/x-pack/platform/packages/shared/logs-overview/jest.config.js similarity index 83% rename from x-pack/platform/packages/shared/logs_overview/jest.config.js rename to x-pack/platform/packages/shared/logs-overview/jest.config.js index 7c887427d6855..d305599f131e8 100644 --- a/x-pack/platform/packages/shared/logs_overview/jest.config.js +++ b/x-pack/platform/packages/shared/logs-overview/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/platform/packages/shared/logs_overview'], + roots: ['/x-pack/platform/packages/shared/logs-overview'], }; diff --git a/x-pack/platform/packages/shared/logs_overview/kibana.jsonc b/x-pack/platform/packages/shared/logs-overview/kibana.jsonc similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/kibana.jsonc rename to x-pack/platform/packages/shared/logs-overview/kibana.jsonc diff --git a/x-pack/platform/packages/shared/logs_overview/package.json b/x-pack/platform/packages/shared/logs-overview/package.json similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/package.json rename to x-pack/platform/packages/shared/logs-overview/package.json diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/discover_link/discover_link.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/discover_link/discover_link.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/discover_link/discover_link.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/discover_link/discover_link.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/discover_link/index.ts b/x-pack/platform/packages/shared/logs-overview/src/components/discover_link/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/discover_link/index.ts rename to x-pack/platform/packages/shared/logs-overview/src/components/discover_link/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/index.ts b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/index.ts rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_control_bar.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_control_bar.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_control_bar.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_control_bar.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_error_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_error_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_error_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_error_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_change_time_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_change_time_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_change_time_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_change_time_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_change_type_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_change_type_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_change_type_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_change_type_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_control_columns.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_control_columns.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_control_columns.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_control_columns.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_count_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_count_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_count_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_count_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_expand_button.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_expand_button.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_expand_button.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_expand_button.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_histogram_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_histogram_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_histogram_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_histogram_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_pattern_cell.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_pattern_cell.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_grid_pattern_cell.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_grid_pattern_cell.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_loading_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_loading_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_loading_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_loading_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_result_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_result_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_categories/log_categories_result_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_categories/log_categories_result_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_error_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_error_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_error_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_error_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_flyout.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_flyout.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_flyout.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_flyout.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_loading_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_loading_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_details_loading_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_details_loading_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_document_examples_table.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_document_examples_table.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/log_category_details/log_category_document_examples_table.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/log_category_details/log_category_document_examples_table.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/index.ts b/x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/index.ts rename to x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview_error_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview_error_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview_error_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview_error_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview_loading_content.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview_loading_content.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/logs_overview/logs_overview_loading_content.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/logs_overview/logs_overview_loading_content.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/components/shared/log_category_pattern.tsx b/x-pack/platform/packages/shared/logs-overview/src/components/shared/log_category_pattern.tsx similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/components/shared/log_category_pattern.tsx rename to x-pack/platform/packages/shared/logs-overview/src/components/shared/log_category_pattern.tsx diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/categorize_documents.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/categorize_documents.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/categorize_documents.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/categorize_documents.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/categorize_logs_service.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/categorize_logs_service.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/categorize_logs_service.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/categorize_logs_service.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/count_documents.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/count_documents.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/count_documents.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/count_documents.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/index.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/index.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/queries.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/queries.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/queries.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/queries.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/types.ts b/x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/types.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/categorize_logs_service/types.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/categorize_logs_service/types.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/category_details_service.ts b/x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/category_details_service.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/category_details_service.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/category_details_service.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/index.ts b/x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/index.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/index.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/index.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/types.ts b/x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/types.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/services/category_details_service/types.ts rename to x-pack/platform/packages/shared/logs-overview/src/services/category_details_service/types.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/types.ts b/x-pack/platform/packages/shared/logs-overview/src/types.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/types.ts rename to x-pack/platform/packages/shared/logs-overview/src/types.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/utils/log_category.ts b/x-pack/platform/packages/shared/logs-overview/src/utils/log_category.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/utils/log_category.ts rename to x-pack/platform/packages/shared/logs-overview/src/utils/log_category.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/utils/logs_source.ts b/x-pack/platform/packages/shared/logs-overview/src/utils/logs_source.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/utils/logs_source.ts rename to x-pack/platform/packages/shared/logs-overview/src/utils/logs_source.ts diff --git a/x-pack/platform/packages/shared/logs_overview/src/utils/xstate5_utils.ts b/x-pack/platform/packages/shared/logs-overview/src/utils/xstate5_utils.ts similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/src/utils/xstate5_utils.ts rename to x-pack/platform/packages/shared/logs-overview/src/utils/xstate5_utils.ts diff --git a/x-pack/platform/packages/shared/logs_overview/tsconfig.json b/x-pack/platform/packages/shared/logs-overview/tsconfig.json similarity index 100% rename from x-pack/platform/packages/shared/logs_overview/tsconfig.json rename to x-pack/platform/packages/shared/logs-overview/tsconfig.json diff --git a/x-pack/platform/plugins/private/canvas/scripts/shareable_runtime.js b/x-pack/platform/plugins/private/canvas/scripts/shareable_runtime.js index f3e1e66c1744a..a0b8421f8da01 100644 --- a/x-pack/platform/plugins/private/canvas/scripts/shareable_runtime.js +++ b/x-pack/platform/plugins/private/canvas/scripts/shareable_runtime.js @@ -55,7 +55,6 @@ run( execa.sync( process.execPath, [ - '--openssl-legacy-provider', require.resolve('webpack-dev-server/bin/webpack-dev-server'), '--config', webpackConfig, @@ -89,7 +88,6 @@ run( execa.sync( process.execPath, [ - '--openssl-legacy-provider', require.resolve('webpack/bin/webpack'), '--config', webpackConfig, diff --git a/x-pack/platform/plugins/private/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap b/x-pack/platform/plugins/private/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap index a3d610ec821e2..2ab52a813abc8 100644 --- a/x-pack/platform/plugins/private/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap +++ b/x-pack/platform/plugins/private/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` App renders properly 1`] = `"
markdown mock
markdown mock

Page level controls

My Canvas Workpad

There is a new region landmark with page level controls at the end of the document.

"`; +exports[` App renders properly 1`] = `"
markdown mock
markdown mock

Page level controls

My Canvas Workpad

There is a new region landmark with page level controls at the end of the document.

"`; diff --git a/x-pack/platform/plugins/private/canvas/shareable_runtime/components/footer/scrubber.module.scss b/x-pack/platform/plugins/private/canvas/shareable_runtime/components/footer/scrubber.module.scss index 7599df7391295..d9529cc9e3e01 100644 --- a/x-pack/platform/plugins/private/canvas/shareable_runtime/components/footer/scrubber.module.scss +++ b/x-pack/platform/plugins/private/canvas/shareable_runtime/components/footer/scrubber.module.scss @@ -18,9 +18,10 @@ } :global .kbnCanvas :local .slideContainer { - @include euiScrollBar; display: flex; overflow-x: auto; overflow-y: hidden; width: 100%; + + @include euiScrollBar; } diff --git a/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack.config.js b/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack.config.js index bfd95fe5e607f..d092fd5ad27f6 100644 --- a/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack.config.js +++ b/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack.config.js @@ -9,7 +9,6 @@ require('@kbn/babel-register').install(); const path = require('path'); const webpack = require('webpack'); -const { stringifyRequest } = require('loader-utils'); const { CiStatsPlugin } = require('./webpack/ci_stats_plugin'); const { @@ -21,11 +20,13 @@ const { const isProd = process.env.NODE_ENV === 'production'; +/** @type {import('webpack').Configuration} */ module.exports = { context: KIBANA_ROOT, entry: { [SHAREABLE_RUNTIME_NAME]: require.resolve('./index.ts'), }, + target: 'web', mode: isProd ? 'production' : 'development', output: { path: SHAREABLE_RUNTIME_OUTPUT, @@ -35,18 +36,28 @@ module.exports = { resolve: { alias: { core_app_image_assets: path.resolve(KIBANA_ROOT, 'src/core/public/styles/core_app/images'), + [require.resolve('@elastic/eui/es/components/drag_and_drop')]: false, }, extensions: ['.js', '.json', '.ts', '.tsx', '.scss'], - mainFields: ['browser', 'main'], + mainFields: ['browser', 'module', 'main'], + fallback: { + fs: false, + child_process: false, + }, }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, - loaders: 'babel-loader', + loader: 'babel-loader', options: { - presets: [require.resolve('@kbn/babel-preset/webpack_preset')], + presets: [ + [ + require.resolve('@kbn/babel-preset/webpack_preset'), + { useTransformRequireDefault: true }, + ], + ], }, }, { @@ -105,15 +116,15 @@ module.exports = { }, { test: /\.module\.s(a|c)ss$/, - loader: [ + use: [ 'style-loader', { loader: 'css-loader', options: { modules: { localIdentName: '[name]__[local]___[hash:base64:5]', + exportLocalsConvention: 'camelCase', }, - localsConvention: 'camelCase', sourceMap: !isProd, }, }, @@ -160,10 +171,16 @@ module.exports = { loader: 'sass-loader', options: { additionalData(content, loaderContext) { - return `@import ${stringifyRequest( - loaderContext, - path.resolve(KIBANA_ROOT, 'src/core/public/styles/core_app/_globals_v8light.scss') - )};\n${content}`; + const req = JSON.stringify( + loaderContext.utils.contextify( + loaderContext.context || loaderContext.rootContext, + path.resolve( + KIBANA_ROOT, + 'src/core/public/styles/core_app/_globals_v8light.scss' + ) + ) + ); + return `@import ${req};\n${content}`; }, implementation: require('sass-embedded'), sassOptions: { @@ -176,11 +193,23 @@ module.exports = { }, { test: require.resolve('jquery'), - loader: 'expose-loader?jQuery!expose-loader?$', + use: [ + { + loader: 'expose-loader', + options: { + exposes: ['jQuery', '$'], + }, + }, + ], }, { test: /\.(woff|woff2|ttf|eot|svg|ico|png|jpg|gif|jpeg)(\?|$)/, - loader: 'url-loader', + type: 'asset', + parser: { + dataUrlCondition: { + maxSize: 8192, + }, + }, sideEffects: false, }, { @@ -188,20 +217,12 @@ module.exports = { loader: 'html-loader', exclude: /node_modules/, }, - { - test: [require.resolve('@elastic/eui/es/components/drag_and_drop')], - use: require.resolve('null-loader'), - }, { test: /\.peggy$/, use: require.resolve('@kbn/peggy-loader'), }, ], }, - node: { - fs: 'empty', - child_process: 'empty', - }, plugins: [ isProd ? new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }) : [], new CiStatsPlugin({ diff --git a/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack/ci_stats_plugin.ts b/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack/ci_stats_plugin.ts index a0f6c8fe0e9bb..7bc0105ef13b9 100644 --- a/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack/ci_stats_plugin.ts +++ b/x-pack/platform/plugins/private/canvas/shareable_runtime/webpack/ci_stats_plugin.ts @@ -67,7 +67,7 @@ export class CiStatsPlugin { throw new Error(`Unable to find bundle entry named [${entryName}]`); } - const moduleCount = compilation.modules.reduce((acc, module) => { + const moduleCount = Array.from(compilation.modules).reduce((acc, module) => { if (isNormalModule(module)) { return acc + 1; } diff --git a/x-pack/platform/plugins/private/canvas/storybook/canvas_webpack.ts b/x-pack/platform/plugins/private/canvas/storybook/canvas_webpack.ts index 751f30cb6cfb9..e7da29b33be24 100644 --- a/x-pack/platform/plugins/private/canvas/storybook/canvas_webpack.ts +++ b/x-pack/platform/plugins/private/canvas/storybook/canvas_webpack.ts @@ -8,15 +8,16 @@ import { resolve } from 'path'; import { defaultConfig, mergeWebpackFinal } from '@kbn/storybook'; import type { StorybookConfig } from '@kbn/storybook'; +import { Configuration } from 'webpack'; import { KIBANA_ROOT } from './constants'; -export const canvasWebpack = { +export const canvasWebpack: Configuration = { module: { rules: [ // Enable CSS Modules in Storybook (Shareable Runtime) { test: /\.module\.s(a|c)ss$/, - loader: [ + use: [ 'style-loader', { loader: 'css-loader', @@ -39,26 +40,21 @@ export const canvasWebpack = { loader: 'sass-loader', options: { implementation: require('sass-embedded'), + sassOptions: { + quietDeps: true, + }, }, }, ], }, - // Exclude large-dependency, troublesome or irrelevant modules. - { - test: [ - resolve( - KIBANA_ROOT, - 'x-pack/platform/plugins/private/canvas/public/components/embeddable_flyout' - ), - resolve(KIBANA_ROOT, 'x-pack/platform/plugins/private/reporting/public'), - ], - use: 'null-loader', - }, ], }, resolve: { alias: { 'src/plugins': resolve(KIBANA_ROOT, 'src/plugins'), + // Exclude large-dependency, troublesome or irrelevant modules. + [resolve(KIBANA_ROOT, 'x-pack/plugins/canvas/public/components/embeddable_flyout')]: false, + [resolve(KIBANA_ROOT, 'x-pack/plugins/reporting/public')]: false, }, }, }; diff --git a/x-pack/platform/plugins/private/data_visualizer/public/lite/file_upload_lite_view.tsx b/x-pack/platform/plugins/private/data_visualizer/public/lite/file_upload_lite_view.tsx index 78435e53d7f49..600f46e2bbf5d 100644 --- a/x-pack/platform/plugins/private/data_visualizer/public/lite/file_upload_lite_view.tsx +++ b/x-pack/platform/plugins/private/data_visualizer/public/lite/file_upload_lite_view.tsx @@ -13,6 +13,7 @@ import { EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, + EuiLink, EuiLoadingSpinner, EuiSpacer, EuiText, @@ -38,6 +39,7 @@ import { IndexInput } from './index_input'; import { OverallUploadStatus } from './overall_upload_status'; import { ImportErrors } from './import_errors'; import { DataViewIllustration } from './data_view_illustration'; +import { useDataVisualizerKibana } from '../application/kibana_context'; interface Props { dataStart: DataPublicPluginStart; @@ -61,6 +63,12 @@ export const FileUploadLiteView: FC = ({ indexSettings, onClose, }) => { + const { + services: { + application: { navigateToApp }, + }, + } = useDataVisualizerKibana(); + const [indexName, setIndexName] = useState(''); const [indexValidationStatus, setIndexValidationStatus] = useState(STATUS.NOT_STARTED); @@ -85,6 +93,11 @@ export const FileUploadLiteView: FC = ({ [uploadStatus.fileClashes] ); + const fullFileUpload = useCallback( + () => navigateToApp('home', { path: '#/tutorial_directory/fileDataViz' }), + [navigateToApp] + ); + useEffect(() => { return () => { fm.destroy(); @@ -128,6 +141,23 @@ export const FileUploadLiteView: FC = ({ id="xpack.dataVisualizer.file.uploadView.uploadFileDescription" defaultMessage="Upload your file, analyze its data, and import the data into an Elasticsearch index. The data can also be automatically vectorized using semantic text." /> + +
+ + + + + ), + }} + />

diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/error_handling.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/error_handling.spec.ts index 97c4e18f7f2dc..81dc8ffad925c 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/error_handling.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/error_handling.spec.ts @@ -18,15 +18,15 @@ spaceTest.describe('Discover app - errors', { tag: tags.ESS_ONLY }, () => { }); }); - spaceTest.afterAll(async ({ scoutSpace }) => { - await scoutSpace.savedObjects.cleanStandardList(); - }); - spaceTest.beforeEach(async ({ browserAuth, pageObjects }) => { await browserAuth.loginAsViewer(); await pageObjects.discover.goto(); }); + spaceTest.afterAll(async ({ scoutSpace }) => { + await scoutSpace.savedObjects.cleanStandardList(); + }); + spaceTest('should render invalid scripted field error', async ({ page }) => { await page.testSubj.locator('discoverErrorCalloutTitle').waitFor({ state: 'visible' }); await expect( diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/saved_searches.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/saved_searches.spec.ts index 24130c6ec5e5d..83368b86e466f 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/saved_searches.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/saved_searches.spec.ts @@ -54,15 +54,15 @@ spaceTest.describe( await scoutSpace.uiSettings.setDefaultTime({ from: START_TIME, to: END_TIME }); }); + spaceTest.beforeEach(async ({ browserAuth }) => { + await browserAuth.loginAsPrivilegedUser(); + }); + spaceTest.afterAll(async ({ scoutSpace }) => { await scoutSpace.uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); await scoutSpace.savedObjects.cleanStandardList(); }); - spaceTest.beforeEach(async ({ browserAuth }) => { - await browserAuth.loginAsPrivilegedUser(); - }); - spaceTest('should customize time range on dashboards', async ({ pageObjects, page }) => { await pageObjects.dashboard.goto(); await pageObjects.dashboard.openNewDashboard(); diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions.spec.ts index 64fe9869f3dc0..69e5aadd8292a 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions.spec.ts @@ -21,16 +21,16 @@ spaceTest.describe( }); }); - spaceTest.afterAll(async ({ scoutSpace }) => { - await scoutSpace.uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); - await scoutSpace.savedObjects.cleanStandardList(); - }); - spaceTest.beforeEach(async ({ browserAuth, pageObjects }) => { await browserAuth.loginAsViewer(); await pageObjects.discover.goto(); }); + spaceTest.afterAll(async ({ scoutSpace }) => { + await scoutSpace.uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); + await scoutSpace.savedObjects.cleanStandardList(); + }); + spaceTest('dont show up if outside of range', async ({ page, pageObjects }) => { await pageObjects.datePicker.setAbsoluteRange(testData.LOGSTASH_OUT_OF_RANGE_DATES); await page.testSubj.fill('queryInput', 'extension.raw : '); diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_non_time_based.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_non_time_based.spec.ts index 6bed83254f003..b4b6e76dbe8ac 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_non_time_based.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_non_time_based.spec.ts @@ -19,16 +19,16 @@ spaceTest.describe( await scoutSpace.uiSettings.setDefaultIndex(testData.DATA_VIEW_NAME.NO_TIME_FIELD); }); - spaceTest.afterAll(async ({ scoutSpace }) => { - await scoutSpace.uiSettings.unset('defaultIndex'); - await scoutSpace.savedObjects.cleanStandardList(); - }); - spaceTest.beforeEach(async ({ browserAuth, pageObjects }) => { await browserAuth.loginAsViewer(); await pageObjects.discover.goto(); }); + spaceTest.afterAll(async ({ scoutSpace }) => { + await scoutSpace.uiSettings.unset('defaultIndex'); + await scoutSpace.savedObjects.cleanStandardList(); + }); + spaceTest( 'shows all auto-suggest options for a filter in discover context app', async ({ page }) => { diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_use_time_range_disabled.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_use_time_range_disabled.spec.ts index db90b22553bff..b31851ce395e3 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_use_time_range_disabled.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel_tests/value_suggestions_use_time_range_disabled.spec.ts @@ -22,17 +22,17 @@ spaceTest.describe( await scoutSpace.uiSettings.set({ 'autocomplete:useTimeRange': false }); }); + spaceTest.beforeEach(async ({ browserAuth, pageObjects }) => { + await browserAuth.loginAsViewer(); + await pageObjects.discover.goto(); + }); + spaceTest.afterAll(async ({ scoutSpace }) => { await scoutSpace.uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); await scoutSpace.uiSettings.set({ 'autocomplete:useTimeRange': true }); await scoutSpace.savedObjects.cleanStandardList(); }); - spaceTest.beforeEach(async ({ browserAuth, pageObjects }) => { - await browserAuth.loginAsViewer(); - await pageObjects.discover.goto(); - }); - spaceTest('show up if outside of range', async ({ page, pageObjects }) => { await pageObjects.datePicker.setAbsoluteRange(testData.LOGSTASH_OUT_OF_RANGE_DATES); await page.testSubj.fill('queryInput', 'extension.raw : '); diff --git a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/saved_search_embeddable.spec.ts b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/saved_search_embeddable.spec.ts index 6c37611dbc202..e6a77e970809a 100644 --- a/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/saved_search_embeddable.spec.ts +++ b/x-pack/platform/plugins/private/discover_enhanced/ui_tests/tests/saved_search_embeddable.spec.ts @@ -40,6 +40,7 @@ const createSavedSearch = async ( test.describe('Discover app - saved search embeddable', { tag: tags.DEPLOYMENT_AGNOSTIC }, () => { const SAVED_SEARCH_TITLE = 'TempSearch'; const SAVED_SEARCH_ID = '90943e30-9a47-11e8-b64d-95841ca0b247'; + test.beforeAll(async ({ esArchiver, kbnClient, uiSettings }) => { await esArchiver.loadIfNeeded(testData.ES_ARCHIVES.LOGSTASH); await kbnClient.importExport.load(testData.KBN_ARCHIVES.DASHBOARD_DRILLDOWNS); @@ -49,16 +50,16 @@ test.describe('Discover app - saved search embeddable', { tag: tags.DEPLOYMENT_A }); }); - test.afterAll(async ({ kbnClient, uiSettings }) => { - await uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); - await kbnClient.savedObjects.cleanStandardList(); - }); - test.beforeEach(async ({ browserAuth, pageObjects }) => { await browserAuth.loginAsPrivilegedUser(); await pageObjects.dashboard.goto(); }); + test.afterAll(async ({ kbnClient, uiSettings }) => { + await uiSettings.unset('defaultIndex', 'timepicker:timeDefaults'); + await kbnClient.savedObjects.cleanStandardList(); + }); + test('should allow removing the dashboard panel after the underlying saved search has been deleted', async ({ kbnClient, page, diff --git a/x-pack/platform/plugins/private/graph/public/services/persistence/deserialize.test.ts b/x-pack/platform/plugins/private/graph/public/services/persistence/deserialize.test.ts index 791ee25dfb84d..8464f17166bd3 100644 --- a/x-pack/platform/plugins/private/graph/public/services/persistence/deserialize.test.ts +++ b/x-pack/platform/plugins/private/graph/public/services/persistence/deserialize.test.ts @@ -172,7 +172,7 @@ describe('deserialize', () => { }, Object { "aggregatable": true, - "color": "#D36086", + "color": "#61A2FF", "hopSize": 5, "icon": Object { "id": "folderOpen", diff --git a/x-pack/platform/plugins/private/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap b/x-pack/platform/plugins/private/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap index e23f395b13ed9..fbbb3b532eef5 100644 --- a/x-pack/platform/plugins/private/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap +++ b/x-pack/platform/plugins/private/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap @@ -179,7 +179,7 @@ exports[`extend index management ilm summary extension should render a phase def >
{ @@ -53,6 +54,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { policies: [], selectedPolicyName: '', selectedAlias: '', + isLoading: true, }; } addPolicy = async () => { @@ -218,7 +220,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { async componentDidMount() { try { const policies = await loadPolicies(); - this.setState({ policies }); + this.setState({ policies, isLoading: false }); } catch (err) { showApiError( err, @@ -233,7 +235,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { } } render() { - const { policies } = this.state; + const { policies, isLoading } = this.state; const { indexName, closeModal, getUrlForApp } = this.props; const title = ( { }} /> ); - if (!policies.length) { + if (!isLoading && !policies.length) { return ( diff --git a/x-pack/platform/plugins/private/monitoring/public/components/no_data/explanations/collection_interval/__snapshots__/collection_interval.test.js.snap b/x-pack/platform/plugins/private/monitoring/public/components/no_data/explanations/collection_interval/__snapshots__/collection_interval.test.js.snap index 7fdc9cc321040..c343d95c24e81 100644 --- a/x-pack/platform/plugins/private/monitoring/public/components/no_data/explanations/collection_interval/__snapshots__/collection_interval.test.js.snap +++ b/x-pack/platform/plugins/private/monitoring/public/components/no_data/explanations/collection_interval/__snapshots__/collection_interval.test.js.snap @@ -92,7 +92,7 @@ Array [ aria-label="Loading" class="euiLoadingSpinner emotion-euiLoadingSpinner-m" role="progressbar" - style="border-color: #0077cc currentcolor currentcolor currentcolor;" + style="border-color: #1750ba currentcolor currentcolor currentcolor;" /> Turn on monitoring diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 057368f38cbba..f72bf26950be3 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -9757,7 +9757,6 @@ "xpack.aiAssistant.chatTimeline.actions.editPrompt": "Modifier l'invite", "xpack.aiAssistant.chatTimeline.actions.inspectPrompt": "Inspecter l'invite", "xpack.aiAssistant.chatTimeline.messages.elasticAssistant.label": "Assistant d'Elastic", - "xpack.aiAssistant.chatTimeline.messages.system.label": "Système", "xpack.aiAssistant.chatTimeline.messages.user.label": "Vous", "xpack.aiAssistant.checkingKbAvailability": "Vérification de la disponibilité de la base de connaissances", "xpack.aiAssistant.conversationList.dateGroupTitle.lastMonth": "Le mois dernier", @@ -16701,13 +16700,9 @@ "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorLabel": "Connecteur", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorNameLabel": "Nom du connecteur", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.descriptionLabel": "Description", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.elasticManagedLabel": "Géré par Elastic", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.selfManagedLabel": "Autogéré", "xpack.enterpriseSearch.createConnector.startStep.h4.configureIndexAndAPILabel": "Configurer l'index et la clé d’API", "xpack.enterpriseSearch.createConnector.startStep.h4.deploymentLabel": "Déploiement", - "xpack.enterpriseSearch.createConnector.startStep.h4.setUpLabel": "Installation", "xpack.enterpriseSearch.createConnector.startStep.p.thisProcessWillCreateLabel": "Ce processus créera un nouvel index, une clé d'API et un ID de connecteur. Cela est facultatif, mais vous pouvez également utiliser votre propre configuration.", - "xpack.enterpriseSearch.createConnector.startStep.p.whereDoYouWantLabel": "Où souhaitez-vous stocker le connecteur et comment souhaitez-vous le gérer ?", "xpack.enterpriseSearch.createConnector.startStep.p.youWillStartTheLabel": "Vous devrez démarrer le processus de création manuelle d'un nouvel index, d'une clé d'API et d'un ID de connecteur de robot d'indexation. Cela est facultatif, mais vous pouvez également utiliser votre propre configuration.", "xpack.enterpriseSearch.createConnector.startStep.startLabel": "Début", "xpack.enterpriseSearch.defaultSettingsFlyout.body.description.ingestPipelinesLink.link": "pipelines d'ingestion", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index a02346ac3f0ca..29a8429212fd1 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -9633,7 +9633,6 @@ "xpack.aiAssistant.chatTimeline.actions.editPrompt": "プロンプトを編集", "xpack.aiAssistant.chatTimeline.actions.inspectPrompt": "プロンプトを検査", "xpack.aiAssistant.chatTimeline.messages.elasticAssistant.label": "Elastic Assistant", - "xpack.aiAssistant.chatTimeline.messages.system.label": "システム", "xpack.aiAssistant.chatTimeline.messages.user.label": "あなた", "xpack.aiAssistant.checkingKbAvailability": "ナレッジベースの利用可能性を確認中", "xpack.aiAssistant.conversationList.dateGroupTitle.lastMonth": "先月", @@ -16563,13 +16562,9 @@ "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorLabel": "コネクター", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorNameLabel": "コネクター名", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.descriptionLabel": "説明", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.elasticManagedLabel": "Elasticマネージド", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.selfManagedLabel": "自己管理", "xpack.enterpriseSearch.createConnector.startStep.h4.configureIndexAndAPILabel": "インデックスとAPIキーを構成", "xpack.enterpriseSearch.createConnector.startStep.h4.deploymentLabel": "デプロイ", - "xpack.enterpriseSearch.createConnector.startStep.h4.setUpLabel": "設定", "xpack.enterpriseSearch.createConnector.startStep.p.thisProcessWillCreateLabel": "このプロセスにより、新しいインデックス、APIキー、コネクターIDが作成されます。任意で、独自の構成を使用することもできます。", - "xpack.enterpriseSearch.createConnector.startStep.p.whereDoYouWantLabel": "コネクターを保存する場所と管理する方法", "xpack.enterpriseSearch.createConnector.startStep.p.youWillStartTheLabel": "新しいインデックス、APIキー、WebクローラーコネクターIDの作成プロセスを手動で開始します。任意で、独自の構成を使用することもできます。", "xpack.enterpriseSearch.createConnector.startStep.startLabel": "開始", "xpack.enterpriseSearch.defaultSettingsFlyout.body.description.ingestPipelinesLink.link": "インジェストパイプライン", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index a31c56921e724..0c06b4f5bd29d 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -9479,7 +9479,6 @@ "xpack.aiAssistant.chatTimeline.actions.editPrompt": "编辑提示", "xpack.aiAssistant.chatTimeline.actions.inspectPrompt": "检查提示", "xpack.aiAssistant.chatTimeline.messages.elasticAssistant.label": "Elastic 助手", - "xpack.aiAssistant.chatTimeline.messages.system.label": "系统", "xpack.aiAssistant.chatTimeline.messages.user.label": "您", "xpack.aiAssistant.checkingKbAvailability": "正在检查知识库的可用性", "xpack.aiAssistant.conversationList.dateGroupTitle.lastMonth": "上月", @@ -16286,13 +16285,9 @@ "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorLabel": "连接器", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.connectorNameLabel": "连接器名称", "xpack.enterpriseSearch.createConnector.startStep.euiFormRow.descriptionLabel": "描述", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.elasticManagedLabel": "Elastic 托管", - "xpack.enterpriseSearch.createConnector.startStep.euiRadio.selfManagedLabel": "自管型", "xpack.enterpriseSearch.createConnector.startStep.h4.configureIndexAndAPILabel": "配置索引和 API 密钥", "xpack.enterpriseSearch.createConnector.startStep.h4.deploymentLabel": "部署", - "xpack.enterpriseSearch.createConnector.startStep.h4.setUpLabel": "设置", "xpack.enterpriseSearch.createConnector.startStep.p.thisProcessWillCreateLabel": "此过程将创建一个新索引、API 密钥和连接器 ID。(可选)您也可以提供自己的配置。", - "xpack.enterpriseSearch.createConnector.startStep.p.whereDoYouWantLabel": "您希望将连接器存储在什么位置?您希望如何管理连接器?", "xpack.enterpriseSearch.createConnector.startStep.p.youWillStartTheLabel": "您将手动开始创建新索引、API 密钥和网络爬虫连接器 ID 的过程。(可选)您也可以提供自己的配置。", "xpack.enterpriseSearch.createConnector.startStep.startLabel": "启动", "xpack.enterpriseSearch.defaultSettingsFlyout.body.description.ingestPipelinesLink.link": "采集管道", diff --git a/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts b/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts index 31edafb0fa09f..de3a185649f30 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts @@ -233,6 +233,7 @@ export interface EnrichedDeprecationInfo | 'ilm_policies' | 'templates'; isCritical: boolean; + frozen?: boolean; status?: estypes.HealthReportIndicatorHealthStatus; index?: string; correctiveAction?: diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap index 753d8bd7db5da..f790b5173ce61 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap @@ -87,3 +87,116 @@ exports[`ChecklistFlyout renders 1`] = ` `; + +exports[`ChecklistFlyout renders for frozen indices 1`] = ` + + + +

+ + Learn more + , + } + } + /> +

+ + } + > + + Learn more + , + } + } + /> + + +

+ +

+
+ + +
+ + + + + + + + + + + + + + +
+`; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx index fff7a05e0b70a..a895f5fad815d 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.test.tsx @@ -36,6 +36,7 @@ jest.mock('../../../../../app_context', () => { describe('ChecklistFlyout', () => { const defaultProps = { indexName: 'myIndex', + frozen: false, closeFlyout: jest.fn(), confirmInputValue: 'CONFIRM', onConfirmInputChange: jest.fn(), @@ -67,6 +68,12 @@ describe('ChecklistFlyout', () => { expect(shallow()).toMatchSnapshot(); }); + it('renders for frozen indices', () => { + const props = cloneDeep(defaultProps); + props.frozen = true; + expect(shallow()).toMatchSnapshot(); + }); + it('disables button while reindexing', () => { const props = cloneDeep(defaultProps); props.reindexState.status = ReindexStatus.inProgress; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx index c6ba5ecff25d4..0710d560d7d93 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/checklist_step.tsx @@ -72,11 +72,12 @@ const buttonLabel = (status?: ReindexStatus) => { * Displays a flyout that shows the current reindexing status for a given index. */ export const ChecklistFlyoutStep: React.FunctionComponent<{ + frozen?: boolean; closeFlyout: () => void; reindexState: ReindexState; startReindex: () => void; cancelReindex: () => void; -}> = ({ closeFlyout, reindexState, startReindex, cancelReindex }) => { +}> = ({ frozen, closeFlyout, reindexState, startReindex, cancelReindex }) => { const { services: { api, @@ -197,6 +198,37 @@ export const ChecklistFlyoutStep: React.FunctionComponent<{ }} />

+ {frozen && ( + <> + + } + iconType="iInCircle" + > + + {i18n.translate( + 'xpack.upgradeAssistant.checkupTab.reindexing.flyout.learnMoreLinkLabel', + { + defaultMessage: 'Learn more', + } + )} + + ), + }} + /> + + + + )}

= ({ /> ) : ( { expect(upgradeStatus.totalCriticalDeprecations).toBe(0); }); + it('filters out frozen indices if old index deprecations exist for the same indices', async () => { + esClient.asCurrentUser.migration.deprecations.mockResponse({ + cluster_settings: [], + node_settings: [], + ml_settings: [], + index_settings: { + frozen_index: [ + { + level: 'critical', + message: 'Old index with a compatibility version < 8.0', + url: 'https://www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.0.html#breaking-changes-8.0', + details: 'This index has version: 7.17.28-8.0.0', + resolve_during_rolling_upgrade: false, + _meta: { reindex_required: true }, + }, + { + level: 'critical', + message: + 'Index [frozen_index] is a frozen index. The frozen indices feature is deprecated and will be removed in version 9.0.', + url: 'https://www.elastic.co/guide/en/elasticsearch/reference/master/frozen-indices.html', + details: + 'Frozen indices must be unfrozen before upgrading to version 9.0. (The legacy frozen indices feature no longer offers any advantages. You may consider cold or frozen tiers in place of frozen indices.)', + resolve_during_rolling_upgrade: false, + }, + ], + }, + data_streams: {}, + // @ts-expect-error not in types yet + ilm_policies: {}, + templates: {}, + }); + + // @ts-expect-error not full interface of response + esClient.asCurrentUser.indices.resolveIndex.mockResponse(resolvedIndices); + + const upgradeStatus = await getESUpgradeStatus(esClient, { + ...featureSet, + }); + + expect([ + ...upgradeStatus.migrationsDeprecations, + ...upgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(1); + expect(upgradeStatus.totalCriticalDeprecations).toBe(1); + }); + it('returns health indicators', async () => { esClient.asCurrentUser.migration.deprecations.mockResponse({ cluster_settings: [], diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/migrations.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/migrations.ts index 707c5ca00ba3a..35647c9df64c4 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/migrations.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/migrations.ts @@ -127,13 +127,13 @@ export const getEnrichedDeprecations = async ( const systemIndicesList = convertFeaturesToIndicesArray(systemIndices.features); - const indexSettingsIndexNames = Object.keys(deprecations.index_settings).map( - (indexName) => indexName! - ); + const indexSettingsIndexNames = Object.keys(deprecations.index_settings); const indexSettingsIndexStates = indexSettingsIndexNames.length ? await esIndicesStateCheck(dataClient.asCurrentUser, indexSettingsIndexNames) : {}; + const deprecationsByIndex = new Map(); + return normalizeEsResponse(deprecations) .filter((deprecation) => { switch (deprecation.type) { @@ -173,10 +173,39 @@ export const getEnrichedDeprecations = async ( indexSettingsIndexStates[deprecation.index!] === 'closed' ? 'index-closed' : undefined; } - const enrichedDeprecation = _.omit(deprecation, 'metadata'); - return { - ...enrichedDeprecation, + const enrichedDeprecation = { + ..._.omit(deprecation, 'metadata'), correctiveAction, }; + + if (deprecation.index) { + const indexDeprecations = deprecationsByIndex.get(deprecation.index) || []; + indexDeprecations.push(enrichedDeprecation); + deprecationsByIndex.set(deprecation.index, indexDeprecations); + } + + return enrichedDeprecation; + }) + .filter((deprecation) => { + if ( + deprecation.index && + deprecation.message.includes(`Index [${deprecation.index}] is a frozen index`) + ) { + // frozen indices are created in 7.x, so they are old / incompatible as well + // reindexing + deleting is required, so no need to bubble up this deprecation in the UI + const indexDeprecations = deprecationsByIndex.get(deprecation.index)!; + const oldIndexDeprecation: EnrichedDeprecationInfo | undefined = indexDeprecations.find( + (elem) => + elem.type === 'index_settings' && + elem.index === deprecation.index && + elem.correctiveAction?.type === 'reindex' + ); + if (oldIndexDeprecation) { + oldIndexDeprecation.frozen = true; + return false; + } + } + + return true; }); }; diff --git a/x-pack/platform/plugins/shared/automatic_import/common/constants.ts b/x-pack/platform/plugins/shared/automatic_import/common/constants.ts index 109de8faf9e1a..15fb68b7d01f4 100644 --- a/x-pack/platform/plugins/shared/automatic_import/common/constants.ts +++ b/x-pack/platform/plugins/shared/automatic_import/common/constants.ts @@ -37,6 +37,7 @@ export enum GenerationErrorCode { UNSUPPORTED_LOG_SAMPLES_FORMAT = 'unsupported-log-samples-format', UNPARSEABLE_CSV_DATA = 'unparseable-csv-data', CEF_ERROR = 'cef-not-supported', + BUILD_INTEGRATION_ERROR = 'build-integration-error', } // Size limits diff --git a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.test.tsx b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.test.tsx index a7dd8eae0fdab..18b670b8d7b93 100644 --- a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.test.tsx +++ b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { render, act, type RenderResult, fireEvent } from '@testing-library/react'; import { TestProvider } from '../../../../../mocks/test_provider'; -import { DataStreamStep } from './data_stream_step'; +import { DataStreamStep, getNameFromTitle } from './data_stream_step'; import { ActionsProvider } from '../../state'; import { mockActions, mockState } from '../../mocks/state'; @@ -284,4 +284,57 @@ describe('DataStreamStep', () => { expect(result.queryByTestId('generationModal')).toBeInTheDocument(); }); }); + + describe('when integrationSettings has an invalid generated name from title', () => { + describe.each(['123 abc', '1a'])('should render error for %s', (invalidTitle) => { + let result: RenderResult; + beforeEach(() => { + jest.clearAllMocks(); + result = render( + , + { wrapper } + ); + }); + + it('should set empty name for invalid title', () => { + const input = result.getByTestId('nameInput'); + expect(input).toHaveValue(''); // name is not set + }); + }); + }); + + describe('when integrationSettings has an valid generated name from title', () => { + describe.each(['abc 123', '$abc123', 'abc 123 abc', 'abc_123', 'abc_123_abc'])( + 'should render error for %s', + (validTitle) => { + let result: RenderResult; + beforeEach(() => { + jest.clearAllMocks(); + result = render( + , + { wrapper } + ); + }); + + it('should auto-generate name from title', () => { + const input = result.getByTestId('nameInput'); + expect(input).toHaveValue(getNameFromTitle(validTitle)); + expect(mockActions.setIntegrationSettings).toHaveBeenCalledWith({ + name: getNameFromTitle(validTitle), + title: validTitle, + }); + }); + } + ); + }); }); diff --git a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.tsx b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.tsx index d929dae7812e3..4c9e9270b9c71 100644 --- a/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.tsx +++ b/x-pack/platform/plugins/shared/automatic_import/public/components/create_integration/create_automatic_import/steps/data_stream_step/data_stream_step.tsx @@ -55,7 +55,8 @@ export const InputTypeOptions: Array> = [ const isValidName = (name: string) => NAME_REGEX_PATTERN.test(name); const isValidDatastreamName = (name: string) => DATASTREAM_NAME_REGEX_PATTERN.test(name); -const getNameFromTitle = (title: string) => title.toLowerCase().replaceAll(/[^a-z0-9]/g, '_'); +export const getNameFromTitle = (title: string) => + title.toLowerCase().replaceAll(/[^a-z0-9]/g, '_'); interface DataStreamStepProps { integrationSettings: State['integrationSettings']; @@ -132,7 +133,7 @@ export const DataStreamStep = React.memo( // Only executed once when the packageNames are loaded if (packageNames != null && integrationSettings?.name == null && integrationSettings?.title) { const generatedName = getNameFromTitle(integrationSettings.title); - if (!packageNames.has(generatedName)) { + if (!packageNames.has(generatedName) && isValidName(generatedName)) { setName(generatedName); setIntegrationValues({ name: generatedName }); } @@ -195,7 +196,7 @@ export const DataStreamStep = React.memo( { if ( attributes.underlyingMessages !== undefined && diff --git a/x-pack/platform/plugins/shared/automatic_import/server/graphs/ecs/graph.test.ts b/x-pack/platform/plugins/shared/automatic_import/server/graphs/ecs/graph.test.ts index 322d71ef4c792..23e6c1e6a8bbf 100644 --- a/x-pack/platform/plugins/shared/automatic_import/server/graphs/ecs/graph.test.ts +++ b/x-pack/platform/plugins/shared/automatic_import/server/graphs/ecs/graph.test.ts @@ -85,7 +85,7 @@ describe('EcsGraph', () => { throw Error(`getEcsGraph threw an error: ${error}`); } - expect(response.results).toStrictEqual(ecsMappingExpectedResults); + expect(response.results).toEqual(ecsMappingExpectedResults); // Check if the functions were called expect(handleEcsMapping).toHaveBeenCalled(); diff --git a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/build_integration.ts b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/build_integration.ts index 30ef7d997a6bc..8eaf00960a3c5 100644 --- a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/build_integration.ts +++ b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/build_integration.ts @@ -20,6 +20,7 @@ import { createDataStream } from './data_stream'; import { createFieldMapping } from './fields'; import { createPipeline } from './pipeline'; import { createReadme } from './readme_files'; +import { BuildIntegrationError } from '../lib/errors/build_integration_error'; const initialVersion = '1.0.0'; @@ -37,46 +38,56 @@ export async function buildPackage(integration: Integration): Promise { configureNunjucks(); if (!isValidName(integration.name)) { - throw new Error( + throw new BuildIntegrationError( `Invalid integration name: ${integration.name}, Should only contain letters, numbers and underscores` ); } - const workingDir = joinPath(getDataPath(), `automatic-import-${generateUniqueId()}`); - const packageDirectoryName = `${integration.name}-${initialVersion}`; - const packageDir = createDirectories(workingDir, integration, packageDirectoryName); - const dataStreamsDir = joinPath(packageDir, 'data_stream'); - const fieldsPerDatastream = integration.dataStreams.map((dataStream) => { - const dataStreamName = dataStream.name; - if (!isValidDatastreamName(dataStreamName)) { - throw new Error( - `Invalid datastream name: ${dataStreamName}, Name must be at least 2 characters long and can only contain lowercase letters, numbers, and underscores` - ); - } - const specificDataStreamDir = joinPath(dataStreamsDir, dataStreamName); + try { + const packageDirectoryName = `${integration.name}-${initialVersion}`; + const packageDir = createDirectories(workingDir, integration, packageDirectoryName); - const dataStreamFields = createDataStream(integration.name, specificDataStreamDir, dataStream); - createAgentInput(specificDataStreamDir, dataStream.inputTypes, dataStream.celInput); - createPipeline(specificDataStreamDir, dataStream.pipeline); - const fields = createFieldMapping( - integration.name, - dataStreamName, - specificDataStreamDir, - dataStream.docs - ); + const dataStreamsDir = joinPath(packageDir, 'data_stream'); + const fieldsPerDatastream = integration.dataStreams.map((dataStream) => { + const dataStreamName = dataStream.name; + if (!isValidDatastreamName(dataStreamName)) { + throw new Error( + `Invalid datastream name: ${dataStreamName}, Name must be at least 2 characters long and can only contain lowercase letters, numbers, and underscores` + ); + } + const specificDataStreamDir = joinPath(dataStreamsDir, dataStreamName); - return { - datastream: dataStreamName, - fields: mergeAndSortFields(fields, dataStreamFields), - }; - }); + const dataStreamFields = createDataStream( + integration.name, + specificDataStreamDir, + dataStream + ); + createAgentInput(specificDataStreamDir, dataStream.inputTypes, dataStream.celInput); + createPipeline(specificDataStreamDir, dataStream.pipeline); + const fields = createFieldMapping( + integration.name, + dataStreamName, + specificDataStreamDir, + dataStream.docs + ); - createReadme(packageDir, integration.name, integration.dataStreams, fieldsPerDatastream); - const zipBuffer = await createZipArchive(integration, workingDir, packageDirectoryName); + return { + datastream: dataStreamName, + fields: mergeAndSortFields(fields, dataStreamFields), + }; + }); - removeDirSync(workingDir); - return zipBuffer; + createReadme(packageDir, integration.name, integration.dataStreams, fieldsPerDatastream); + const zipBuffer = await createZipArchive(integration, workingDir, packageDirectoryName); + + removeDirSync(workingDir); + return zipBuffer; + } catch (error) { + throw new BuildIntegrationError('Building the Integration failed'); + } finally { + removeDirSync(workingDir); + } } export function isValidName(input: string): boolean { diff --git a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.test.ts b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.test.ts index 01e8b0d384dfe..dd6bc0c19ff5c 100644 --- a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.test.ts +++ b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.test.ts @@ -89,17 +89,6 @@ describe('createDataStream', () => { // dataStream files expect(copySync).toHaveBeenCalledWith(expect.any(String), `${dataStreamPath}/fields`); - // test files - expect(ensureDirSync).toHaveBeenCalledWith(`${dataStreamPath}/_dev/test/pipeline`); - expect(copySync).toHaveBeenCalledWith( - expect.any(String), - `${dataStreamPath}/_dev/test/pipeline/test-common-config.yml` - ); - expect(createSync).toHaveBeenCalledWith( - `${dataStreamPath}/_dev/test/pipeline/test-${packageName}-datastream-1.log`, - samples - ); - // // Manifest files expect(createSync).toHaveBeenCalledWith(`${dataStreamPath}/manifest.yml`, undefined); expect(render).toHaveBeenCalledWith(`filestream_manifest.yml.njk`, expect.anything()); diff --git a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.ts b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.ts index c6fa4e07a6dba..c44d8c9424636 100644 --- a/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.ts +++ b/x-pack/platform/plugins/shared/automatic_import/server/integration_builder/data_stream.ts @@ -27,8 +27,6 @@ export function createDataStream( ensureDirSync(specificDataStreamDir); const fields = createDataStreamFolders(specificDataStreamDir, pipelineDir); - createPipelineTests(specificDataStreamDir, dataStream.rawSamples, packageName, dataStreamName); - const dataStreams: string[] = []; for (const inputType of dataStream.inputTypes) { let mappedValues = { @@ -89,30 +87,6 @@ function loadFieldsFromFiles(sourcePath: string, files: string[]): Field[] { }); } -function createPipelineTests( - specificDataStreamDir: string, - rawSamples: string[], - packageName: string, - dataStreamName: string -): void { - const pipelineTestTemplatesDir = joinPath(__dirname, '../templates/pipeline_tests'); - const pipelineTestsDir = joinPath(specificDataStreamDir, '_dev/test/pipeline'); - ensureDirSync(pipelineTestsDir); - const items = listDirSync(pipelineTestTemplatesDir); - for (const item of items) { - const s = joinPath(pipelineTestTemplatesDir, item); - const d = joinPath(pipelineTestsDir, item.replaceAll('_', '-')); - copySync(s, d); - } - const formattedPackageName = packageName.replace(/_/g, '-'); - const formattedDataStreamName = dataStreamName.replace(/_/g, '-'); - const testFileName = joinPath( - pipelineTestsDir, - `test-${formattedPackageName}-${formattedDataStreamName}.log` - ); - createSync(testFileName, rawSamples.join('\n')); -} - function prepareCelValues(mappedValues: object, celInput: CelInput | undefined) { if (celInput != null) { // Ready the program for printing with correct indentation diff --git a/x-pack/platform/plugins/shared/automatic_import/server/lib/errors/build_integration_error.ts b/x-pack/platform/plugins/shared/automatic_import/server/lib/errors/build_integration_error.ts new file mode 100644 index 0000000000000..6c04f974817bc --- /dev/null +++ b/x-pack/platform/plugins/shared/automatic_import/server/lib/errors/build_integration_error.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KibanaResponseFactory } from '@kbn/core/server'; +import { ErrorThatHandlesItsOwnResponse } from './types'; +import { GenerationErrorCode } from '../../../common/constants'; + +export class BuildIntegrationError extends Error implements ErrorThatHandlesItsOwnResponse { + private readonly errorCode: GenerationErrorCode = GenerationErrorCode.BUILD_INTEGRATION_ERROR; + + public sendResponse(res: KibanaResponseFactory) { + return res.badRequest({ + body: { message: this.message, attributes: { errorCode: this.errorCode } }, + }); + } +} diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/pipeline_tests/test_common_config.yml b/x-pack/platform/plugins/shared/automatic_import/server/templates/pipeline_tests/test_common_config.yml deleted file mode 100644 index 772cb40587804..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/pipeline_tests/test_common_config.yml +++ /dev/null @@ -1,3 +0,0 @@ -fields: - tags: - - preserve_original_event \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/docker_compose.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/docker_compose.yml.njk deleted file mode 100644 index 74ebed9dd0a75..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/docker_compose.yml.njk +++ /dev/null @@ -1,3 +0,0 @@ -version: "{{ docker_compose_version }}" -services: {% for service in services %} - {{ service }}{% endfor %} \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_filestream.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_filestream.njk deleted file mode 100644 index 642897a0fbfea..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_filestream.njk +++ /dev/null @@ -1,6 +0,0 @@ -{{package_name}}-{{data_stream_name}}-filestream: - image: alpine - volumes: - - ./sample_logs:/sample_logs:ro - - ${SERVICE_LOGS_DIR}:/var/log - command: /bin/sh -c "cp /sample_logs/* /var/log/" \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_gcs.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_gcs.njk deleted file mode 100644 index 3a1010d0b0bfb..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_gcs.njk +++ /dev/null @@ -1,7 +0,0 @@ -{{package_name}}-{{data_stream_name}}-gcs: - image: fsouza/fake-gcs-server:latest - command: -host=0.0.0.0 -public-host=elastic-package-service_{{package_name}}-{{data_stream_name}}-gcs_1 -port=4443 -scheme=http - volumes: - - ./sample_logs:/data - ports: - - 4443/tcp \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_logfile.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_logfile.njk deleted file mode 100644 index 1393ef7cc1098..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_logfile.njk +++ /dev/null @@ -1,6 +0,0 @@ -{{package_name}}-{{data_stream_name}}-logfile: - image: alpine - volumes: - - ./sample_logs:/sample_logs:ro - - ${SERVICE_LOGS_DIR}:/var/log - command: /bin/sh -c "cp /sample_logs/* /var/log/" \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_tcp.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_tcp.njk deleted file mode 100644 index 0267c60d00d4d..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_tcp.njk +++ /dev/null @@ -1,6 +0,0 @@ -{{package_name}}-{{data_stream_name}}-tcp: - image: docker.elastic.co/observability/stream:{{stream_version}} - volumes: - - ./sample_logs:/sample_logs:ro - entrypoint: /bin/bash - command: -c "/stream log --start-signal=SIGHUP --delay=5s --addr elastic-agent:9025 -p=tcp /sample_logs/{{package_name}}.log" \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_udp.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_udp.njk deleted file mode 100644 index bdb8b5b91b8ff..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/service_udp.njk +++ /dev/null @@ -1,6 +0,0 @@ -{{package_name}}-{{data_stream_name}}-udp: - image: docker.elastic.co/observability/stream:{{stream_version}} - volumes: - - ./sample_logs:/sample_logs:ro - entrypoint: /bin/bash - command: -c "/stream log --start-signal=SIGHUP --delay=5s --addr elastic-agent:9025 -p=udp /sample_logs/{{package_name}}.log" \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_filestream_config.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_filestream_config.yml.njk deleted file mode 100644 index 3a861dfe3b7d1..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_filestream_config.yml.njk +++ /dev/null @@ -1,13 +0,0 @@ -service: {{package_name}}-{{data_stream_name}}-filestream -input: filestream -data_stream: - vars: - preserve_original_event: true - paths: - - '{% raw %}{{SERVICE_LOGS_DIR}}{% endraw %}/test-{{package_name}}-{{data_stream_name}}.log' -numeric_keyword_fields: - - log.file.device_id - - log.file.inode - - log.file.idxhi - - log.file.idxlo - - log.file.vol \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_gcs_config.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_gcs_config.yml.njk deleted file mode 100644 index 3bdf39c42fac7..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_gcs_config.yml.njk +++ /dev/null @@ -1,10 +0,0 @@ -service: {{package_name}}-{{data_stream_name}}-gcs -input: gcs -data_stream: - vars: - project_id: testproject - alternative_host: "http://{% raw %}{{Hostname}}:{{Port}}{% endraw %}" - buckets: | - - name: testbucket - poll: true - poll_interval: 15s diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_logfile_config.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_logfile_config.yml.njk deleted file mode 100644 index d6d891cd7038b..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_logfile_config.yml.njk +++ /dev/null @@ -1,13 +0,0 @@ -service: {{package_name}}-{{data_stream_name}}-logfile -input: logfile -data_stream: - vars: - preserve_original_event: true - paths: - - '{% raw %}{{SERVICE_LOGS_DIR}}{% endraw %}/{{package_name}}-{{data_stream_name}}.log' -numeric_keyword_fields: - - log.file.device_id - - log.file.inode - - log.file.idxhi - - log.file.idxlo - - log.file.vol \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_tcp_config.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_tcp_config.yml.njk deleted file mode 100644 index 1c5377a87e213..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_tcp_config.yml.njk +++ /dev/null @@ -1,7 +0,0 @@ -service: {{package_name}}-{{data_stream_name}}-tcp -input: tcp -data_stream: - vars: - preserve_original_event: true - listen_address: 0.0.0.0 - listen_port: 9025 diff --git a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_udp_config.yml.njk b/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_udp_config.yml.njk deleted file mode 100644 index 634f151b97198..0000000000000 --- a/x-pack/platform/plugins/shared/automatic_import/server/templates/system_tests/test_udp_config.yml.njk +++ /dev/null @@ -1,7 +0,0 @@ -service: {{package_name}}-{{data_stream_name}}-udp -input: udp -data_stream: - vars: - preserve_original_event: true - listen_address: 0.0.0.0 - listen_port: 9025 diff --git a/x-pack/platform/plugins/shared/automatic_import/server/util/samples.ts b/x-pack/platform/plugins/shared/automatic_import/server/util/samples.ts index 9f14f20816415..9eb051855ec0d 100644 --- a/x-pack/platform/plugins/shared/automatic_import/server/util/samples.ts +++ b/x-pack/platform/plugins/shared/automatic_import/server/util/samples.ts @@ -153,20 +153,46 @@ export function generateFields(mergedDocs: string): string { return dump(fieldsStructure, { sortKeys: false }); } +export function isObject(value: any): boolean { + return typeof value === 'object' && value !== null; +} + +export function isEmptyValue(value: unknown): boolean { + if (value == null) return true; + if (isObject(value)) { + if (Array.isArray(value)) return value.length === 0; + return value && Object.keys(value).length === 0; + } + return false; +} + +export function isUnsafeProperty(key: string, obj: Record): boolean { + return ( + key === '__proto__' || key === 'constructor' || key === 'prototype' || !Object.hasOwn(obj, key) + ); +} + export function merge( target: Record, source: Record ): Record { - const filteredTarget = filterOwnProperties(target); + const filteredTarget = Object.create(null); + + for (const [key, targetValue] of Object.entries(target)) { + if (!isUnsafeProperty(key, target)) { + filteredTarget[key] = targetValue; + } + } + for (const [key, sourceValue] of Object.entries(source)) { - if (!isBuiltInProperties(key, source)) { + if (!isUnsafeProperty(key, source)) { const targetValue = filteredTarget[key]; + if (Array.isArray(sourceValue)) { - // Directly assign arrays - filteredTarget[key] = sourceValue; - } else if (isObject(sourceValue) && !Array.isArray(targetValue)) { + filteredTarget[key] = [...sourceValue]; + } else if (isObject(sourceValue) && !Array.isArray(sourceValue)) { if (!isObject(targetValue) || isEmptyValue(targetValue)) { - filteredTarget[key] = merge({}, sourceValue); + filteredTarget[key] = merge(Object.create(null), sourceValue); } else { filteredTarget[key] = merge(targetValue, sourceValue); } @@ -178,36 +204,8 @@ export function merge( } } } - return filteredTarget; -} - -function isEmptyValue(value: unknown): boolean { - if (value == null) return true; - if (isObject(value)) { - if (Array.isArray(value)) return value.length === 0; - return value && Object.keys(value).length === 0; - } - return false; -} -function isObject(value: any): boolean { - return typeof value === 'object' && value !== null; -} - -function isBuiltInProperties(key: string, obj: Record): boolean { - return key === 'constructor' || !Object.prototype.hasOwnProperty.call(obj, key); -} - -function filterOwnProperties(obj: Record): Record { - const ownProps: Record = {}; - - for (const key of Object.getOwnPropertyNames(obj)) { - if (!isBuiltInProperties(key, obj)) { - ownProps[key] = (obj as any)[key]; - } - } - - return ownProps; + return filteredTarget; } export function mergeSamples(objects: any[]): string { diff --git a/x-pack/platform/plugins/shared/cloud/common/types.ts b/x-pack/platform/plugins/shared/cloud/common/types.ts index b3a32270af6cc..ffbf553ea33a0 100644 --- a/x-pack/platform/plugins/shared/cloud/common/types.ts +++ b/x-pack/platform/plugins/shared/cloud/common/types.ts @@ -8,3 +8,20 @@ export interface ElasticsearchConfigType { elasticsearch_url?: string; } + +export type SolutionType = 'search' | 'elasticsearch' | 'observability' | 'security'; +export interface CloudDataAttributes { + onboardingData: { + solutionType?: SolutionType; + token: string; + security?: CloudSecurityAnswer; + }; +} + +export interface CloudSecurityAnswer { + useCase: 'siem' | 'cloud' | 'edr' | 'other'; + migration?: { + value: boolean; + type?: 'splunk' | 'other'; + }; +} diff --git a/x-pack/platform/plugins/shared/cloud/server/cloud_data/persist_token.ts b/x-pack/platform/plugins/shared/cloud/server/cloud_data/persist_token.ts index 7a758f417f16c..cd1fe9d99f2d0 100644 --- a/x-pack/platform/plugins/shared/cloud/server/cloud_data/persist_token.ts +++ b/x-pack/platform/plugins/shared/cloud/server/cloud_data/persist_token.ts @@ -8,7 +8,7 @@ import { isDeepEqual } from 'react-use/lib/util'; import { Logger, SavedObjectsClientContract, SavedObjectsErrorHelpers } from '@kbn/core/server'; -import { CloudDataAttributes, CloudSecurityAnswer, SolutionType } from '../routes/types'; +import { CloudDataAttributes, CloudSecurityAnswer, SolutionType } from '../../common/types'; import { CLOUD_DATA_SAVED_OBJECT_TYPE } from '../saved_objects'; import { CLOUD_DATA_SAVED_OBJECT_ID } from '../routes/constants'; diff --git a/x-pack/platform/plugins/shared/cloud/server/routes/get_cloud_data_route.ts b/x-pack/platform/plugins/shared/cloud/server/routes/get_cloud_data_route.ts index c905e4b641c0c..2d9864cca843d 100644 --- a/x-pack/platform/plugins/shared/cloud/server/routes/get_cloud_data_route.ts +++ b/x-pack/platform/plugins/shared/cloud/server/routes/get_cloud_data_route.ts @@ -8,7 +8,7 @@ import { RouteOptions } from '.'; import { CLOUD_DATA_SAVED_OBJECT_ID } from './constants'; import { CLOUD_DATA_SAVED_OBJECT_TYPE } from '../saved_objects'; -import { CloudDataAttributes } from './types'; +import { CloudDataAttributes } from '../../common/types'; export const setGetCloudSolutionDataRoute = ({ router }: RouteOptions) => { router.versioned diff --git a/x-pack/platform/plugins/shared/cloud/server/routes/types.ts b/x-pack/platform/plugins/shared/cloud/server/routes/types.ts index 0b4cf36caf1e4..0b42629d5ad78 100644 --- a/x-pack/platform/plugins/shared/cloud/server/routes/types.ts +++ b/x-pack/platform/plugins/shared/cloud/server/routes/types.ts @@ -11,19 +11,3 @@ import { CustomRequestHandlerContext } from '@kbn/core/server'; * @internal */ export type CloudRequestHandlerContext = CustomRequestHandlerContext<{}>; -export type SolutionType = 'search' | 'elasticsearch' | 'observability' | 'security'; -export interface CloudDataAttributes { - onboardingData: { - solutionType?: SolutionType; - token: string; - security?: CloudSecurityAnswer; - }; -} - -export interface CloudSecurityAnswer { - useCase: 'siem' | 'cloud' | 'edr' | 'other'; - migration?: { - value: boolean; - type?: 'splunk' | 'other'; - }; -} diff --git a/x-pack/platform/plugins/shared/fleet/package.json b/x-pack/platform/plugins/shared/fleet/package.json index bf91a6f0443c2..0efa137a0ac88 100644 --- a/x-pack/platform/plugins/shared/fleet/package.json +++ b/x-pack/platform/plugins/shared/fleet/package.json @@ -5,11 +5,11 @@ "private": true, "license": "Elastic License 2.0", "scripts": { - "cypress_space_awareness": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../x-pack/solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/fleet/cypress.config.space_awareness.ts --ftr-config-file ../../../../../x-pack/test/fleet_cypress/cli_config.space_awareness", + "cypress_space_awareness": "node ../../../../../x-pack/solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/fleet/cypress.config.space_awareness.ts --ftr-config-file ../../../../../x-pack/test/fleet_cypress/cli_config.space_awareness", "cypress_space_awareness:open": "yarn cypress_space_awareness open", "cypress_space_awareness:run": "yarn cypress_space_awareness run", "cypress_space_awareness:run:reporter": "yarn cypress_space_awareness run --reporter ../../../../../node_modules/cypress-multi-reporters --reporter-options configFile=cypress/reporter_config.json", - "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../x-pack/solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/fleet/cypress.config.ts --ftr-config-file ../../../../../x-pack/test/fleet_cypress/cli_config", + "cypress": "node ../../../../../x-pack/solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/fleet/cypress.config.ts --ftr-config-file ../../../../../x-pack/test/fleet_cypress/cli_config", "cypress:open": "yarn cypress open", "cypress:run": "yarn cypress run", "cypress:run:reporter": "yarn cypress run --reporter ../../../../../node_modules/cypress-multi-reporters --reporter-options configFile=cypress/reporter_config.json", diff --git a/x-pack/platform/plugins/shared/fleet/public/components/agentless_enrollment_flyout/next_steps.tsx b/x-pack/platform/plugins/shared/fleet/public/components/agentless_enrollment_flyout/next_steps.tsx index 93ca4b03af458..94783aaa77f49 100644 --- a/x-pack/platform/plugins/shared/fleet/public/components/agentless_enrollment_flyout/next_steps.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/components/agentless_enrollment_flyout/next_steps.tsx @@ -88,12 +88,12 @@ export const NextSteps = ({ }); const connectorCards = packagePolicy.inputs - .filter((input) => !!input?.vars?.connector_id.value || !!input?.vars?.connector_name.value) + .filter((input) => !!input?.vars?.connector_id?.value || !!input?.vars?.connector_name?.value) .map((input, index) => { return ( { application.navigateToApp(ELASTICSEARCH_PLUGIN_ID, { - path: input?.vars?.connector_id.value - ? `content/connectors/${input?.vars?.connector_id.value}` + path: input?.vars?.connector_id?.value + ? `content/connectors/${input?.vars?.connector_id?.value}` : `content/connectors`, }); }} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/reauthorize.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/reauthorize.ts index 03975fbb13aa4..9a15763b3ddd9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/reauthorize.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/elasticsearch/transform/reauthorize.ts @@ -10,17 +10,16 @@ import type { Logger } from '@kbn/logging'; import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { sortBy, uniqBy } from 'lodash'; -import pMap from 'p-map'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import type { ErrorResponseBase } from '@elastic/elasticsearch/lib/api/types'; +import pMap from 'p-map'; +import { MAX_CONCURRENT_TRANSFORMS_OPERATIONS } from '../../../../constants'; import type { SecondaryAuthorizationHeader } from '../../../../../common/types/models/transform_api_key'; import { updateEsAssetReferences } from '../../packages/es_assets_reference'; import type { Installation } from '../../../../../common'; import { ElasticsearchAssetType, PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common'; - import { retryTransientEsErrors } from '../retry'; -import { MAX_CONCURRENT_TRANSFORMS_OPERATIONS } from '../../../../constants'; interface FleetTransformMetadata { fleet_transform_version?: string; @@ -32,6 +31,7 @@ interface FleetTransformMetadata { last_authorized_by?: string; run_as_kibana_system?: boolean; transformId: string; + unattended?: boolean; } const isErrorResponse = (arg: unknown): arg is ErrorResponseBase => @@ -43,6 +43,7 @@ async function reauthorizeAndStartTransform({ transformId, secondaryAuth, meta, + shouldStopBeforeStart, }: { esClient: ElasticsearchClient; logger: Logger; @@ -50,6 +51,7 @@ async function reauthorizeAndStartTransform({ secondaryAuth?: SecondaryAuthorizationHeader; shouldInstallSequentially?: boolean; meta?: object; + shouldStopBeforeStart?: boolean; }): Promise<{ transformId: string; success: boolean; error: null | any }> { try { await retryTransientEsErrors( @@ -71,6 +73,18 @@ async function reauthorizeAndStartTransform({ } try { + // For unattended transforms, we need to stop the transform before starting it + // otherwise, starting transform will fail with a 409 error + if (shouldStopBeforeStart) { + await retryTransientEsErrors( + () => + esClient.transform.stopTransform( + { transform_id: transformId, wait_for_completion: true }, + { ignore: [404, 409] } + ), + { logger, additionalResponseStatuses: [400] } + ); + } const startedTransform = await retryTransientEsErrors( () => esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), { logger, additionalResponseStatuses: [400] } @@ -121,30 +135,23 @@ export async function handleTransformReauthorizeAndStart({ ); } - const transformInfos = await pMap( - transforms, - ({ transformId }) => - retryTransientEsErrors( - () => - esClient.transform.getTransform( - { - transform_id: transformId, - }, - { ...(secondaryAuth ? secondaryAuth : {}), ignore: [404] } - ), - { logger, additionalResponseStatuses: [400] } + const transformInfos = await retryTransientEsErrors( + () => + esClient.transform.getTransform( + { + transform_id: transforms.map((t) => t.transformId).join(','), + }, + { ...(secondaryAuth ? secondaryAuth : {}), ignore: [404] } ), - { - concurrency: MAX_CONCURRENT_TRANSFORMS_OPERATIONS, - } + { logger, additionalResponseStatuses: [400] } ); - - const transformsMetadata: FleetTransformMetadata[] = transformInfos - .flat() - .filter((t) => t.transforms !== undefined) - .map((t) => { - const transform = t.transforms?.[0]; - return { ...transform._meta, transformId: transform?.id }; + const transformsMetadata: FleetTransformMetadata[] = transformInfos.transforms + .map((transform) => { + return { + ...transform._meta, + transformId: transform?.id, + unattended: Boolean(transform.settings?.unattended), + }; }) .filter((t) => t?.run_as_kibana_system === false); @@ -160,13 +167,14 @@ export async function handleTransformReauthorizeAndStart({ (t) => t.order, ]); - for (const { transformId, ...meta } of sortedTransformsMetadata) { + for (const { transformId, unattended, ...meta } of sortedTransformsMetadata) { const authorizedTransform = await reauthorizeAndStartTransform({ esClient, logger, transformId, secondaryAuth, meta: { ...meta, last_authorized_by: username }, + shouldStopBeforeStart: unattended, }); authorizedTransforms.push(authorizedTransform); @@ -175,13 +183,14 @@ export async function handleTransformReauthorizeAndStart({ // Else, create & start all the transforms at once for speed authorizedTransforms = await pMap( transformsMetadata, - async ({ transformId, ...meta }) => + async ({ transformId, unattended, ...meta }) => reauthorizeAndStartTransform({ esClient, logger, transformId, secondaryAuth, meta: { ...meta, last_authorized_by: username }, + shouldStopBeforeStart: unattended, }), { concurrency: MAX_CONCURRENT_TRANSFORMS_OPERATIONS, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/filtered_packages.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/filtered_packages.ts index 4f18f6fbfddb8..b2f02a20f6496 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/filtered_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/filtered_packages.ts @@ -10,7 +10,7 @@ import { FLEET_SERVER_PACKAGE } from '../../../common/constants'; export function getFilteredSearchPackages() { const shouldFilterFleetServer = appContextService.getConfig()?.internal?.fleetServerStandalone; - const filtered: string[] = ['profiler_collector', 'profiler_symbolizer']; + const filtered: string[] = ['profiler_collector', 'profiler_symbolizer', 'elastic_connectors']; // Do not allow to search for Fleet server integration if configured to use standalone fleet server if (shouldFilterFleetServer) { filtered.push(FLEET_SERVER_PACKAGE); @@ -22,7 +22,7 @@ export function getFilteredSearchPackages() { } export function getFilteredInstallPackages() { - const filtered: string[] = []; + const filtered: string[] = ['elastic_connectors']; const excludePackages = appContextService.getConfig()?.internal?.registry?.excludePackages ?? []; diff --git a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/empty_list.tsx b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/empty_list.tsx index f021055dd2934..566663a65bb76 100644 --- a/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/empty_list.tsx +++ b/x-pack/platform/plugins/shared/ingest_pipelines/public/application/sections/manage_processors/empty_list.tsx @@ -8,7 +8,7 @@ import { EuiPageTemplate } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import { css } from '@emotion/react/dist/emotion-react.cjs'; +import { css } from '@emotion/react'; export const EmptyList = ({ addDatabaseButton }: { addDatabaseButton: JSX.Element }) => { return ( diff --git a/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/trigger.test.tsx b/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/trigger.test.tsx index fcc7ccf2bba1d..7ce360628b853 100644 --- a/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/trigger.test.tsx +++ b/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/trigger.test.tsx @@ -56,8 +56,8 @@ describe('TriggerButton', () => { isMissingCurrent /> ); - // EUI danger red: rgb(171, 35, 28) - expect(screen.getByTestId('test-id')).toHaveStyle({ color: 'rgb(171, 35, 28)' }); + // EUI danger red: rgb(167, 22, 39) + expect(screen.getByTestId('test-id')).toHaveStyle({ color: 'rgb(167, 22, 39)' }); }); }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/layers/vector_layer/mvt_vector_layer/__snapshots__/mvt_vector_layer.test.tsx.snap b/x-pack/platform/plugins/shared/maps/public/classes/layers/vector_layer/mvt_vector_layer/__snapshots__/mvt_vector_layer.test.tsx.snap index faae8892a2a85..033db51142764 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/layers/vector_layer/mvt_vector_layer/__snapshots__/mvt_vector_layer.test.tsx.snap +++ b/x-pack/platform/plugins/shared/maps/public/classes/layers/vector_layer/mvt_vector_layer/__snapshots__/mvt_vector_layer.test.tsx.snap @@ -4,8 +4,8 @@ exports[`getLayerIcon Layers with non-elasticsearch sources should display icon { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, @@ -155,7 +155,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#D36086', + color: '#61A2FF', }, type: 'STATIC', }, @@ -231,7 +231,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), lineColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, @@ -308,7 +308,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, @@ -387,7 +387,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#D36086', + color: '#61A2FF', }, type: 'STATIC', }, @@ -457,7 +457,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), lineColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, @@ -536,7 +536,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, @@ -615,7 +615,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), fillColor: { options: { - color: '#D36086', + color: '#61A2FF', }, type: 'STATIC', }, @@ -685,7 +685,7 @@ describe('createLayerDescriptor', () => { ...getDefaultStaticProperties(), lineColor: { options: { - color: '#6092C0', + color: '#A6EDEA', }, type: 'STATIC', }, diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/color_palettes.test.ts b/x-pack/platform/plugins/shared/maps/public/classes/styles/color_palettes.test.ts index d5a6ea694b3e0..707c33ce3994e 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/color_palettes.test.ts +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/color_palettes.test.ts @@ -15,21 +15,21 @@ import { describe('getColorPalette', () => { test('Should create RGB color ramp', () => { expect(getColorPalette('Blues')).toEqual([ - '#ecf1f7', - '#d9e3ef', - '#c5d5e7', - '#b2c7df', - '#9eb9d8', - '#8bacd0', - '#769fc8', - '#6092c0', + '#e4eefd', + '#d3e3fe', + '#c1d8fe', + '#afceff', + '#9dc3ff', + '#8bb8ff', + '#77adff', + '#61a2ff', ]); }); }); describe('getColorRampCenterColor', () => { test('Should get center color from color ramp', () => { - expect(getColorRampCenterColor('Blues')).toBe('#9eb9d8'); + expect(getColorRampCenterColor('Blues')).toBe('#9dc3ff'); }); }); @@ -37,47 +37,47 @@ describe('getOrdinalMbColorRampStops', () => { test('Should create color stops', () => { expect(getOrdinalMbColorRampStops('Blues', 0, 1000, false)).toEqual([ 0, - '#ecf1f7', + '#e4eefd', 125, - '#d9e3ef', + '#d3e3fe', 250, - '#c5d5e7', + '#c1d8fe', 375, - '#b2c7df', + '#afceff', 500, - '#9eb9d8', + '#9dc3ff', 625, - '#8bacd0', + '#8bb8ff', 750, - '#769fc8', + '#77adff', 875, - '#6092c0', + '#61a2ff', ]); }); test('Should create inverted color stops', () => { expect(getOrdinalMbColorRampStops('Blues', 0, 1000, true)).toEqual([ 0, - '#6092c0', + '#61a2ff', 125, - '#769fc8', + '#77adff', 250, - '#8bacd0', + '#8bb8ff', 375, - '#9eb9d8', + '#9dc3ff', 500, - '#b2c7df', + '#afceff', 625, - '#c5d5e7', + '#c1d8fe', 750, - '#d9e3ef', + '#d3e3fe', 875, - '#ecf1f7', + '#e4eefd', ]); }); - test('Should snap to end of color stops for identical range', () => { - expect(getOrdinalMbColorRampStops('Blues', 23, 23, false)).toEqual([23, '#6092c0']); + test('xShould snap to end of color stops for identical range', () => { + expect(getOrdinalMbColorRampStops('Blues', 23, 23, false)).toEqual([23, '#61a2ff']); }); }); @@ -92,15 +92,15 @@ describe('getPercentilesMbColorRampStops', () => { ]; expect(getPercentilesMbColorRampStops('Blues', percentiles, false)).toEqual([ 5567.83, - '#e0e8f2', + '#dae8fd', 8069, - '#c2d2e6', + '#bed6fe', 9581.13, - '#a2bcd9', + '#a1c5ff', 11145.5, - '#82a7cd', + '#83b3ff', 16958.18, - '#6092c0', + '#61a2ff', ]); }); @@ -114,15 +114,15 @@ describe('getPercentilesMbColorRampStops', () => { ]; expect(getPercentilesMbColorRampStops('Blues', percentiles, true)).toEqual([ 5567.83, - '#6092c0', + '#61a2ff', 8069, - '#82a7cd', + '#83b3ff', 9581.13, - '#a2bcd9', + '#a1c5ff', 11145.5, - '#c2d2e6', + '#bed6fe', 16958.18, - '#e0e8f2', + '#dae8fd', ]); }); }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap b/x-pack/platform/plugins/shared/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap index 85de0cc0f7e30..cb3676cdeba48 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.tsx.snap @@ -13,14 +13,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#ecf1f7", - "#d9e3ef", - "#c5d5e7", - "#b2c7df", - "#9eb9d8", - "#8bacd0", - "#769fc8", - "#6092c0", + "#e4eefd", + "#d3e3fe", + "#c1d8fe", + "#afceff", + "#9dc3ff", + "#8bb8ff", + "#77adff", + "#61a2ff", ], "title": "", "type": "gradient", @@ -29,14 +29,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#e6f1ee", - "#cce4de", - "#b3d6cd", - "#9ac8bd", - "#80bbae", - "#65ad9e", - "#47a08f", - "#209280", + "#e1f3ee", + "#cbece1", + "#b5e6d3", + "#9fdfc6", + "#87d8b9", + "#6dd1ac", + "#50c99f", + "#24c292", ], "title": "", "type": "gradient", @@ -45,14 +45,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#e0e4eb", - "#c3c9d4", - "#a8afbc", - "#8e95a3", - "#757c8a", - "#5e6471", - "#494d58", - "#343741", + "#d5dce8", + "#b6c0d3", + "#98a5bc", + "#7b8aa4", + "#61718b", + "#485872", + "#324058", + "#1d2a3e", ], "title": "", "type": "gradient", @@ -61,14 +61,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#fdeae5", - "#f9d5cc", - "#f4c0b4", - "#eeab9c", - "#e79685", - "#df816e", - "#d66c58", - "#cc5642", + "#fae9e9", + "#fcd8d6", + "#fec8c3", + "#feb7b0", + "#fda69e", + "#fc968d", + "#f9847b", + "#f6726a", ], "title": "", "type": "gradient", @@ -77,14 +77,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#f9eac5", - "#f6d9af", - "#f3c89a", - "#efb785", - "#eba672", - "#e89361", - "#e58053", - "#e7664c", + "#ffdad5", + "#ffccc6", + "#ffbeb6", + "#ffafa6", + "#fea097", + "#fc9188", + "#f98279", + "#f6726a", ], "title": "", "type": "gradient", @@ -93,14 +93,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#209280", - "#3aa38d", - "#54b399", - "#95b978", - "#df9352", - "#e7664c", - "#da5e47", - "#cc5642", + "#24c292", + "#69d5b2", + "#aee8d2", + "#d5e0ab", + "#fed1a3", + "#ffc9c2", + "#fb9e96", + "#f6726a", ], "title": "", "type": "gradient", @@ -109,14 +109,14 @@ exports[`HeatmapStyleEditor is rendered 1`] = ` Object { "getPalette": [Function], "palette": Array [ - "#6092c0", - "#84a9cd", - "#a8bfda", - "#cad7e8", - "#f5d9b1", - "#efb785", - "#eb8f69", - "#e7664c", + "#61a2ff", + "#85b6ff", + "#a8caff", + "#c8deff", + "#ffccc6", + "#ffafa6", + "#fb9188", + "#f6726a", ], "title": "", "type": "gradient", diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/__snapshots__/vector_style_editor.test.tsx.snap b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/__snapshots__/vector_style_editor.test.tsx.snap index 691327928eb67..9c9a417f97bf5 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/__snapshots__/vector_style_editor.test.tsx.snap +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/__snapshots__/vector_style_editor.test.tsx.snap @@ -16,7 +16,7 @@ exports[`should render 1`] = ` } defaultStaticStyleOptions={ Object { - "color": "#54B399", + "color": "#16C5C0", } } disabled={false} @@ -38,23 +38,23 @@ exports[`should render 1`] = ` styleProperty={ StaticColorProperty { "_options": Object { - "color": "#54B399", + "color": "#16C5C0", }, "_styleName": "fillColor", } } swatches={ Array [ - "#54B399", - "#6092C0", - "#D36086", - "#9170B8", - "#CA8EAE", - "#D6BF57", - "#B9A888", - "#DA8B45", - "#AA6556", - "#E7664C", + "#16C5C0", + "#A6EDEA", + "#61A2FF", + "#BFDBFF", + "#EE72A6", + "#FFC7DB", + "#F6726A", + "#FFC9C2", + "#EAAE01", + "#FCD883", ] } /> @@ -75,7 +75,7 @@ exports[`should render 1`] = ` } defaultStaticStyleOptions={ Object { - "color": "#41937c", + "color": "#119793", } } disabled={false} @@ -97,23 +97,23 @@ exports[`should render 1`] = ` styleProperty={ StaticColorProperty { "_options": Object { - "color": "#41937c", + "color": "#119793", }, "_styleName": "lineColor", } } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] @@ -256,16 +256,16 @@ exports[`should render 1`] = ` } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] @@ -351,16 +351,16 @@ exports[`should render 1`] = ` } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] @@ -420,7 +420,7 @@ exports[`should render with no style fields 1`] = ` } defaultStaticStyleOptions={ Object { - "color": "#54B399", + "color": "#16C5C0", } } disabled={false} @@ -431,23 +431,23 @@ exports[`should render with no style fields 1`] = ` styleProperty={ StaticColorProperty { "_options": Object { - "color": "#54B399", + "color": "#16C5C0", }, "_styleName": "fillColor", } } swatches={ Array [ - "#54B399", - "#6092C0", - "#D36086", - "#9170B8", - "#CA8EAE", - "#D6BF57", - "#B9A888", - "#DA8B45", - "#AA6556", - "#E7664C", + "#16C5C0", + "#A6EDEA", + "#61A2FF", + "#BFDBFF", + "#EE72A6", + "#FFC7DB", + "#F6726A", + "#FFC9C2", + "#EAAE01", + "#FCD883", ] } /> @@ -468,7 +468,7 @@ exports[`should render with no style fields 1`] = ` } defaultStaticStyleOptions={ Object { - "color": "#41937c", + "color": "#119793", } } disabled={false} @@ -479,23 +479,23 @@ exports[`should render with no style fields 1`] = ` styleProperty={ StaticColorProperty { "_options": Object { - "color": "#41937c", + "color": "#119793", }, "_styleName": "lineColor", } } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] @@ -616,16 +616,16 @@ exports[`should render with no style fields 1`] = ` } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] @@ -700,16 +700,16 @@ exports[`should render with no style fields 1`] = ` } swatches={ Array [ - "#41937c", - "#4379aa", - "#c83868", - "#7751a4", - "#ba6b95", - "#c9ad31", - "#a69168", - "#c57127", - "#885145", - "#e1401f", + "#119793", + "#7ce4e0", + "#2e84ff", + "#8cbeff", + "#e94489", + "#ff94ba", + "#f3443a", + "#ff9c8f", + "#b78801", + "#fbc851", "#000", "#FFF", ] diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.test.ts b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.test.ts index aeeeff361d5a0..7d65839824430 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.test.ts +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/components/legend/extract_color_from_style_property.test.ts @@ -137,7 +137,7 @@ describe('dynamic', () => { fieldMetaOptions, } as ColorDynamicOptions, } as ColorDynamicStylePropertyDescriptor; - expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe('#9eb9d8'); + expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe('#9dc3ff'); }); }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index f94b63e02163d..5896333afd0ac 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -62,7 +62,7 @@ exports[`renderLegendDetailRow categorical Should render categorical legend with key="0" > { -1, 'rgba(0,0,0,0)', 0, - '#ecf1f7', + '#e4eefd', 12.5, - '#d9e3ef', + '#d3e3fe', 25, - '#c5d5e7', + '#c1d8fe', 37.5, - '#b2c7df', + '#afceff', 50, - '#9eb9d8', + '#9dc3ff', 62.5, - '#8bacd0', + '#8bb8ff', 75, - '#769fc8', + '#77adff', 87.5, - '#6092c0', + '#61a2ff', ]); }); }); @@ -612,9 +612,9 @@ describe('get mapbox color expression (via internal _getMbColor)', () => { 'match', ['to-string', ['get', 'foobar']], 'US', - '#54B399', + '#16C5C0', 'CN', - '#6092C0', + '#A6EDEA', 'grey', ]); }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style.test.js b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style.test.js index 1bbaad11534b0..eae517f34ff98 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style.test.js +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style.test.js @@ -103,7 +103,7 @@ describe('getDescriptorWithUpdatedStyleProps', () => { expect(hasChanges).toBe(true); expect(nextStyleDescriptor.properties[VECTOR_STYLES.LINE_COLOR]).toEqual({ options: { - color: '#41937c', + color: '#119793', }, type: 'STATIC', }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style_defaults.test.ts b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style_defaults.test.ts index 856ae869e0bab..65d6ba9c6d941 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style_defaults.test.ts +++ b/x-pack/platform/plugins/shared/maps/public/classes/styles/vector/vector_style_defaults.test.ts @@ -19,13 +19,13 @@ import { getDefaultStaticProperties } from './vector_style_defaults'; describe('getDefaultStaticProperties', () => { test('Should use first color in DEFAULT_*_COLORS when no colors are used on the map', () => { const styleProperties = getDefaultStaticProperties([]); - expect(styleProperties[VECTOR_STYLES.FILL_COLOR].options.color).toBe('#54B399'); - expect(styleProperties[VECTOR_STYLES.LINE_COLOR].options.color).toBe('#41937c'); + expect(styleProperties[VECTOR_STYLES.FILL_COLOR].options.color).toBe('#16C5C0'); + expect(styleProperties[VECTOR_STYLES.LINE_COLOR].options.color).toBe('#119793'); }); test('Should next color in DEFAULT_*_COLORS when colors are used on the map', () => { const styleProperties = getDefaultStaticProperties(['#54B399']); - expect(styleProperties[VECTOR_STYLES.FILL_COLOR].options.color).toBe('#6092C0'); - expect(styleProperties[VECTOR_STYLES.LINE_COLOR].options.color).toBe('#4379aa'); + expect(styleProperties[VECTOR_STYLES.FILL_COLOR].options.color).toBe('#16C5C0'); + expect(styleProperties[VECTOR_STYLES.LINE_COLOR].options.color).toBe('#119793'); }); }); diff --git a/x-pack/platform/plugins/shared/maps/ui_tests/tests/full_screen_mode.spec.ts b/x-pack/platform/plugins/shared/maps/ui_tests/tests/full_screen_mode.spec.ts index 861baafc7e8c3..07a179ad5116a 100644 --- a/x-pack/platform/plugins/shared/maps/ui_tests/tests/full_screen_mode.spec.ts +++ b/x-pack/platform/plugins/shared/maps/ui_tests/tests/full_screen_mode.spec.ts @@ -22,7 +22,7 @@ test.describe( test.beforeEach(async ({ browserAuth, pageObjects }) => { await browserAuth.loginAsViewer(); await pageObjects.maps.gotoNewMap(); - await pageObjects.renderable.waitForRender(); + await pageObjects.maps.waitForRenderComplete(); }); test('Full screen mode', async ({ page }) => { @@ -33,16 +33,16 @@ test.describe( const baseMapBtn = page.getByRole('button', { name: 'Basemap' }); await expect(fullScreenBtn).toBeVisible(); - await expect(exitFullScreenBtn).not.toBeVisible(); + await expect(exitFullScreenBtn).toBeHidden(); await expect(visibleChrome).toBeVisible(); - await expect(hiddenChrome).not.toBeVisible(); + await expect(hiddenChrome).toBeHidden(); await expect(baseMapBtn).toBeVisible(); await fullScreenBtn.click(); - await expect(fullScreenBtn).not.toBeVisible(); + await expect(fullScreenBtn).toBeHidden(); await expect(exitFullScreenBtn).toBeVisible(); - await expect(visibleChrome).not.toBeVisible(); + await expect(visibleChrome).toBeHidden(); await expect(hiddenChrome).toBeVisible(); await expect(baseMapBtn).toBeVisible(); diff --git a/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/ner/ner_output.test.tsx b/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/ner/ner_output.test.tsx index 772fe59965130..b38c15f328196 100644 --- a/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/ner/ner_output.test.tsx +++ b/x-pack/platform/plugins/shared/ml/public/application/model_management/test_models/models/ner/ner_output.test.tsx @@ -54,23 +54,23 @@ describe('NER output', () => { describe('getClassColor', () => { test('returns the correct color for class PER', () => { - expect(getClassColor('PER', true)).toBe('#f1d86f'); + expect(getClassColor('PER', true)).toBe('#ffe0f5'); }); test('returns the correct color for class LOC', () => { - expect(getClassColor('LOC', true)).toBe('#79aad9'); + expect(getClassColor('LOC', true)).toBe('#bfffff'); }); test('returns the correct color for class ORG', () => { - expect(getClassColor('ORG', true)).toBe('#6dccb1'); + expect(getClassColor('ORG', true)).toBe('#45ded9'); }); test('returns the correct color for class MISC', () => { - expect(getClassColor('MISC', true)).toBe('#f5a35c'); + expect(getClassColor('MISC', true)).toBe('#ffe2db'); }); test('returns the default color for an unknown class', () => { - expect(getClassColor('UNKNOWN', true)).toBe('#f1d86f'); + expect(getClassColor('UNKNOWN', true)).toBe('#ffe0f5'); }); }); }); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts index 210eb08b31e1a..e0f353b252564 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts @@ -63,6 +63,7 @@ export interface Conversation { last_updated: string; token_count?: TokenCount; }; + systemMessage?: string; messages: Message[]; labels: Record; numeric_labels: Record; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts index 7fab15137d933..e737d534f3367 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts @@ -12,7 +12,7 @@ import { ObservabilityAIAssistantTelemetryEventType } from '../telemetry_event_t export interface ChatFeedback { feedback: Feedback; - conversation: Omit, 'conversation'> & { + conversation: Omit, 'conversation'> & { conversation: Omit; }; } diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts index 64fcdda7612ae..d760e2dc996ba 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts @@ -32,13 +32,7 @@ const mockChatService: MockedChatService = { hasFunction: jest.fn().mockReturnValue(false), hasRenderFunction: jest.fn().mockReturnValue(true), renderFunction: jest.fn(), - getSystemMessage: jest.fn().mockReturnValue({ - '@timestamp': new Date().toISOString(), - message: { - content: 'system', - role: MessageRole.System, - }, - }), + getSystemMessage: jest.fn().mockReturnValue('system'), getScopes: jest.fn(), }; @@ -88,11 +82,11 @@ describe('useChat', () => { }); }); - it('returns the initial messages including the system message', () => { + it('returns the initial messages', () => { const { messages } = hookResult.result.current; - expect(messages.length).toBe(2); - expect(messages[0].message.role).toBe('system'); - expect(messages[1].message.content).toBe('hello'); + expect(messages.length).toBe(1); + expect(messages[0].message.role).toBe(MessageRole.User); + expect(messages[0].message.content).toBe('hello'); }); it('sets chatState to ready', () => { @@ -166,8 +160,7 @@ describe('useChat', () => { }); it('shows an empty list of messages', () => { - expect(hookResult.result.current.messages.length).toBe(1); - expect(hookResult.result.current.messages[0].message.role).toBe(MessageRole.System); + expect(hookResult.result.current.messages.length).toBe(0); }); it('aborts the running request', () => { @@ -187,7 +180,7 @@ describe('useChat', () => { }); }); - expect(hookResult.result.current.messages[2].message.content).toBe('good'); + expect(hookResult.result.current.messages[1].message.content).toBe('good'); }); }); @@ -222,7 +215,7 @@ describe('useChat', () => { subject.complete(); }); - expect(hookResult.result.current.messages[2].message.content).toBe('goodbye'); + expect(hookResult.result.current.messages[1].message.content).toBe('goodbye'); expect(hookResult.result.current.state).toBe(ChatState.Ready); }); }); @@ -242,7 +235,7 @@ describe('useChat', () => { }); it('shows the partial message and sets chatState to aborted', () => { - expect(hookResult.result.current.messages[2].message.content).toBe('good'); + expect(hookResult.result.current.messages[1].message.content).toBe('good'); expect(hookResult.result.current.state).toBe(ChatState.Aborted); }); @@ -285,7 +278,7 @@ describe('useChat', () => { }); it('shows the partial message and sets chatState to error', () => { - expect(hookResult.result.current.messages[2].message.content).toBe('good'); + expect(hookResult.result.current.messages[1].message.content).toBe('good'); expect(hookResult.result.current.state).toBe(ChatState.Error); }); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts index 86aeb8f519e87..f05ea83a4894b 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts @@ -30,13 +30,6 @@ export enum ChatState { Aborted = 'aborted', } -function getWithSystemMessage(messages: Message[], systemMessage: Message) { - return [ - systemMessage, - ...messages.filter((message) => message.message.role !== MessageRole.System), - ]; -} - export interface UseChatResult { messages: Message[]; setMessages: (messages: Message[]) => void; @@ -160,7 +153,8 @@ function useChatWithoutContext({ const next$ = chatService.complete({ getScreenContexts: () => service.getScreenContexts(), connectorId, - messages: getWithSystemMessage(nextMessages, systemMessage), + messages: nextMessages, + systemMessage, persist, disableFunctions: disableFunctions ?? false, signal: abortControllerRef.current.signal, @@ -275,8 +269,8 @@ function useChatWithoutContext({ }, []); const memoizedMessages = useMemo(() => { - return getWithSystemMessage(messages.concat(pendingMessages ?? []), systemMessage); - }, [systemMessage, messages, pendingMessages]); + return messages.concat(pendingMessages ?? []); + }, [messages, pendingMessages]); const setMessagesWithAbort = useCallback((nextMessages: Message[]) => { abortControllerRef.current.abort(); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx index 7be61a65e263d..b71e74b1aa1fa 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx @@ -13,7 +13,7 @@ import type { ChatCompletionChunkEvent, StreamingChatResponseEventWithoutError, } from '../common/conversation_complete'; -import { MessageRole, ScreenContextActionDefinition } from '../common/types'; +import { ScreenContextActionDefinition } from '../common/types'; import type { ObservabilityAIAssistantAPIClient } from './api'; import type { ObservabilityAIAssistantChatService, @@ -40,13 +40,7 @@ export const mockChatService: ObservabilityAIAssistantChatService = { ), hasFunction: () => true, hasRenderFunction: () => true, - getSystemMessage: () => ({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }), + getSystemMessage: () => 'System', getScopes: jest.fn(), }; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts index dd69c8e309989..b9d2d66d34b38 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts @@ -28,14 +28,8 @@ const client = { const connectorId = 'foo'; +const systemMessage = 'System message'; const messages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System message', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -97,6 +91,7 @@ describe('complete', () => { client, connectorId, getScreenContexts: () => [], + systemMessage, messages, persist: false, disableFunctions: false, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts index f059196f2e681..27e4c747b9df6 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts @@ -83,6 +83,7 @@ describe('createChatService', () => { function chat({ signal }: { signal: AbortSignal } = { signal: new AbortController().signal }) { return service.chat('my_test', { signal, + systemMessage: 'system', messages: [], connectorId: '', scopes: ['observability'], diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts index e3ccb38319896..a9e268ffbecd0 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts @@ -25,7 +25,7 @@ import { } from 'rxjs'; import { BehaviorSubject } from 'rxjs'; import type { AssistantScope } from '@kbn/ai-assistant-common'; -import { ChatCompletionChunkEvent, Message, MessageRole } from '../../common'; +import { ChatCompletionChunkEvent } from '../../common'; import { StreamingChatResponseEventType, type BufferFlushEvent, @@ -186,7 +186,6 @@ class ChatService { async initialize() { this.functionRegistry = new Map(); - const systemMessages: string[] = []; const scopePromise = this.apiClient('GET /internal/observability_ai_assistant/functions', { signal: this.abortSignal, params: { @@ -196,7 +195,7 @@ class ChatService { }, }).then(({ functionDefinitions, systemMessage }) => { functionDefinitions.forEach((fn) => this.functionRegistry.set(fn.name, fn)); - systemMessages.push(systemMessage); + this.systemMessage = systemMessage; }); await Promise.all([ @@ -210,8 +209,6 @@ class ChatService { }), ]); - this.systemMessage = systemMessages.join('\n'); - this.functions$.next(this.getFunctions()); } @@ -278,24 +275,17 @@ class ChatService { return this.renderFunctionRegistry.has(name); }; - public getSystemMessage = (): Message => { - return { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: this.systemMessage, - }, - }; - }; + public getSystemMessage = (): string => this.systemMessage; public chat: ObservabilityAIAssistantChatService['chat'] = ( name: string, - { connectorId, messages, functionCall, functions, signal } + { connectorId, systemMessage, messages, functionCall, functions, signal } ) => { return this.callStreamingApi('POST /internal/observability_ai_assistant/chat', { params: { body: { name, + systemMessage, messages, connectorId, functionCall, @@ -316,6 +306,7 @@ class ChatService { getScreenContexts, connectorId, conversationId, + systemMessage, messages, persist, disableFunctions, @@ -327,6 +318,7 @@ class ChatService { getScreenContexts, connectorId, conversationId, + systemMessage, messages, persist, disableFunctions, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts index 0559d65a14a81..38a3dc2b08a93 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts @@ -7,7 +7,7 @@ import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { BehaviorSubject } from 'rxjs'; -import { FunctionDefinition, MessageRole } from '../../common'; +import { FunctionDefinition } from '../../common'; import type { ObservabilityAIAssistantChatService } from '../types'; type MockedChatService = DeeplyMockedKeys; @@ -22,13 +22,7 @@ export const createMockChatService = (): MockedChatService => { hasFunction: jest.fn().mockReturnValue(false), hasRenderFunction: jest.fn().mockReturnValue(true), renderFunction: jest.fn(), - getSystemMessage: jest.fn().mockReturnValue({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'system', - }, - }), + getSystemMessage: jest.fn().mockReturnValue('system'), getScopes: jest.fn(), }; return mockChatService; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx index 004ad25aa4a86..5f2b70b1af99b 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx @@ -9,7 +9,7 @@ import { noop } from 'lodash'; import React from 'react'; import { BehaviorSubject, Observable, of } from 'rxjs'; import { AssistantScope } from '@kbn/ai-assistant-common'; -import { ChatCompletionChunkEvent, FunctionDefinition, MessageRole } from '.'; +import { ChatCompletionChunkEvent, FunctionDefinition } from '.'; import type { StreamingChatResponseEventWithoutError } from '../common/conversation_complete'; import type { ObservabilityAIAssistantAPIClient } from './api'; import type { ObservabilityAIAssistantChatService, ObservabilityAIAssistantService } from './types'; @@ -30,13 +30,7 @@ export const createStorybookChatService = (): ObservabilityAIAssistantChatServic ), hasFunction: () => true, hasRenderFunction: () => true, - getSystemMessage: () => ({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'System', - }, - }), + getSystemMessage: () => 'System', functions$: new BehaviorSubject( [] ) as ObservabilityAIAssistantChatService['functions$'], diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts index 72517df5bffbc..9c4223705e9a8 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts @@ -49,6 +49,7 @@ export interface ObservabilityAIAssistantChatService { chat: ( name: string, options: { + systemMessage: string; messages: Message[]; connectorId: string; functions?: Array>; @@ -61,6 +62,7 @@ export interface ObservabilityAIAssistantChatService { getScreenContexts: () => ObservabilityAIAssistantScreenContext[]; conversationId?: string; connectorId: string; + systemMessage?: string; messages: Message[]; persist: boolean; disableFunctions: @@ -79,7 +81,7 @@ export interface ObservabilityAIAssistantChatService { }) => FunctionDefinition[]; functions$: BehaviorSubject; hasFunction: (name: string) => boolean; - getSystemMessage: () => Message; + getSystemMessage: () => string; hasRenderFunction: (name: string) => boolean; renderFunction: ( name: string, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts index 2f36d27889c14..6669c991fe2bd 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts @@ -11,6 +11,7 @@ export const config = schema.object({ enabled: schema.boolean({ defaultValue: true }), scope: schema.maybe(schema.oneOf([schema.literal('observability'), schema.literal('search')])), enableKnowledgeBase: schema.boolean({ defaultValue: true }), + disableKbSemanticTextMigration: schema.boolean({ defaultValue: false }), }); export type ObservabilityAIAssistantConfig = TypeOf; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts index d87ded0cd2c5a..f3565f0bb36b1 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts @@ -100,20 +100,14 @@ export async function getRelevantFieldNames({ await chat('get_relevant_dataset_names', { signal, stream: true, - messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: `You are a helpful assistant for Elastic Observability. + systemMessage: `You are a helpful assistant for Elastic Observability. Your task is to create a list of field names that are relevant to the conversation, using ONLY the list of fields and types provided in the last user message. DO NOT UNDER ANY CIRCUMSTANCES include fields not mentioned in this list.`, - }, - }, - // remove the system message and the function request - ...messages.slice(1, -1), + messages: [ + // remove the function request + ...messages.filter((msg) => !msg.message?.function_call), { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts index 7ff878bfa7a9d..fd2e8d0d4b45e 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts @@ -31,7 +31,8 @@ import { registerFunctions } from './functions'; import { recallRankingEvent } from './analytics/recall_ranking'; import { initLangtrace } from './service/client/instrumentation/init_langtrace'; import { aiAssistantCapabilities } from '../common/capabilities'; -import { registerMigrateKnowledgeBaseEntriesTask } from './service/task_manager_definitions/register_migrate_knowledge_base_entries_task'; +import { registerAndScheduleKbSemanticTextMigrationTask } from './service/task_manager_definitions/register_kb_semantic_text_migration_task'; +import { updateExistingIndexAssets } from './service/create_or_update_index_assets'; export class ObservabilityAIAssistantPlugin implements @@ -128,14 +129,22 @@ export class ObservabilityAIAssistantPlugin config: this.config, })); - registerMigrateKnowledgeBaseEntriesTask({ + // Update existing index assets (mappings, templates, etc). This will not create assets if they do not exist. + updateExistingIndexAssets({ logger: this.logger.get('index_assets'), core }).catch((e) => + this.logger.error(`Index assets could not be updated: ${e.message}`) + ); + + // register task to migrate knowledge base entries to include semantic_text field + registerAndScheduleKbSemanticTextMigrationTask({ core, taskManager: plugins.taskManager, - logger: this.logger, + logger: this.logger.get('kb_semantic_text_migration_task'), config: this.config, - }).catch((e) => { - this.logger.error(`Knowledge base migration was not successfully: ${e.message}`); - }); + }).catch((e) => + this.logger.error( + `Knowledge base semantic_text migration task could not be registered: ${e.message}` + ) + ); service.register(registerFunctions); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts index 1ca0eb9d1dc39..23e7a70cecb31 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts @@ -135,6 +135,7 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ body: t.intersection([ t.type({ name: t.string, + systemMessage: t.string, messages: t.array(messageRt), connectorId: t.string, functions: t.array(functionRt), @@ -149,7 +150,7 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ const { params } = resources; const { - body: { name, messages, connectorId, functions, functionCall }, + body: { name, systemMessage, messages, connectorId, functions, functionCall }, } = params; const { client, simulateFunctionCalling, signal, isCloudEnabled } = await initializeChatRequest( @@ -158,6 +159,7 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ const response$ = client.chat(name, { stream: true, + systemMessage, messages, connectorId, signal, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts index e320376bc7357..cd2bb5b6331cd 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts @@ -6,10 +6,23 @@ */ import { notImplemented } from '@hapi/boom'; import * as t from 'io-ts'; -import { Conversation } from '../../../common/types'; +import { Conversation, MessageRole } from '../../../common/types'; import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; import { conversationCreateRt, conversationUpdateRt } from '../runtime_types'; +// backwards compatibility for messages with system role +const getConversationWithoutSystemMessages = (conversation: Conversation) => { + if (!conversation.systemMessage) { + conversation.systemMessage = + conversation.messages.find((message) => message.message.role === 'system')?.message + ?.content ?? ''; + } + conversation.messages = conversation.messages.filter( + (message) => message.message.role !== MessageRole.System + ); + return conversation; +}; + const getConversationRoute = createObservabilityAIAssistantServerRoute({ endpoint: 'GET /internal/observability_ai_assistant/conversation/{conversationId}', params: t.type({ @@ -31,7 +44,9 @@ const getConversationRoute = createObservabilityAIAssistantServerRoute({ throw notImplemented(); } - return client.get(params.path.conversationId); + const conversation = await client.get(params.path.conversationId); + // conversation without system messages + return getConversationWithoutSystemMessages(conversation); }, }); @@ -56,7 +71,12 @@ const findConversationsRoute = createObservabilityAIAssistantServerRoute({ throw notImplemented(); } - return client.find({ query: params?.body?.query }); + const conversations = await client.find({ query: params?.body?.query }); + + return { + // conversations without system messages + conversations: conversations.map(getConversationWithoutSystemMessages), + }; }, }); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts index 846a05797f975..ffdf9939ad7de 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts @@ -10,9 +10,11 @@ import { connectorRoutes } from './connectors/route'; import { conversationRoutes } from './conversations/route'; import { functionRoutes } from './functions/route'; import { knowledgeBaseRoutes } from './knowledge_base/route'; +import { topLevelRoutes } from './top_level/route'; export function getGlobalObservabilityAIAssistantServerRouteRepository() { return { + ...topLevelRoutes, ...chatRoutes, ...conversationRoutes, ...connectorRoutes, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts index 1597d43ce52b9..e9c7078c0062e 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts @@ -101,7 +101,7 @@ const resetKnowledgeBase = createObservabilityAIAssistantServerRoute({ }); const semanticTextMigrationKnowledgeBase = createObservabilityAIAssistantServerRoute({ - endpoint: 'POST /internal/observability_ai_assistant/kb/semantic_text_migration', + endpoint: 'POST /internal/observability_ai_assistant/kb/migrations/kb_semantic_text', security: { authz: { requiredPrivileges: ['ai_assistant'], @@ -114,7 +114,7 @@ const semanticTextMigrationKnowledgeBase = createObservabilityAIAssistantServerR throw notImplemented(); } - return client.migrateKnowledgeBaseToSemanticText(); + return client.reIndexKnowledgeBaseAndPopulateSemanticTextField(); }, }); diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts index 68f91f7e09858..cfa0410364efb 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts @@ -57,21 +57,26 @@ const tokenCountRt = t.type({ total: t.number, }); -export const baseConversationRt: t.Type = t.type({ - '@timestamp': t.string, - conversation: t.intersection([ - t.type({ - title: t.string, - }), - t.partial({ - token_count: tokenCountRt, - }), - ]), - messages: t.array(messageRt), - labels: t.record(t.string, t.string), - numeric_labels: t.record(t.string, t.number), - public: toBooleanRt, -}); +export const baseConversationRt: t.Type = t.intersection([ + t.type({ + '@timestamp': t.string, + conversation: t.intersection([ + t.type({ + title: t.string, + }), + t.partial({ + token_count: tokenCountRt, + }), + ]), + messages: t.array(messageRt), + labels: t.record(t.string, t.string), + numeric_labels: t.record(t.string, t.number), + public: toBooleanRt, + }), + t.partial({ + systemMessage: t.string, + }), +]); export const assistantScopeType = t.union([ t.literal('observability'), diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/top_level/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/top_level/route.ts new file mode 100644 index 0000000000000..dc817f378263f --- /dev/null +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/top_level/route.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createOrUpdateIndexAssets } from '../../service/create_or_update_index_assets'; +import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; + +const createOrUpdateIndexAssetsRoute = createObservabilityAIAssistantServerRoute({ + endpoint: 'POST /internal/observability_ai_assistant/index_assets', + security: { + authz: { + requiredPrivileges: ['ai_assistant'], + }, + }, + handler: async (resources): Promise => { + return createOrUpdateIndexAssets({ + logger: resources.logger, + core: resources.plugins.core.setup, + }); + }, +}); + +export const topLevelRoutes = { + ...createOrUpdateIndexAssetsRoute, +}; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts index 83cc9d9e60762..63861061408d4 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts @@ -44,7 +44,7 @@ interface ChunkDelta { type LlmSimulator = ReturnType; -const EXPECTED_STORED_SYSTEM_MESSAGE = `system`; +const EXPECTED_STORED_SYSTEM_MESSAGE = `this is a system message`; const nextTick = () => { return new Promise(process.nextTick); @@ -185,7 +185,7 @@ describe('Observability AI Assistant client', () => { knowledgeBaseServiceMock.getUserInstructions.mockResolvedValue([]); - functionClientMock.getInstructions.mockReturnValue(['system']); + functionClientMock.getInstructions.mockReturnValue([EXPECTED_STORED_SYSTEM_MESSAGE]); functionClientMock.getAdhocInstructions.mockReturnValue([]); return new ObservabilityAIAssistantClient({ @@ -208,18 +208,6 @@ describe('Observability AI Assistant client', () => { }); } - function system(content: string | Omit): Message { - return merge( - { - '@timestamp': new Date().toString(), - message: { - role: MessageRole.System, - }, - }, - typeof content === 'string' ? { message: { content } } : content - ); - } - function user(content: string | Omit): Message { return merge( { @@ -286,7 +274,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, persist: true, @@ -313,6 +301,8 @@ describe('Observability AI Assistant client', () => { expect.objectContaining({ connectorId: 'foo', stream: false, + system: + 'You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on the content below. DO NOT UNDER ANY CIRCUMSTANCES wrap this title in single or double quotes. This title is shown in a list of conversations to the user, so title it for the user, not for you.', functionCalling: 'auto', toolChoice: expect.objectContaining({ function: 'title_conversation', @@ -346,6 +336,7 @@ describe('Observability AI Assistant client', () => { { connectorId: 'foo', stream: true, + system: EXPECTED_STORED_SYSTEM_MESSAGE, messages: expect.arrayContaining([ { role: 'user', content: 'How many alerts do I have?' }, ]), @@ -497,14 +488,8 @@ describe('Observability AI Assistant client', () => { user: { name: 'johndoe', }, + systemMessage: EXPECTED_STORED_SYSTEM_MESSAGE, messages: [ - { - '@timestamp': expect.any(String), - message: { - content: EXPECTED_STORED_SYSTEM_MESSAGE, - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -567,10 +552,7 @@ describe('Observability AI Assistant client', () => { labels: {}, numeric_labels: {}, public: false, - messages: [ - system('This is a system message'), - user('How many alerts do I have?'), - ], + messages: [user('How many alerts do I have?')], }, }, ], @@ -585,7 +567,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, conversationId: 'my-conversation-id', @@ -645,14 +627,8 @@ describe('Observability AI Assistant client', () => { user: { name: 'johndoe', }, + systemMessage: EXPECTED_STORED_SYSTEM_MESSAGE, messages: [ - { - '@timestamp': expect.any(String), - message: { - content: EXPECTED_STORED_SYSTEM_MESSAGE, - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -694,7 +670,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, title: 'My predefined title', @@ -784,7 +760,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, title: 'My predefined title', @@ -845,13 +821,6 @@ describe('Observability AI Assistant client', () => { signal: expect.any(AbortSignal), connectorId: 'foo', messages: [ - { - '@timestamp': expect.any(String), - message: { - role: MessageRole.System, - content: EXPECTED_STORED_SYSTEM_MESSAGE, - }, - }, { '@timestamp': expect.any(String), message: { @@ -916,6 +885,7 @@ describe('Observability AI Assistant client', () => { { connectorId: 'foo', stream: true, + system: EXPECTED_STORED_SYSTEM_MESSAGE, messages: expect.arrayContaining([ { role: 'user', content: 'How many alerts do I have?' }, ]), @@ -983,13 +953,6 @@ describe('Observability AI Assistant client', () => { expect( (internalUserEsClientMock.index.mock.lastCall![0] as any).document.messages ).toEqual([ - { - '@timestamp': expect.any(String), - message: { - content: EXPECTED_STORED_SYSTEM_MESSAGE, - role: MessageRole.System, - }, - }, { '@timestamp': expect.any(String), message: { @@ -1077,6 +1040,7 @@ describe('Observability AI Assistant client', () => { { connectorId: 'foo', stream: true, + system: EXPECTED_STORED_SYSTEM_MESSAGE, messages: expect.arrayContaining([ { role: 'user', content: 'How many alerts do I have?' }, ]), @@ -1221,7 +1185,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, persist: false, @@ -1346,7 +1310,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, title: 'My predefined title', @@ -1424,7 +1388,7 @@ describe('Observability AI Assistant client', () => { const stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, persist: false, @@ -1512,7 +1476,7 @@ describe('Observability AI Assistant client', () => { stream = observableIntoStream( await client.complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('How many alerts do I have?')], + messages: [user('How many alerts do I have?')], functionClient: functionClientMock, signal: new AbortController().signal, title: 'My predefined title', @@ -1577,7 +1541,7 @@ describe('Observability AI Assistant client', () => { client .complete({ connectorId: 'foo', - messages: [system('This is a system message'), user('A user message to cause completion')], + messages: [user('A user message to cause completion')], functionClient: functionClientMock, signal: new AbortController().signal, title: 'My predefined title', @@ -1586,9 +1550,7 @@ describe('Observability AI Assistant client', () => { .subscribe(() => {}); // To trigger call to chat await nextTick(); - expect(chatSpy.mock.calls[0][1].messages[0].message.content).toEqual( - EXPECTED_STORED_SYSTEM_MESSAGE - ); + expect(chatSpy.mock.calls[0][1].systemMessage).toEqual(EXPECTED_STORED_SYSTEM_MESSAGE); }); describe('when executing an action', () => { @@ -1605,10 +1567,7 @@ describe('Observability AI Assistant client', () => { const complete$ = await client.complete({ connectorId: 'foo', - messages: [ - system('This is a system message'), - user('Can you call the my_action function?'), - ], + messages: [user('Can you call the my_action function?')], functionClient: new ChatFunctionClient([ { actions: [ diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts index 3885057fd28c5..bb2064a3dbb6b 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts @@ -14,7 +14,6 @@ import { context } from '@opentelemetry/api'; import { last, merge, omit } from 'lodash'; import { catchError, - combineLatest, defer, filter, forkJoin, @@ -56,7 +55,6 @@ import { type Message, KnowledgeBaseType, KnowledgeBaseEntryRole, - MessageRole, } from '../../../common/types'; import { withoutTokenCountEvents } from '../../../common/utils/without_token_count_events'; import { CONTEXT_FUNCTION_NAME } from '../../functions/context'; @@ -64,7 +62,6 @@ import type { ChatFunctionClient } from '../chat_function_client'; import { KnowledgeBaseService, RecalledEntry } from '../knowledge_base_service'; import { getAccessQuery } from '../util/get_access_query'; import { getSystemMessageFromInstructions } from '../util/get_system_message_from_instructions'; -import { replaceSystemMessage } from '../util/replace_system_message'; import { failOnNonExistingFunctionCall } from './operators/fail_on_non_existing_function_call'; import { getContextFunctionRequestIfNeeded } from './get_context_function_request_if_needed'; import { LangTracer } from './instrumentation/lang_tracer'; @@ -75,9 +72,9 @@ import { extractTokenCount } from './operators/extract_token_count'; import { getGeneratedTitle } from './operators/get_generated_title'; import { instrumentAndCountTokens } from './operators/instrument_and_count_tokens'; import { - runSemanticTextKnowledgeBaseMigration, - scheduleSemanticTextMigration, -} from '../task_manager_definitions/register_migrate_knowledge_base_entries_task'; + reIndexKnowledgeBaseAndPopulateSemanticTextField, + scheduleKbSemanticTextMigrationTask, +} from '../task_manager_definitions/register_kb_semantic_text_migration_task'; import { ObservabilityAIAssistantPluginStartDependencies } from '../../types'; import { ObservabilityAIAssistantConfig } from '../../config'; import { getElserModelId } from '../knowledge_base_service/get_elser_model_id'; @@ -215,28 +212,6 @@ export class ObservabilityAIAssistantClient { const registeredAdhocInstructions = functionClient.getAdhocInstructions(); const allAdHocInstructions = adHocInstructions.concat(registeredAdhocInstructions); - // from the initial messages, override any system message with - // the one that is based on the instructions (registered, request, kb) - const messagesWithUpdatedSystemMessage$ = userInstructions$.pipe( - map((userInstructions) => { - // this is what we eventually store in the conversation - const messagesWithUpdatedSystemMessage = replaceSystemMessage( - getSystemMessageFromInstructions({ - applicationInstructions: functionClient.getInstructions(), - userInstructions, - adHocInstructions: allAdHocInstructions, - availableFunctionNames: functionClient - .getFunctions() - .map((fn) => fn.definition.name), - }), - initialMessages - ); - - return messagesWithUpdatedSystemMessage; - }), - shareReplay() - ); - // if it is: // - a new conversation // - no predefined title is given @@ -246,35 +221,39 @@ export class ObservabilityAIAssistantClient { const title$ = predefinedTitle || isConversationUpdate || !persist ? of(predefinedTitle || '').pipe(shareReplay()) - : messagesWithUpdatedSystemMessage$.pipe( - switchMap((messages) => - getGeneratedTitle({ - messages, - logger: this.dependencies.logger, - chat: (name, chatParams) => - this.chat(name, { - ...chatParams, - simulateFunctionCalling, - connectorId, - signal, - stream: false, - }), - tracer: completeTracer, - }) - ), - shareReplay() - ); + : getGeneratedTitle({ + messages: initialMessages, + logger: this.dependencies.logger, + chat: (name, chatParams) => + this.chat(name, { + ...chatParams, + simulateFunctionCalling, + connectorId, + signal, + stream: false, + }), + tracer: completeTracer, + }).pipe(shareReplay()); + + const systemMessage$ = userInstructions$.pipe( + map((userInstructions) => { + return getSystemMessageFromInstructions({ + applicationInstructions: functionClient.getInstructions(), + userInstructions, + adHocInstructions: allAdHocInstructions, + availableFunctionNames: functionClient.getFunctions().map((fn) => fn.definition.name), + }); + }), + shareReplay() + ); // we continue the conversation here, after resolving both the materialized // messages and the knowledge base instructions - const nextEvents$ = combineLatest([ - messagesWithUpdatedSystemMessage$, - userInstructions$, - ]).pipe( - switchMap(([messagesWithUpdatedSystemMessage, userInstructions]) => { + const nextEvents$ = forkJoin([systemMessage$, userInstructions$]).pipe( + switchMap(([systemMessage, userInstructions]) => { // if needed, inject a context function request here const contextRequest = functionClient.hasFunction(CONTEXT_FUNCTION_NAME) - ? getContextFunctionRequestIfNeeded(messagesWithUpdatedSystemMessage) + ? getContextFunctionRequestIfNeeded(initialMessages) : undefined; return mergeOperator( @@ -283,14 +262,12 @@ export class ObservabilityAIAssistantClient { // and add it to the conversation ...(contextRequest ? [of(contextRequest)] : []), continueConversation({ - messages: [ - ...messagesWithUpdatedSystemMessage, - ...(contextRequest ? [contextRequest.message] : []), - ], + messages: [...initialMessages, ...(contextRequest ? [contextRequest.message] : [])], chat: (name, chatParams) => { // inject a chat function with predefined parameters return this.chat(name, { ...chatParams, + systemMessage, signal, simulateFunctionCalling, connectorId, @@ -319,7 +296,6 @@ export class ObservabilityAIAssistantClient { nextEvents$, // wait until all dependencies have completed forkJoin([ - messagesWithUpdatedSystemMessage$, // get just the new messages nextEvents$.pipe(withoutTokenCountEvents(), extractMessages()), // count all the token count events emitted during completion @@ -329,101 +305,100 @@ export class ObservabilityAIAssistantClient { ).pipe(extractTokenCount()), // get just the title, and drop the token count events title$.pipe(filter((value): value is string => typeof value === 'string')), + systemMessage$, ]).pipe( - switchMap( - ([messagesWithUpdatedSystemMessage, addedMessages, tokenCountResult, title]) => { - const initialMessagesWithAddedMessages = - messagesWithUpdatedSystemMessage.concat(addedMessages); - - const lastMessage = last(initialMessagesWithAddedMessages); - - // if a function request is at the very end, close the stream to consumer - // without persisting or updating the conversation. we need to wait - // on the function response to have a valid conversation - const isFunctionRequest = !!lastMessage?.message.function_call?.name; - - if (!persist || isFunctionRequest) { - return of(); - } - - if (isConversationUpdate) { - return from(this.getConversationWithMetaFields(conversationId)) - .pipe( - switchMap((conversation) => { - if (!conversation) { - return throwError(() => createConversationNotFoundError()); - } - - const persistedTokenCount = conversation._source?.conversation - .token_count ?? { - prompt: 0, - completion: 0, - total: 0, - }; - - return from( - this.update( - conversationId, - - merge( - {}, - - // base conversation without messages - omit(conversation._source, 'messages'), - - // update messages - { messages: initialMessagesWithAddedMessages }, - - // update token count - { - conversation: { - title: title || conversation._source?.conversation.title, - token_count: { - prompt: persistedTokenCount.prompt + tokenCountResult.prompt, - completion: - persistedTokenCount.completion + tokenCountResult.completion, - total: persistedTokenCount.total + tokenCountResult.total, - }, + switchMap(([addedMessages, tokenCountResult, title, systemMessage]) => { + const initialMessagesWithAddedMessages = initialMessages.concat(addedMessages); + + const lastMessage = last(initialMessagesWithAddedMessages); + + // if a function request is at the very end, close the stream to consumer + // without persisting or updating the conversation. we need to wait + // on the function response to have a valid conversation + const isFunctionRequest = !!lastMessage?.message.function_call?.name; + + if (!persist || isFunctionRequest) { + return of(); + } + + if (isConversationUpdate) { + return from(this.getConversationWithMetaFields(conversationId)) + .pipe( + switchMap((conversation) => { + if (!conversation) { + return throwError(() => createConversationNotFoundError()); + } + + const persistedTokenCount = conversation._source?.conversation + .token_count ?? { + prompt: 0, + completion: 0, + total: 0, + }; + + return from( + this.update( + conversationId, + + merge( + {}, + + // base conversation without messages + omit(conversation._source, 'messages'), + + // update messages and system message + { messages: initialMessagesWithAddedMessages, systemMessage }, + + // update token count + { + conversation: { + title: title || conversation._source?.conversation.title, + token_count: { + prompt: persistedTokenCount.prompt + tokenCountResult.prompt, + completion: + persistedTokenCount.completion + tokenCountResult.completion, + total: persistedTokenCount.total + tokenCountResult.total, }, - } - ) + }, + } ) - ); - }) - ) - .pipe( - map((conversation): ConversationUpdateEvent => { - return { - conversation: conversation.conversation, - type: StreamingChatResponseEventType.ConversationUpdate, - }; - }) - ); - } - - return from( - this.create({ - '@timestamp': new Date().toISOString(), - conversation: { - title, - id: conversationId, - token_count: tokenCountResult, - }, - public: !!isPublic, - labels: {}, - numeric_labels: {}, - messages: initialMessagesWithAddedMessages, - }) - ).pipe( - map((conversation): ConversationCreateEvent => { - return { - conversation: conversation.conversation, - type: StreamingChatResponseEventType.ConversationCreate, - }; - }) - ); + ) + ); + }) + ) + .pipe( + map((conversation): ConversationUpdateEvent => { + return { + conversation: conversation.conversation, + type: StreamingChatResponseEventType.ConversationUpdate, + }; + }) + ); } - ) + + return from( + this.create({ + '@timestamp': new Date().toISOString(), + conversation: { + title, + id: conversationId, + token_count: tokenCountResult, + }, + public: !!isPublic, + labels: {}, + numeric_labels: {}, + systemMessage, + messages: initialMessagesWithAddedMessages, + }) + ).pipe( + map((conversation): ConversationCreateEvent => { + return { + conversation: conversation.conversation, + type: StreamingChatResponseEventType.ConversationCreate, + }; + }) + ); + }) ) ); @@ -466,6 +441,7 @@ export class ObservabilityAIAssistantClient { chat( name: string, { + systemMessage, messages, connectorId, functions, @@ -475,6 +451,7 @@ export class ObservabilityAIAssistantClient { tracer, stream, }: { + systemMessage?: string; messages: Message[]; connectorId: string; functions?: Array<{ name: string; description: string; parameters?: CompatibleJSONSchema }>; @@ -508,9 +485,8 @@ export class ObservabilityAIAssistantClient { const options = { connectorId, - messages: convertMessagesForInference( - messages.filter((message) => message.message.role !== MessageRole.System) - ), + system: systemMessage, + messages: convertMessagesForInference(messages), toolChoice, tools, functionCalling: (simulateFunctionCalling ? 'simulated' : 'auto') as FunctionCallingMode, @@ -546,7 +522,7 @@ export class ObservabilityAIAssistantClient { } } - find = async (options?: { query?: string }): Promise<{ conversations: Conversation[] }> => { + find = async (options?: { query?: string }): Promise => { const response = await this.dependencies.esClient.asInternalUser.search({ index: resourceNames.aliases.conversations, allow_no_indices: true, @@ -566,9 +542,7 @@ export class ObservabilityAIAssistantClient { size: 100, }); - return { - conversations: response.hits.hits.map((hit) => hit._source!), - }; + return response.hits.hits.map((hit) => hit._source!); }; update = async ( @@ -686,12 +660,11 @@ export class ObservabilityAIAssistantClient { core .getStartServices() - .then(([_, pluginsStart]) => { - logger.debug('Schedule semantic text migration task'); - return scheduleSemanticTextMigration(pluginsStart); - }) + .then(([_, pluginsStart]) => + scheduleKbSemanticTextMigrationTask({ taskManager: pluginsStart.taskManager, logger }) + ) .catch((error) => { - logger.error(`Failed to run semantic text migration task: ${error}`); + logger.error(`Failed to schedule semantic text migration task: ${error}`); }); return res; @@ -702,8 +675,8 @@ export class ObservabilityAIAssistantClient { return this.dependencies.knowledgeBaseService.reset(esClient); }; - migrateKnowledgeBaseToSemanticText = () => { - return runSemanticTextKnowledgeBaseMigration({ + reIndexKnowledgeBaseAndPopulateSemanticTextField = () => { + return reIndexKnowledgeBaseAndPopulateSemanticTextField({ esClient: this.dependencies.esClient, logger: this.dependencies.logger, config: this.dependencies.config, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts index ba19aca714eb4..a78f0b4aa70be 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts @@ -35,8 +35,6 @@ import { withoutTokenCountEvents } from '../../../../common/utils/without_token_ import type { ChatFunctionClient } from '../../chat_function_client'; import type { AutoAbortedChatFunction } from '../../types'; import { createServerSideFunctionResponseError } from '../../util/create_server_side_function_response_error'; -import { getSystemMessageFromInstructions } from '../../util/get_system_message_from_instructions'; -import { replaceSystemMessage } from '../../util/replace_system_message'; import { LangTracer } from '../instrumentation/lang_tracer'; import { catchFunctionNotFoundError } from './catch_function_not_found_error'; import { extractMessages } from './extract_messages'; @@ -213,20 +211,7 @@ export function continueConversation({ disableFunctions, }); - const registeredAdhocInstructions = functionClient.getAdhocInstructions(); - const allAdHocInstructions = adHocInstructions.concat(registeredAdhocInstructions); - - const messagesWithUpdatedSystemMessage = replaceSystemMessage( - getSystemMessageFromInstructions({ - applicationInstructions: functionClient.getInstructions(), - userInstructions, - adHocInstructions: allAdHocInstructions, - availableFunctionNames: definitions.map((def) => def.name), - }), - initialMessages - ); - - const lastMessage = last(messagesWithUpdatedSystemMessage)?.message; + const lastMessage = last(initialMessages)?.message; const isUserMessage = lastMessage?.role === MessageRole.User; return executeNextStep().pipe(handleEvents()); @@ -239,7 +224,7 @@ export function continueConversation({ : 'user_message'; return chat(operationName, { - messages: messagesWithUpdatedSystemMessage, + messages: initialMessages, functions: definitions, tracer, connectorId, @@ -314,7 +299,7 @@ export function continueConversation({ args: lastMessage.function_call!.arguments, chat, functionClient, - messages: messagesWithUpdatedSystemMessage, + messages: initialMessages, signal, logger, tracer, @@ -337,7 +322,7 @@ export function continueConversation({ return EMPTY; } return continueConversation({ - messages: messagesWithUpdatedSystemMessage.concat(extractedMessages), + messages: initialMessages.concat(extractedMessages), chat, functionCallsLeft: nextFunctionCallsLeft, functionClient, diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts index 42453f8d407b6..776881378ce99 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts @@ -92,10 +92,9 @@ describe('getGeneratedTitle', () => { await lastValueFrom(title$); const [name, params] = chatSpy.mock.calls[0]; - expect(name).toEqual('generate_title'); - expect(params.messages.length).toBe(2); - expect(params.messages[1].message.content).toContain('A message'); + expect(params.messages.length).toBe(1); + expect(params.messages[0].message.content).toContain('A message'); }); it('strips quotes from the title', async () => { diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts index 3f1b9f43cd35f..20d6c1217aa6d 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts @@ -36,23 +36,16 @@ export function getGeneratedTitle({ }): Observable { return from( chat('generate_title', { + systemMessage: + 'You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on the content below. DO NOT UNDER ANY CIRCUMSTANCES wrap this title in single or double quotes. This title is shown in a list of conversations to the user, so title it for the user, not for you.', messages: [ - { - '@timestamp': new Date().toString(), - message: { - role: MessageRole.System, - content: `You are a helpful assistant for Elastic Observability. Assume the following message is the start of a conversation between you and a user; give this conversation a title based on the content below. DO NOT UNDER ANY CIRCUMSTANCES wrap this title in single or double quotes. This title is shown in a list of conversations to the user, so title it for the user, not for you.`, - }, - }, { '@timestamp': new Date().toISOString(), message: { role: MessageRole.User, - content: messages - .filter((msg) => msg.message.role !== MessageRole.System) - .reduce((acc, curr) => { - return `${acc} ${curr.message.role}: ${curr.message.content}`; - }, 'Generate a title, using the title_conversation_function, based on the following conversation:\n\n'), + content: messages.reduce((acc, curr) => { + return `${acc} ${curr.message.role}: ${curr.message.content}`; + }, 'Generate a title, using the title_conversation_function, based on the following conversation:\n\n'), }, }, ], diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/create_or_update_index_assets.ts similarity index 65% rename from x-pack/platform/plugins/shared/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/create_or_update_index_assets.ts index b56628ce4b7ee..85a0e9ba8e42a 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/create_or_update_index_assets.ts @@ -6,13 +6,39 @@ */ import { createConcreteWriteIndex, getDataStreamAdapter } from '@kbn/alerting-plugin/server'; -import type { CoreSetup, Logger } from '@kbn/core/server'; +import type { CoreSetup, ElasticsearchClient, Logger } from '@kbn/core/server'; import type { ObservabilityAIAssistantPluginStartDependencies } from '../types'; import { conversationComponentTemplate } from './conversation_component_template'; import { kbComponentTemplate } from './kb_component_template'; import { resourceNames } from '.'; -export async function setupConversationAndKbIndexAssets({ +export async function updateExistingIndexAssets({ + logger, + core, +}: { + logger: Logger; + core: CoreSetup; +}) { + const [coreStart] = await core.getStartServices(); + const { asInternalUser } = coreStart.elasticsearch.client; + + const hasKbIndex = await asInternalUser.indices.exists({ + index: resourceNames.aliases.kb, + }); + + const hasConversationIndex = await asInternalUser.indices.exists({ + index: resourceNames.aliases.conversations, + }); + + if (!hasKbIndex && !hasConversationIndex) { + logger.debug('Index assets do not exist. Aborting updating index assets'); + return; + } + + await createOrUpdateIndexAssets({ logger, core }); +} + +export async function createOrUpdateIndexAssets({ logger, core, }: { @@ -56,7 +82,7 @@ export async function setupConversationAndKbIndexAssets({ alias: conversationAliasName, pattern: `${conversationAliasName}*`, basePattern: `${conversationAliasName}*`, - name: `${conversationAliasName}-000001`, + name: resourceNames.concreteIndexName.conversations, template: resourceNames.indexTemplate.conversations, }, dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts: false }), @@ -86,20 +112,7 @@ export async function setupConversationAndKbIndexAssets({ }); // Knowledge base: write index - const kbAliasName = resourceNames.aliases.kb; - await createConcreteWriteIndex({ - esClient: asInternalUser, - logger, - totalFieldsLimit: 10000, - indexPatterns: { - alias: kbAliasName, - pattern: `${kbAliasName}*`, - basePattern: `${kbAliasName}*`, - name: `${kbAliasName}-000001`, - template: resourceNames.indexTemplate.kb, - }, - dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts: false }), - }); + await createKbConcreteIndex({ logger, esClient: coreStart.elasticsearch.client }); logger.info('Successfully set up index assets'); } catch (error) { @@ -107,3 +120,28 @@ export async function setupConversationAndKbIndexAssets({ logger.debug(error); } } + +export async function createKbConcreteIndex({ + logger, + esClient, +}: { + logger: Logger; + esClient: { + asInternalUser: ElasticsearchClient; + }; +}) { + const kbAliasName = resourceNames.aliases.kb; + return createConcreteWriteIndex({ + esClient: esClient.asInternalUser, + logger, + totalFieldsLimit: 10000, + indexPatterns: { + alias: kbAliasName, + pattern: `${kbAliasName}*`, + basePattern: `${kbAliasName}*`, + name: resourceNames.concreteIndexName.kb, + template: resourceNames.indexTemplate.kb, + }, + dataStreamAdapter: getDataStreamAdapter({ useDataStreamForAlerts: false }), + }); +} diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts index dcd79f5d57873..adc7ea2822747 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts @@ -17,7 +17,7 @@ import { ObservabilityAIAssistantClient } from './client'; import { KnowledgeBaseService } from './knowledge_base_service'; import type { RegistrationCallback, RespondFunctionResources } from './types'; import { ObservabilityAIAssistantConfig } from '../config'; -import { setupConversationAndKbIndexAssets } from './setup_conversation_and_kb_index_assets'; +import { createOrUpdateIndexAssets } from './create_or_update_index_assets'; function getResourceName(resource: string) { return `.kibana-observability-ai-assistant-${resource}`; @@ -40,11 +40,15 @@ export const resourceNames = { conversations: getResourceName('index-template-conversations'), kb: getResourceName('index-template-kb'), }, + concreteIndexName: { + conversations: getResourceName('conversations-000001'), + kb: getResourceName('kb-000001'), + }, }; const createIndexAssetsOnce = once( (logger: Logger, core: CoreSetup) => - pRetry(() => setupConversationAndKbIndexAssets({ logger, core })) + pRetry(() => createOrUpdateIndexAssets({ logger, core })) ); export class ObservabilityAIAssistantService { diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts index a73be984920c4..aea384b4c0aa6 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts @@ -28,6 +28,11 @@ import { import { recallFromSearchConnectors } from './recall_from_search_connectors'; import { ObservabilityAIAssistantPluginStartDependencies } from '../../types'; import { ObservabilityAIAssistantConfig } from '../../config'; +import { + isKnowledgeBaseIndexWriteBlocked, + isSemanticTextUnsupportedError, +} from './reindex_knowledge_base'; +import { scheduleKbSemanticTextMigrationTask } from '../task_manager_definitions/register_kb_semantic_text_migration_task'; interface Dependencies { core: CoreSetup; @@ -406,7 +411,9 @@ export class KnowledgeBaseService { } try { - await this.dependencies.esClient.asInternalUser.index({ + await this.dependencies.esClient.asInternalUser.index< + Omit & { namespace: string } + >({ index: resourceNames.aliases.kb, id, document: { @@ -418,10 +425,40 @@ export class KnowledgeBaseService { }, refresh: 'wait_for', }); + this.dependencies.logger.debug(`Entry added to knowledge base`); } catch (error) { + this.dependencies.logger.debug(`Failed to add entry to knowledge base ${error}`); if (isInferenceEndpointMissingOrUnavailable(error)) { throwKnowledgeBaseNotReady(error.body); } + + if (isSemanticTextUnsupportedError(error)) { + this.dependencies.core + .getStartServices() + .then(([_, pluginsStart]) => { + return scheduleKbSemanticTextMigrationTask({ + taskManager: pluginsStart.taskManager, + logger: this.dependencies.logger, + runSoon: true, + }); + }) + .catch((e) => { + this.dependencies.logger.error( + `Failed to schedule knowledge base semantic text migration task: ${e}` + ); + }); + + throw serverUnavailable( + 'The knowledge base is currently being re-indexed. Please try again later' + ); + } + + if (isKnowledgeBaseIndexWriteBlocked(error)) { + throw new Error( + `Writes to the knowledge base are currently blocked due to an Elasticsearch write index block. This is most likely due to an ongoing re-indexing operation. Please try again later. Error: ${error.message}` + ); + } + throw error; } }; diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/reindex_knowledge_base.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/reindex_knowledge_base.ts new file mode 100644 index 0000000000000..7b65576a1e6da --- /dev/null +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/reindex_knowledge_base.ts @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { errors as EsErrors } from '@elastic/elasticsearch'; +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { Logger } from '@kbn/logging'; +import { resourceNames } from '..'; +import { createKbConcreteIndex } from '../create_or_update_index_assets'; + +export async function reIndexKnowledgeBase({ + logger, + esClient, +}: { + logger: Logger; + esClient: { + asInternalUser: ElasticsearchClient; + }; +}): Promise { + logger.debug('Initiating knowledge base re-indexing...'); + + try { + const originalIndex = resourceNames.concreteIndexName.kb; + const tempIndex = `${resourceNames.aliases.kb}-000002`; + + const indexSettingsResponse = await esClient.asInternalUser.indices.getSettings({ + index: originalIndex, + }); + + const indexSettings = indexSettingsResponse[originalIndex].settings; + const createdVersion = parseInt(indexSettings?.index?.version?.created ?? '', 10); + + // Check if the index was created before version 8.11 + const versionThreshold = 8110000; // Version 8.11.0 + if (createdVersion >= versionThreshold) { + logger.warn( + `Knowledge base index "${originalIndex}" was created in version ${createdVersion}, and does not require re-indexing. Semantic text field is already supported. Aborting` + ); + return; + } + + logger.info( + `Knowledge base index was created in ${createdVersion} and must be re-indexed in order to support semantic_text field. Re-indexing now...` + ); + + // Create temporary index + logger.debug(`Creating temporary index "${tempIndex}"...`); + await esClient.asInternalUser.indices.delete({ index: tempIndex }, { ignore: [404] }); + await esClient.asInternalUser.indices.create({ index: tempIndex }); + + // Perform reindex to temporary index + logger.debug(`Re-indexing knowledge base to temporary index "${tempIndex}"...`); + await esClient.asInternalUser.reindex({ + body: { + source: { index: originalIndex }, + dest: { index: tempIndex }, + }, + refresh: true, + wait_for_completion: true, + }); + + // Delete and re-create original index + logger.debug(`Deleting original index "${originalIndex}" and re-creating it...`); + await esClient.asInternalUser.indices.delete({ index: originalIndex }); + await createKbConcreteIndex({ logger, esClient }); + + // Perform reindex back to original index + logger.debug(`Re-indexing knowledge base back to original index "${originalIndex}"...`); + await esClient.asInternalUser.reindex({ + body: { + source: { index: tempIndex }, + dest: { index: originalIndex }, + }, + refresh: true, + wait_for_completion: true, + }); + + // Delete temporary index + logger.debug(`Deleting temporary index "${tempIndex}"...`); + await esClient.asInternalUser.indices.delete({ index: tempIndex }); + + logger.info( + 'Re-indexing knowledge base completed successfully. Semantic text field is now supported.' + ); + } catch (error) { + throw new Error(`Failed to reindex knowledge base: ${error.message}`); + } +} + +export function isKnowledgeBaseIndexWriteBlocked(error: any) { + return ( + error instanceof EsErrors.ResponseError && + error.message.includes( + `cluster_block_exception: index [${resourceNames.concreteIndexName.kb}] blocked` + ) + ); +} + +export function isSemanticTextUnsupportedError(error: Error) { + const semanticTextUnsupportedError = + 'The [sparse_vector] field type is not supported on indices created on versions 8.0 to 8.10'; + + const isSemanticTextUnspported = + error instanceof EsErrors.ResponseError && + (error.message.includes(semanticTextUnsupportedError) || + // @ts-expect-error + error.meta?.body?.error?.caused_by?.reason.includes(semanticTextUnsupportedError)); + + return isSemanticTextUnspported; +} diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_kb_semantic_text_migration_task.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_kb_semantic_text_migration_task.ts new file mode 100644 index 0000000000000..29dd1418b2818 --- /dev/null +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_kb_semantic_text_migration_task.ts @@ -0,0 +1,228 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import pLimit from 'p-limit'; +import { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; +import type { CoreSetup, CoreStart, Logger } from '@kbn/core/server'; +import pRetry from 'p-retry'; +import { KnowledgeBaseEntry } from '../../../common'; +import { resourceNames } from '..'; +import { getElserModelStatus } from '../inference_endpoint'; +import { ObservabilityAIAssistantPluginStartDependencies } from '../../types'; +import { ObservabilityAIAssistantConfig } from '../../config'; +import { reIndexKnowledgeBase } from '../knowledge_base_service/reindex_knowledge_base'; + +const TASK_ID = 'obs-ai-assistant:knowledge-base-migration-task-id'; +const TASK_TYPE = 'obs-ai-assistant:knowledge-base-migration'; + +// This task will re-index all knowledge base entries without `semantic_text` field +// to ensure the field is populated with the correct embeddings. +// After the migration we will no longer need to use the `ml.tokens` field. +export async function registerAndScheduleKbSemanticTextMigrationTask({ + taskManager, + logger, + core, + config, +}: { + taskManager: TaskManagerSetupContract; + logger: Logger; + core: CoreSetup; + config: ObservabilityAIAssistantConfig; +}) { + const [coreStart, pluginsStart] = await core.getStartServices(); + + // register task + registerKbSemanticTextMigrationTask({ taskManager, logger, coreStart, config }); + + // schedule task + await scheduleKbSemanticTextMigrationTask({ taskManager: pluginsStart.taskManager, logger }); +} + +function registerKbSemanticTextMigrationTask({ + taskManager, + logger, + coreStart, + config, +}: { + taskManager: TaskManagerSetupContract; + logger: Logger; + coreStart: CoreStart; + config: ObservabilityAIAssistantConfig; +}) { + try { + logger.debug(`Register task "${TASK_TYPE}"`); + taskManager.registerTaskDefinitions({ + [TASK_TYPE]: { + title: 'Add support for semantic_text in Knowledge Base', + description: `This task will reindex the knowledge base and populate the semantic_text fields for all entries without it.`, + timeout: '1h', + maxAttempts: 5, + createTaskRunner() { + return { + async run() { + logger.debug(`Run task: "${TASK_TYPE}"`); + const esClient = coreStart.elasticsearch.client; + + const hasKbIndex = await esClient.asInternalUser.indices.exists({ + index: resourceNames.aliases.kb, + }); + + if (!hasKbIndex) { + logger.debug('Knowledge base index does not exist. Skipping migration.'); + return; + } + + if (config.disableKbSemanticTextMigration) { + logger.info( + 'Semantic text migration is disabled via config "xpack.observabilityAIAssistant.disableKbSemanticTextMigration=true". Skipping migration.' + ); + return; + } + + await reIndexKnowledgeBaseAndPopulateSemanticTextField({ esClient, logger, config }); + }, + }; + }, + }, + }); + } catch (error) { + logger.error(`Failed to register task "${TASK_TYPE}". Error: ${error}`); + } +} + +export async function scheduleKbSemanticTextMigrationTask({ + taskManager, + logger, + runSoon = false, +}: { + taskManager: ObservabilityAIAssistantPluginStartDependencies['taskManager']; + logger: Logger; + runSoon?: boolean; +}) { + logger.debug('Schedule migration task'); + await taskManager.ensureScheduled({ + id: TASK_ID, + taskType: TASK_TYPE, + scope: ['aiAssistant'], + params: {}, + state: {}, + }); + + if (runSoon) { + logger.debug('Run migration task soon'); + await taskManager.runSoon(TASK_ID); + } +} + +export async function reIndexKnowledgeBaseAndPopulateSemanticTextField({ + esClient, + logger, + config, +}: { + esClient: { asInternalUser: ElasticsearchClient }; + logger: Logger; + config: ObservabilityAIAssistantConfig; +}) { + logger.debug('Starting migration...'); + + try { + await reIndexKnowledgeBase({ logger, esClient }); + await populateSemanticTextFieldRecursively({ esClient, logger, config }); + } catch (e) { + logger.error(`Migration failed: ${e.message}`); + } + + logger.debug('Migration succeeded'); +} + +async function populateSemanticTextFieldRecursively({ + esClient, + logger, + config, +}: { + esClient: { asInternalUser: ElasticsearchClient }; + logger: Logger; + config: ObservabilityAIAssistantConfig; +}) { + logger.debug('Populating semantic_text field for entries without it'); + + const response = await esClient.asInternalUser.search({ + size: 100, + track_total_hits: true, + index: [resourceNames.aliases.kb], + query: { + bool: { + must_not: { + exists: { + field: 'semantic_text', + }, + }, + }, + }, + _source: { + excludes: ['ml.tokens'], + }, + }); + + if (response.hits.hits.length === 0) { + logger.debug('No remaining entries to migrate'); + return; + } + + logger.debug(`Found ${response.hits.hits.length} entries to migrate`); + + await waitForModel({ esClient, logger, config }); + + // Limit the number of concurrent requests to avoid overloading the cluster + const limiter = pLimit(10); + const promises = response.hits.hits.map((hit) => { + return limiter(() => { + if (!hit._source || !hit._id) { + return; + } + + return esClient.asInternalUser.update({ + refresh: 'wait_for', + index: resourceNames.aliases.kb, + id: hit._id, + body: { + doc: { + ...hit._source, + semantic_text: hit._source.text, + }, + }, + }); + }); + }); + + await Promise.all(promises); + + logger.debug(`Populated ${promises.length} entries`); + await populateSemanticTextFieldRecursively({ esClient, logger, config }); +} + +async function waitForModel({ + esClient, + logger, + config, +}: { + esClient: { asInternalUser: ElasticsearchClient }; + logger: Logger; + config: ObservabilityAIAssistantConfig; +}) { + return pRetry( + async () => { + const { ready } = await getElserModelStatus({ esClient, logger, config }); + if (!ready) { + logger.debug('Elser model is not yet ready. Retrying...'); + throw new Error('Elser model is not yet ready'); + } + }, + { retries: 30, factor: 2, maxTimeout: 30_000 } + ); +} diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts deleted file mode 100644 index b75074dc7ea54..0000000000000 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import pLimit from 'p-limit'; -import { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; -import type { CoreSetup, Logger } from '@kbn/core/server'; -import pRetry from 'p-retry'; -import { KnowledgeBaseEntry } from '../../../common'; -import { resourceNames } from '..'; -import { getElserModelStatus } from '../inference_endpoint'; -import { ObservabilityAIAssistantPluginStartDependencies } from '../../types'; -import { ObservabilityAIAssistantConfig } from '../../config'; -import { setupConversationAndKbIndexAssets } from '../setup_conversation_and_kb_index_assets'; - -const TASK_ID = 'obs-ai-assistant:knowledge-base-migration-task-id'; -const TASK_TYPE = 'obs-ai-assistant:knowledge-base-migration'; - -// This task will re-index all knowledge base entries without `semantic_text` field -// to ensure the field is populated with the correct embeddings. -// After the migration we will no longer need to use the `ml.tokens` field. -export async function registerMigrateKnowledgeBaseEntriesTask({ - taskManager, - logger, - core, - config, -}: { - taskManager: TaskManagerSetupContract; - logger: Logger; - core: CoreSetup; - config: ObservabilityAIAssistantConfig; -}) { - const [coreStart, pluginsStart] = await core.getStartServices(); - - try { - logger.debug(`Register task "${TASK_TYPE}"`); - taskManager.registerTaskDefinitions({ - [TASK_TYPE]: { - title: 'Migrate AI Assistant Knowledge Base', - description: `Migrates AI Assistant knowledge base entries`, - timeout: '1h', - maxAttempts: 5, - createTaskRunner() { - return { - async run() { - logger.debug(`Run task: "${TASK_TYPE}"`); - const esClient = coreStart.elasticsearch.client; - - const hasKbIndex = await esClient.asInternalUser.indices.exists({ - index: resourceNames.aliases.kb, - }); - - if (!hasKbIndex) { - logger.debug( - 'Knowledge base index does not exist. Skipping semantic text migration.' - ); - return; - } - - // update fields and mappings - await setupConversationAndKbIndexAssets({ logger, core }); - - // run migration - await runSemanticTextKnowledgeBaseMigration({ esClient, logger, config }); - }, - }; - }, - }, - }); - } catch (error) { - logger.error(`Failed to register task "${TASK_TYPE}". Error: ${error}`); - } - - try { - logger.debug(`Scheduled task: "${TASK_TYPE}"`); - await scheduleSemanticTextMigration(pluginsStart); - } catch (error) { - logger.error(`Failed to schedule task "${TASK_TYPE}". Error: ${error}`); - } -} - -export function scheduleSemanticTextMigration( - pluginsStart: ObservabilityAIAssistantPluginStartDependencies -) { - return pluginsStart.taskManager.ensureScheduled({ - id: TASK_ID, - taskType: TASK_TYPE, - scope: ['aiAssistant'], - params: {}, - state: {}, - }); -} - -export async function runSemanticTextKnowledgeBaseMigration({ - esClient, - logger, - config, -}: { - esClient: { asInternalUser: ElasticsearchClient }; - logger: Logger; - config: ObservabilityAIAssistantConfig; -}) { - logger.debug('Knowledge base migration: Running migration'); - - try { - const response = await esClient.asInternalUser.search({ - size: 100, - track_total_hits: true, - index: [resourceNames.aliases.kb], - query: { - bool: { - must_not: { - exists: { - field: 'semantic_text', - }, - }, - }, - }, - _source: { - excludes: ['ml.tokens'], - }, - }); - - if (response.hits.hits.length === 0) { - logger.debug('Knowledge base migration: No remaining entries to migrate'); - return; - } - - logger.debug(`Knowledge base migration: Found ${response.hits.hits.length} entries to migrate`); - - await waitForModel({ esClient, logger, config }); - - // Limit the number of concurrent requests to avoid overloading the cluster - const limiter = pLimit(10); - const promises = response.hits.hits.map((hit) => { - return limiter(() => { - if (!hit._source || !hit._id) { - return; - } - - return esClient.asInternalUser.update({ - refresh: 'wait_for', - index: resourceNames.aliases.kb, - id: hit._id, - body: { - doc: { - ...hit._source, - semantic_text: hit._source.text, - }, - }, - }); - }); - }); - - await Promise.all(promises); - logger.debug(`Knowledge base migration: Migrated ${promises.length} entries`); - await runSemanticTextKnowledgeBaseMigration({ esClient, logger, config }); - } catch (e) { - logger.error(`Knowledge base migration failed: ${e.message}`); - } -} - -async function waitForModel({ - esClient, - logger, - config, -}: { - esClient: { asInternalUser: ElasticsearchClient }; - logger: Logger; - config: ObservabilityAIAssistantConfig; -}) { - return pRetry( - async () => { - const { ready } = await getElserModelStatus({ esClient, logger, config }); - if (!ready) { - logger.debug('Elser model is not yet ready. Retrying...'); - throw new Error('Elser model is not yet ready'); - } - }, - { retries: 30, factor: 2, maxTimeout: 30_000 } - ); -} diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/replace_system_message.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/replace_system_message.ts deleted file mode 100644 index c8c3b251c53e5..0000000000000 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/replace_system_message.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Message, MessageRole } from '../../../common'; - -export function replaceSystemMessage(systemMessage: string, messages: Message[]): Message[] { - return [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: systemMessage, - }, - }, - ...messages.filter((msg) => msg.message.role !== MessageRole.System), - ]; -} diff --git a/x-pack/platform/plugins/shared/osquery/package.json b/x-pack/platform/plugins/shared/osquery/package.json index bccc1894467f1..6f3738ee94b0c 100644 --- a/x-pack/platform/plugins/shared/osquery/package.json +++ b/x-pack/platform/plugins/shared/osquery/package.json @@ -7,13 +7,13 @@ "scripts": { "cypress:burn": "yarn cypress:run --env burn=2 --headed", "cypress:changed-specs-only": "yarn cypress:run --changed-specs-only --env burn=2", - "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/cypress.config.ts --ftr-config-file ../../../../../x-pack/test/osquery_cypress/cli_config", + "cypress": "node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/cypress.config.ts --ftr-config-file ../../../../../x-pack/test/osquery_cypress/cli_config", "cypress:open": "yarn cypress open", "cypress:run": "yarn cypress run", - "cypress:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/serverless_cypress.config.ts --ftr-config-file ../../../../../x-pack/test/osquery_cypress/serverless_cli_config", + "cypress:serverless": "node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/serverless_cypress.config.ts --ftr-config-file ../../../../../x-pack/test/osquery_cypress/serverless_cli_config", "cypress:serverless:open": "yarn cypress:serverless open", "cypress:serverless:run": "yarn cypress:serverless run", - "cypress:qa:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel_serverless --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/serverless_cypress_qa.config.ts --onBeforeHook ../../../../test/osquery_cypress/runner_qa.ts", + "cypress:qa:serverless": "node ../../../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel_serverless --config-file ../../../x-pack/platform/plugins/shared/osquery/cypress/serverless_cypress_qa.config.ts --onBeforeHook ../../../../test/osquery_cypress/runner_qa.ts", "cypress:qa:serverless:run": "yarn cypress:qa:serverless run", "nyc": "../../../../../node_modules/.bin/nyc report --reporter=text-summary", "junit:merge": "../../../../../node_modules/.bin/mochawesome-merge ../../../../../target/kibana-osquery/cypress/results/mochawesome*.json > ../../../../../target/kibana-osquery/cypress/results/output.json && ../../../../../node_modules/.bin/marge ../../../../../target/kibana-osquery/cypress/results/output.json --reportDir ../../../../../target/kibana-osquery/cypress/results && yarn junit:transform && mkdir -p ../../../../../target/junit && cp ../../../../../target/kibana-osquery/cypress/results/*.xml ../../../../../target/junit/", @@ -21,4 +21,4 @@ "openapi:generate": "node scripts/openapi/generate", "openapi:bundle": "node scripts/openapi/bundle" } -} +} \ No newline at end of file diff --git a/x-pack/platform/plugins/shared/security/public/account_management/user_profile/user_profile.test.tsx b/x-pack/platform/plugins/shared/security/public/account_management/user_profile/user_profile.test.tsx index af3a5dce4ead3..141bb04f4be6b 100644 --- a/x-pack/platform/plugins/shared/security/public/account_management/user_profile/user_profile.test.tsx +++ b/x-pack/platform/plugins/shared/security/public/account_management/user_profile/user_profile.test.tsx @@ -71,7 +71,7 @@ describe('useUserProfileForm', () => { "avatarType": "initials", "data": Object { "avatar": Object { - "color": "#D36086", + "color": "#61A2FF", "imageUrl": "", "initials": "fn", }, diff --git a/x-pack/platform/plugins/shared/security/server/__snapshots__/prompt_page.test.tsx.snap b/x-pack/platform/plugins/shared/security/server/__snapshots__/prompt_page.test.tsx.snap index f59b9c5a4c7ca..e1061a099af31 100644 --- a/x-pack/platform/plugins/shared/security/server/__snapshots__/prompt_page.test.tsx.snap +++ b/x-pack/platform/plugins/shared/security/server/__snapshots__/prompt_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PromptPage renders as expected with additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; +exports[`PromptPage renders as expected with additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; -exports[`PromptPage renders as expected without additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; +exports[`PromptPage renders as expected without additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; diff --git a/x-pack/platform/plugins/shared/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap b/x-pack/platform/plugins/shared/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap index cac755dbefa00..9d33edbcd8dd2 100644 --- a/x-pack/platform/plugins/shared/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap +++ b/x-pack/platform/plugins/shared/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`UnauthenticatedPage renders as expected 1`] = `"ElasticMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; +exports[`UnauthenticatedPage renders as expected 1`] = `"ElasticMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; -exports[`UnauthenticatedPage renders as expected with custom title 1`] = `"My Company NameMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; +exports[`UnauthenticatedPage renders as expected with custom title 1`] = `"My Company NameMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; diff --git a/x-pack/platform/plugins/shared/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap b/x-pack/platform/plugins/shared/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap index 7d6b24e6ba2e7..69b47c49417eb 100644 --- a/x-pack/platform/plugins/shared/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap +++ b/x-pack/platform/plugins/shared/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ResetSessionPage renders as expected 1`] = `"ElasticMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; +exports[`ResetSessionPage renders as expected 1`] = `"ElasticMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; -exports[`ResetSessionPage renders as expected with custom page title 1`] = `"My Company NameMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; +exports[`ResetSessionPage renders as expected with custom page title 1`] = `"My Company NameMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; diff --git a/x-pack/platform/plugins/shared/spaces/public/management/components/customize_space/customize_space.test.tsx b/x-pack/platform/plugins/shared/spaces/public/management/components/customize_space/customize_space.test.tsx index bea3dbe7b39ca..7b91fdec32135 100644 --- a/x-pack/platform/plugins/shared/spaces/public/management/components/customize_space/customize_space.test.tsx +++ b/x-pack/platform/plugins/shared/spaces/public/management/components/customize_space/customize_space.test.tsx @@ -78,7 +78,7 @@ test('updates identifier, initials and color when name is changed', () => { id: 'space-2', name: 'Space 2', initials: 'S2', - color: '#9170B8', + color: '#BFDBFF', }); }); diff --git a/x-pack/platform/plugins/shared/spaces/public/management/create_space/create_space_page.test.tsx b/x-pack/platform/plugins/shared/spaces/public/management/create_space/create_space_page.test.tsx index 14413b0b2f47b..6e07b39c1591c 100644 --- a/x-pack/platform/plugins/shared/spaces/public/management/create_space/create_space_page.test.tsx +++ b/x-pack/platform/plugins/shared/spaces/public/management/create_space/create_space_page.test.tsx @@ -107,7 +107,7 @@ describe('ManageSpacePage', () => { name: 'New Space Name', description: 'some description', initials: 'NS', - color: '#AA6556', + color: '#EAAE01', imageUrl: '', disabledFeatures: [], solution: 'oblt', diff --git a/x-pack/platform/plugins/shared/spaces/public/management/edit_space/edit_space_general_tab.test.tsx b/x-pack/platform/plugins/shared/spaces/public/management/edit_space/edit_space_general_tab.test.tsx index 353c64b835c0e..ac3e84f8d4c4c 100644 --- a/x-pack/platform/plugins/shared/spaces/public/management/edit_space/edit_space_general_tab.test.tsx +++ b/x-pack/platform/plugins/shared/spaces/public/management/edit_space/edit_space_general_tab.test.tsx @@ -205,7 +205,7 @@ describe('EditSpaceSettings', () => { name: 'Updated Name Of Space', initials: 'UN', imageUrl: '', - color: '#D6BF57', + color: '#FFC7DB', }); }); @@ -284,7 +284,7 @@ describe('EditSpaceSettings', () => { expect(updateSpaceSpy).toHaveBeenCalledWith({ ...spaceToUpdate, name: 'Updated Existing Space', - color: '#D6BF57', + color: '#FFC7DB', initials: 'UE', imageUrl: '', }); diff --git a/x-pack/platform/plugins/shared/spaces/public/space_avatar/space_avatar_internal.test.tsx b/x-pack/platform/plugins/shared/spaces/public/space_avatar/space_avatar_internal.test.tsx index b42208c965a40..e7f5cda518b05 100644 --- a/x-pack/platform/plugins/shared/spaces/public/space_avatar/space_avatar_internal.test.tsx +++ b/x-pack/platform/plugins/shared/spaces/public/space_avatar/space_avatar_internal.test.tsx @@ -19,7 +19,7 @@ test('renders without crashing', () => { const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` { const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` setIsPopoverOpen(true), [setIsPopoverOpen]); - const closePopover = useCallback(() => setIsPopoverOpen(false), [setIsPopoverOpen]); + const togglePopover = useCallback(() => { + setIsPopoverOpen((prev) => { + const newState = !prev; + if (!newState) focusTrapButtonRef.current?.blur(); + return newState; + }); + }, []); + // const openPopover = useCallback(() => setIsPopoverOpen(true), [setIsPopoverOpen]); + const closePopover = useCallback(() => { + setIsPopoverOpen(false); + focusTrapButtonRef.current?.blur(); + }, [setIsPopoverOpen]); const isSnoozedUntil = snoozeSettings?.isSnoozedUntil; const muteAll = snoozeSettings?.muteAll ?? false; const isSnoozedIndefinitely = muteAll; @@ -209,13 +219,13 @@ export const RulesListNotifyBadge: React.FunctionComponent {formattedSnoozeText} ); - }, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover, formattedSnoozeText]); + }, [isLoading, isDisabled, snoozeButtonAriaLabel, togglePopover, formattedSnoozeText]); const scheduledSnoozeButton = useMemo(() => { return ( @@ -228,13 +238,13 @@ export const RulesListNotifyBadge: React.FunctionComponent {formattedSnoozeText} ); - }, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover, formattedSnoozeText]); + }, [isLoading, isDisabled, snoozeButtonAriaLabel, togglePopover, formattedSnoozeText]); const unsnoozedButton = useMemo(() => { // This show on hover is needed because we need style sheets to achieve the @@ -251,11 +261,11 @@ export const RulesListNotifyBadge: React.FunctionComponent ); - }, [showOnHover, isLoading, isDisabled, snoozeButtonAriaLabel, isPopoverOpen, openPopover]); + }, [showOnHover, isLoading, isDisabled, snoozeButtonAriaLabel, isPopoverOpen, togglePopover]); const onApplyUnsnooze = useCallback( async (scheduleIds?: string[]) => { @@ -286,11 +296,11 @@ export const RulesListNotifyBadge: React.FunctionComponent ); - }, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover]); + }, [isLoading, isDisabled, snoozeButtonAriaLabel, togglePopover]); const button = useMemo(() => { if (!isSnoozeValid) { diff --git a/x-pack/solutions/observability/packages/alert_details/README.md b/x-pack/solutions/observability/packages/alert-details/README.md similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/README.md rename to x-pack/solutions/observability/packages/alert-details/README.md diff --git a/x-pack/solutions/observability/packages/alert_details/index.ts b/x-pack/solutions/observability/packages/alert-details/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/index.ts rename to x-pack/solutions/observability/packages/alert-details/index.ts diff --git a/x-pack/solutions/observability/packages/alert_details/jest.config.js b/x-pack/solutions/observability/packages/alert-details/jest.config.js similarity index 96% rename from x-pack/solutions/observability/packages/alert_details/jest.config.js rename to x-pack/solutions/observability/packages/alert-details/jest.config.js index b7c6f40e5bd51..ccdc72ec05af7 100644 --- a/x-pack/solutions/observability/packages/alert_details/jest.config.js +++ b/x-pack/solutions/observability/packages/alert-details/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/alert_details'], + roots: ['/x-pack/solutions/observability/packages/alert-details'], }; diff --git a/x-pack/solutions/observability/packages/alert_details/kibana.jsonc b/x-pack/solutions/observability/packages/alert-details/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/kibana.jsonc rename to x-pack/solutions/observability/packages/alert-details/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/alert_details/package.json b/x-pack/solutions/observability/packages/alert-details/package.json similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/package.json rename to x-pack/solutions/observability/packages/alert-details/package.json diff --git a/x-pack/solutions/observability/packages/alert_details/src/components/alert_active_time_range_annotation.tsx b/x-pack/solutions/observability/packages/alert-details/src/components/alert_active_time_range_annotation.tsx similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/components/alert_active_time_range_annotation.tsx rename to x-pack/solutions/observability/packages/alert-details/src/components/alert_active_time_range_annotation.tsx diff --git a/x-pack/solutions/observability/packages/alert_details/src/components/alert_annotation.tsx b/x-pack/solutions/observability/packages/alert-details/src/components/alert_annotation.tsx similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/components/alert_annotation.tsx rename to x-pack/solutions/observability/packages/alert-details/src/components/alert_annotation.tsx diff --git a/x-pack/solutions/observability/packages/alert_details/src/components/alert_threshold_annotation.tsx b/x-pack/solutions/observability/packages/alert-details/src/components/alert_threshold_annotation.tsx similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/components/alert_threshold_annotation.tsx rename to x-pack/solutions/observability/packages/alert-details/src/components/alert_threshold_annotation.tsx diff --git a/x-pack/solutions/observability/packages/alert_details/src/components/alert_threshold_time_range_rect.tsx b/x-pack/solutions/observability/packages/alert-details/src/components/alert_threshold_time_range_rect.tsx similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/components/alert_threshold_time_range_rect.tsx rename to x-pack/solutions/observability/packages/alert-details/src/components/alert_threshold_time_range_rect.tsx diff --git a/x-pack/solutions/observability/packages/alert_details/src/hooks/use_alerts_history.test.tsx b/x-pack/solutions/observability/packages/alert-details/src/hooks/use_alerts_history.test.tsx similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/hooks/use_alerts_history.test.tsx rename to x-pack/solutions/observability/packages/alert-details/src/hooks/use_alerts_history.test.tsx diff --git a/x-pack/solutions/observability/packages/alert_details/src/hooks/use_alerts_history.ts b/x-pack/solutions/observability/packages/alert-details/src/hooks/use_alerts_history.ts similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/src/hooks/use_alerts_history.ts rename to x-pack/solutions/observability/packages/alert-details/src/hooks/use_alerts_history.ts diff --git a/x-pack/solutions/observability/packages/alert_details/tsconfig.json b/x-pack/solutions/observability/packages/alert-details/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/alert_details/tsconfig.json rename to x-pack/solutions/observability/packages/alert-details/tsconfig.json diff --git a/x-pack/solutions/observability/packages/alerting_test_data/README.md b/x-pack/solutions/observability/packages/alerting-test-data/README.md similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/README.md rename to x-pack/solutions/observability/packages/alerting-test-data/README.md diff --git a/x-pack/solutions/observability/packages/alerting_test_data/index.ts b/x-pack/solutions/observability/packages/alerting-test-data/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/index.ts rename to x-pack/solutions/observability/packages/alerting-test-data/index.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/jest.config.js b/x-pack/solutions/observability/packages/alerting-test-data/jest.config.js similarity index 95% rename from x-pack/solutions/observability/packages/alerting_test_data/jest.config.js rename to x-pack/solutions/observability/packages/alerting-test-data/jest.config.js index 6a296e9d22c0d..02b19c9b924e2 100644 --- a/x-pack/solutions/observability/packages/alerting_test_data/jest.config.js +++ b/x-pack/solutions/observability/packages/alerting-test-data/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/alerting_test_data'], + roots: ['/x-pack/solutions/observability/packages/alerting-test-data'], }; diff --git a/x-pack/solutions/observability/packages/alerting_test_data/kibana.jsonc b/x-pack/solutions/observability/packages/alerting-test-data/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/kibana.jsonc rename to x-pack/solutions/observability/packages/alerting-test-data/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/alerting_test_data/package.json b/x-pack/solutions/observability/packages/alerting-test-data/package.json similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/package.json rename to x-pack/solutions/observability/packages/alerting-test-data/package.json diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/constants.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/constants.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/constants.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/constants.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_apm_error_count_threshold_rule.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_apm_error_count_threshold_rule.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_apm_error_count_threshold_rule.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_apm_error_count_threshold_rule.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_apm_failed_transaction_rate_rule.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_apm_failed_transaction_rate_rule.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_apm_failed_transaction_rate_rule.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_apm_failed_transaction_rate_rule.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_custom_threshold_rule.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_custom_threshold_rule.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_custom_threshold_rule.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_custom_threshold_rule.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_data_view.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_data_view.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_data_view.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_data_view.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_index_connector.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_index_connector.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_index_connector.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_index_connector.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/create_rule.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/create_rule.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/create_rule.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/create_rule.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/get_kibana_url.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/get_kibana_url.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/get_kibana_url.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/get_kibana_url.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/run.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/run.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/run.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/run.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count_groupby.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count_groupby.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count_groupby.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count_groupby.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count_nodata.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count_nodata.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_log_count_nodata.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_log_count_nodata.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg_groupby.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg_groupby.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg_groupby.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg_groupby.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg_nodata.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg_nodata.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/custom_threshold_metric_avg_nodata.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/custom_threshold_metric_avg_nodata.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/index.ts b/x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/src/scenarios/index.ts rename to x-pack/solutions/observability/packages/alerting-test-data/src/scenarios/index.ts diff --git a/x-pack/solutions/observability/packages/alerting_test_data/tsconfig.json b/x-pack/solutions/observability/packages/alerting-test-data/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/alerting_test_data/tsconfig.json rename to x-pack/solutions/observability/packages/alerting-test-data/tsconfig.json diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/README.md b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/README.md similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/README.md rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/README.md diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/index.ts b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/index.ts rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/index.ts diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/jest.config.js b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/jest.config.js similarity index 92% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/jest.config.js rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/jest.config.js index 6941925a188e2..422d4c195600d 100644 --- a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/jest.config.js +++ b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/get_padded_alert_time_range_util'], + roots: ['/x-pack/solutions/observability/packages/get-padded-alert-time-range-util'], }; diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/kibana.jsonc b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/kibana.jsonc rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/package.json b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/package.json similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/package.json rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/package.json diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/src/get_padded_alert_time_range.test.ts b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/src/get_padded_alert_time_range.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/src/get_padded_alert_time_range.test.ts rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/src/get_padded_alert_time_range.test.ts diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/src/get_padded_alert_time_range.ts b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/src/get_padded_alert_time_range.ts similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/src/get_padded_alert_time_range.ts rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/src/get_padded_alert_time_range.ts diff --git a/x-pack/solutions/observability/packages/get_padded_alert_time_range_util/tsconfig.json b/x-pack/solutions/observability/packages/get-padded-alert-time-range-util/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/get_padded_alert_time_range_util/tsconfig.json rename to x-pack/solutions/observability/packages/get-padded-alert-time-range-util/tsconfig.json diff --git a/x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/page_objects/custom_logs.ts b/x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/page_objects/custom_logs.ts index 6001bf086fed3..825d8475ce64a 100644 --- a/x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/page_objects/custom_logs.ts +++ b/x-pack/solutions/observability/packages/kbn-scout-oblt/src/playwright/page_objects/custom_logs.ts @@ -104,8 +104,7 @@ export class CustomLogsPage { async clickAdvancedSettingsButton() { return this.page.testSubj .locator('obltOnboardingCustomLogsAdvancedSettings') - .getByRole('button') - .first() + .locator('button.euiAccordion__button') .click(); } diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/jest.config.js b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/jest.config.js similarity index 87% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/jest.config.js rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/jest.config.js index 3620ef5a1c254..fda41606e56b1 100644 --- a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/jest.config.js +++ b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/jest.config.js @@ -9,7 +9,7 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../../..', roots: [ - '/x-pack/solutions/observability/packages/observability_ai/observability_ai_common', - '/x-pack/solutions/observability/packages/observability_ai/observability_ai_server', + '/x-pack/solutions/observability/packages/observability-ai/observability-ai-common', + '/x-pack/solutions/observability/packages/observability-ai/observability-ai-server', ], }; diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/kibana.jsonc b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/kibana.jsonc rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/package.json b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/package.json similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/package.json rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/package.json diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/root_cause_analysis/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/root_cause_analysis/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/root_cause_analysis/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/root_cause_analysis/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/root_cause_analysis/tool_names.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/root_cause_analysis/tool_names.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/root_cause_analysis/tool_names.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/root_cause_analysis/tool_names.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_common/tsconfig.json b/x-pack/solutions/observability/packages/observability-ai/observability-ai-common/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_common/tsconfig.json rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-common/tsconfig.json diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/jest.config.js b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/jest.config.js similarity index 92% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/jest.config.js rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/jest.config.js index 8aa1c2d673222..fff212e040dcc 100644 --- a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/jest.config.js +++ b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/jest.config.js @@ -9,6 +9,6 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../../..', roots: [ - '/x-pack/solutions/observability/packages/observability_ai/observability_ai_server', + '/x-pack/solutions/observability/packages/observability-ai/observability-ai-server', ], }; diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/kibana.jsonc b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/kibana.jsonc rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/package.json b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/package.json similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/package.json rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/package.json diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_end_rca_process_tool.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_end_rca_process_tool.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_end_rca_process_tool.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_end_rca_process_tool.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_investigate_entity_tool.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_investigate_entity_tool.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_investigate_entity_tool.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_investigate_entity_tool.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_observe_tool.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_observe_tool.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/call_observe_tool.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/call_observe_tool.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/empty_assistant_message.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/empty_assistant_message.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/empty_assistant_message.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/empty_assistant_message.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/prompts/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/prompts/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/prompts/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/prompts/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/run_root_cause_analysis.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/run_root_cause_analysis.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/run_root_cause_analysis.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/run_root_cause_analysis.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/analyze_log_patterns/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/analyze_log_patterns/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/analyze_log_patterns/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/analyze_log_patterns/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/describe_entity/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/describe_entity/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/describe_entity/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/describe_entity/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/describe_log_patterns/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/describe_log_patterns/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/describe_log_patterns/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/describe_log_patterns/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/analyze_fetched_related_entities.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/extract_related_entities.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/extract_related_entities.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/extract_related_entities.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/extract_related_entities.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/write_keyword_searches_for_related_entities.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/write_keyword_searches_for_related_entities.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/find_related_entities/write_keyword_searches_for_related_entities.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/find_related_entities/write_keyword_searches_for_related_entities.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/generate_timeline/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/generate_timeline/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/generate_timeline/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/generate_timeline/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/get_knowledge_base_entries/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/get_knowledge_base_entries/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/get_knowledge_base_entries/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/get_knowledge_base_entries/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/prompts.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/prompts.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/prompts.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/prompts.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/types.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/types.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/investigate_entity/types.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/investigate_entity/types.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/observe_investigation_results/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/observe_investigation_results/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/observe_investigation_results/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/observe_investigation_results/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/write_entity_investigation_report/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/write_entity_investigation_report/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/write_entity_investigation_report/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/write_entity_investigation_report/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/write_final_report/index.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/write_final_report/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tasks/write_final_report/index.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tasks/write_final_report/index.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tools.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tools.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/tools.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/tools.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/types.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/types.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/types.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/types.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/call_tools.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/call_tools.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/call_tools.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/call_tools.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/chunk_output_calls.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/chunk_output_calls.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/chunk_output_calls.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/chunk_output_calls.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/format_entity.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/format_entity.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/format_entity.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/format_entity.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/get_previously_investigated_entities.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/get_previously_investigated_entities.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/get_previously_investigated_entities.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/get_previously_investigated_entities.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/serialize_knowledge_base_entries.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/serialize_knowledge_base_entries.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/serialize_knowledge_base_entries.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/serialize_knowledge_base_entries.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/stringify_summaries.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/stringify_summaries.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/stringify_summaries.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/stringify_summaries.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/to_blockquote.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/to_blockquote.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/to_blockquote.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/to_blockquote.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/validate_investigate_entity_tool_call.ts b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/validate_investigate_entity_tool_call.ts similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/root_cause_analysis/util/validate_investigate_entity_tool_call.ts rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/root_cause_analysis/util/validate_investigate_entity_tool_call.ts diff --git a/x-pack/solutions/observability/packages/observability_ai/observability_ai_server/tsconfig.json b/x-pack/solutions/observability/packages/observability-ai/observability-ai-server/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/observability_ai/observability_ai_server/tsconfig.json rename to x-pack/solutions/observability/packages/observability-ai/observability-ai-server/tsconfig.json diff --git a/x-pack/solutions/observability/packages/utils_browser/chart/utils.ts b/x-pack/solutions/observability/packages/utils-browser/chart/utils.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/chart/utils.ts rename to x-pack/solutions/observability/packages/utils-browser/chart/utils.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_abort_controller.ts b/x-pack/solutions/observability/packages/utils-browser/hooks/use_abort_controller.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/hooks/use_abort_controller.ts rename to x-pack/solutions/observability/packages/utils-browser/hooks/use_abort_controller.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts b/x-pack/solutions/observability/packages/utils-browser/hooks/use_abortable_async.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/hooks/use_abortable_async.ts rename to x-pack/solutions/observability/packages/utils-browser/hooks/use_abortable_async.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_date_range.ts b/x-pack/solutions/observability/packages/utils-browser/hooks/use_date_range.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/hooks/use_date_range.ts rename to x-pack/solutions/observability/packages/utils-browser/hooks/use_date_range.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_local_storage.ts b/x-pack/solutions/observability/packages/utils-browser/hooks/use_local_storage.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/hooks/use_local_storage.ts rename to x-pack/solutions/observability/packages/utils-browser/hooks/use_local_storage.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/hooks/use_theme.ts b/x-pack/solutions/observability/packages/utils-browser/hooks/use_theme.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/hooks/use_theme.ts rename to x-pack/solutions/observability/packages/utils-browser/hooks/use_theme.ts diff --git a/x-pack/solutions/observability/packages/utils_browser/jest.config.js b/x-pack/solutions/observability/packages/utils-browser/jest.config.js similarity index 96% rename from x-pack/solutions/observability/packages/utils_browser/jest.config.js rename to x-pack/solutions/observability/packages/utils-browser/jest.config.js index 3fa1852414d8d..fcbf23a4d887f 100644 --- a/x-pack/solutions/observability/packages/utils_browser/jest.config.js +++ b/x-pack/solutions/observability/packages/utils-browser/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/utils_browser'], + roots: ['/x-pack/solutions/observability/packages/utils-browser'], }; diff --git a/x-pack/solutions/observability/packages/utils_browser/kibana.jsonc b/x-pack/solutions/observability/packages/utils-browser/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/kibana.jsonc rename to x-pack/solutions/observability/packages/utils-browser/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/utils_browser/package.json b/x-pack/solutions/observability/packages/utils-browser/package.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/package.json rename to x-pack/solutions/observability/packages/utils-browser/package.json diff --git a/x-pack/solutions/observability/packages/utils_browser/tsconfig.json b/x-pack/solutions/observability/packages/utils-browser/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/tsconfig.json rename to x-pack/solutions/observability/packages/utils-browser/tsconfig.json diff --git a/x-pack/solutions/observability/packages/utils_browser/utils/ui_settings/get_timezone.ts b/x-pack/solutions/observability/packages/utils-browser/utils/ui_settings/get_timezone.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_browser/utils/ui_settings/get_timezone.ts rename to x-pack/solutions/observability/packages/utils-browser/utils/ui_settings/get_timezone.ts diff --git a/x-pack/solutions/observability/packages/utils_common/array/join_by_key.test.ts b/x-pack/solutions/observability/packages/utils-common/array/join_by_key.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/array/join_by_key.test.ts rename to x-pack/solutions/observability/packages/utils-common/array/join_by_key.test.ts diff --git a/x-pack/solutions/observability/packages/utils_common/array/join_by_key.ts b/x-pack/solutions/observability/packages/utils-common/array/join_by_key.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/array/join_by_key.ts rename to x-pack/solutions/observability/packages/utils-common/array/join_by_key.ts diff --git a/x-pack/solutions/observability/packages/utils_common/entities/get_entity_kuery.ts b/x-pack/solutions/observability/packages/utils-common/entities/get_entity_kuery.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/entities/get_entity_kuery.ts rename to x-pack/solutions/observability/packages/utils-common/entities/get_entity_kuery.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/format_value_for_kql.ts b/x-pack/solutions/observability/packages/utils-common/es/format_value_for_kql.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/format_value_for_kql.ts rename to x-pack/solutions/observability/packages/utils-common/es/format_value_for_kql.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/entity_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/entity_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/entity_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/entity_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/exclude_frozen_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/exclude_frozen_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/exclude_frozen_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/exclude_frozen_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/exclude_tiers_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/exclude_tiers_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/exclude_tiers_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/exclude_tiers_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/kql_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/kql_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/kql_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/kql_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/range_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/range_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/range_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/range_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/es/queries/term_query.ts b/x-pack/solutions/observability/packages/utils-common/es/queries/term_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/es/queries/term_query.ts rename to x-pack/solutions/observability/packages/utils-common/es/queries/term_query.ts diff --git a/x-pack/solutions/observability/packages/utils_common/format/integer.ts b/x-pack/solutions/observability/packages/utils-common/format/integer.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/format/integer.ts rename to x-pack/solutions/observability/packages/utils-common/format/integer.ts diff --git a/x-pack/solutions/observability/packages/utils_server/jest.config.js b/x-pack/solutions/observability/packages/utils-common/jest.config.js similarity index 96% rename from x-pack/solutions/observability/packages/utils_server/jest.config.js rename to x-pack/solutions/observability/packages/utils-common/jest.config.js index ed77899c0323a..4e6eb0b3c4a1b 100644 --- a/x-pack/solutions/observability/packages/utils_server/jest.config.js +++ b/x-pack/solutions/observability/packages/utils-common/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/utils_server'], + roots: ['/x-pack/solutions/observability/packages/utils-common'], }; diff --git a/x-pack/solutions/observability/packages/utils_common/kibana.jsonc b/x-pack/solutions/observability/packages/utils-common/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/kibana.jsonc rename to x-pack/solutions/observability/packages/utils-common/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/utils_common/llm/log_analysis/document_analysis.ts b/x-pack/solutions/observability/packages/utils-common/llm/log_analysis/document_analysis.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/log_analysis/document_analysis.ts rename to x-pack/solutions/observability/packages/utils-common/llm/log_analysis/document_analysis.ts diff --git a/x-pack/solutions/observability/packages/utils_common/llm/log_analysis/highlight_patterns_from_regex.ts b/x-pack/solutions/observability/packages/utils-common/llm/log_analysis/highlight_patterns_from_regex.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/log_analysis/highlight_patterns_from_regex.ts rename to x-pack/solutions/observability/packages/utils-common/llm/log_analysis/highlight_patterns_from_regex.ts diff --git a/x-pack/solutions/observability/packages/utils_common/llm/log_analysis/merge_sample_documents_with_field_caps.ts b/x-pack/solutions/observability/packages/utils-common/llm/log_analysis/merge_sample_documents_with_field_caps.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/log_analysis/merge_sample_documents_with_field_caps.ts rename to x-pack/solutions/observability/packages/utils-common/llm/log_analysis/merge_sample_documents_with_field_caps.ts diff --git a/x-pack/solutions/observability/packages/utils_common/llm/log_analysis/sort_and_truncate_analyzed_fields.ts b/x-pack/solutions/observability/packages/utils-common/llm/log_analysis/sort_and_truncate_analyzed_fields.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/log_analysis/sort_and_truncate_analyzed_fields.ts rename to x-pack/solutions/observability/packages/utils-common/llm/log_analysis/sort_and_truncate_analyzed_fields.ts diff --git a/x-pack/solutions/observability/packages/utils_common/llm/short_id_table.test.ts b/x-pack/solutions/observability/packages/utils-common/llm/short_id_table.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/short_id_table.test.ts rename to x-pack/solutions/observability/packages/utils-common/llm/short_id_table.test.ts diff --git a/x-pack/solutions/observability/packages/utils_common/llm/short_id_table.ts b/x-pack/solutions/observability/packages/utils-common/llm/short_id_table.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/llm/short_id_table.ts rename to x-pack/solutions/observability/packages/utils-common/llm/short_id_table.ts diff --git a/x-pack/solutions/observability/packages/utils_common/ml/p_value_to_label.ts b/x-pack/solutions/observability/packages/utils-common/ml/p_value_to_label.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/ml/p_value_to_label.ts rename to x-pack/solutions/observability/packages/utils-common/ml/p_value_to_label.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/flatten_object.test.ts b/x-pack/solutions/observability/packages/utils-common/object/flatten_object.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/flatten_object.test.ts rename to x-pack/solutions/observability/packages/utils-common/object/flatten_object.test.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/flatten_object.ts b/x-pack/solutions/observability/packages/utils-common/object/flatten_object.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/flatten_object.ts rename to x-pack/solutions/observability/packages/utils-common/object/flatten_object.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/merge_plain_object.test.ts b/x-pack/solutions/observability/packages/utils-common/object/merge_plain_object.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/merge_plain_object.test.ts rename to x-pack/solutions/observability/packages/utils-common/object/merge_plain_object.test.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/merge_plain_objects.ts b/x-pack/solutions/observability/packages/utils-common/object/merge_plain_objects.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/merge_plain_objects.ts rename to x-pack/solutions/observability/packages/utils-common/object/merge_plain_objects.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/unflatten_object.test.ts b/x-pack/solutions/observability/packages/utils-common/object/unflatten_object.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/unflatten_object.test.ts rename to x-pack/solutions/observability/packages/utils-common/object/unflatten_object.test.ts diff --git a/x-pack/solutions/observability/packages/utils_common/object/unflatten_object.ts b/x-pack/solutions/observability/packages/utils-common/object/unflatten_object.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/object/unflatten_object.ts rename to x-pack/solutions/observability/packages/utils-common/object/unflatten_object.ts diff --git a/x-pack/solutions/observability/packages/utils_common/package.json b/x-pack/solutions/observability/packages/utils-common/package.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/package.json rename to x-pack/solutions/observability/packages/utils-common/package.json diff --git a/x-pack/solutions/observability/packages/utils_common/tsconfig.json b/x-pack/solutions/observability/packages/utils-common/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_common/tsconfig.json rename to x-pack/solutions/observability/packages/utils-common/tsconfig.json diff --git a/x-pack/solutions/observability/packages/utils_server/entities/analyze_documents.ts b/x-pack/solutions/observability/packages/utils-server/entities/analyze_documents.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/analyze_documents.ts rename to x-pack/solutions/observability/packages/utils-server/entities/analyze_documents.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts b/x-pack/solutions/observability/packages/utils-server/entities/get_data_streams_for_entity.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/get_data_streams_for_entity.ts rename to x-pack/solutions/observability/packages/utils-server/entities/get_data_streams_for_entity.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/get_entities_by_fuzzy_search.ts b/x-pack/solutions/observability/packages/utils-server/entities/get_entities_by_fuzzy_search.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/get_entities_by_fuzzy_search.ts rename to x-pack/solutions/observability/packages/utils-server/entities/get_entities_by_fuzzy_search.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/get_log_patterns.ts b/x-pack/solutions/observability/packages/utils-server/entities/get_log_patterns.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/get_log_patterns.ts rename to x-pack/solutions/observability/packages/utils-server/entities/get_log_patterns.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/signals/get_alerts_for_entity.ts b/x-pack/solutions/observability/packages/utils-server/entities/signals/get_alerts_for_entity.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/signals/get_alerts_for_entity.ts rename to x-pack/solutions/observability/packages/utils-server/entities/signals/get_alerts_for_entity.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/signals/get_anomalies_for_entity.ts b/x-pack/solutions/observability/packages/utils-server/entities/signals/get_anomalies_for_entity.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/signals/get_anomalies_for_entity.ts rename to x-pack/solutions/observability/packages/utils-server/entities/signals/get_anomalies_for_entity.ts diff --git a/x-pack/solutions/observability/packages/utils_server/entities/signals/get_slos_for_entity.ts b/x-pack/solutions/observability/packages/utils-server/entities/signals/get_slos_for_entity.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/entities/signals/get_slos_for_entity.ts rename to x-pack/solutions/observability/packages/utils-server/entities/signals/get_slos_for_entity.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/client/create_observability_es_client.ts b/x-pack/solutions/observability/packages/utils-server/es/client/create_observability_es_client.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/client/create_observability_es_client.ts rename to x-pack/solutions/observability/packages/utils-server/es/client/create_observability_es_client.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/esql_result_to_plain_objects.test.ts b/x-pack/solutions/observability/packages/utils-server/es/esql_result_to_plain_objects.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/esql_result_to_plain_objects.test.ts rename to x-pack/solutions/observability/packages/utils-server/es/esql_result_to_plain_objects.test.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/esql_result_to_plain_objects.ts b/x-pack/solutions/observability/packages/utils-server/es/esql_result_to_plain_objects.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/esql_result_to_plain_objects.ts rename to x-pack/solutions/observability/packages/utils-server/es/esql_result_to_plain_objects.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/queries/exclude_frozen_query.ts b/x-pack/solutions/observability/packages/utils-server/es/queries/exclude_frozen_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/queries/exclude_frozen_query.ts rename to x-pack/solutions/observability/packages/utils-server/es/queries/exclude_frozen_query.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/queries/kql_query.ts b/x-pack/solutions/observability/packages/utils-server/es/queries/kql_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/queries/kql_query.ts rename to x-pack/solutions/observability/packages/utils-server/es/queries/kql_query.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/queries/range_query.ts b/x-pack/solutions/observability/packages/utils-server/es/queries/range_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/queries/range_query.ts rename to x-pack/solutions/observability/packages/utils-server/es/queries/range_query.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/queries/term_query.ts b/x-pack/solutions/observability/packages/utils-server/es/queries/term_query.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/queries/term_query.ts rename to x-pack/solutions/observability/packages/utils-server/es/queries/term_query.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/README.md b/x-pack/solutions/observability/packages/utils-server/es/storage/README.md similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/README.md rename to x-pack/solutions/observability/packages/utils-server/es/storage/README.md diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/get_schema_version.ts b/x-pack/solutions/observability/packages/utils-server/es/storage/get_schema_version.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/get_schema_version.ts rename to x-pack/solutions/observability/packages/utils-server/es/storage/get_schema_version.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/index.ts b/x-pack/solutions/observability/packages/utils-server/es/storage/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/index.ts rename to x-pack/solutions/observability/packages/utils-server/es/storage/index.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/index_adapter/index.ts b/x-pack/solutions/observability/packages/utils-server/es/storage/index_adapter/index.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/index_adapter/index.ts rename to x-pack/solutions/observability/packages/utils-server/es/storage/index_adapter/index.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/index_adapter/integration_tests/index.test.ts b/x-pack/solutions/observability/packages/utils-server/es/storage/index_adapter/integration_tests/index.test.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/index_adapter/integration_tests/index.test.ts rename to x-pack/solutions/observability/packages/utils-server/es/storage/index_adapter/integration_tests/index.test.ts diff --git a/x-pack/solutions/observability/packages/utils_server/es/storage/types.ts b/x-pack/solutions/observability/packages/utils-server/es/storage/types.ts similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/es/storage/types.ts rename to x-pack/solutions/observability/packages/utils-server/es/storage/types.ts diff --git a/x-pack/solutions/observability/packages/utils_common/jest.config.js b/x-pack/solutions/observability/packages/utils-server/jest.config.js similarity index 96% rename from x-pack/solutions/observability/packages/utils_common/jest.config.js rename to x-pack/solutions/observability/packages/utils-server/jest.config.js index ab3e800cf586b..cb655f4858eab 100644 --- a/x-pack/solutions/observability/packages/utils_common/jest.config.js +++ b/x-pack/solutions/observability/packages/utils-server/jest.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/utils_common'], + roots: ['/x-pack/solutions/observability/packages/utils-server'], }; diff --git a/x-pack/solutions/observability/packages/utils_server/jest.integration.config.js b/x-pack/solutions/observability/packages/utils-server/jest.integration.config.js similarity index 96% rename from x-pack/solutions/observability/packages/utils_server/jest.integration.config.js rename to x-pack/solutions/observability/packages/utils-server/jest.integration.config.js index 4cda010dac65c..bc0723cc66c2e 100644 --- a/x-pack/solutions/observability/packages/utils_server/jest.integration.config.js +++ b/x-pack/solutions/observability/packages/utils-server/jest.integration.config.js @@ -8,5 +8,5 @@ module.exports = { preset: '@kbn/test/jest_integration', rootDir: '../../../../..', - roots: ['/x-pack/solutions/observability/packages/utils_server'], + roots: ['/x-pack/solutions/observability/packages/utils-server'], }; diff --git a/x-pack/solutions/observability/packages/utils_server/kibana.jsonc b/x-pack/solutions/observability/packages/utils-server/kibana.jsonc similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/kibana.jsonc rename to x-pack/solutions/observability/packages/utils-server/kibana.jsonc diff --git a/x-pack/solutions/observability/packages/utils_server/package.json b/x-pack/solutions/observability/packages/utils-server/package.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/package.json rename to x-pack/solutions/observability/packages/utils-server/package.json diff --git a/x-pack/solutions/observability/packages/utils_server/tsconfig.json b/x-pack/solutions/observability/packages/utils-server/tsconfig.json similarity index 100% rename from x-pack/solutions/observability/packages/utils_server/tsconfig.json rename to x-pack/solutions/observability/packages/utils-server/tsconfig.json diff --git a/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json b/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json index 6b8749fc1e5be..9194f96e78e61 100644 --- a/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json +++ b/x-pack/solutions/observability/plugins/apm/ftr_e2e/package.json @@ -5,7 +5,7 @@ "private": true, "license": "Elastic License 2.0", "scripts": { - "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/apm/ftr_e2e/cypress.config.ts --ftr-config-file ../../../../../test/apm_cypress/cli_config", + "cypress": "node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/apm/ftr_e2e/cypress.config.ts --ftr-config-file ../../../../../test/apm_cypress/cli_config", "cypress:open": "yarn cypress open", "cypress:run": "yarn cypress run", "cypress:run:headed": "yarn cypress run --headed", diff --git a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/__snapshots__/timeline.test.tsx.snap index 09b48cc47b302..c1fb5292bf04a 100644 --- a/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/apm/public/components/shared/charts/timeline/__snapshots__/timeline.test.tsx.snap @@ -32,7 +32,7 @@ exports[`Timeline TimelineAxisContainer should render with data 1`] = ` transform="translate(0 80)" >
@@ -136,15 +136,15 @@ exports[`Timeline TimelineAxisContainer should render with data 1`] = ` >
@@ -168,15 +168,15 @@ exports[`Timeline TimelineAxisContainer should render with data 1`] = ` >
@@ -210,70 +210,70 @@ exports[`Timeline VerticalLinesContainer should render with data 1`] = ` transform="translate(0 100)" > { }); describe('colorTransformer()', () => { it('should just work', () => { - expect(colorTransformer(Color.color0)).toBe('#54B399'); + expect(colorTransformer(Color.color0)).toBe('#16C5C0'); }); }); }); diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/common/components/threshold.test.tsx b/x-pack/solutions/observability/plugins/infra/public/alerting/common/components/threshold.test.tsx index 754665c18adf3..69c00d1cd44fa 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/common/components/threshold.test.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/common/components/threshold.test.tsx @@ -65,7 +65,7 @@ describe('Threshold', () => { expect((Metric as jest.Mock).mock.calls[0][0].data[0][0]).toMatchInlineSnapshot(` Object { - "color": "#f8e9e9", + "color": "#FFE8E5", "extra": Alert when >= 7%
diff --git a/x-pack/solutions/observability/plugins/infra/public/alerting/metric_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap b/x-pack/solutions/observability/plugins/infra/public/alerting/metric_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap index 0df66d4c3dca3..6d019d22e786a 100644 --- a/x-pack/solutions/observability/plugins/infra/public/alerting/metric_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/infra/public/alerting/metric_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap @@ -6,7 +6,7 @@ Array [ "additionalFilters": undefined, "annotations": Array [ Object { - "color": "#BD271E", + "color": "#C61E25", "icon": "alert", "id": "metric_threshold_alert_start_annotation", "key": Object { @@ -17,7 +17,7 @@ Array [ "type": "manual", }, Object { - "color": "rgba(189,39,30,0.2)", + "color": "rgba(198,30,37,0.2)", "id": "metric_threshold_active_alert_range_annotation", "key": Object { "endTimestamp": "2024-06-13T07:00:33.381Z", diff --git a/x-pack/solutions/observability/plugins/infra/public/components/logs_deprecation_callout.tsx b/x-pack/solutions/observability/plugins/infra/public/components/logs_deprecation_callout.tsx index f9cd6efb211b9..46f997e4d5be5 100644 --- a/x-pack/solutions/observability/plugins/infra/public/components/logs_deprecation_callout.tsx +++ b/x-pack/solutions/observability/plugins/infra/public/components/logs_deprecation_callout.tsx @@ -22,14 +22,14 @@ const pageConfigurations = { dismissalStorageKey: 'log_stream_deprecation_callout_dismissed', message: i18n.translate('xpack.infra.logsDeprecationCallout.stream.exploreWithDiscover', { defaultMessage: - 'Logs Stream and Logs Explorer are set to be deprecated. Switch to Discover which now includes their functionality plus more features, better performance, and more intuitive navigation. ', + 'Logs Stream and Logs Explorer are set to be deprecated. Switch to Discover and enable the new Observability solution for an improved logs experience.', }), }, settings: { dismissalStorageKey: 'log_settings_deprecation_callout_dismissed', message: i18n.translate('xpack.infra.logsDeprecationCallout.settings.exploreWithDiscover', { defaultMessage: - 'These settings only apply to the legacy Logs Stream app. Switch to Discover for the same functionality plus more features, better performance, and more intuitive navigation.', + 'These settings only apply to the legacy Logs Stream app. Switch to Discover and enable the new Observability solution for an improved logs experience.', }), }, }; diff --git a/x-pack/solutions/observability/plugins/infra/public/pages/metrics/inventory_view/components/waffle/__snapshots__/conditional_tooltip.test.tsx.snap b/x-pack/solutions/observability/plugins/infra/public/pages/metrics/inventory_view/components/waffle/__snapshots__/conditional_tooltip.test.tsx.snap index a9a64f08f6834..b7a4ba9e24133 100644 --- a/x-pack/solutions/observability/plugins/infra/public/pages/metrics/inventory_view/components/waffle/__snapshots__/conditional_tooltip.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/infra/public/pages/metrics/inventory_view/components/waffle/__snapshots__/conditional_tooltip.test.tsx.snap @@ -6,7 +6,7 @@ exports[`ConditionalToolTip renders correctly 1`] = ` style="min-width: 220px;" >
host-01
diff --git a/x-pack/solutions/observability/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts b/x-pack/solutions/observability/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts index 55628d208873d..573bcce14cf92 100644 --- a/x-pack/solutions/observability/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts +++ b/x-pack/solutions/observability/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts @@ -27,7 +27,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -44,7 +44,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:bytes,id:test-id,label:'rate(host.network.egress.bytes)',line_width:2,metrics:!((field:host.network.egress.bytes,id:test-id,type:max),(field:test-id,id:test-id,type:derivative,unit:'1s'),(field:test-id,id:test-id,type:positive_only)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}}/s)),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:bytes,id:test-id,label:'rate(host.network.egress.bytes)',line_width:2,metrics:!((field:host.network.egress.bytes,id:test-id,type:max),(field:test-id,id:test-id,type:derivative,unit:'1s'),(field:test-id,id:test-id,type:positive_only)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}}/s)),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -57,7 +57,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-10m,to:now))', type: 'metrics', }, @@ -71,7 +71,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'my-beats-*',filter:(language:kuery,query:'system.network.name:lo* and host.name : \"example-01\"'),id:test-id,index_pattern:'my-beats-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'my-beats-*',filter:(language:kuery,query:'system.network.name:lo* and host.name : \"example-01\"'),id:test-id,index_pattern:'my-beats-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -85,7 +85,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -99,7 +99,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0.5,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0.5,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -117,7 +117,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0.5,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:stacked,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0.5,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:stacked,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, @@ -130,7 +130,7 @@ describe('createTSVBLink()', () => { app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metric*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metric*',interval:auto,series:!((axis_position:right,chart_type:line,color:#54B399,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metric*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metric*',interval:auto,series:!((axis_position:right,chart_type:line,color:#16C5C0,fill:0,formatter:percent,id:test-id,label:'avg(system.cpu.user.pct)',line_width:2,metrics:!((field:system.cpu.user.pct,id:test-id,type:avg)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}})),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, diff --git a/x-pack/solutions/observability/plugins/inventory/scripts/test/e2e.js b/x-pack/solutions/observability/plugins/inventory/scripts/test/e2e.js index 5c0d897cc671d..6bd8d7ccfd83f 100644 --- a/x-pack/solutions/observability/plugins/inventory/scripts/test/e2e.js +++ b/x-pack/solutions/observability/plugins/inventory/scripts/test/e2e.js @@ -73,7 +73,6 @@ function runTests() { env: { ...process.env, CYPRESS_CLI_ARGS: JSON.stringify(cypressCliArgs), - NODE_OPTIONS: '--openssl-legacy-provider', }, encoding: 'utf8', stdio: 'inherit', diff --git a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap index 79c58c84a1f30..d810b965b3bd5 100644 --- a/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap @@ -15,7 +15,7 @@ Array [ ], "annotations": Array [ Object { - "color": "#BD271E", + "color": "#C61E25", "icon": "alert", "id": "custom_threshold_alert_start_annotation", "key": Object { diff --git a/x-pack/solutions/observability/plugins/observability/public/navigation_tree.ts b/x-pack/solutions/observability/plugins/observability/public/navigation_tree.ts index 858b48f1e05e0..7578a12ef41a8 100644 --- a/x-pack/solutions/observability/plugins/observability/public/navigation_tree.ts +++ b/x-pack/solutions/observability/plugins/observability/public/navigation_tree.ts @@ -509,6 +509,10 @@ function createNavTree({ streamsAvailable }: { streamsAvailable?: boolean }) { }, ], }, + { + id: 'monitoring', + link: 'monitoring', + }, { link: 'integrations', }, diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx index d472449f2e9d1..39ae85f14f2cd 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx @@ -15,13 +15,12 @@ import { XYBrushEvent, } from '@elastic/charts'; import { timeFormatter } from '@elastic/charts/dist/utils/data/formatters'; -import { EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiIcon } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiIcon, useEuiTheme } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import React, { useContext } from 'react'; +import React from 'react'; import { useHistory } from 'react-router-dom'; -import { ThemeContext } from 'styled-components'; import { useChartThemes, FETCH_STATUS, useFetcher } from '@kbn/observability-shared-plugin/public'; import { useDatePickerContext } from '../../../../../hooks/use_date_picker_context'; import { SectionContainer } from '../section_container'; @@ -54,7 +53,7 @@ function formatTpmStat(value?: number) { } export function APMSection({ bucketSize }: Props) { - const theme = useContext(ThemeContext); + const { euiTheme } = useEuiTheme(); const chartThemes = useChartThemes(); const history = useHistory(); const { forceUpdate, hasDataMap } = useHasData(); @@ -92,8 +91,6 @@ export function APMSection({ bucketSize }: Props) { const isLoading = status === FETCH_STATUS.LOADING; - const transactionsColor = theme.eui.euiColorVis1; - return ( } isLoading={isLoading} - color={transactionsColor} + // color={transactionsColor} /> @@ -164,7 +161,7 @@ export function APMSection({ bucketSize }: Props) { yScaleType={ScaleType.Linear} xAccessor={'x'} yAccessors={['y']} - color={transactionsColor} + color={euiTheme.colors.vis.euiColorVis0} /> string; - color: number; + color: string; } export function MetricWithSparkline({ id, formatter, value, timeseries, color }: Props) { const { baseTheme, sparklineTheme } = useChartThemes(); - const colors = baseTheme.colors?.vizColors ?? []; if (!value) { return ( @@ -53,7 +52,7 @@ export function MetricWithSparkline({ id, formatter, value, timeseries, color }: data={timeseries} xAccessor={'timestamp'} yAccessors={[id]} - color={colors[color] || '#006BB4'} + color={color} /> diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/metrics/metrics_section.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/metrics/metrics_section.tsx index 99d526a66facd..660048bcb7e70 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/metrics/metrics_section.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/overview/components/sections/metrics/metrics_section.tsx @@ -12,6 +12,7 @@ import { EuiBasicTableColumn, EuiLoadingChart, EuiTableSortingType, + useEuiTheme, } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; @@ -32,11 +33,6 @@ import { formatDuration } from './lib/format_duration'; import { MetricWithSparkline } from './metric_with_sparkline'; import type { BucketSize } from '../../../helpers/calculate_bucket_size'; -const COLOR_ORANGE = 7; -const COLOR_BLUE = 1; -const COLOR_GREEN = 0; -const COLOR_PURPLE = 3; - interface Props { bucketSize: BucketSize; } @@ -51,6 +47,7 @@ const bytesPerSecondFormatter = (value: NumberOrNull) => value === null ? '' : numeral(value).format('0b') + '/s'; export function MetricsSection({ bucketSize }: Props) { + const { euiTheme } = useEuiTheme(); const { forceUpdate, hasDataMap } = useHasData(); const { relativeStart, relativeEnd, absoluteStart, absoluteEnd, lastUpdated } = useDatePickerContext(); @@ -141,7 +138,7 @@ export function MetricsSection({ bucketSize }: Props) { value={value} formatter={percentFormatter} timeseries={record.timeseries} - color={COLOR_ORANGE} + color={euiTheme.colors.vis.euiColorVis0} /> ), }, @@ -157,7 +154,7 @@ export function MetricsSection({ bucketSize }: Props) { value={value} formatter={numberFormatter} timeseries={record.timeseries} - color={COLOR_BLUE} + color={euiTheme.colors.vis.euiColorVis1} /> ), }, @@ -171,7 +168,7 @@ export function MetricsSection({ bucketSize }: Props) { value={value} formatter={bytesPerSecondFormatter} timeseries={record.timeseries} - color={COLOR_GREEN} + color={euiTheme.colors.vis.euiColorVis2} /> ), }, @@ -185,7 +182,7 @@ export function MetricsSection({ bucketSize }: Props) { value={value} formatter={bytesPerSecondFormatter} timeseries={record.timeseries} - color={COLOR_PURPLE} + color={euiTheme.colors.vis.euiColorVis3} /> ), }, diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts index 7b078d4cb5fc9..b10c583a5bcdf 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/scripts/evaluation/kibana_client.ts @@ -73,7 +73,7 @@ type CompleteFunction = (params: CompleteFunctionParams) => Promise<{ }>; export interface ChatClient { - chat: (message: StringOrMessageList) => Promise; + chat: (message: StringOrMessageList, system: string) => Promise; complete: CompleteFunction; evaluate: ( {}: { conversationId?: string; messages: InnerMessage[]; errors: ChatCompletionErrorEvent[] }, @@ -349,11 +349,13 @@ export class KibanaClient { async function chat( name: string, { + systemMessage, messages, functions, functionCall, connectorIdOverride, }: { + systemMessage: string; messages: Message[]; functions: FunctionDefinition[]; functionCall?: string; @@ -367,6 +369,7 @@ export class KibanaClient { const params: ObservabilityAIAssistantAPIClientRequestParamsOf<'POST /internal/observability_ai_assistant/chat'>['params']['body'] = { name, + systemMessage, messages, connectorId: connectorIdOverride || connectorId, functions: functions.map((fn) => pick(fn, 'name', 'description', 'parameters')), @@ -403,14 +406,14 @@ export class KibanaClient { const results: EvaluationResult[] = []; return { - chat: async (message) => { + chat: async (message, systemMessage) => { const messages = [ ...this.getMessages(message).map((msg) => ({ message: msg, '@timestamp': new Date().toISOString(), })), ]; - return chat('chat', { messages, functions: [] }); + return chat('chat', { systemMessage, messages, functions: [] }); }, complete: async ({ messages: messagesArg, @@ -515,20 +518,14 @@ export class KibanaClient { evaluate: async ({ messages, conversationId, errors }, criteria) => { const message = await chat('evaluate', { connectorIdOverride: evaluationConnectorId, - messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: `You are a critical assistant for evaluating conversations with the Elastic Observability AI Assistant, + systemMessage: `You are a critical assistant for evaluating conversations with the Elastic Observability AI Assistant, which helps our users make sense of their Observability data. Your goal is to verify whether a conversation between the user and the assistant matches the given criteria. For each criterion, calculate a score. Explain your score, by describing what the assistant did right, and describing and quoting what the assistant did wrong, where it could improve, and what the root cause was in case of a failure.`, - }, - }, + messages: [ { '@timestamp': new Date().toString(), message: { diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.test.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.test.ts index e2c0f97d14a0d..c2e5456bd9511 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.test.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.test.ts @@ -21,13 +21,6 @@ import { MessageRole } from '@kbn/observability-ai-assistant-plugin/public'; import { AlertDetailsContextualInsightsService } from '@kbn/observability-plugin/server/services'; const buildConversation = (contentMessage: string) => [ - { - '@timestamp': expect.any(String), - message: { - role: MessageRole.System, - content: '', - }, - }, { '@timestamp': expect.any(String), message: { diff --git a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.ts b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.ts index 207e4e9488354..5a11a5b9bfb97 100644 --- a/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.ts +++ b/x-pack/solutions/observability/plugins/observability_ai_assistant_app/server/rule_connector/index.ts @@ -34,7 +34,6 @@ import { import { concatenateChatCompletionChunks } from '@kbn/observability-ai-assistant-plugin/common/utils/concatenate_chat_completion_chunks'; import { CompatibleJSONSchema } from '@kbn/observability-ai-assistant-plugin/common/functions/types'; import { AlertDetailsContextualInsightsService } from '@kbn/observability-plugin/server/services'; -import { getSystemMessageFromInstructions } from '@kbn/observability-ai-assistant-plugin/server/service/util/get_system_message_from_instructions'; import { AdHocInstruction } from '@kbn/observability-ai-assistant-plugin/common/types'; import { EXECUTE_CONNECTOR_FUNCTION_NAME } from '@kbn/observability-ai-assistant-plugin/server/functions/execute_connector'; import { ObservabilityAIAssistantClient } from '@kbn/observability-ai-assistant-plugin/server'; @@ -315,18 +314,6 @@ If available, include the link of the conversation at the end of your answer.` kibanaPublicUrl: (await resources.plugins.core.start()).http.basePath.publicBaseUrl, instructions: [backgroundInstruction], messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: getSystemMessageFromInstructions({ - availableFunctionNames: functionClient.getFunctions().map((fn) => fn.definition.name), - applicationInstructions: functionClient.getInstructions(), - userInstructions: [], - adHocInstructions: functionClient.getAdhocInstructions(), - }), - }, - }, { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/solutions/observability/plugins/observability_logs_explorer/common/translations.ts b/x-pack/solutions/observability/plugins/observability_logs_explorer/common/translations.ts index 380bc3c3c5a26..bbfa477585780 100644 --- a/x-pack/solutions/observability/plugins/observability_logs_explorer/common/translations.ts +++ b/x-pack/solutions/observability/plugins/observability_logs_explorer/common/translations.ts @@ -33,7 +33,7 @@ export const deprecationBadgeDescription = i18n.translate( 'xpack.observabilityLogsExplorer.deprecationBadgeDescription', { defaultMessage: - 'Logs Stream and Logs Explorer are set to be deprecated. Switch to Discover which now includes their functionality plus more features and better performance.', + 'Logs Stream and Logs Explorer are set to be deprecated. Switch to Discover and enable the new Observability solution for an improved logs experience.', } ); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e.js b/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e.js index fd2da7b56fb68..e5c7901bb869e 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e.js +++ b/x-pack/solutions/observability/plugins/observability_onboarding/scripts/test/e2e.js @@ -80,7 +80,6 @@ function runTests() { env: { ...process.env, CYPRESS_CLI_ARGS: JSON.stringify(cypressCliArgs), - NODE_OPTIONS: '--openssl-legacy-provider', }, encoding: 'utf8', stdio: 'inherit', diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/add_custom_integration.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/add_custom_integration.spec.ts index ad22d72cbe34b..e04abdec5e5cf 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/add_custom_integration.spec.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/add_custom_integration.spec.ts @@ -56,7 +56,7 @@ test.describe( await customLogs.selectPlatform('windows'); await expect(customLogs.autoDownloadConfigurationToggle).toBeDisabled(); await expect(customLogs.windowsInstallElasticAgentDocLink).toBeVisible(); - await expect(customLogs.installCodeSnippet).not.toBeVisible(); + await expect(customLogs.installCodeSnippet).toBeHidden(); await expect( customLogs.configureElasticAgentStep.getByText('Step 2 is disabled') ).toBeVisible(); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/configuration.spec.ts b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/configuration.spec.ts index c3cd104b461a8..d3bbff71d7eca 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/configuration.spec.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/ui_tests/parallel_tests/custom_logs/configuration.spec.ts @@ -47,7 +47,7 @@ test.describe( test(`should allow updating Advanced Settings`, async ({ pageObjects: { customLogs } }) => { await customLogs.getLogFilePathInputField(0).fill(logsFilePath); - await expect(customLogs.advancedSettingsContent).not.toBeVisible(); + await expect(customLogs.advancedSettingsContent).toBeHidden(); await customLogs.clickAdvancedSettingsButton(); await expect( customLogs.advancedSettingsContent, @@ -63,13 +63,13 @@ test.describe( await customLogs.namespaceInput.fill('default'); await expect(customLogs.customConfigInput).toHaveValue(''); - await expect(customLogs.continueButton).not.toBeDisabled(); + await expect(customLogs.continueButton).toBeEnabled(); await customLogs.clickAdvancedSettingsButton(); await expect( customLogs.advancedSettingsContent, 'Advanced Settings should be closed' - ).not.toBeVisible(); + ).toBeHidden(); }); test('should validate Integration Name field', async ({ diff --git a/x-pack/solutions/observability/plugins/profiling/common/topn.test.ts b/x-pack/solutions/observability/plugins/profiling/common/topn.test.ts index 036b298d9e794..3cc83f792f235 100644 --- a/x-pack/solutions/observability/plugins/profiling/common/topn.test.ts +++ b/x-pack/solutions/observability/plugins/profiling/common/topn.test.ts @@ -10,16 +10,16 @@ import { getCategoryColor } from './topn'; describe('topn', () => { describe('getCategoryColor', () => { const categories = [ - { category: 'elasticsearch', expectedColor: '#D6BF57' }, - { category: 'metricbeat', expectedColor: '#B9A888' }, - { category: 'auditbeat', expectedColor: '#E7664C' }, - { category: 'dockerd', expectedColor: '#B9A888' }, - { category: 'Other', expectedColor: '#CA8EAE' }, - { category: 'node', expectedColor: '#D36086' }, - { category: 'filebeat', expectedColor: '#54B399' }, - { category: 'containerd', expectedColor: '#DA8B45' }, - { category: 'C2 CompilerThre', expectedColor: '#6092C0' }, - { category: '[metrics]>worke', expectedColor: '#D6BF57' }, + { category: 'elasticsearch', expectedColor: '#FFC7DB' }, + { category: 'metricbeat', expectedColor: '#F6726A' }, + { category: 'auditbeat', expectedColor: '#FCD883' }, + { category: 'dockerd', expectedColor: '#F6726A' }, + { category: 'Other', expectedColor: '#EE72A6' }, + { category: 'node', expectedColor: '#61A2FF' }, + { category: 'filebeat', expectedColor: '#16C5C0' }, + { category: 'containerd', expectedColor: '#FFC9C2' }, + { category: 'C2 CompilerThre', expectedColor: '#A6EDEA' }, + { category: '[metrics]>worke', expectedColor: '#FFC7DB' }, ]; const colors = euiPaletteColorBlind({ rotations: Math.ceil(categories.length / 10), diff --git a/x-pack/solutions/observability/plugins/profiling/e2e/package.json b/x-pack/solutions/observability/plugins/profiling/e2e/package.json index 2bc70d1057d20..65461757086e5 100644 --- a/x-pack/solutions/observability/plugins/profiling/e2e/package.json +++ b/x-pack/solutions/observability/plugins/profiling/e2e/package.json @@ -5,7 +5,7 @@ "private": true, "license": "Elastic License 2.0", "scripts": { - "cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/profiling/e2e/cypress.config.ts --ftr-config-file ../../../../../test/profiling_cypress/cli_config", + "cypress": "node ../../../../security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../observability/plugins/profiling/e2e/cypress.config.ts --ftr-config-file ../../../../../test/profiling_cypress/cli_config", "cypress:open": "yarn cypress open", "cypress:run": "yarn cypress run", "cypress:run:headed": "yarn cypress run --headed", diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/slo_inspect/slo_inspect.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/slo_inspect/slo_inspect.tsx index 1b4a49bc81894..21b25ecc1cc6a 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/slo_inspect/slo_inspect.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/common/slo_inspect/slo_inspect.tsx @@ -26,10 +26,8 @@ import { useFetcher } from '@kbn/observability-shared-plugin/public'; import { GetSLOResponse } from '@kbn/slo-schema'; import React, { useState } from 'react'; import { useFormContext } from 'react-hook-form'; -import { enableInspectEsQueries } from '@kbn/observability-plugin/common'; import { useKibana } from '../../../../../hooks/use_kibana'; import { useFetchSloInspect } from '../../../../../hooks/use_fetch_slo_inspect'; -import { usePluginContext } from '../../../../../hooks/use_plugin_context'; import { transformCreateSLOFormToCreateSLOInput } from '../../../helpers/process_slo_form_values'; import { CreateSLOForm } from '../../../types'; import { CodeBlockAccordion } from './code_block_accordion'; @@ -41,18 +39,7 @@ interface Props { disabled: boolean; } -export function SLOInspectWrapper({ slo, disabled }: Props) { - const { - services: { uiSettings }, - } = useKibana(); - - const { isDev } = usePluginContext(); - const isInspectorEnabled = uiSettings?.get(enableInspectEsQueries); - - return isDev || isInspectorEnabled ? : null; -} - -function SLOInspect({ slo, disabled }: Props) { +export function SLOInspect({ slo, disabled }: Props) { const { share, http } = useKibana().services; const { trigger, getValues } = useFormContext(); diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx index ab0c7ff235fbf..ee307b9360d63 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx @@ -25,7 +25,7 @@ import { } from '../helpers/process_slo_form_values'; import { CreateSLOForm } from '../types'; import { EquivalentApiRequest } from './common/equivalent_api_request'; -import { SLOInspectWrapper } from './common/slo_inspect/slo_inspect'; +import { SLOInspect } from './common/slo_inspect/slo_inspect'; export interface Props { slo?: GetSLOResponse; @@ -133,7 +133,7 @@ export function SloEditFormFooter({ slo, onSave }: Props) { /> - diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/slo_edit.test.tsx b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/slo_edit.test.tsx index 00c4cbb471ee8..bae113ec59fe0 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/slo_edit.test.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slo_edit/slo_edit.test.tsx @@ -9,7 +9,7 @@ import { ILicense } from '@kbn/licensing-plugin/common/types'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock'; import { useFetchDataViews } from '@kbn/observability-plugin/public'; -import { HeaderMenuPortal } from '@kbn/observability-shared-plugin/public'; +import { HeaderMenuPortal, useFetcher } from '@kbn/observability-shared-plugin/public'; import { cleanup, fireEvent, waitFor } from '@testing-library/react'; import { createBrowserHistory } from 'history'; import React from 'react'; @@ -30,6 +30,7 @@ import { kibanaStartMock } from '../../utils/kibana_react.mock'; import { render } from '../../utils/test_helper'; import { SLO_EDIT_FORM_DEFAULT_VALUES } from './constants'; import { SloEditPage } from './slo_edit'; +import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -63,6 +64,7 @@ const useUpdateSloMock = useUpdateSlo as jest.Mock; const useCreateRuleMock = useCreateRule as jest.Mock; const useFetchApmSuggestionsMock = useFetchApmSuggestions as jest.Mock; const usePermissionsMock = usePermissions as jest.Mock; +const useFetcherMock = useFetcher as jest.Mock; const HeaderMenuPortalMock = HeaderMenuPortal as jest.Mock; HeaderMenuPortalMock.mockReturnValue(
Portal node
); @@ -144,6 +146,7 @@ const mockKibana = (license: ILicense | null = licenseMock) => { licensing: { license$: new BehaviorSubject(license), }, + share: sharePluginMock.createStartContract(), }, }); }; @@ -221,6 +224,7 @@ describe('SLO Edit Page', () => { }, }); licenseMock.hasAtLeast.mockReturnValue(true); + useFetcherMock.mockReturnValue({ data: undefined, isLoading: false }); }); afterEach(cleanup); diff --git a/x-pack/solutions/observability/plugins/slo/public/utils/test_helper.tsx b/x-pack/solutions/observability/plugins/slo/public/utils/test_helper.tsx index 723d2fc68bee1..d1b20cd5e7171 100644 --- a/x-pack/solutions/observability/plugins/slo/public/utils/test_helper.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/utils/test_helper.tsx @@ -16,6 +16,7 @@ import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render as testLibRender } from '@testing-library/react'; import React from 'react'; +import { i18n } from '@kbn/i18n'; import type { SLORouteRepository } from '../../server/routes/get_slo_server_route_repository'; import { PluginContext } from '../context/plugin_context'; @@ -54,7 +55,13 @@ export const render = (component: React.ReactNode) => { createExploratoryViewUrl: jest.fn(), getAppDataView: jest.fn(), - ExploratoryViewEmbeddable: () =>
Embeddable exploratory view
, + ExploratoryViewEmbeddable: () => ( +
+ {i18n.translate('xpack.slo.render.div.embeddableExploratoryViewLabel', { + defaultMessage: 'Embeddable exploratory view', + })} +
+ ), }, }} > diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts index 7313d21dd3ffb..6492f518131c7 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts @@ -218,21 +218,21 @@ describe('getConnectingTime', () => { describe('Palettes', () => { it('A colour palette comprising timing and mime type colours is correctly generated', () => { expect(colourPalette).toEqual({ - blocked: '#b0c9e0', - connect: '#c8b8dc', - dns: '#aad9cc', - font: '#d36086', - html: '#6092c0', - image: '#ca8eae', - media: '#d6bf57', - other: '#b9a888', - receive: '#ebdfab', - script: '#da8b45', - send: '#f3b3a6', - ssl: '#e5c7d7', - stylesheet: '#9170b8', - wait: '#e7664c', - xhr: '#54b399', + blocked: '#d3f6f5', + connect: '#dfedff', + dns: '#8be2e0', + font: '#61a2ff', + html: '#a6edea', + image: '#ee72a6', + media: '#ffc7db', + other: '#f6726a', + receive: '#ffe3ed', + script: '#ffc9c2', + send: '#feecc1', + ssl: '#f7b9d3', + stylesheet: '#bfdbff', + wait: '#fcd883', + xhr: '#16c5c0', }); }); }); @@ -250,7 +250,7 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 0, "isHighlighted": true, }, @@ -260,7 +260,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#aad9cc", + "colour": "#8be2e0", "id": 0, "isHighlighted": true, }, @@ -270,7 +270,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#c8b8dc", + "colour": "#dfedff", "id": 0, "isHighlighted": true, }, @@ -280,7 +280,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#e5c7d7", + "colour": "#f7b9d3", "id": 0, "isHighlighted": true, }, @@ -290,7 +290,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#f3b3a6", + "colour": "#feecc1", "id": 0, "isHighlighted": true, }, @@ -300,7 +300,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#e7664c", + "colour": "#fcd883", "id": 0, "isHighlighted": true, }, @@ -310,7 +310,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "id": 0, "isHighlighted": true, }, @@ -320,7 +320,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 1, "isHighlighted": true, }, @@ -330,7 +330,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#f3b3a6", + "colour": "#feecc1", "id": 1, "isHighlighted": true, }, @@ -340,7 +340,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#e7664c", + "colour": "#fcd883", "id": 1, "isHighlighted": true, }, @@ -350,7 +350,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "id": 1, "isHighlighted": true, }, @@ -368,7 +368,7 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 0, "isHighlighted": true, }, @@ -378,7 +378,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#aad9cc", + "colour": "#8be2e0", "id": 0, "isHighlighted": true, }, @@ -388,7 +388,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#c8b8dc", + "colour": "#dfedff", "id": 0, "isHighlighted": true, }, @@ -398,7 +398,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#e5c7d7", + "colour": "#f7b9d3", "id": 0, "isHighlighted": true, }, @@ -408,7 +408,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#f3b3a6", + "colour": "#feecc1", "id": 0, "isHighlighted": true, }, @@ -418,7 +418,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#e7664c", + "colour": "#fcd883", "id": 0, "isHighlighted": true, }, @@ -428,7 +428,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "id": 0, "isHighlighted": true, }, @@ -438,7 +438,7 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "isHighlighted": true, }, "x": 1, diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/browser_journey/api.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/browser_journey/api.ts index 3fdca50592ddd..6cb4a4cbe71cb 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/browser_journey/api.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/browser_journey/api.ts @@ -24,9 +24,13 @@ export interface FetchJourneyStepsParams { } export async function fetchScreenshotBlockSet(params: string[]): Promise { - return apiService.post(SYNTHETICS_API_URLS.JOURNEY_SCREENSHOT_BLOCKS, { - hashes: params, - }); + const response = await apiService.post<{ result: ScreenshotBlockDoc[] }>( + SYNTHETICS_API_URLS.JOURNEY_SCREENSHOT_BLOCKS, + { + hashes: params, + } + ); + return response.result; } export async function fetchBrowserJourney( diff --git a/x-pack/solutions/observability/plugins/synthetics/server/routes/pings/journey_screenshot_blocks.ts b/x-pack/solutions/observability/plugins/synthetics/server/routes/pings/journey_screenshot_blocks.ts index e155e2f320584..292242a6e6ab2 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/routes/pings/journey_screenshot_blocks.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/routes/pings/journey_screenshot_blocks.ts @@ -6,13 +6,9 @@ */ import { schema } from '@kbn/config-schema'; -import { IKibanaResponse } from '@kbn/core-http-server'; -import { isRight } from 'fp-ts/Either'; -import * as t from 'io-ts'; import { getJourneyScreenshotBlocks } from '../../queries/get_journey_screenshot_blocks'; -import { ScreenshotBlockDoc } from '../../../common/runtime_types'; import { SYNTHETICS_API_URLS } from '../../../common/constants'; -import { RouteContext, SyntheticsRestApiRouteFactory } from '../types'; +import { SyntheticsRestApiRouteFactory } from '../types'; export const createJourneyScreenshotBlocksRoute: SyntheticsRestApiRouteFactory = () => ({ method: 'POST', @@ -23,34 +19,16 @@ export const createJourneyScreenshotBlocksRoute: SyntheticsRestApiRouteFactory = }), }, writeAccess: false, - handler: (routeProps) => { - return journeyScreenshotBlocksHandler(routeProps); - }, -}); - -export const journeyScreenshotBlocksHandler = async ({ - response, - request, - syntheticsEsClient, -}: RouteContext): Promise> => { - const { hashes: blockIds } = request.body; - - if (!isStringArray(blockIds)) return response.badRequest(); + handler: async ({ request, syntheticsEsClient }) => { + const { hashes: blockIds } = request.body; - const result = await getJourneyScreenshotBlocks({ - blockIds, - syntheticsEsClient, - }); + const result = await getJourneyScreenshotBlocks({ + blockIds, + syntheticsEsClient, + }); - if (result.length === 0) { - return response.notFound(); - } - - return response.ok({ - body: result, - }); -}; - -function isStringArray(data: unknown): data is string[] { - return isRight(t.array(t.string).decode(data)); -} + return { + result, + }; + }, +}); diff --git a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap index a8f1a6bcfc335..d65adda95d21e 100644 --- a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap @@ -697,7 +697,7 @@ exports[`DonutChart component renders a donut chart 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -739,7 +739,7 @@ exports[`DonutChart component renders a donut chart 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -856,7 +856,7 @@ exports[`DonutChart component renders a green check when all monitors are up 1`] class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -898,7 +898,7 @@ exports[`DonutChart component renders a green check when all monitors are up 1`] class="euiFlexItem emotion-euiFlexItem-growZero" >
diff --git a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ml/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ml/__snapshots__/ml_integerations.test.tsx.snap index 733eda0561f9a..1b065228bd20d 100644 --- a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ml/__snapshots__/ml_integerations.test.tsx.snap +++ b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/monitor/ml/__snapshots__/ml_integerations.test.tsx.snap @@ -18,7 +18,7 @@ exports[`ML Integrations renders without errors 1`] = ` aria-label="Loading" class="euiLoadingSpinner emotion-euiLoadingSpinner-m" role="progressbar" - style="border-color:#0077CC currentcolor currentcolor currentcolor" + style="border-color:#1750BA currentcolor currentcolor currentcolor" /> { describe('Palettes', () => { it('A colour palette comprising timing and mime type colours is correctly generated', () => { expect(colourPalette).toEqual({ - blocked: '#dcd4c4', - connect: '#da8b45', - dns: '#54b399', - font: '#aa6556', - html: '#f3b3a6', - media: '#d6bf57', - other: '#e7664c', - receive: '#54b399', - script: '#9170b8', - send: '#d36086', - ssl: '#edc5a2', - stylesheet: '#ca8eae', - wait: '#b0c9e0', - xhr: '#e7664c', + blocked: '#fbb9b5', + connect: '#ffc9c2', + dns: '#16c5c0', + font: '#eaae01', + html: '#feecc1', + media: '#ffc7db', + other: '#fcd883', + receive: '#16c5c0', + script: '#bfdbff', + send: '#61a2ff', + ssl: '#ffe4e1', + stylesheet: '#ee72a6', + wait: '#d3f6f5', + xhr: '#fcd883', }); }); }); @@ -222,12 +222,12 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "value": "Queued / Blocked: 0.854ms", }, }, @@ -237,12 +237,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#54b399", + "colour": "#16c5c0", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#54b399", + "colour": "#16c5c0", "value": "DNS: 3.560ms", }, }, @@ -252,12 +252,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "value": "Connecting: 25.721ms", }, }, @@ -267,12 +267,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#edc5a2", + "colour": "#ffe4e1", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#edc5a2", + "colour": "#ffe4e1", "value": "TLS: 55.387ms", }, }, @@ -282,12 +282,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#61a2ff", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#61a2ff", "value": "Sending request: 0.360ms", }, }, @@ -297,12 +297,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "value": "Waiting (TTFB): 34.578ms", }, }, @@ -312,12 +312,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#ca8eae", + "colour": "#ee72a6", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#ca8eae", + "colour": "#ee72a6", "value": "Content downloading (CSS): 0.552ms", }, }, @@ -327,12 +327,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "value": "Queued / Blocked: 84.546ms", }, }, @@ -342,12 +342,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#61a2ff", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#61a2ff", "value": "Sending request: 0.239ms", }, }, @@ -357,12 +357,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "value": "Waiting (TTFB): 52.561ms", }, }, @@ -372,12 +372,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "value": "Content downloading (JS): 3.068ms", }, }, @@ -395,12 +395,12 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#fbb9b5", "value": "Queued / Blocked: 0.854ms", }, }, @@ -410,12 +410,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#54b399", + "colour": "#16c5c0", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#54b399", + "colour": "#16c5c0", "value": "DNS: 3.560ms", }, }, @@ -425,12 +425,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#da8b45", + "colour": "#ffc9c2", "value": "Connecting: 25.721ms", }, }, @@ -440,12 +440,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#edc5a2", + "colour": "#ffe4e1", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#edc5a2", + "colour": "#ffe4e1", "value": "TLS: 55.387ms", }, }, @@ -455,12 +455,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#61a2ff", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#61a2ff", "value": "Sending request: 0.360ms", }, }, @@ -470,12 +470,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#d3f6f5", "value": "Waiting (TTFB): 34.578ms", }, }, @@ -485,12 +485,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#ca8eae", + "colour": "#ee72a6", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#ca8eae", + "colour": "#ee72a6", "value": "Content downloading (CSS): 0.552ms", }, }, @@ -500,11 +500,11 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#9170b8", + "colour": "#bfdbff", "value": "Content downloading (JS): 2.793ms", }, }, diff --git a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/synthetics/console_event.test.tsx b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/synthetics/console_event.test.tsx index 2db3b2ec004fc..2012cc0bbc076 100644 --- a/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/synthetics/console_event.test.tsx +++ b/x-pack/solutions/observability/plugins/uptime/public/legacy_uptime/components/synthetics/console_event.test.tsx @@ -46,7 +46,7 @@ describe('ConsoleEvent component', () => { grow={false} style={ Object { - "color": "#BD271E", + "color": "#C61E25", } } > diff --git a/x-pack/solutions/search/packages/shared_ui/README.md b/x-pack/solutions/search/packages/shared-ui/README.md similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/README.md rename to x-pack/solutions/search/packages/shared-ui/README.md diff --git a/x-pack/solutions/search/packages/shared_ui/index.ts b/x-pack/solutions/search/packages/shared-ui/index.ts similarity index 93% rename from x-pack/solutions/search/packages/shared_ui/index.ts rename to x-pack/solutions/search/packages/shared-ui/index.ts index 5db02d31b4f97..66b35fc503371 100644 --- a/x-pack/solutions/search/packages/shared_ui/index.ts +++ b/x-pack/solutions/search/packages/shared-ui/index.ts @@ -9,4 +9,3 @@ export * from './src/connector_icon'; export * from './src/decorative_horizontal_stepper'; export * from './src/form_info_field/form_info_field'; export * from './src/search_empty_prompt'; -export * from './src/icons'; diff --git a/x-pack/solutions/search/packages/shared_ui/jest.config.js b/x-pack/solutions/search/packages/shared-ui/jest.config.js similarity index 81% rename from x-pack/solutions/search/packages/shared_ui/jest.config.js rename to x-pack/solutions/search/packages/shared-ui/jest.config.js index b18e5ba2e0965..9783c5c4d3937 100644 --- a/x-pack/solutions/search/packages/shared_ui/jest.config.js +++ b/x-pack/solutions/search/packages/shared-ui/jest.config.js @@ -7,10 +7,10 @@ module.exports = { coverageDirectory: - '/target/kibana-coverage/jest/x-pack/solutions/search/packages/shared_ui', + '/target/kibana-coverage/jest/x-pack/solutions/search/packages/shared-ui', coverageReporters: ['text', 'html'], - collectCoverageFrom: ['/x-pack/solutions/search/packages/shared_ui/**/*.{ts,tsx}'], + collectCoverageFrom: ['/x-pack/solutions/search/packages/shared-ui/**/*.{ts,tsx}'], preset: '@kbn/test', rootDir: '../../../../..', - roots: ['/x-pack/solutions/search/packages/shared_ui'], + roots: ['/x-pack/solutions/search/packages/shared-ui'], }; diff --git a/x-pack/solutions/search/packages/shared_ui/kibana.jsonc b/x-pack/solutions/search/packages/shared-ui/kibana.jsonc similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/kibana.jsonc rename to x-pack/solutions/search/packages/shared-ui/kibana.jsonc diff --git a/x-pack/solutions/search/packages/shared_ui/package.json b/x-pack/solutions/search/packages/shared-ui/package.json similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/package.json rename to x-pack/solutions/search/packages/shared-ui/package.json diff --git a/x-pack/solutions/search/packages/shared_ui/src/connector_icon/connector_icon.tsx b/x-pack/solutions/search/packages/shared-ui/src/connector_icon/connector_icon.tsx similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/connector_icon/connector_icon.tsx rename to x-pack/solutions/search/packages/shared-ui/src/connector_icon/connector_icon.tsx diff --git a/x-pack/solutions/search/packages/shared_ui/src/connector_icon/index.ts b/x-pack/solutions/search/packages/shared-ui/src/connector_icon/index.ts similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/connector_icon/index.ts rename to x-pack/solutions/search/packages/shared-ui/src/connector_icon/index.ts diff --git a/x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx b/x-pack/solutions/search/packages/shared-ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx rename to x-pack/solutions/search/packages/shared-ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx diff --git a/x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/index.ts b/x-pack/solutions/search/packages/shared-ui/src/decorative_horizontal_stepper/index.ts similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/index.ts rename to x-pack/solutions/search/packages/shared-ui/src/decorative_horizontal_stepper/index.ts diff --git a/x-pack/solutions/search/packages/shared_ui/src/form_info_field/form_info_field.tsx b/x-pack/solutions/search/packages/shared-ui/src/form_info_field/form_info_field.tsx similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/form_info_field/form_info_field.tsx rename to x-pack/solutions/search/packages/shared-ui/src/form_info_field/form_info_field.tsx diff --git a/x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/index.ts b/x-pack/solutions/search/packages/shared-ui/src/search_empty_prompt/index.ts similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/index.ts rename to x-pack/solutions/search/packages/shared-ui/src/search_empty_prompt/index.ts diff --git a/x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx b/x-pack/solutions/search/packages/shared-ui/src/search_empty_prompt/search_empty_prompt.tsx similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx rename to x-pack/solutions/search/packages/shared-ui/src/search_empty_prompt/search_empty_prompt.tsx diff --git a/x-pack/solutions/search/packages/shared_ui/tsconfig.json b/x-pack/solutions/search/packages/shared-ui/tsconfig.json similarity index 100% rename from x-pack/solutions/search/packages/shared_ui/tsconfig.json rename to x-pack/solutions/search/packages/shared-ui/tsconfig.json diff --git a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx deleted file mode 100644 index ce7af9b282747..0000000000000 --- a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -// Temporary custom asset while it's available in EUI - -import * as React from 'react'; -import type { SVGProps } from 'react'; -interface SVGRProps { - title?: string; - titleId?: string; -} -export const EuiIconPlugs = ({ title, titleId, ...props }: SVGProps & SVGRProps) => ( - - {title ? {title} : null} - - -); diff --git a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx deleted file mode 100644 index 32200171345bf..0000000000000 --- a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -// Temporary custom asset while it's available in EUI - -import * as React from 'react'; -import type { SVGProps } from 'react'; -interface SVGRProps { - title?: string; - titleId?: string; -} -export const EuiIconWeb = ({ title, titleId, ...props }: SVGProps & SVGRProps) => ( - - {title ? {title} : null} - - -); diff --git a/x-pack/solutions/search/packages/shared_ui/src/icons/index.ts b/x-pack/solutions/search/packages/shared_ui/src/icons/index.ts deleted file mode 100644 index 6d4485a3296cf..0000000000000 --- a/x-pack/solutions/search/packages/shared_ui/src/icons/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -export * from './EuiIconPlugs'; -export * from './EuiIconWeb'; diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_detail.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_detail.tsx index b3251ad5a15b8..1f4d84c2ae784 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_detail.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_detail.tsx @@ -97,7 +97,7 @@ export const ConnectorDetail: React.FC = () => { }, { content: , - disabled: !index, + disabled: !index || connector?.is_native, id: ConnectorDetailTabId.DOCUMENTS, isSelected: tabId === ConnectorDetailTabId.DOCUMENTS, label: i18n.translate( @@ -116,7 +116,7 @@ export const ConnectorDetail: React.FC = () => { }, { content: , - disabled: !index, + disabled: !index || connector?.is_native, id: ConnectorDetailTabId.INDEX_MAPPINGS, isSelected: tabId === ConnectorDetailTabId.INDEX_MAPPINGS, label: i18n.translate( @@ -140,7 +140,7 @@ export const ConnectorDetail: React.FC = () => { ? [ { content: , - disabled: !index, + disabled: !index || connector?.is_native, id: ConnectorDetailTabId.SYNC_RULES, isSelected: tabId === ConnectorDetailTabId.SYNC_RULES, label: i18n.translate( @@ -161,7 +161,7 @@ export const ConnectorDetail: React.FC = () => { : []), { content: , - disabled: !connector?.index_name, + disabled: !connector?.index_name || connector?.is_native, id: ConnectorDetailTabId.SCHEDULING, isSelected: tabId === ConnectorDetailTabId.SCHEDULING, label: i18n.translate( @@ -183,6 +183,7 @@ export const ConnectorDetail: React.FC = () => { const CONFIG_TAB = [ { content: , + disabled: connector?.is_native, id: ConnectorDetailTabId.CONFIGURATION, isSelected: tabId === ConnectorDetailTabId.CONFIGURATION, label: i18n.translate( @@ -203,7 +204,7 @@ export const ConnectorDetail: React.FC = () => { const PIPELINES_TAB = { content: , - disabled: !index, + disabled: !index || connector?.is_native, id: ConnectorDetailTabId.PIPELINES, isSelected: tabId === ConnectorDetailTabId.PIPELINES, label: i18n.translate( diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx index fb22247de46ad..d963901168b40 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx @@ -28,7 +28,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { Connector, ConnectorStatus, ElasticsearchIndex } from '@kbn/search-connectors'; -import { EuiIconPlugs } from '@kbn/search-shared-ui'; import { KibanaDeps } from '../../../../../common/types'; import { generateEncodedPath } from '../../../shared/encode_path_params'; @@ -403,7 +402,7 @@ export const ConnectorStats: React.FC = ({ { const { indexData } = useValues(IndexViewLogic); - const { connector, error, isWaitingOnAgentlessDeployment, connectorAgentlessPolicy } = - useValues(ConnectorViewLogic); + const { connector, error, connectorAgentlessPolicy } = useValues(ConnectorViewLogic); - const { isCloud } = useValues(KibanaLogic); const { showModal } = useActions(ConvertConnectorLogic); const { isModalVisible } = useValues(ConvertConnectorLogic); @@ -85,35 +72,55 @@ export const ConnectorDetailOverview: React.FC = () => { ) } - {isWaitingOnAgentlessDeployment && ( + {connector?.is_native && ( <> + {isModalVisible && } - - - - - {i18n.translate( - 'xpack.enterpriseSearch.content.connectors.overview.agentlessDeploymentNotReadyCallOut.title', - { - defaultMessage: 'Provisioning infrastructure', - } - )} - - - } + title={i18n.translate( + 'xpack.enterpriseSearch.content.connectors.overview.nativeCloudCallout.title', + { + defaultMessage: 'Elastic managed connectors are no longer supported', + } + )} > +

+ + {i18n.translate( + 'xpack.enterpriseSearch.content.connectors.overview.nativeCloudCallout.connectorClient', + { defaultMessage: 'self-managed connector' } + )} + + ), + }} + /> +

+
+ + showModal()} + > {i18n.translate( - 'xpack.enterpriseSearch.content.connectors.overview.agentlessDeploymentNotReadyCallOut.description', - { - defaultMessage: 'Setting up the agentless infrastructure to run the connector.', - } + 'xpack.enterpriseSearch.content.indices.connectors.overview.convertConnector.buttonLabel', + { defaultMessage: 'Convert connector' } )} - +
@@ -203,73 +210,23 @@ export const ConnectorDetailOverview: React.FC = () => { )} - {connector?.is_native && !isCloud && ( - <> - {isModalVisible && } - - - -

- - {i18n.translate( - 'xpack.enterpriseSearch.content.connectors.overview.nativeCloudCallout.connectorClient', - { defaultMessage: 'self-managed connector' } - )} - - ), - }} - /> -

-
- - showModal()} - > - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.connectors.overview.convertConnector.buttonLabel', - { defaultMessage: 'Convert connector' } - )} - -
- - - )} - {connector && connector.service_type !== ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE && ( - - )} - {connector && connector.service_type !== ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE && ( - <> - - - - )} + {connector && + !connector.is_native && + connector.service_type !== ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE && ( + + )} + {connector && + !connector.is_native && + connector.service_type !== ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE && ( + <> + + + + )} ); }; diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx index d630ab9ff7005..03f2d6bfc6aac 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx @@ -24,7 +24,6 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { EuiIconPlugs } from '@kbn/search-shared-ui'; import { BETA_LABEL, @@ -151,7 +150,7 @@ export const ChooseConnector: React.FC = ({ 'xpack.enterpriseSearch.createConnector.chooseConnectorSelectable.euiComboBox.accessibleScreenReaderLabelLabel', { defaultMessage: 'Select a data source for your connector to use.' } )} - prepend={} + prepend={} singleSelection fullWidth placeholder={i18n.translate( diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/connector_description_popover.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/connector_description_popover.tsx index 101cc1493fb7f..912d7ee7a0f03 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/connector_description_popover.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/connector_description_popover.tsx @@ -23,8 +23,6 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { EuiIconPlugs } from '@kbn/search-shared-ui'; - import { KibanaLogic } from '../../../../../shared/kibana'; const nativePopoverPanels = [ @@ -41,7 +39,7 @@ const nativePopoverPanels = [ 'xpack.enterpriseSearch.connectorDescriptionPopover.connectorDescriptionBadge.native.configureConnectorLabel', { defaultMessage: 'Configure your connector using our Kibana UI' } ), - icons: [, ], + icons: [, ], id: 'native-configure-connector', }, ]; @@ -64,7 +62,7 @@ const connectorClientPopoverPanels = [ } ), icons: [ - , + , , , ], @@ -80,7 +78,7 @@ const connectorClientPopoverPanels = [ icons: [ , , - , + , , , ], @@ -91,11 +89,13 @@ const connectorClientPopoverPanels = [ export interface ConnectorDescriptionPopoverProps { isNative: boolean; showIsOnlySelfManaged: boolean; + isElasticManagedDiscontinued?: boolean; } export const ConnectorDescriptionPopover: React.FC = ({ isNative, showIsOnlySelfManaged, + isElasticManagedDiscontinued, }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const panels = isNative ? nativePopoverPanels : connectorClientPopoverPanels; @@ -126,28 +126,49 @@ export const ConnectorDescriptionPopover: React.FC - {((isNative && !isAgentlessEnabled) || showIsOnlySelfManaged) && ( + {((isNative && !isAgentlessEnabled) || showIsOnlySelfManaged) && + !isElasticManagedDiscontinued && ( + <> + + + + + + + + )} + {isElasticManagedDiscontinued && ( <> )} - {isNative && !isAgentlessEnabled && ( + {isNative && !isAgentlessEnabled && !isElasticManagedDiscontinued && ( <> diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/create_connector.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/create_connector.tsx index d9df123fcbe9a..20eb98fa17114 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/create_connector.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/create_connector.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { css } from '@emotion/react'; @@ -56,25 +56,17 @@ export const CreateConnector: React.FC = () => { const { overlays } = useKibana().services; const { http } = useValues(HttpLogic); - const { application, history, isAgentlessEnabled } = useValues(KibanaLogic); + const { application, history } = useValues(KibanaLogic); const { error } = useValues(AddConnectorApiLogic); const { euiTheme } = useEuiTheme(); - const [selfManagePreference, setSelfManagePreference] = useState('native'); + const [selfManagePreference, setSelfManagePreference] = + useState('selfManaged'); const { selectedConnector, currentStep, isFormDirty } = useValues(NewConnectorLogic); const { setCurrentStep } = useActions(NewConnectorLogic); const stepStates = generateStepState(currentStep); - useEffect(() => { - if ( - (selectedConnector && !selectedConnector.isNative && selfManagePreference === 'native') || - !isAgentlessEnabled - ) { - setSelfManagePreference('selfManaged'); - } - }, [selectedConnector]); - const getSteps = (selfManaged: boolean): EuiContainedStepProps[] => { return [ { @@ -209,7 +201,7 @@ export const CreateConnector: React.FC = () => { background-size: contain; background-repeat: no-repeat; background-position: bottom center; - min-height: 550px; + min-height: 466px; border: 1px solid ${euiTheme.colors.lightShade}; `} > diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/start_step.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/start_step.tsx index f1e9957cd6f3a..93172e3a5c2ac 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/start_step.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/start_step.tsx @@ -17,18 +17,15 @@ import { EuiForm, EuiFormRow, EuiPanel, - EuiRadio, EuiSpacer, EuiText, useIsWithinBreakpoints, EuiTitle, - useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import * as Constants from '../../../../shared/constants'; -import { KibanaLogic } from '../../../../shared/kibana'; import { isValidIndexName } from '../../../utils/validate_index_name'; import { GeneratedConfigFields } from '../../connector_detail/components/generated_config_fields'; @@ -36,7 +33,6 @@ import { ConnectorViewLogic } from '../../connector_detail/connector_view_logic' import { NewConnectorLogic } from '../../new_index/method_connector/new_connector_logic'; import { ChooseConnector } from './components/choose_connector'; -import { ConnectorDescriptionPopover } from './components/connector_description_popover'; import { ManualConfiguration } from './components/manual_configuration'; import { SelfManagePreference } from './create_connector'; @@ -52,12 +48,9 @@ export const StartStep: React.FC = ({ title, selfManagePreference, setCurrentStep, - onSelfManagePreferenceChange, error, }) => { const isMediumDevice = useIsWithinBreakpoints(['xs', 's', 'm', 'l']); - const elasticManagedRadioButtonId = useGeneratedHtmlId({ prefix: 'elasticManagedRadioButton' }); - const selfManagedRadioButtonId = useGeneratedHtmlId({ prefix: 'selfManagedRadioButton' }); const { rawName, @@ -66,12 +59,10 @@ export const StartStep: React.FC = ({ generatedConfigData, isGenerateLoading, isCreateLoading, - isFormDirty, } = useValues(NewConnectorLogic); const { setRawName, createConnector, generateConnectorName, setFormDirty } = useActions(NewConnectorLogic); const { connector } = useValues(ConnectorViewLogic); - const { isAgentlessEnabled } = useValues(KibanaLogic); const handleNameChange = (e: ChangeEvent) => { setRawName(e.target.value); @@ -183,69 +174,6 @@ export const StartStep: React.FC = ({ {/* Set up */} - - - -

- {i18n.translate('xpack.enterpriseSearch.createConnector.startStep.h4.setUpLabel', { - defaultMessage: 'Setup', - })} -

-
- - -

- {i18n.translate( - 'xpack.enterpriseSearch.createConnector.startStep.p.whereDoYouWantLabel', - { - defaultMessage: 'Choose how to deploy and manage your connector:', - } - )} -

-
- - - - onSelfManagePreferenceChange('native')} - name="setUp" - /> - - - - -     - - onSelfManagePreferenceChange('selfManaged')} - name="setUp" - /> - - - - - -
-
{selfManagePreference === 'selfManaged' ? ( { label: BACK_BUTTON_LABEL, onClickBack: () => KibanaLogic.values.navigateToUrl(CRAWLERS_PATH), }} - icon={EuiIconWeb} + icon="web" title={i18n.translate('xpack.enterpriseSearch.elasticManagedWebCrawlerEmpty.title', { defaultMessage: 'Elastic managed web crawlers', })} @@ -85,7 +85,7 @@ export const ElasticManagedWebCrawlerEmptyPrompt: React.FC = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx index 64f3764412449..6b98c066b0f1b 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx @@ -7,7 +7,6 @@ import React from 'react'; import { - EuiBadge, EuiButton, EuiFlexGroup, EuiFlexItem, @@ -18,17 +17,14 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; -import { COMING_SOON_LABEL } from '../../../shared/constants'; import { GithubIcon } from '../../../shared/icons/github_icon'; -import { KibanaLogic } from '../../../shared/kibana'; -import { CRAWLERS_ELASTIC_MANAGED_PATH } from '../../routes'; export const SelfManagedWebCrawlerEmptyPrompt: React.FC = () => { return ( { justifyContent="center" > - + @@ -152,7 +148,7 @@ export const SelfManagedWebCrawlerEmptyPrompt: React.FC = () => { - + @@ -197,23 +193,6 @@ export const SelfManagedWebCrawlerEmptyPrompt: React.FC = () => { })} - - - - KibanaLogic.values.navigateToUrl(CRAWLERS_ELASTIC_MANAGED_PATH)} - > - {i18n.translate('xpack.enterpriseSearch.webCrawlersEmpty.elasticManagedButton', { - defaultMessage: 'Elastic managed web crawler', - })} - - - - {COMING_SOON_LABEL} - - - } /> diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/navigation_tree.ts b/x-pack/solutions/search/plugins/enterprise_search/public/navigation_tree.ts index fd766389f7588..75abcd5b34839 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/navigation_tree.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/public/navigation_tree.ts @@ -312,6 +312,10 @@ export const getNavigationTreeDefinition = ({ defaultMessage: 'Stack Management', }), }, + { + id: 'monitoring', + link: 'monitoring', + }, ], icon: 'gear', id: 'project_settings_project_nav', diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts b/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts index 43592796844cf..c9ce96e7a2c5e 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/plugin.ts @@ -117,7 +117,6 @@ export class EnterpriseSearchPlugin implements Plugin { title: 'Customized connector', type: 'Elasticsearch', url: { - path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/select_connector?connector_type=connector_client&service_type=`, + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/select_connector`, + prependBasePath: true, + }, + }; + + const mongodbConnectorResult = { + icon: 'mongodb.svg', + id: 'mongodb', + score: 75, + title: 'MongoDB', + type: 'Elasticsearch', + url: { + path: `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/select_connector`, prependBasePath: true, }, }; @@ -95,8 +107,7 @@ describe('Search search provider', () => { { hasConnectors: true, } as any, - connectors, - false + connectors ); beforeEach(() => {}); @@ -132,7 +143,7 @@ describe('Search search provider', () => { mockSearchProviderContext ) ).toBe('(a|)', { - a: expect.arrayContaining([{ ...customizedConnectorResult, score: 80 }]), + a: expect.arrayContaining([{ ...mongodbConnectorResult, score: 80 }]), }); }); }); @@ -142,8 +153,7 @@ describe('Search search provider', () => { { hasConnectors: false, } as any, - connectors, - false + connectors ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -203,8 +213,7 @@ describe('Search search provider', () => { { hasConnectors: false, } as any, - connectors, - false + connectors ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -223,8 +232,7 @@ describe('Search search provider', () => { { hasConnectors: false, } as any, - connectors, - false + connectors ); getTestScheduler().run(({ expectObservable }) => { expectObservable( @@ -244,8 +252,7 @@ describe('Search search provider', () => { { hasConnectors: true, } as any, - connectors, - true + connectors ); getTestScheduler().run(({ expectObservable }) => { expectObservable( diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts b/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts index 49fd7d4330187..5d72a6811a7af 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/utils/search_result_provider.ts @@ -12,11 +12,7 @@ import { i18n } from '@kbn/i18n'; import { ConnectorServerSideDefinition } from '@kbn/search-connectors'; import { ConfigType } from '..'; -import { - ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE, - ENTERPRISE_SEARCH_CONTENT_PLUGIN, - AI_SEARCH_PLUGIN, -} from '../../common/constants'; +import { ENTERPRISE_SEARCH_CONTENT_PLUGIN, AI_SEARCH_PLUGIN } from '../../common/constants'; type ServiceDefinition = | ConnectorServerSideDefinition @@ -31,30 +27,18 @@ type ServiceDefinition = export function toSearchResult({ iconPath, - isCloud, - isNative, name, score, serviceType, url, }: { iconPath?: string; - isCloud: boolean; - isNative?: boolean; name: string; score: number; serviceType: string; url?: string; }) { - const isCrawler = serviceType === ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE; - const connectorTypeParam = !isCrawler - ? isCloud && isNative - ? 'native' - : 'connector_client' - : null; - const newUrl = isCrawler - ? `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/crawlers/new_crawler` - : `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/select_connector?connector_type=${connectorTypeParam}&service_type=${serviceType}`; + const newUrl = `${ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL}/connectors/select_connector`; return { icon: iconPath || 'logoEnterpriseSearch', @@ -71,8 +55,7 @@ export function toSearchResult({ export function getSearchResultProvider( config: ConfigType, - connectorTypes: ConnectorServerSideDefinition[], - isCloud: boolean + connectorTypes: ConnectorServerSideDefinition[] ): GlobalSearchResultProvider { return { find: ({ term, types, tags }, { aborted$, maxResults }, { core: { capabilities } }) => { @@ -89,9 +72,8 @@ export function getSearchResultProvider( if (!caps.catalogue.enterpriseSearch) { return []; } - const selfManagedConnectors = connectorTypes.filter((connector) => !connector.isNative); const services: ServiceDefinition[] = [ - ...(config.hasConnectors ? selfManagedConnectors : []), + ...(config.hasConnectors ? connectorTypes : []), { keywords: ['esre', 'search'], @@ -104,7 +86,7 @@ export function getSearchResultProvider( ]; const result = services .map((service) => { - const { isNative, iconPath, name, keywords, serviceType } = service; + const { iconPath, name, keywords, serviceType } = service; const url = 'url' in service ? service.url : undefined; let score = 0; const searchTerm = (term || '').toLowerCase(); @@ -124,8 +106,6 @@ export function getSearchResultProvider( } return toSearchResult({ iconPath, - isCloud, - isNative, name, score, serviceType, diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx index 8c7927887836d..196747533bb4d 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx @@ -20,7 +20,6 @@ import { EuiTextTruncate, EuiBadgeGroup, } from '@elastic/eui'; -import { EuiIconPlugs } from '@kbn/search-shared-ui'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Connector as BaseConnector } from '@kbn/search-connectors'; import { css } from '@emotion/react'; @@ -233,7 +232,7 @@ export const EditServiceType: React.FC = ({ connector, isD connector.service_type ? connectorTypes.find((conn) => conn.serviceType === connector.service_type) ?.iconPath ?? '' - : EuiIconPlugs + : 'plugs' } size="l" /> diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx index 2212d4f4c0efe..97a2a5a60df33 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx @@ -9,11 +9,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiIcon, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ConnectorIcon } from '@kbn/search-shared-ui'; -import { - SearchEmptyPrompt, - DecorativeHorizontalStepper, - EuiIconPlugs, -} from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; import { SERVERLESS_ES_CONNECTORS_ID } from '@kbn/deeplinks-search/constants'; import { BACK_LABEL, COMING_SOON_LABEL } from '../../../../common/i18n_string'; import { useKibanaServices } from '../../hooks/use_kibana'; @@ -35,7 +31,7 @@ export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { label: BACK_LABEL, onClickBack: () => navigateToApp(SERVERLESS_ES_CONNECTORS_ID), }} - icon={EuiIconPlugs} + icon="plugs" title={i18n.translate('xpack.serverlessSearch.elasticManagedConnectorEmpty.title', { defaultMessage: 'Elastic managed connectors', })} @@ -114,7 +110,7 @@ export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx index 90789d913fb2a..6ae33eac16074 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx @@ -12,25 +12,17 @@ import { EuiIcon, EuiLink, EuiButton, - EuiBadge, EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { ConnectorIcon } from '@kbn/search-shared-ui'; -import { - SearchEmptyPrompt, - DecorativeHorizontalStepper, - EuiIconPlugs, -} from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; import { docLinks } from '../../../../common/doc_links'; -import { useKibanaServices } from '../../hooks/use_kibana'; import { useConnectorTypes } from '../../hooks/api/use_connector_types'; import { useCreateConnector } from '../../hooks/api/use_create_connector'; import { useConnectors } from '../../hooks/api/use_connectors'; -import { ELASTIC_MANAGED_CONNECTOR_PATH, BASE_CONNECTORS_PATH } from '../../constants'; -import { BACK_LABEL } from '../../../../common/i18n_string'; export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { const connectorTypes = useConnectorTypes(); @@ -39,13 +31,10 @@ export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { ); const { createConnector, isLoading } = useCreateConnector(); const { data } = useConnectors(); - const { - application: { navigateToUrl }, - } = useKibanaServices(); return ( { justifyContent="center" > - + @@ -184,7 +173,7 @@ export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { - + @@ -230,26 +219,6 @@ export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { })} - - - - - navigateToUrl(`${BASE_CONNECTORS_PATH}/${ELASTIC_MANAGED_CONNECTOR_PATH}`) - } - > - {i18n.translate('xpack.serverlessSearch.connectorsEmpty.elasticManagedButton', { - defaultMessage: 'Elastic managed connector', - })} - - - - {BACK_LABEL} - - -
} /> diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx index 6f6cdb767591b..0c75b87054472 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; import { SERVERLESS_ES_WEB_CRAWLERS_ID } from '@kbn/deeplinks-search/constants'; import { BACK_LABEL, COMING_SOON_LABEL } from '../../../../common/i18n_string'; import { useKibanaServices } from '../../hooks/use_kibana'; @@ -23,7 +23,7 @@ export const ElasticManagedWebCrawlersEmptyPrompt = () => { label: BACK_LABEL, onClickBack: () => navigateToApp(SERVERLESS_ES_WEB_CRAWLERS_ID), }} - icon={EuiIconWeb} + icon="web" title={i18n.translate('xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.title', { defaultMessage: 'Elastic managed web crawlers', })} @@ -87,7 +87,7 @@ export const ElasticManagedWebCrawlersEmptyPrompt = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx index f35664defb113..05377641bbad0 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; import { - EuiBadge, EuiButton, EuiFlexGroup, EuiFlexItem, @@ -16,24 +15,17 @@ import { EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ELASTIC_MANAGED_WEB_CRAWLERS_PATH, BASE_WEB_CRAWLERS_PATH } from '../../constants'; -import { COMING_SOON_LABEL } from '../../../../common/i18n_string'; -import { useKibanaServices } from '../../hooks/use_kibana'; import { useAssetBasePath } from '../../hooks/use_asset_base_path'; export const SelfManagedWebCrawlersEmptyPrompt = () => { - const { - application: { navigateToUrl }, - } = useKibanaServices(); - const assetBasePath = useAssetBasePath(); const githubIcon = assetBasePath + '/github_white.svg'; return ( { justifyContent="center" > - + @@ -157,7 +149,7 @@ export const SelfManagedWebCrawlersEmptyPrompt = () => { - + @@ -202,25 +194,6 @@ export const SelfManagedWebCrawlersEmptyPrompt = () => { })} - - - - - navigateToUrl(`${BASE_WEB_CRAWLERS_PATH}/${ELASTIC_MANAGED_WEB_CRAWLERS_PATH}`) - } - > - {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.elasticManagedButton', { - defaultMessage: 'Elastic managed web crawler', - })} - - - - {COMING_SOON_LABEL} - - - } /> diff --git a/x-pack/solutions/security/packages/distribution_bar/README.md b/x-pack/solutions/security/packages/distribution-bar/README.md similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/README.md rename to x-pack/solutions/security/packages/distribution-bar/README.md diff --git a/x-pack/solutions/security/packages/distribution_bar/index.ts b/x-pack/solutions/security/packages/distribution-bar/index.ts similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/index.ts rename to x-pack/solutions/security/packages/distribution-bar/index.ts diff --git a/x-pack/solutions/security/packages/distribution_bar/jest.config.js b/x-pack/solutions/security/packages/distribution-bar/jest.config.js similarity index 97% rename from x-pack/solutions/security/packages/distribution_bar/jest.config.js rename to x-pack/solutions/security/packages/distribution-bar/jest.config.js index 296ff5369079c..8d577c36568c2 100644 --- a/x-pack/solutions/security/packages/distribution_bar/jest.config.js +++ b/x-pack/solutions/security/packages/distribution-bar/jest.config.js @@ -7,6 +7,6 @@ module.exports = { preset: '@kbn/test', - roots: ['/x-pack/solutions/security/packages/distribution_bar'], + roots: ['/x-pack/solutions/security/packages/distribution-bar'], rootDir: '../../../../..', }; diff --git a/x-pack/solutions/security/packages/distribution_bar/kibana.jsonc b/x-pack/solutions/security/packages/distribution-bar/kibana.jsonc similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/kibana.jsonc rename to x-pack/solutions/security/packages/distribution-bar/kibana.jsonc diff --git a/x-pack/solutions/security/packages/distribution_bar/package.json b/x-pack/solutions/security/packages/distribution-bar/package.json similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/package.json rename to x-pack/solutions/security/packages/distribution-bar/package.json diff --git a/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx b/x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.stories.tsx similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.stories.tsx rename to x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.stories.tsx diff --git a/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.test.tsx b/x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.test.tsx similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.test.tsx rename to x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.test.tsx diff --git a/x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.tsx b/x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.tsx similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/src/distribution_bar.tsx rename to x-pack/solutions/security/packages/distribution-bar/src/distribution_bar.tsx diff --git a/x-pack/solutions/security/packages/distribution_bar/tsconfig.json b/x-pack/solutions/security/packages/distribution-bar/tsconfig.json similarity index 100% rename from x-pack/solutions/security/packages/distribution_bar/tsconfig.json rename to x-pack/solutions/security/packages/distribution-bar/tsconfig.json diff --git a/x-pack/solutions/security/packages/features/src/product_features_keys.ts b/x-pack/solutions/security/packages/features/src/product_features_keys.ts index 7b2849565ca4b..30ea5bd8bc018 100644 --- a/x-pack/solutions/security/packages/features/src/product_features_keys.ts +++ b/x-pack/solutions/security/packages/features/src/product_features_keys.ts @@ -169,6 +169,7 @@ export enum SecuritySubFeatureId { hostIsolationExceptionsBasic = 'hostIsolationExceptionsBasicSubFeature', blocklist = 'blocklistSubFeature', eventFilters = 'eventFiltersSubFeature', + globalArtifactManagement = 'globalArtifactManagementSubFeature', policyManagement = 'policyManagementSubFeature', responseActionsHistory = 'responseActionsHistorySubFeature', workflowInsights = 'workflowInsightsSubFeature', diff --git a/x-pack/solutions/security/packages/features/src/security/product_feature_config.ts b/x-pack/solutions/security/packages/features/src/security/product_feature_config.ts index f6c90a194bd6d..219af9f531a32 100644 --- a/x-pack/solutions/security/packages/features/src/security/product_feature_config.ts +++ b/x-pack/solutions/security/packages/features/src/security/product_feature_config.ts @@ -83,6 +83,7 @@ export const securityDefaultProductFeaturesConfig: DefaultSecurityProductFeature SecuritySubFeatureId.trustedApplications, SecuritySubFeatureId.blocklist, SecuritySubFeatureId.eventFilters, + SecuritySubFeatureId.globalArtifactManagement, ], }, diff --git a/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts index d4a20c92bc74c..d698572ae652e 100644 --- a/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts +++ b/x-pack/solutions/security/packages/features/src/security/v2_features/kibana_sub_features.ts @@ -17,6 +17,21 @@ import { SecuritySubFeatureId } from '../../product_features_keys'; import { APP_ID } from '../../constants'; import type { SecurityFeatureParams } from '../types'; +const TRANSLATIONS = Object.freeze({ + all: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.allPrivilegeName', + { + defaultMessage: 'All', + } + ), + read: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.readPrivilegeName', + { + defaultMessage: 'Read', + } + ), +}); + const endpointListSubFeature = (): SubFeatureConfig => ({ requireAllSpaces: true, privilegesTooltip: i18n.translate( @@ -46,7 +61,7 @@ const endpointListSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeEndpointList`, `${APP_ID}-readEndpointList`], id: 'endpoint_list_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -57,7 +72,7 @@ const endpointListSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-readEndpointList`], id: 'endpoint_list_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -104,7 +119,7 @@ const trustedApplicationsSubFeature = (): SubFeatureConfig => ({ ], id: 'trusted_applications_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], read: [], @@ -115,7 +130,7 @@ const trustedApplicationsSubFeature = (): SubFeatureConfig => ({ api: ['lists-read', 'lists-summary', `${APP_ID}-readTrustedApplications`], id: 'trusted_applications_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -161,7 +176,7 @@ const hostIsolationExceptionsBasicSubFeature = (): SubFeatureConfig => ({ ], id: 'host_isolation_exceptions_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], read: [], @@ -172,7 +187,7 @@ const hostIsolationExceptionsBasicSubFeature = (): SubFeatureConfig => ({ api: ['lists-read', 'lists-summary', `${APP_ID}-readHostIsolationExceptions`], id: 'host_isolation_exceptions_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -215,7 +230,7 @@ const blocklistSubFeature = (): SubFeatureConfig => ({ ], id: 'blocklist_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], read: [], @@ -226,7 +241,7 @@ const blocklistSubFeature = (): SubFeatureConfig => ({ api: ['lists-read', 'lists-summary', `${APP_ID}-readBlocklist`], id: 'blocklist_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -272,7 +287,7 @@ const eventFiltersSubFeature = (): SubFeatureConfig => ({ ], id: 'event_filters_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [EXCEPTION_LIST_NAMESPACE_AGNOSTIC], read: [], @@ -283,7 +298,7 @@ const eventFiltersSubFeature = (): SubFeatureConfig => ({ api: ['lists-read', 'lists-summary', `${APP_ID}-readEventFilters`], id: 'event_filters_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -323,7 +338,7 @@ const policyManagementSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writePolicyManagement`, `${APP_ID}-readPolicyManagement`], id: 'policy_management_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: ['policy-settings-protection-updates-note'], read: [], @@ -334,7 +349,7 @@ const policyManagementSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-readPolicyManagement`], id: 'policy_management_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: ['policy-settings-protection-updates-note'], @@ -374,7 +389,7 @@ const responseActionsHistorySubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeActionsLogManagement`, `${APP_ID}-readActionsLogManagement`], id: 'actions_log_management_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -385,7 +400,7 @@ const responseActionsHistorySubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-readActionsLogManagement`], id: 'actions_log_management_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -422,7 +437,7 @@ const hostIsolationSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeHostIsolationRelease`], id: 'host_isolation_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -462,7 +477,7 @@ const processOperationsSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeProcessOperations`], id: 'process_operations_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -501,7 +516,7 @@ const fileOperationsSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeFileOperations`], id: 'file_operations_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -543,7 +558,7 @@ const executeActionSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeExecuteOperations`], id: 'execute_operations_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -584,7 +599,7 @@ const scanActionSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeScanOperations`], id: 'scan_operations_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -625,7 +640,7 @@ const workflowInsightsSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-writeWorkflowInsights`, `${APP_ID}-readWorkflowInsights`], id: 'workflow_insights_all', includeIn: 'none', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -636,7 +651,7 @@ const workflowInsightsSubFeature = (): SubFeatureConfig => ({ api: [`${APP_ID}-readWorkflowInsights`], id: 'workflow_insights_read', includeIn: 'none', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -675,7 +690,7 @@ const endpointExceptionsSubFeature = (): SubFeatureConfig => ({ { id: 'endpoint_exceptions_all', includeIn: 'all', - name: 'All', + name: TRANSLATIONS.all, savedObject: { all: [], read: [], @@ -685,7 +700,7 @@ const endpointExceptionsSubFeature = (): SubFeatureConfig => ({ { id: 'endpoint_exceptions_read', includeIn: 'read', - name: 'Read', + name: TRANSLATIONS.read, savedObject: { all: [], read: [], @@ -697,6 +712,44 @@ const endpointExceptionsSubFeature = (): SubFeatureConfig => ({ ], }); +const globalArtifactManagementSubFeature = (): SubFeatureConfig => ({ + requireAllSpaces: false, + privilegesTooltip: undefined, + name: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.globalArtifactManagement', + { + defaultMessage: 'Global Artifact Management', + } + ), + description: i18n.translate( + 'securitySolutionPackages.features.featureRegistry.subFeatures.globalArtifactManagement.description', + { + defaultMessage: + 'Manage global assignment of endpoint artifacts (e.g., Trusted Applications, Event Filters) ' + + 'across all policies. This privilege controls global assignment rights only; privileges for each ' + + 'artifact type are required for full artifact management.', + } + ), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [`${APP_ID}-writeGlobalArtifacts`], + id: 'global_artifact_management_all', + includeIn: 'none', + name: TRANSLATIONS.all, + savedObject: { + all: [], + read: [], + }, + ui: ['writeGlobalArtifacts'], + }, + ], + }, + ], +}); + /** * Sub-features that will always be available for Security * regardless of the product type. @@ -728,6 +781,16 @@ export const getSecurityV2SubFeaturesMap = ({ SecuritySubFeatureId.endpointExceptions, enableSpaceAwarenessIfNeeded(endpointExceptionsSubFeature()), ], + + ...((experimentalFeatures.endpointManagementSpaceAwarenessEnabled + ? [ + [ + SecuritySubFeatureId.globalArtifactManagement, + enableSpaceAwarenessIfNeeded(globalArtifactManagementSubFeature()), + ], + ] + : []) as Array<[SecuritySubFeatureId, SubFeatureConfig]>), + [ SecuritySubFeatureId.trustedApplications, enableSpaceAwarenessIfNeeded(trustedApplicationsSubFeature()), @@ -738,6 +801,7 @@ export const getSecurityV2SubFeaturesMap = ({ ], [SecuritySubFeatureId.blocklist, enableSpaceAwarenessIfNeeded(blocklistSubFeature())], [SecuritySubFeatureId.eventFilters, enableSpaceAwarenessIfNeeded(eventFiltersSubFeature())], + [ SecuritySubFeatureId.policyManagement, enableSpaceAwarenessIfNeeded(policyManagementSubFeature()), diff --git a/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/.storybook/main.ts b/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/.storybook/main.ts index b5e6c436a29b6..2936cad4c0ddb 100644 --- a/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/.storybook/main.ts +++ b/x-pack/solutions/security/packages/kbn-cloud-security-posture/graph/.storybook/main.ts @@ -18,11 +18,11 @@ const graphWebpack: Configuration = { '../src/components/mock/use_fetch_graph_data.mock.ts' ), }, - }, - node: { - fs: 'empty', - stream: false, - os: false, + fallback: { + fs: false, + stream: false, + os: false, + }, }, }; diff --git a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap index f814be75fa63e..fa4757c76f1a1 100644 --- a/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap +++ b/x-pack/solutions/security/packages/kbn-securitysolution-exception-list-components/src/exception_item_card/conditions/entry_content/__snapshots__/entry_content.test.tsx.snap @@ -13,7 +13,7 @@ exports[`EntryContent should render a nested value 1`] = ` data-test-subj="EntryContentNestedEntry" > : diff --git a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx index 65383d9a441aa..004b24f367dc9 100644 --- a/x-pack/solutions/security/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx +++ b/x-pack/solutions/security/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx @@ -63,7 +63,6 @@ import { import { usePackagePolicyList } from '../../common/api/use_package_policy_list'; import { GCP_CREDENTIALS_TYPE, - GCP_SETUP_ACCESS, gcpField, getInputVarsFields, } from './gcp_credentials_form/gcp_credential_form'; @@ -727,7 +726,7 @@ export const CspPolicyTemplateForm = memo { }); it('should execute func correctly and return expected results', async () => { + (isString as unknown as jest.Mock).mockReturnValue(true); const mockSearchResult = { hits: { hits: [ @@ -177,6 +175,7 @@ describe('getStructuredToolForIndexEntry', () => { _index: 'exampleIndex', _id: 'exampleId', _source: { + '@timestamp': '2021-01-01T00:00:00.000Z', field1: 'value1', field2: 2, }, @@ -200,10 +199,14 @@ describe('getStructuredToolForIndexEntry', () => { (contentReferencesStore.add as jest.Mock).mockImplementation( (creator: Parameters[0]) => { const reference = creator({ id: 'exampleContentReferenceId' }); - expect(reference.type).toEqual('EsqlQuery'); - expect((reference as EsqlContentReference).label).toEqual('exampleIndex'); - expect((reference as EsqlContentReference).query).toEqual( - 'FROM exampleIndex METADATA _id\n | WHERE _id == "exampleId"' + expect(reference).toEqual( + expect.objectContaining({ + id: 'exampleContentReferenceId', + type: 'EsqlQuery', + label: 'Index: exampleIndex', + query: 'FROM exampleIndex METADATA _id\n | WHERE _id == "exampleId"', + timerange: { from: '2021-01-01T00:00:00.000Z', to: '2021-01-01T00:00:00.000Z' }, + }) ); return reference; } diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/helpers.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/helpers.ts index 174fd1c6d923b..ab03e525c27fe 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/helpers.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/ai_assistant_data_clients/knowledge_base/helpers.ts @@ -8,7 +8,11 @@ import { z } from '@kbn/zod'; import { DynamicStructuredTool } from '@langchain/core/tools'; import { errors } from '@elastic/elasticsearch'; -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import { + QueryDslQueryContainer, + SearchHit, + SearchRequest, +} from '@elastic/elasticsearch/lib/api/types'; import { AuthenticatedUser } from '@kbn/core-security-common'; import { contentReferenceBlock, @@ -17,6 +21,7 @@ import { IndexEntry, } from '@kbn/elastic-assistant-common'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { isString } from 'lodash'; export const isModelAlreadyExistsError = (error: Error) => { return ( @@ -217,13 +222,8 @@ export const getStructuredToolForIndexEntry = ({ const result = await esClient.search(params); const kbDocs = result.hits.hits.map((hit) => { - const esqlQuery = `FROM ${hit._index} ${ - hit._id ? `METADATA _id\n | WHERE _id == "${hit._id}"` : '' - }`; - const reference = - contentReferencesStore && - contentReferencesStore.add((p) => esqlQueryReference(p.id, esqlQuery, hit._index)); + contentReferencesStore && contentReferencesStore.add((p) => createReference(p.id, hit)); if (indexEntry.outputFields && indexEntry.outputFields.length > 0) { return indexEntry.outputFields.reduce( @@ -257,3 +257,23 @@ export const getStructuredToolForIndexEntry = ({ // TODO: Remove after ZodAny is fixed https://github.com/langchain-ai/langchainjs/blob/main/langchain-core/src/tools.ts }) as unknown as DynamicStructuredTool; }; + +const createReference = (id: string, hit: SearchHit) => { + const hitIndex = hit._index; + const hitId = hit._id; + const esqlQuery = `FROM ${hitIndex} ${hitId ? `METADATA _id\n | WHERE _id == "${hitId}"` : ''}`; + + let timerange; + const source = hit._source as Record; + + if ('@timestamp' in source && isString(source['@timestamp']) && hitId) { + timerange = { from: source['@timestamp'], to: source['@timestamp'] }; + } + + return esqlQueryReference({ + id, + query: esqlQuery, + label: `Index: ${hit._index}`, + timerange, + }); +}; diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts index af478ef04ac03..dd39e650f2bf5 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts @@ -7,7 +7,7 @@ export const KNOWLEDGE_HISTORY = 'If available, use the Knowledge History provided to try and answer the question. If not provided, you can try and query for additional knowledge via the KnowledgeBaseRetrievalTool.'; -export const INCLUDE_CITATIONS = `\n\nAnnotate your answer with relevant citations. For example: "The sky is blue. {reference(prSit)}"\n\n`; +export const INCLUDE_CITATIONS = `\n\nAnnotate your answer with relevant citations. Here are some example responses with citations: \n1. "Machine learning is increasingly used in cyber threat detection. {reference(prSit)}" \n2. "The alert has a risk score of 72. {reference(OdRs2)}"\n\nOnly use the citations returned by tools\n\n`; export const DEFAULT_SYSTEM_PROMPT = `You are a security analyst and expert in resolving security incidents. Your role is to assist by answering questions about Elastic Security. Do not answer questions unrelated to Elastic Security. ${KNOWLEDGE_HISTORY} {include_citations_prompt_placeholder}`; // system prompt from @afirstenberg const BASE_GEMINI_PROMPT = diff --git a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts index 8b0fa71f2222f..be683e3ec6ca9 100644 --- a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts +++ b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.ts @@ -14,7 +14,7 @@ import { nullableMetaOrUndefined, serializerOrUndefined, tie_breaker_id, - timestampOrUndefined, + timestampFromEsResponse, updated_at, updated_by, } from '@kbn/securitysolution-io-ts-list-types'; @@ -47,7 +47,7 @@ import { export const searchEsListItemSchema = t.exact( t.type({ - '@timestamp': timestampOrUndefined, + '@timestamp': timestampFromEsResponse, binary: binaryOrUndefined, boolean: booleanOrUndefined, byte: byteOrUndefined, diff --git a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts index 1d4b282d5352a..00ce8b58d7e0a 100644 --- a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts +++ b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts @@ -41,7 +41,9 @@ export const getSearchEsListMock = (): SearchEsListSchema => ({ version: VERSION, }); -export const getSearchListMock = (): estypes.SearchResponse => ({ +export const getSearchListMock = ( + source?: SearchEsListSchema +): estypes.SearchResponse => ({ _scroll_id: '123', _shards: getShardMock(), hits: { @@ -50,7 +52,7 @@ export const getSearchListMock = (): estypes.SearchResponse _id: LIST_ID, _index: LIST_INDEX, _score: 0, - _source: getSearchEsListMock(), + _source: source || getSearchEsListMock(), }, ], max_score: 0, diff --git a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts index 17d2e64fb7542..93ae1cb1ce6f9 100644 --- a/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts +++ b/x-pack/solutions/security/plugins/lists/server/schemas/elastic_response/search_es_list_schema.ts @@ -16,7 +16,7 @@ import { nullableMetaOrUndefined, serializerOrUndefined, tie_breaker_id, - timestampOrUndefined, + timestampFromEsResponse, type, updated_at, updated_by, @@ -25,7 +25,7 @@ import { version } from '@kbn/securitysolution-io-ts-types'; export const searchEsListSchema = t.exact( t.type({ - '@timestamp': timestampOrUndefined, + '@timestamp': timestampFromEsResponse, created_at, created_by, description, diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/convert_date_number_to_string.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/convert_date_number_to_string.ts new file mode 100644 index 0000000000000..ca105834456ca --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/convert_date_number_to_string.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * if date field is number, converts it to ISO string + */ +export const convertDateNumberToString = ( + dateValue: string | number | undefined +): string | undefined => { + if (typeof dateValue === 'number') { + return new Date(dateValue).toISOString(); + } + return dateValue; +}; diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts index 5d03c8f6707b3..959c5478bbc95 100644 --- a/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/find_source_value.ts @@ -79,7 +79,7 @@ export const deserializeValue = ({ deserializer: DeserializerOrUndefined; defaultValueDeserializer: string; defaultDeserializer: string; - value: string | object | undefined; + value: string | object | number | undefined; }): string | null => { if (esDataTypeRange.is(value)) { const template = diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.test.ts new file mode 100644 index 0000000000000..b6fde32050dd1 --- /dev/null +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + getSearchEsListMock, + getSearchListMock, +} from '../../schemas/elastic_response/search_es_list_schema.mock'; + +import { transformElasticToList } from './transform_elastic_to_list'; +describe('transformElasticToList', () => { + test('does not change timestamp in string format', () => { + const response = getSearchListMock({ + ...getSearchEsListMock(), + '@timestamp': '2020-04-20T15:25:31.830Z', + }); + + const result = transformElasticToList({ + response, + }); + + expect(result[0]['@timestamp']).toBe('2020-04-20T15:25:31.830Z'); + }); + test('converts timestamp from number format to ISO string', () => { + const response = getSearchListMock({ ...getSearchEsListMock(), '@timestamp': 0 }); + + const result = transformElasticToList({ + response, + }); + + expect(result[0]['@timestamp']).toBe('1970-01-01T00:00:00.000Z'); + }); +}); diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts index e5e917a147ac9..8247f5281d6ee 100644 --- a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list.ts @@ -11,6 +11,8 @@ import { encodeHitVersion } from '@kbn/securitysolution-es-utils'; import { SearchEsListSchema } from '../../schemas/elastic_response'; +import { convertDateNumberToString } from './convert_date_number_to_string'; + export interface TransformElasticToListOptions { response: estypes.SearchResponse; } @@ -24,6 +26,7 @@ export const transformElasticToList = ({ _version: encodeHitVersion(hit), id: hit._id, ...hit._source, + '@timestamp': convertDateNumberToString(hit._source?.['@timestamp']), // meta can be null if deleted (empty in PUT payload), since update_by_query set deleted values as null // return it as undefined to keep it consistent with payload meta: hit._source?.meta ?? undefined, diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts index e2ec36e533bd1..797cff33cda53 100644 --- a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.test.ts @@ -8,7 +8,10 @@ import type { ListItemArraySchema } from '@kbn/securitysolution-io-ts-list-types'; import { getListItemResponseMock } from '../../../common/schemas/response/list_item_schema.mock'; -import { getSearchListItemMock } from '../../schemas/elastic_response/search_es_list_item_schema.mock'; +import { + getSearchEsListItemMock, + getSearchListItemMock, +} from '../../schemas/elastic_response/search_es_list_item_schema.mock'; import { transformElasticHitsToListItem, @@ -84,5 +87,32 @@ describe('transform_elastic_to_list_item', () => { const expected: ListItemArraySchema = [listItemResponse]; expect(queryFilter).toEqual(expected); }); + + test('converts timestamp from number format to ISO string', () => { + const hits = [{ _index: 'test', _source: { ...getSearchEsListItemMock(), '@timestamp': 0 } }]; + + const result = transformElasticHitsToListItem({ + hits, + type: 'keyword', + }); + + expect(result[0]['@timestamp']).toBe('1970-01-01T00:00:00.000Z'); + }); + + test('converts negative from number timestamp to ISO string', () => { + const hits = [ + { + _index: 'test', + _source: { ...getSearchEsListItemMock(), '@timestamp': -63549289600000 }, + }, + ]; + + const result = transformElasticHitsToListItem({ + hits, + type: 'keyword', + }); + + expect(result[0]['@timestamp']).toBe('-000044-03-15T19:33:20.000Z'); + }); }); }); diff --git a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts index a41a78a6b8fed..060f4fa279681 100644 --- a/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts +++ b/x-pack/solutions/security/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts @@ -13,6 +13,7 @@ import { ErrorWithStatusCode } from '../../error_with_status_code'; import { SearchEsListItemSchema } from '../../schemas/elastic_response'; import { findSourceValue } from './find_source_value'; +import { convertDateNumberToString } from './convert_date_number_to_string'; export interface TransformElasticToListItemOptions { response: estypes.SearchResponse; @@ -56,7 +57,7 @@ export const transformElasticHitsToListItem = ({ throw new ErrorWithStatusCode(`Was expected ${type} to not be null/undefined`, 400); } else { return { - '@timestamp': _source?.['@timestamp'], + '@timestamp': convertDateNumberToString(_source?.['@timestamp']), _version: encodeHitVersion(hit), created_at, created_by, diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/log_level.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/log_level.ts index e7004455160bd..c66dada55adff 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/log_level.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/log_level.ts @@ -53,7 +53,7 @@ export const logLevelFromNumber = (num: number | null | undefined): LogLevel => return LogLevelEnum.error; }; -export const logLevelFromExecutionStatus = (status: RuleExecutionStatus): LogLevel => { +export const eventLogLevelFromExecutionStatus = (status: RuleExecutionStatus): LogLevel => { switch (status) { case RuleExecutionStatusEnum['going to run']: case RuleExecutionStatusEnum.running: @@ -68,3 +68,13 @@ export const logLevelFromExecutionStatus = (status: RuleExecutionStatus): LogLev return LogLevelEnum.trace; } }; + +export const consoleLogLevelFromExecutionStatus = ( + status: RuleExecutionStatus, + userError?: boolean +): LogLevel => { + if (!userError && status === RuleExecutionStatusEnum.failed) { + return LogLevelEnum.error; + } + return LogLevelEnum.debug; +}; diff --git a/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.test.ts b/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.test.ts index b1d8024bd107d..4a878669c6f61 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.test.ts @@ -21,40 +21,18 @@ describe('utils', () => { }); describe('getDisabledEntityTypes', () => { - it('should return disabled entity types when serviceEntityStoreEnabled is false', () => { - const experimentalFeatures: ExperimentalFeatures = { - ...mockedExperimentalFeatures, - serviceEntityStoreEnabled: false, - assetInventoryStoreEnabled: true, - }; - const disabledEntityTypes = getDisabledEntityTypes(experimentalFeatures); - expect(disabledEntityTypes).toEqual([EntityType.service]); - }); - it('should return disabled entity types when assetInventoryStoreEnabled is false', () => { const experimentalFeatures: ExperimentalFeatures = { ...mockedExperimentalFeatures, - serviceEntityStoreEnabled: true, assetInventoryStoreEnabled: false, }; const disabledEntityTypes = getDisabledEntityTypes(experimentalFeatures); expect(disabledEntityTypes).toEqual([EntityType.universal]); }); - it('should return both disabled entity types when both features are false', () => { - const experimentalFeatures: ExperimentalFeatures = { - ...mockedExperimentalFeatures, - serviceEntityStoreEnabled: false, - assetInventoryStoreEnabled: false, - }; - const disabledEntityTypes = getDisabledEntityTypes(experimentalFeatures); - expect(disabledEntityTypes).toEqual([EntityType.service, EntityType.universal]); - }); - it('should return no disabled entity types when both features are true', () => { const experimentalFeatures: ExperimentalFeatures = { ...mockedExperimentalFeatures, - serviceEntityStoreEnabled: true, assetInventoryStoreEnabled: true, }; const disabledEntityTypes = getDisabledEntityTypes(experimentalFeatures); diff --git a/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.ts b/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.ts index 74299eacc0afe..062f0909b0231 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/entity_analytics/utils.ts @@ -13,13 +13,8 @@ export const getDisabledEntityTypes = ( experimentalFeatures: ExperimentalFeatures ): EntityType[] => { const disabledEntityTypes: EntityType[] = []; - const isServiceEntityStoreEnabled = experimentalFeatures.serviceEntityStoreEnabled; const isUniversalEntityStoreEnabled = experimentalFeatures.assetInventoryStoreEnabled; - if (!isServiceEntityStoreEnabled) { - disabledEntityTypes.push(EntityType.service); - } - if (!isUniversalEntityStoreEnabled) { disabledEntityTypes.push(EntityType.universal); } diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/rule_customization.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_customization.md similarity index 67% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/rule_customization.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_customization.md index 4579a457f0eb4..e98a45d00c32d 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/rule_customization.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_customization.md @@ -1,8 +1,54 @@ -# Prebuilt Rule Customization Workflows - -This is a test plan for rule customization workflows specifically related to prebuilt rules - -Status: `in progress`. +# Test plan: customizing prebuilt rules + +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). + +## Summary + +This is a test plan for the workflows of customizing prebuilt rules via: + +- editing single rules one-by-one on the Rule Editing page: + - initiated from the Rule Details page + - initiated from the Rule Management page +- editing multiple rules in bulk on the Rule Management page via bulk actions, such as: + - bulk adding or removing index patterns + - bulk updating rule schedule + +as well as un-customizing prebuilt rules by reverting rule parameters back to their original values. + +## Table of contents + + + +- [Useful information](#useful-information) + - [Tickets](#tickets) + - [Terminology](#terminology) + - [Assumptions](#assumptions) +- [Scenarios](#scenarios) + - [Editing prebuilt rules](#editing-prebuilt-rules) + - [**Scenario: User can edit a non-customized prebuilt rule from the rule edit page**](#scenario-user-can-edit-a-non-customized-prebuilt-rule-from-the-rule-edit-page) + - [**Scenario: User can edit a customized prebuilt rule from the rule edit page**](#scenario-user-can-edit-a-customized-prebuilt-rule-from-the-rule-edit-page) + - [**Scenario: User can navigate to rule editing page from the rule details page**](#scenario-user-can-navigate-to-rule-editing-page-from-the-rule-details-page) + - [**Scenario: User can navigate to rule editing page from the rule management page**](#scenario-user-can-navigate-to-rule-editing-page-from-the-rule-management-page) + - [**Scenario: User can bulk edit prebuilt rules from rules management page**](#scenario-user-can-bulk-edit-prebuilt-rules-from-rules-management-page) + - [Detecting rule customizations](#detecting-rule-customizations) + - [**Scenario: is\_customized is set to true when user edits a customizable rule field**](#scenario-is_customized-is-set-to-true-when-user-edits-a-customizable-rule-field) + - [**Scenario: is\_customized calculation is not affected by specific fields**](#scenario-is_customized-calculation-is-not-affected-by-specific-fields) + - [**Scenario: User cannot change non-customizable rule fields on prebuilt rules**](#scenario-user-cannot-change-non-customizable-rule-fields-on-prebuilt-rules) + - [**Scenario: User can revert a customized prebuilt rule to its original state**](#scenario-user-can-revert-a-customized-prebuilt-rule-to-its-original-state) + - [Calculating the Modified badge in the UI](#calculating-the-modified-badge-in-the-ui) + - [**Scenario: Modified badge should appear on the rule details page when prebuilt rule is customized**](#scenario-modified-badge-should-appear-on-the-rule-details-page-when-prebuilt-rule-is-customized) + - [**Scenario: Modified badge should not appear on the rule details page when prebuilt rule isn't customized**](#scenario-modified-badge-should-not-appear-on-the-rule-details-page-when-prebuilt-rule-isnt-customized) + - [**Scenario: Modified badge should not appear on a custom rule's rule details page**](#scenario-modified-badge-should-not-appear-on-a-custom-rules-rule-details-page) + - [**Scenario: Modified badge should appear on the rule management table when prebuilt rule is modified**](#scenario-modified-badge-should-appear-on-the-rule-management-table-when-prebuilt-rule-is-modified) + - [**Scenario: Modified badge should not appear on the rule management table when prebuilt rule isn't customized**](#scenario-modified-badge-should-not-appear-on-the-rule-management-table-when-prebuilt-rule-isnt-customized) + - [**Scenario: Modified badge should not appear on the rule management table when row is a custom rule**](#scenario-modified-badge-should-not-appear-on-the-rule-management-table-when-row-is-a-custom-rule) + - [**Scenario: Modified badge should appear on the rule updates table when prebuilt rule is customized**](#scenario-modified-badge-should-appear-on-the-rule-updates-table-when-prebuilt-rule-is-customized) + - [**Scenario: Modified badge should not appear on the rule updates table when prebuilt rule isn't customized**](#scenario-modified-badge-should-not-appear-on-the-rule-updates-table-when-prebuilt-rule-isnt-customized) + - [**Scenario: User should be able to see only customized rules in the rule updates table**](#scenario-user-should-be-able-to-see-only-customized-rules-in-the-rule-updates-table) + - [**Scenario: User should be able to filter by non-customized rules on the rule updates table**](#scenario-user-should-be-able-to-filter-by-non-customized-rules-on-the-rule-updates-table) ## Useful information diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_export.md similarity index 69% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_export.md index 3c9527a7329c9..c42e649cddc07 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/exporting.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_export.md @@ -1,8 +1,42 @@ -# Detection Rule Export +# Test plan: exporting prebuilt rules -This is a test plan for the exporting of prebuilt and custom rules. This feature is an aspect of `Milestone 3` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). -Status: `in progress`. +## Summary + +This is a test plan for the workflows of: + +- exporting single prebuilt rules from the Rule Details page +- exporting single prebuilt rules one-by-one from the Rule Management page +- exporting multiple prebuilt rules in bulk from the Rule Management page +- exporting a mixture of prebuilt and custom rules from the Rule Management page + +where each prebuilt rule: + +- can be an original (non-customized) prebuilt rule from Elastic, or +- can be a prebuilt rule customized by the user. + +## Table of contents + + + +- [Useful information](#useful-information) + - [Tickets](#tickets) + - [Terminology](#terminology) +- [Scenarios](#scenarios) + - [Core Functionality](#core-functionality) + - [Scenario: Exporting prebuilt rule individually from rule details page](#scenario-exporting-prebuilt-rule-individually-from-rule-details-page) + - [Scenario: Exporting custom rule individually from rule details page](#scenario-exporting-custom-rule-individually-from-rule-details-page) + - [Scenario: Exporting prebuilt rule individually from rules management table](#scenario-exporting-prebuilt-rule-individually-from-rules-management-table) + - [Scenario: Exporting custom rule individually from rules management table](#scenario-exporting-custom-rule-individually-from-rules-management-table) + - [Scenario: Exporting prebuilt rules in bulk](#scenario-exporting-prebuilt-rules-in-bulk) + - [Scenario: Exporting custom rules in bulk](#scenario-exporting-custom-rules-in-bulk) + - [Scenario: Exporting both prebuilt and custom rules in bulk](#scenario-exporting-both-prebuilt-and-custom-rules-in-bulk) + - [Error Handling](#error-handling) + - [Scenario: Exporting beyond the export limit](#scenario-exporting-beyond-the-export-limit) ## Useful information diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_import.md similarity index 66% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_import.md index b1765b948e6fd..2e61b731efbf0 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/importing.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_import.md @@ -1,8 +1,43 @@ -# Detections Rule Import - -This is a test plan for the importing of prebuilt and custom rules. This feature is an aspect of `Milestone 3` of the [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic. - -Status: `in progress`. +# Test plan: importing prebuilt rules + +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). + +## Summary + +This is a test plan for the workflows of: + +- importing prebuilt non-customized rules +- importing prebuilt customized rules +- importing any mixture of prebuilt and custom rules + +from the Rule Management page. + +## Table of contents + + + +- [Useful information](#useful-information) + - [Tickets](#tickets) + - [Terminology](#terminology) +- [Scenarios](#scenarios) + - [Core Functionality](#core-functionality) + - [Scenario: Importing an unmodified prebuilt rule with a matching rule\_id and version](#scenario-importing-an-unmodified-prebuilt-rule-with-a-matching-rule_id-and-version) + - [Scenario: Importing a customized prebuilt rule with a matching rule\_id and version](#scenario-importing-a-customized-prebuilt-rule-with-a-matching-rule_id-and-version) + - [Scenario: Importing a custom rule with a matching rule\_id and version](#scenario-importing-a-custom-rule-with-a-matching-rule_id-and-version) + - [Scenario: Importing a prebuilt rule with a matching rule\_id but no matching version](#scenario-importing-a-prebuilt-rule-with-a-matching-rule_id-but-no-matching-version) + - [Scenario: Importing a prebuilt rule with a non-existent rule\_id](#scenario-importing-a-prebuilt-rule-with-a-non-existent-rule_id) + - [Scenario: Importing a prebuilt rule without a rule\_id field](#scenario-importing-a-prebuilt-rule-without-a-rule_id-field) + - [Scenario: Importing a prebuilt rule with a matching rule\_id but missing a version field](#scenario-importing-a-prebuilt-rule-with-a-matching-rule_id-but-missing-a-version-field) + - [Scenario: Importing an existing custom rule missing a version field](#scenario-importing-an-existing-custom-rule-missing-a-version-field) + - [Scenario: Importing a new custom rule missing a version field](#scenario-importing-a-new-custom-rule-missing-a-version-field) + - [Scenario: Importing a rule with overwrite flag set to true](#scenario-importing-a-rule-with-overwrite-flag-set-to-true) + - [Scenario: Importing a rule with overwrite flag set to false](#scenario-importing-a-rule-with-overwrite-flag-set-to-false) + - [Scenario: Importing both custom and prebuilt rules](#scenario-importing-both-custom-and-prebuilt-rules) + - [Scenario: Importing prebuilt rules when the rules package is not installed](#scenario-importing-prebuilt-rules-when-the-rules-package-is-not-installed) + - [Scenario: User imports a custom rule before a prebuilt rule asset is created with the same rule\_id](#scenario-user-imports-a-custom-rule-before-a-prebuilt-rule-asset-is-created-with-the-same-rule_id) ## Useful information diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_installation.md similarity index 96% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_installation.md index 6f91d4958650c..128e90042f395 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_installation.md @@ -1,10 +1,22 @@ -# Installation of Prebuilt Rules +# Test plan: installing prebuilt rules -This is a test plan for the workflows of installing prebuilt rules. +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). -Status: `in progress`. The current test plan matches [Rule Immutability/Customization Milestone 3 epic](https://github.com/elastic/kibana/issues/174168). +## Summary -## Table of Contents +This is a test plan for the workflows of: + +- installing single prebuilt rules one-by-one +- installing multiple prebuilt rules in bulk + +from the Rule Installation page. + +## Table of contents + + - [Useful information](#useful-information) - [Tickets](#tickets) @@ -13,7 +25,7 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz - [Non-functional requirements](#non-functional-requirements) - [Functional requirements](#functional-requirements) - [Scenarios](#scenarios) - - [Rule installation notifications on the Rule Management page](#rule-installation-and-upgrade-notifications-on-the-rule-management-page) + - [Rule installation notifications on the Rule Management page](#rule-installation-notifications-on-the-rule-management-page) - [**Scenario: User is NOT notified when no prebuilt rules are installed and there are no prebuilt rules assets**](#scenario-user-is-not-notified-when-no-prebuilt-rules-are-installed-and-there-are-no-prebuilt-rules-assets) - [**Scenario: User is NOT notified when all prebuilt rules are installed and up to date**](#scenario-user-is-not-notified-when-all-prebuilt-rules-are-installed-and-up-to-date) - [**Scenario: User is notified when no prebuilt rules are installed and there are rules available to install**](#scenario-user-is-notified-when-no-prebuilt-rules-are-installed-and-there-are-rules-available-to-install) @@ -28,17 +40,17 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz - [**Scenario: User can preview rules available for installation**](#scenario-user-can-preview-rules-available-for-installation) - [**Scenario: User can install a rule using the rule preview**](#scenario-user-can-install-a-rule-using-the-rule-preview) - [**Scenario: User can see correct rule information in preview before installing**](#scenario-user-can-see-correct-rule-information-in-preview-before-installing) - - [**Scenario: Tabs and sections without content should be hidden in preview before installing**](#scenario-tabs-and-sections-without-content-should-be-hidden-in-preview-before-installing) + - [**Scenario: Optional tabs and sections without content should be hidden in preview before installing**](#scenario-optional-tabs-and-sections-without-content-should-be-hidden-in-preview-before-installing) - [Rule installation workflow: filtering, sorting, pagination](#rule-installation-workflow-filtering-sorting-pagination) - [Rule installation workflow: misc cases](#rule-installation-workflow-misc-cases) - [**Scenario: User opening the Add Rules page sees a loading skeleton until the package installation is completed**](#scenario-user-opening-the-add-rules-page-sees-a-loading-skeleton-until-the-package-installation-is-completed) - [**Scenario: User can navigate from the Add Rules page to the Rule Management page via breadcrumbs**](#scenario-user-can-navigate-from-the-add-rules-page-to-the-rule-management-page-via-breadcrumbs) - - [Rule installation and upgrade via the Prebuilt rules API](#rule-installation-and-upgrade-via-the-prebuilt-rules-api) + - [Rule installation via the Prebuilt rules API](#rule-installation-via-the-prebuilt-rules-api) - [**Scenario: API can install all prebuilt rules**](#scenario-api-can-install-all-prebuilt-rules) - [**Scenario: API can install prebuilt rules that are not yet installed**](#scenario-api-can-install-prebuilt-rules-that-are-not-yet-installed) - - [**Scenario: API does not install prebuilt rules if they are up to date**](#scenario-api-does-not-installupgrade-prebuilt-rules-if-they-are-up-to-date) + - [**Scenario: API does not install prebuilt rules if they are up to date**](#scenario-api-does-not-install-prebuilt-rules-if-they-are-up-to-date) - [Error handling](#error-handling) - - [**Scenario: Error is handled when any operation on prebuilt rules fails**](#scenario-error-is-handled-when-any-operation-on-prebuilt-rules-fails) + - [**Scenario: Error is handled when any installation operation on prebuilt rules fails**](#scenario-error-is-handled-when-any-installation-operation-on-prebuilt-rules-fails) - [Authorization / RBAC](#authorization--rbac) - [**Scenario: User with read privileges on Security Solution cannot install prebuilt rules**](#scenario-user-with-read-privileges-on-security-solution-cannot-install-prebuilt-rules) diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade_review_algorithms.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_diff_algorithms.md similarity index 98% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade_review_algorithms.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_diff_algorithms.md index c4a39a994144f..0db233c3fb357 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade_review_algorithms.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_diff_algorithms.md @@ -1,19 +1,25 @@ -# Diff Algorithms for `upgrade/_review` Endpoint +# Test plan: diff algorithms for upgrading prebuilt rules -This is a test plan for the `upgrade/_review` endpoint diff algorithms that are a part of the larger prebuilt rules customization feature. These algorithms determine what fields get returned when a user makes an API request to review changes as a part of the rule update process and determine what version of those fields should be displayed by the UI. +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). -Status: `in progress`. +## Summary -## Table of Contents +This is a test plan for the diff algorithms used in the workflows of upgrading prebuilt rules and specifically in the `upgrade/_review` endpoint. + +These algorithms determine what fields get returned when a user makes an API request to review changes as a part of the rule upgrade process and determine what version of those fields should be displayed by the UI. + +## Table of contents + + - [Useful information](#useful-information) - [Tickets](#tickets) - [Terminology](#terminology) - [Assumptions](#assumptions) - - [Non-functional requirements](#non-functional-requirements) - - [Functional requirements](#functional-requirements) - [Scenarios](#scenarios) - - [Rule field doesn't have an update and has no custom value - `AAA`](#rule-field-doesnt-have-an-update-and-has-no-custom-value---aaa) - [**Scenario: `AAA` - Rule field is any type**](#scenario-aaa---rule-field-is-any-type) - [Rule field doesn't have an update but has a custom value - `ABA`](#rule-field-doesnt-have-an-update-but-has-a-custom-value---aba) diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_with_preview.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_with_preview.md new file mode 100644 index 0000000000000..31f36d86ed773 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_with_preview.md @@ -0,0 +1,712 @@ +# Test plan: upgrading prebuilt rules one-by-one with preview + +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). + +## Summary + +This is a test plan for the workflow of: + +- upgrading single prebuilt rules one-by-one + +from the Rule Upgrade table with previewing incoming updates from Elastic and user customizations in the Rule Upgrade flyout. + +## Table of contents + + + +- [Useful information](#useful-information) + - [Tickets](#tickets) + - [Terminology](#terminology) + - [Assumptions](#assumptions) + - [Functional requirements](#functional-requirements) +- [Scenarios](#scenarios) + - [Rule upgrade field preview](#rule-upgrade-field-preview) + - [Preview non-customized field that has an upgrade (AAB)](#preview-non-customized-field-that-has-an-upgrade-aab) + - [Preview customized field that doesn't have an upgrade (ABA)](#preview-customized-field-that-doesnt-have-an-upgrade-aba) + - [Preview customized field that has a matching upgrade (ABB)](#preview-customized-field-that-has-a-matching-upgrade-abb) + - [Preview customized field that has an upgrade resulting in a solvable conflict (ABC, conflict solvable by diff algo)](#preview-customized-field-that-has-an-upgrade-resulting-in-a-solvable-conflict-abc-conflict-solvable-by-diff-algo) + - [Preview customized field that has an upgrade resulting in a non-solvable conflict (ABC, conflict non-solvable by diff algo)](#preview-customized-field-that-has-an-upgrade-resulting-in-a-non-solvable-conflict-abc-conflict-non-solvable-by-diff-algo) + - [Rule upgrade field preview Diff View options](#rule-upgrade-field-preview-diff-view-options) + - [Preview customized field that doesn't have an upgrade (AAB diff case)](#preview-customized-field-that-doesnt-have-an-upgrade-aab-diff-case) + - [Preview non-customized field that has an upgrade (ABA diff case)](#preview-non-customized-field-that-has-an-upgrade-aba-diff-case) + - [Preview customized field diff that has a matching upgrade (ABB diff case)](#preview-customized-field-diff-that-has-a-matching-upgrade-abb-diff-case) + - [Preview customized field diff that has an upgrade with a solvable conflict (ABC diff case, conflict solvable by diff algo)](#preview-customized-field-diff-that-has-an-upgrade-with-a-solvable-conflict-abc-diff-case-conflict-solvable-by-diff-algo) + - [Preview customized field diff that has an upgrade with a non-solvable conflict (ABC diff case, conflict non-solvable by diff algo)](#preview-customized-field-diff-that-has-an-upgrade-with-a-non-solvable-conflict-abc-diff-case-conflict-non-solvable-by-diff-algo) + - [Field editing](#field-editing) + - [Validation blocks saving field form when value is invalid](#validation-blocks-saving-field-form-when-value-is-invalid) + - [Saving unchanged field form value doesn't add up or remove anything to the field diff in Diff View](#saving-unchanged-field-form-value-doesnt-add-up-or-remove-anything-to-the-field-diff-in-diff-view) + - [Rule upgrade button](#rule-upgrade-button) + - [Rule upgrade button is disabled when num of conflicts \>= 1](#rule-upgrade-button-is-disabled-when-num-of-conflicts--1) + - [Rule upgrade button is disabled when num fields in edit mode \>= 1](#rule-upgrade-button-is-disabled-when-num-fields-in-edit-mode--1) + - [Rule upgrade button is disabled when num of conflicts \>= 1 or num fields in edit mode \>= 1](#rule-upgrade-button-is-disabled-when-num-of-conflicts--1-or-num-fields-in-edit-mode--1) + - [Rule upgrade after field preview](#rule-upgrade-after-field-preview) + - [Non-customized rule upgrade after preview (AAB diff case)](#non-customized-rule-upgrade-after-preview-aab-diff-case) + - [Non-customized rule upgrade after preview and customizing field values (AAB diff case)](#non-customized-rule-upgrade-after-preview-and-customizing-field-values-aab-diff-case) + - [Customized rule upgrade after preview customized fields that don't have upgrades (ABA diff case)](#customized-rule-upgrade-after-preview-customized-fields-that-dont-have-upgrades-aba-diff-case) + - [Customized rule upgrade after preview customized fields that don't have upgrades and changing that field values (ABA diff case)](#customized-rule-upgrade-after-preview-customized-fields-that-dont-have-upgrades-and-changing-that-field-values-aba-diff-case) + - [Customized rule upgrade after preview and accepting solvable conflicts (ABC diff case, conflict solvable by diff algo)](#customized-rule-upgrade-after-preview-and-accepting-solvable-conflicts-abc-diff-case-conflict-solvable-by-diff-algo) + - [Customized rule upgrade after preview and accepting edited solvable conflicts (ABC diff case, conflict solvable by diff algo)](#customized-rule-upgrade-after-preview-and-accepting-edited-solvable-conflicts-abc-diff-case-conflict-solvable-by-diff-algo) + - [Customized rule upgrade after preview non-solvable conflicts and accepting suggested field value (ABC diff case, non-solvable by diff algo)](#customized-rule-upgrade-after-preview-non-solvable-conflicts-and-accepting-suggested-field-value-abc-diff-case-non-solvable-by-diff-algo) + - [Customized rule upgrade after preview non-solvable conflicts and accepting edited field value (ABC diff case, non-solvable by diff algo)](#customized-rule-upgrade-after-preview-non-solvable-conflicts-and-accepting-edited-field-value-abc-diff-case-non-solvable-by-diff-algo) + - [Rule type upgrade](#rule-type-upgrade) + - [Non-customized rule upgrade to a different rule type after preview](#non-customized-rule-upgrade-to-a-different-rule-type-after-preview) + - [Customized rule upgrade to a different rule type after preview](#customized-rule-upgrade-to-a-different-rule-type-after-preview) + - [Concurrency control](#concurrency-control) + - [User gets notified after someone edited a rule being previewed](#user-gets-notified-after-someone-edited-a-rule-being-previewed) + - [User gets notified after a new rule versions is released](#user-gets-notified-after-a-new-rule-versions-is-released) + +## Useful information + +### Tickets + +- [Users can Customize Prebuilt Detection Rules](https://github.com/elastic/security-team/issues/1974) (internal) +- [Users can Customize Prebuilt Detection Rules: Milestone 3](https://github.com/elastic/kibana/issues/174168) +- [Tests for prebuilt rule upgrade workflow](https://github.com/elastic/kibana/issues/202078) + +### Terminology + +- **CTA**: "call to action", usually a button, a link, or a callout message with a button, etc, that invites the user to do some action. + + - **CTA to upgrade the prebuilt rule**: the button to upgrade the prebuilt rule currently shown in the Rule Upgrade flyout. + +- **Non-customized field**: a prebuilt rule's field that has the original value from the originally installed prebuilt rule. + +- **Customized field**: a prebuilt rule's field that has a value that differs from the original field value of the originally installed prebuilt rule. + +- **Non-customized rule**: a prebuilt rule that doesn't have any customized fields. + +- **Customized rule**: a prebuilt rule that has one or more customized fields. + +### Assumptions + +- Below scenarios only apply to prebuilt detection rules. +- A prebuilt rule is shown in the Rule Upgrade table when there's a newer version of this rule in the currently installed package with prebuilt rules. + +### Functional requirements + +- User should be able to upgrade prebuilt rules one-by-one with the ability to preview: + - what updates they would receive from Elastic in the latest rule version; + - what user customizations they would retain in the rule; + - are there any conflicts between the updates from Elastic and the user customizations; + - what they should pay attention to in case there are any conflicts. +- A preview should be shown in the Rule Upgrade flyout. +- The Rule Upgrade flyout should contain a few tabs: + - The "Updates" tab. + - The "Overview" tab. + - The "Investigation guide" tab. +- On the "Updates" tab: + - We should show the updates from Elastic and the user-customized fields. + - We should show only those fields that are [customizable](./shared_assets/customizable_rule_fields.md). + - We shouldn't show technical fields and those that are [not customizable](./shared_assets/non_customizable_rule_fields.md). +- User should be able to upgrade a prebuilt rule that has some updates to [non-customizable fields](./shared_assets/non_customizable_rule_fields.md) in the latest version. +- Any other fields that are not involved in the rule upgrade workflow, such as `enabled` or `exceptions`, should stay unchanged after rule upgrade. + +## Scenarios + +### Rule upgrade field preview + +#### Preview non-customized field that has an upgrade (AAB) + +**Automation**: Jest functional test for each \. + +```Gherkin +Given an installed prebuilt rule +And that rule has no customizations +And has an upgrade +When user opens the Rule Update Flyout +Then user should see has no conflicts +And is shown collapsed +When user expands +Then user should see Diff View +And user should see Readonly View + +Examples: + = all customizable fields +``` + +#### Preview customized field that doesn't have an upgrade (ABA) + +**Automation**: Jest functional test for each \. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has no upgrades +When user opens the Rule Update Flyout +Then user should see has a customized value +And has no conflicts +And is shown collapsed +When user expands +Then user should see Diff View +And user should see Readonly View + +Examples: + = all customizable fields +``` + +#### Preview customized field that has a matching upgrade (ABB) + +**Automation**: Jest functional test for each \. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has an upgrade matching customization +When user opens the Rule Update Flyout +Then user should see has matching upgrade +And has no conflicts +And is shown collapsed +When user expands +Then user should see Diff View +And user should see Readonly View + +Examples: + = all customizable fields +``` + +#### Preview customized field that has an upgrade resulting in a solvable conflict (ABC, conflict solvable by diff algo) + +**Automation**: Jest functional test for each \. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has an upgrade resulting in a solvable conflict +When user opens the Rule Update Flyout +Then user should see has a customized value +And has a conflict +And is shown expanded +And Diff View is shown +And Readonly View is shown +And Readonly View displays a merged value +When user switches to edit form +Then user should see edit form +And edit form has merged value + +Examples: whose diff algo supports values merging +| data_source | +| tags | +| description | +| references | +| note | +| setup | +| threat_index | +| new_terms_fields | +``` + +#### Preview customized field that has an upgrade resulting in a non-solvable conflict (ABC, conflict non-solvable by diff algo) + +**Automation**: Jest functional test for each \. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has an upgrade resulting in a non-solvable conflict +When user opens the Rule Update Flyout +Then user should see has a customized value +And has a conflict +And is shown expanded +And Diff View is shown +And edit form is shown +And edit form displays current rule version field value +When user saves and accepts the form +Then user should see Readonly mode +And Readonly mode displays the current rule version field value + +Examples: + = all customizable fields, but always mergeable fields "tags", "references", "threat_index", "new_terms_fields" +``` + +### Rule upgrade field preview Diff View options + +#### Preview customized field that doesn't have an upgrade (AAB diff case) + +**Automation**: 1 Jest integration test. + +```Gherkin +Given an installed prebuilt rule +And is customized +And doesn't have an upgrade +When user opens the Rule Update Flyout +Then user should see Diff View +And it shows a diff between original and current values +When user edits and saves the form +Then user should see a diff between original and edited values + +Examples: + = all customizable fields +``` + +#### Preview non-customized field that has an upgrade (ABA diff case) + +**Automation**: 1 Jest integration test. + +```Gherkin +Given an installed prebuilt rule +And isn't customized +And has an upgrade +When user opens the Rule Update Flyout +Then user should see Diff View +And it shows a diff between original and upgraded values +When user edits and saves the form +Then user should see a diff between original and edited values +And user should have an ability to see + +Examples: + = all customizable fields + + + - Elastic update, a diff between original and upgrade field values +``` + +#### Preview customized field diff that has a matching upgrade (ABB diff case) + +**Automation**: 1 Jest integration test. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has a matching upgrade +When user opens the Rule Update Flyout +Then user should see Diff View +And it shows a diff between original and customized values +And user should have an ability to see a +When user edits and saves the form +Then user should see a diff between original and edited values +And user should have an ability to see a + +Examples: + = all customizable fields + + + - Elastic update, a diff between original and upgrade field values +``` + +#### Preview customized field diff that has an upgrade with a solvable conflict (ABC diff case, conflict solvable by diff algo) + +**Automation**: 1 Jest integration test. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has an upgrade resulting in a solvable conflict +When user opens the Rule Update Flyout +Then user should see Diff View +And it shows a diff between original and merged (customization + upgrade) values +And user should have an ability to see a +When user edits and saves the form +Then user should see a diff between original and edited values +And user should have an ability to see a + +Examples: + = all customizable fields + + + - Elastic update, a diff between original and upgrade field values + - Original field customization, a diff between original and customized field values +``` + +#### Preview customized field diff that has an upgrade with a non-solvable conflict (ABC diff case, conflict non-solvable by diff algo) + +**Automation**: 1 Jest integration test. + +```Gherkin +Given an installed prebuilt rule +And is customized +And has an upgrade resulting in a non-solvable conflict +When user opens the Rule Update Flyout +Then user should see Diff View +And it shows a diff between original and customized values +And user should have an ability to see a +When user edits and saves the form +Then user should see a diff between original and edited values +And user should have an ability to see a + +Examples: + = all customizable fields + + + - Elastic upgrade, a diff between original and upgrade field values + + + - Elastic upgrade, a diff between original and upgrade field values + - Original customization, a diff between original and customized field values +``` + +### Field editing + +#### Validation blocks saving field form when value is invalid + +**Automation**: 1 Jest integration test per \ + \ variation. + +```Gherkin +Given an installed prebuilt rule +And corresponds to a +And appears in the Rule Update Flyout +When user edits 's in a form +And enters an invalid value +Then Save button should be disabled +And user should not be able to save the form until a valid value is entered + +Examples: + = all customizable fields + + + - AAB = a customized field that has doesn't have an upgrade + - ABA = a non-customized field that has an upgrade + - ABB = a customized field diff that has a matching upgrade + - ABC solvable = customized field diff that has an upgrade with a solvable conflict + - ABC non-solvable = customized field diff that has an upgrade with a non-solvable conflict +``` + +#### Saving unchanged field form value doesn't add up or remove anything to the field diff in Diff View + +**Automation**: 1 Jest integration test per \ + \ variation. + +```Gherkin +Given an installed prebuilt rule +And corresponds to a +And appears in the Rule Update Flyout +When user opens a form +And saves the form without changes +Then Diff View should not have any new lines added up or removed + +Examples: + = all customizable fields + + + - AAB = a customized field that has doesn't have an upgrade + - ABA = a non-customized field that has an upgrade + - ABB = a customized field diff that has a matching upgrade + - ABC solvable = customized field diff that has an upgrade with a solvable conflict + - ABC non-solvable = customized field diff that has an upgrade with a non-solvable conflict +``` + +### Rule upgrade button + +#### Rule upgrade button is disabled when num of conflicts >= 1 + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customizations +And it has an upgrade resulting to conflicts +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +When user hover on the INACTIVE CTA +Then explanation tooltip appears +When user resolves all conflicts +Then the INACTIVE CTA becomes ACTIVE +``` + +#### Rule upgrade button is disabled when num fields in edit mode >= 1 + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And it has an upgrade without conflicts +When user opens the Rule Update Flyout +Then user should see ACTIVE CTA to upgrade the prebuilt rule +When user switch one or more fields to edit mode +Then user should see INACTIVE CTA +When user hover on the INACTIVE CTA +Then explanation tooltip appears +When user every field in readonly mode +Then the INACTIVE CTA becomes ACTIVE +``` + +#### Rule upgrade button is disabled when num of conflicts >= 1 or num fields in edit mode >= 1 + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customizations +And it has an upgrade resulting to conflicts +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +When user resolves all conflicts +Then the INACTIVE CTA becomes ACTIVE +When user switches one or more fields to edit mode +Then user should see INACTIVE CTA +``` + +### Rule upgrade after field preview + +#### Non-customized rule upgrade after preview (AAB diff case) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule does not have any customizations +And has an upgrade +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And user should see has no conflicts +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has an upgraded value + +Examples: + = all customizable fields +``` + +#### Non-customized rule upgrade after preview and customizing field values (AAB diff case) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule does not have any customizations +And has an upgrade +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And user should see has no conflicts +When user edits form to something different but valid and saves the form +Then user should see has a new value +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has a new value + +Examples: + = all customizable fields +``` + +#### Customized rule upgrade after preview customized fields that don't have upgrades (ABA diff case) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade for ( != ) +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And user should see has a customized value and there are no conflicts +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has preserved the customized value + +Examples: + = all customizable fields +``` + +#### Customized rule upgrade after preview customized fields that don't have upgrades and changing that field values (ABA diff case) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade for ( != ) +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And user should see has a customized value and there are no conflicts +When user edits form to something different but valid and saves the form +Then user should see has a new value +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has a new value + +Examples: + = all customizable fields +``` + +#### Customized rule upgrade after preview and accepting solvable conflicts (ABC diff case, conflict solvable by diff algo) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade resulting in a solvable conflict +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +And user should see has a conflict +When user accepts the suggested merged upgrade value for +Then user should see an ACTIVE CTA to upgrade the prebuilt rule +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has an upgraded value user accepted + +Examples: is one of +| data_source | +| tags | +| description | +| references | +| note | +| setup | +| threat_index | +| new_terms_fields | +``` + +#### Customized rule upgrade after preview and accepting edited solvable conflicts (ABC diff case, conflict solvable by diff algo) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade resulting in a solvable conflict +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +And user should see has a conflict +And readonly view with merged value is shown +When user switches to "edit mode" +Then user should see edit form +And edit form has a merged value +When user edits the suggested upgrade value and saves the form +Then user should see an ACTIVE CTA to upgrade the prebuilt rule +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has an upgraded value user entered and saved in the form + +Examples: is one of +| data_source | +| tags | +| description | +| references | +| note | +| setup | +| threat_index | +| new_terms_fields | +``` + +#### Customized rule upgrade after preview non-solvable conflicts and accepting suggested field value (ABC diff case, non-solvable by diff algo) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade resulting to a non-solvable conflict +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +And has a conflict +And edit form is shown +And edit form inputs have current customized value +When user saves the form without changes +Then user should see an ACTIVE CTA to upgrade the prebuilt rule +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has an upgraded value accepted by user + +Examples: + = all customizable fields +``` + +#### Customized rule upgrade after preview non-solvable conflicts and accepting edited field value (ABC diff case, non-solvable by diff algo) + +**Automation**: Jest integration test per \ and 1 bulk Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customized +And it has an upgrade resulting to a non-solvable conflict +When user opens the Rule Update Flyout +Then user should see INACTIVE CTA to upgrade the prebuilt rule +And has a conflict +And edit form is shown +And edit form inputs have current customized value +When user edits form and saves it +Then user should see an ACTIVE CTA to upgrade the prebuilt rule +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has an upgraded value user entered and saved in the form + +Examples: + = all customizable fields, but always mergeable fields "tags", "references", "threat_index", "new_terms_fields" +``` + +### Rule type upgrade + +#### Non-customized rule upgrade to a different rule type after preview + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has no customizations +And it has an upgrade +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And a warning message saying rule upgrade changes its type +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has changed its type +And has upgraded field values +``` + +#### Customized rule upgrade to a different rule type after preview + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has customizations +And it has an upgrade +When user opens the Rule Update Flyout +Then user should see a CTA to upgrade the prebuilt rule +And a warning message saying rule upgrade changes its type +And user is gonna lose all customizations +When user clicks on CTA +Then success message should be displayed after upgrade +And upgraded prebuilt rule should be removed from the table +When user opens rule details page for that prebuilt rule +Then user should see has changed its type +And has upgraded field values +``` + +### Concurrency control + +#### User gets notified after someone edited a rule being previewed + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has an upgrade +And opened Rule Update Preview +And saved custom field values via field forms +When edits the same rule providing changed field values +Then should see a notification that rule has been edited +And saved custom field values got discarded +``` + +#### User gets notified after a new rule versions is released + +**Automation**: 1 Cypress test. + +```Gherkin +Given an installed prebuilt rule +And that rule has an upgrade +And user opened Rule Update Preview +And saved custom field values via field forms +When a new version of the same rule gets available +Then user should see a notification that a new rule version was detected +And saved custom field values got discarded +``` diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_without_preview.md similarity index 64% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_without_preview.md index 4beb517f9598a..6cf8ba78270df 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/upgrade.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rule_upgrade_without_preview.md @@ -1,10 +1,22 @@ -# Upgrade of Prebuilt Rules +# Test plan: upgrading prebuilt rules one-by-one or in bulk without preview -This is a test plan for the workflow of upgrading prebuilt rules. +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). -Status: `in progress`. The current test plan matches [Rule Immutability/Customization Milestone 3 epic](https://github.com/elastic/kibana/issues/174168). +## Summary -## Table of Contents +This is a test plan for the workflows of: + +- upgrading single prebuilt rules one-by-one +- upgrading multiple prebuilt rules in bulk + +from the Rule Upgrade table without previewing incoming updates from Elastic and user customizations in the Rule Upgrade flyout. + +## Table of contents + + - [Useful information](#useful-information) - [Tickets](#tickets) @@ -12,71 +24,72 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz - [Assumptions](#assumptions) - [Non-functional requirements](#non-functional-requirements) - [Functional requirements](#functional-requirements) - - [Scenarios](#scenarios) - - [Rule installation and upgrade notifications on the Rule Management page](#rule-installation-and-upgrade-notifications-on-the-rule-management-page) - - [**Scenario: User is NOT notified when all installed prebuilt rules are up to date**](#scenario-user-is-not-notified-when-all-installed-prebuilt-rules-are-up-to-date) - - [**Scenario: User is notified when some prebuilt rules can be upgraded**](#scenario-user-is-notified-when-some-prebuilt-rules-can-be-upgraded) - - [**Scenario: User is notified when both rules to install and upgrade are available**](#scenario-user-is-notified-when-both-rules-to-install-and-upgrade-are-available) - - [Rule upgrade workflow: individual upgrade from Rule Updates table](#rule-upgrade-workflow-individual-and-bulk-updates-from-rule-updates-table) - - [**Scenario: User can upgrade conflict-free prebuilt rules one by one**](#scenario-user-can-upgrade-conflict-free-prebuilt-rules-one-by-one) - - [**Scenario: User cannot upgrade prebuilt rules one by one from Rules Update table if they have conflicts**](#scenario-user-cannot-upgrade-prebuilt-rules-one-by-one-from-rules-update-table-if-they-have-conflicts) - - [Rule upgrade workflow: bulk upgrade from Rule Updates table](#rule-upgrade-workflow-individual-and-bulk-updates-from-rule-updates-table) - - [**Scenario: User can upgrade multiple conflict-free prebuilt rules selected on the page**](#scenario-user-can-upgrade-multiple-conflict-free-prebuilt-rules-selected-on-the-page) - - [**Scenario: User cannot upgrade multiple prebuilt rules selected on the page when they have upgrade conflicts**](#scenario-user-cannot-upgrade-multiple-prebuilt-rules-selected-on-the-page-when-they-have-upgrade-conflicts) - - [**Scenario: User can upgrade all available conflict-free prebuilt rules at once**](#scenario-user-can-upgrade-all-available-conflict-free-prebuilt-rules-at-once) - - [**Scenario: User cannot upgrade all prebuilt rules at once if they have upgrade conflicts**](#scenario-user-cannot-upgrade-all-prebuilt-rules-at-once-if-they-have-upgrade-conflicts) - - [**Scenario: User can upgrade only conflict-free rules when a mix of rules with and without conflicts are selected for upgrade in the Rules Table**](#scenario-user-can-upgrade-only-conflict-free-rules-when-a-mix-of-rules-with-and-without-conflicts-are-selected-for-upgrade-in-the-rules-table) - - [**Scenario: User can upgrade only conflict-free rules when user attempts to upgrade all rules and only a subset contains upgrade conflicts**](#scenario-user-can-upgrade-only-conflict-free-rules-when-user-attempts-to-upgrade-all-rules-and-only-a-subset-contains-upgrade-conflicts) - - [Rule upgrade workflow: upgrading rules with rule type change](#rule-upgrade-workflow-upgrading-rules-with-rule-type-change) - - [**Scenario: User can upgrade rule with rule type change individually**](#scenario-user-can-upgrade-rule-with-rule-type-change-individually) - - [**Scenario: User can bulk upgrade selected rules with rule type changes**](#scenario-user-can-bulk-upgrade-selected-rules-with-rule-type-changes) - - [**Scenario: User can bulk upgrade all rules with rule type changes**](#scenario-user-can-bulk-upgrade-all-rules-with-rule-type-changes) - - [Rule upgrade workflow: rule previews](#rule-upgrade-workflow-rule-previews) - - [**Scenario: User can preview rules available for upgrade**](#scenario-user-can-preview-rules-available-for-upgrade) - - [**Scenario: User can upgrade a rule using the rule preview**](#scenario-user-can-upgrade-a-rule-using-the-rule-preview) - - [**Scenario: User can see correct rule information in preview before upgrading**](#scenario-user-can-see-correct-rule-information-in-preview-before-upgrading) - - [**Scenario: Tabs and sections without content should be hidden in preview before upgrading**](#scenario-tabs-and-sections-without-content-should-be-hidden-in-preview-before-upgrading) - - [Rule upgrade workflow: filtering, sorting, pagination](#rule-upgrade-workflow-filtering-sorting-pagination) - - [MILESTONE 2 (Legacy) - Rule upgrade workflow: viewing rule changes in JSON diff view](#milestone-2-legacy---rule-upgrade-workflow-viewing-rule-changes-in-json-diff-view) - - [**Scenario: User can see changes in a side-by-side JSON diff view**](#scenario-user-can-see-changes-in-a-side-by-side-json-diff-view) - - [**Scenario: User can see precisely how property values would change after upgrade**](#scenario-user-can-see-precisely-how-property-values-would-change-after-upgrade) - - [**Scenario: Rule actions and exception lists should not be shown as modified**](#scenario-rule-actions-and-exception-lists-should-not-be-shown-as-modified) - - [**Scenario: Dynamic properties should not be included in preview**](#scenario-dynamic-properties-should-not-be-included-in-preview) - - [**Scenario: Technical properties should not be included in preview**](#scenario-technical-properties-should-not-be-included-in-preview) - - [**Scenario: Properties with semantically equal values should not be shown as modified**](#scenario-properties-with-semantically-equal-values-should-not-be-shown-as-modified) - - [**Scenario: Unchanged sections of a rule should be hidden by default**](#scenario-unchanged-sections-of-a-rule-should-be-hidden-by-default) - - [**Scenario: Properties should be sorted alphabetically**](#scenario-properties-should-be-sorted-alphabetically) - - [MILESTONE 2 (Legacy) - Rule upgrade workflow: viewing rule changes in per-field diff view](#milestone-2-legacy---rule-upgrade-workflow-viewing-rule-changes-in-per-field-diff-view) - - [**Scenario: User can see changes in a side-by-side per-field diff view**](#scenario-user-can-see-changes-in-a-side-by-side-per-field-diff-view) - - [**Scenario: User can see changes when updated rule is a different rule type**](#scenario-user-can-see-changes-when-updated-rule-is-a-different-rule-type) - - [**Scenario: Field groupings should be rendered together in the same accordion panel**](#scenario-field-groupings-should-be-rendered-together-in-the-same-accordion-panel) - - [**Scenario: Undefined values are displayed with empty diffs**](#scenario-undefined-values-are-displayed-with-empty-diffs) - - [**Scenario: Field diff components have the same grouping and order as in rule details overview**](#scenario-field-diff-components-have-the-same-grouping-and-order-as-in-rule-details-overview) - - [Rule upgrade workflow: preserving rule bound data](#rule-upgrade-workflow-preserving-rule-bound-data) - - [**Scenario: Rule bound data is preserved after upgrading a rule to a newer version with the same rule type**](#scenario-rule-bound-data-is-preserved-after-upgrading-a-rule-to-a-newer-version-with-the-same-rule-type) - - [**Scenario: Rule bound data is preserved after upgrading a rule to a newer version with a different rule type**](#scenario-rule-bound-data-is-preserved-after-upgrading-a-rule-to-a-newer-version-with-a-different-rule-type) - - [Rule upgrade workflow: misc cases](#rule-upgrade-workflow-misc-cases) - - [**Scenario: User doesn't see the Rule Updates tab until the package installation is completed**](#scenario-user-doesnt-see-the-rule-updates-tab-until-the-package-installation-is-completed) - - [Error handling](#error-handling) - - [**Scenario: Error is handled when any upgrade operation on prebuilt rules fails**](#scenario-error-is-handled-when-any-upgrade-operation-on-prebuilt-rules-fails) - - [Rule upgrade via the Prebuilt rules API](#rule-upgrade-via-the-prebuilt-rules-api) - - [**Scenario: API can upgrade prebuilt rules that are outdated**](#scenario-api-can-upgrade-prebuilt-rules-that-are-outdated) - - [**Scenario: API does not upgrade prebuilt rules if they are up to date**](#scenario-api-does-not-upgrade-prebuilt-rules-if-they-are-up-to-date) - - [Authorization / RBAC](#authorization-rbac) - - [**Scenario: User with read privileges on Security Solution cannot upgrade prebuilt rules**](#scenario-user-with-read-privileges-on-security-solution-cannot-upgrade-prebuilt-rules) - +- [Scenarios](#scenarios) + - [Rule upgrade notifications on the Rule Management page](#rule-upgrade-notifications-on-the-rule-management-page) + - [**Scenario: User is NOT notified when all installed prebuilt rules are up to date**](#scenario-user-is-not-notified-when-all-installed-prebuilt-rules-are-up-to-date) + - [**Scenario: User is notified when some prebuilt rules can be upgraded**](#scenario-user-is-notified-when-some-prebuilt-rules-can-be-upgraded) + - [**Scenario: User is notified when both rules to install and upgrade are available**](#scenario-user-is-notified-when-both-rules-to-install-and-upgrade-are-available) + - [Rule upgrade workflow: individual updates from Rule Updates table](#rule-upgrade-workflow-individual-updates-from-rule-updates-table) + - [**Scenario: User can upgrade conflict-free prebuilt rules one by one**](#scenario-user-can-upgrade-conflict-free-prebuilt-rules-one-by-one) + - [**Scenario: User cannot upgrade prebuilt rules one by one from Rules Update table if they have conflicts**](#scenario-user-cannot-upgrade-prebuilt-rules-one-by-one-from-rules-update-table-if-they-have-conflicts) + - [Rule upgrade workflow: bulk updates from Rule Updates table](#rule-upgrade-workflow-bulk-updates-from-rule-updates-table) + - [**Scenario: User can upgrade multiple conflict-free prebuilt rules selected on the page**](#scenario-user-can-upgrade-multiple-conflict-free-prebuilt-rules-selected-on-the-page) + - [**Scenario: User cannot upgrade multiple prebuilt rules selected on the page when they have upgrade conflicts**](#scenario-user-cannot-upgrade-multiple-prebuilt-rules-selected-on-the-page-when-they-have-upgrade-conflicts) + - [**Scenario: User can upgrade all available conflict-free prebuilt rules at once**](#scenario-user-can-upgrade-all-available-conflict-free-prebuilt-rules-at-once) + - [**Scenario: User cannot upgrade all prebuilt rules at once if they have upgrade conflicts**](#scenario-user-cannot-upgrade-all-prebuilt-rules-at-once-if-they-have-upgrade-conflicts) + - [**Scenario: User can upgrade only conflict-free rules when a mix of rules with and without conflicts are selected for upgrade**](#scenario-user-can-upgrade-only-conflict-free-rules-when-a-mix-of-rules-with-and-without-conflicts-are-selected-for-upgrade) + - [**Scenario: User can upgrade only conflict-free rules when attempting to upgrade all rules**](#scenario-user-can-upgrade-only-conflict-free-rules-when-attempting-to-upgrade-all-rules) + - [Rule upgrade workflow: upgrading rules with rule type changes](#rule-upgrade-workflow-upgrading-rules-with-rule-type-changes) + - [**Scenario: User can upgrade rules with rule type changes one-by-one**](#scenario-user-can-upgrade-rules-with-rule-type-changes-one-by-one) + - [**Scenario: User can NOT bulk upgrade rules with rule type changes when upgrading selected rules**](#scenario-user-can-not-bulk-upgrade-rules-with-rule-type-changes-when-upgrading-selected-rules) + - [**Scenario: User can NOT bulk upgrade rules with rule type changes when upgrading all rules**](#scenario-user-can-not-bulk-upgrade-rules-with-rule-type-changes-when-upgrading-all-rules) + - [Rule upgrade workflow: rule previews](#rule-upgrade-workflow-rule-previews) + - [**Scenario: User can preview rules available for upgrade**](#scenario-user-can-preview-rules-available-for-upgrade) + - [**Scenario: User can upgrade a rule using the rule preview**](#scenario-user-can-upgrade-a-rule-using-the-rule-preview) + - [**Scenario: User can see correct rule information in preview before upgrading**](#scenario-user-can-see-correct-rule-information-in-preview-before-upgrading) + - [**Scenario: Tabs and sections without content should be hidden in preview before upgrading**](#scenario-tabs-and-sections-without-content-should-be-hidden-in-preview-before-upgrading) + - [Rule upgrade workflow: filtering, sorting, pagination](#rule-upgrade-workflow-filtering-sorting-pagination) + - [MILESTONE 2 (Legacy) - Rule upgrade workflow: viewing rule changes in JSON diff view](#milestone-2-legacy---rule-upgrade-workflow-viewing-rule-changes-in-json-diff-view) + - [**Scenario: User can see changes in a side-by-side JSON diff view**](#scenario-user-can-see-changes-in-a-side-by-side-json-diff-view) + - [**Scenario: User can see precisely how property values would change after upgrade**](#scenario-user-can-see-precisely-how-property-values-would-change-after-upgrade) + - [**Scenario: Rule actions and exception lists should not be shown as modified**](#scenario-rule-actions-and-exception-lists-should-not-be-shown-as-modified) + - [**Scenario: Dynamic properties should not be included in preview**](#scenario-dynamic-properties-should-not-be-included-in-preview) + - [**Scenario: Technical properties should not be included in preview**](#scenario-technical-properties-should-not-be-included-in-preview) + - [**Scenario: Properties with semantically equal values should not be shown as modified**](#scenario-properties-with-semantically-equal-values-should-not-be-shown-as-modified) + - [**Scenario: Unchanged sections of a rule should be hidden by default**](#scenario-unchanged-sections-of-a-rule-should-be-hidden-by-default) + - [**Scenario: Properties should be sorted alphabetically**](#scenario-properties-should-be-sorted-alphabetically) + - [MILESTONE 2 (Legacy) - Rule upgrade workflow: viewing rule changes in per-field diff view](#milestone-2-legacy---rule-upgrade-workflow-viewing-rule-changes-in-per-field-diff-view) + - [**Scenario: User can see changes in a side-by-side per-field diff view**](#scenario-user-can-see-changes-in-a-side-by-side-per-field-diff-view) + - [**Scenario: User can see changes when updated rule is a different rule type**](#scenario-user-can-see-changes-when-updated-rule-is-a-different-rule-type) + - [**Scenario: Field groupings should be rendered together in the same accordion panel**](#scenario-field-groupings-should-be-rendered-together-in-the-same-accordion-panel) + - [**Scenario: Undefined values are displayed with empty diffs**](#scenario-undefined-values-are-displayed-with-empty-diffs) + - [**Scenario: Field diff components have the same grouping and order as in rule details overview**](#scenario-field-diff-components-have-the-same-grouping-and-order-as-in-rule-details-overview) + - [Rule upgrade workflow: preserving rule bound data](#rule-upgrade-workflow-preserving-rule-bound-data) + - [**Scenario: Rule bound data is preserved after upgrading a rule to a newer version with the same rule type**](#scenario-rule-bound-data-is-preserved-after-upgrading-a-rule-to-a-newer-version-with-the-same-rule-type) + - [**Scenario: Rule bound data is preserved after upgrading a rule to a newer version with a different rule type**](#scenario-rule-bound-data-is-preserved-after-upgrading-a-rule-to-a-newer-version-with-a-different-rule-type) + - [Rule upgrade workflow: misc cases](#rule-upgrade-workflow-misc-cases) + - [**Scenario: User doesn't see the Rule Updates tab until the package installation is completed**](#scenario-user-doesnt-see-the-rule-updates-tab-until-the-package-installation-is-completed) + - [Error handling](#error-handling) + - [**Scenario: Error is handled when any upgrade operation on prebuilt rules fails**](#scenario-error-is-handled-when-any-upgrade-operation-on-prebuilt-rules-fails) + - [Rule upgrade via the Prebuilt rules API](#rule-upgrade-via-the-prebuilt-rules-api) + - [**Scenario: API can upgrade prebuilt rules that are outdated**](#scenario-api-can-upgrade-prebuilt-rules-that-are-outdated) + - [**Scenario: API does not upgrade prebuilt rules if they are up to date**](#scenario-api-does-not-upgrade-prebuilt-rules-if-they-are-up-to-date) + - [Authorization / RBAC](#authorization--rbac) + - [**Scenario: User with read privileges on Security Solution cannot upgrade prebuilt rules**](#scenario-user-with-read-privileges-on-security-solution-cannot-upgrade-prebuilt-rules) ## Useful information ### Tickets -- [Rule Immutability/Customization](https://github.com/elastic/security-team/issues/1974) epic +- [Users can Customize Prebuilt Detection Rules](https://github.com/elastic/security-team/issues/1974) epic **Milestone 3 - Prebuilt Rules Customization:** + - [Milestone 3 epic ticket](https://github.com/elastic/kibana/issues/174168) - [Tests for prebuilt rule upgrade workflow #202078](https://github.com/elastic/kibana/issues/202078) **Milestone 2:** + - [Ensure full test coverage for existing workflows of installing and upgrading prebuilt rules](https://github.com/elastic/kibana/issues/148176) - [Write test plan and add test coverage for the new workflows of installing and upgrading prebuilt rules](https://github.com/elastic/kibana/issues/148192) @@ -99,9 +112,12 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz ### Assumptions - Below scenarios only apply to prebuilt detection rules. -- Users should be able to install and upgrade prebuilt rules on the `Basic` license and higher. -- EPR is available for fetching the package unless explicitly indicated otherwise. +- EPR is available for fetching the package with prebuilt rules unless explicitly indicated otherwise. - Only the latest **stable** package is checked for installation/upgrade and pre-release packages are ignored. +- Users have the required [privileges for managing detection rules](https://www.elastic.co/guide/en/security/current/detections-permissions-section.html). +- Users are: + - on the `Basic` license and higher in self-hosted and ECH environments; + - on the `Essentials` tier and higher in Serverless environments. ### Non-functional requirements @@ -114,83 +130,61 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz ### Functional requirements -- User should be able to install prebuilt rules with and without previewing what exactly they would install (rule properties). -- User should be able to upgrade prebuilt rules with and without previewing what updates they would apply (rule properties of target rule versions). -- If user chooses to preview a prebuilt rule to be installed/upgraded, we currently show this preview in a flyout. -- In the prebuilt rule preview a tab that doesn't have any sections should not be displayed and a section that doesn't have any properties also should not be displayed. - -Examples of rule properties we show in the prebuilt rule preview flyout: - -```Gherkin -Examples: -| rule_type | property | tab | section | -│ All rule types │ Author │ Overview │ About │ -│ All rule types │ Building block │ Overview │ About │ -│ All rule types │ Severity │ Overview │ About │ -│ All rule types │ Severity override │ Overview │ About │ -│ All rule types │ Risk score │ Overview │ About │ -│ All rule types │ Risk score override │ Overview │ About │ -│ All rule types │ Reference URLs │ Overview │ About │ -│ All rule types │ False positive examples │ Overview │ About │ -│ All rule types │ Custom highlighted fields │ Overview │ About │ -│ All rule types │ License │ Overview │ About │ -│ All rule types │ Rule name override │ Overview │ About │ -│ All rule types │ MITRE ATT&CK™ │ Overview │ About │ -│ All rule types │ Timestamp override │ Overview │ About │ -│ All rule types │ Tags │ Overview │ About │ -│ All rule types │ Type │ Overview │ Definition │ -│ All rule types │ Related integrations │ Overview │ Definition │ -│ All rule types │ Required fields │ Overview │ Definition │ -│ All rule types │ Timeline template │ Overview │ Definition │ -│ All rule types │ Runs every │ Overview │ Schedule │ -│ All rule types │ Additional look-back time │ Overview │ Schedule │ -│ All rule types │ Setup guide │ Overview │ Setup guide │ -│ All rule types │ Investigation guide │ Investigation guide │ Investigation guide │ -│ Custom Query │ Index patterns │ Overview │ Definition │ -│ Custom Query │ Data view ID │ Overview │ Definition │ -│ Custom Query │ Data view index pattern │ Overview │ Definition │ -│ Custom Query │ Custom query │ Overview │ Definition │ -│ Custom Query │ Filters │ Overview │ Definition │ -│ Custom Query │ Saved query name │ Overview │ Definition │ -│ Custom Query │ Saved query filters │ Overview │ Definition │ -│ Custom Query │ Saved query │ Overview │ Definition │ -│ Custom Query │ Suppress alerts by │ Overview │ Definition │ -│ Custom Query │ Suppress alerts for │ Overview │ Definition │ -│ Custom Query │ If a suppression field is missing │ Overview │ Definition │ -│ Machine Learning │ Anomaly score threshold │ Overview │ Definition │ -│ Machine Learning │ Machine Learning job │ Overview │ Definition │ -│ Threshold │ Threshold │ Overview │ Definition │ -│ Threshold │ Index patterns │ Overview │ Definition │ -│ Threshold │ Data view ID │ Overview │ Definition │ -│ Threshold │ Data view index pattern │ Overview │ Definition │ -│ Threshold │ Custom query │ Overview │ Definition │ -│ Threshold │ Filters │ Overview │ Definition │ -│ Event Correlation │ EQL query │ Overview │ Definition │ -│ Event Correlation │ Filters │ Overview │ Definition │ -│ Event Correlation │ Index patterns │ Overview │ Definition │ -│ Event Correlation │ Data view ID │ Overview │ Definition │ -│ Event Correlation │ Data view index pattern │ Overview │ Definition │ -│ Indicator Match │ Indicator index patterns │ Overview │ Definition │ -│ Indicator Match │ Indicator mapping │ Overview │ Definition │ -│ Indicator Match │ Indicator filters │ Overview │ Definition │ -│ Indicator Match │ Indicator index query │ Overview │ Definition │ -│ Indicator Match │ Index patterns │ Overview │ Definition │ -│ Indicator Match │ Data view ID │ Overview │ Definition │ -│ Indicator Match │ Data view index pattern │ Overview │ Definition │ -│ Indicator Match │ Custom query │ Overview │ Definition │ -│ Indicator Match │ Filters │ Overview │ Definition │ -│ New Terms │ Fields │ Overview │ Definition │ -│ New Terms │ History Window Size │ Overview │ Definition │ -│ New Terms │ Index patterns │ Overview │ Definition │ -│ New Terms │ Data view ID │ Overview │ Definition │ -│ New Terms │ Data view index pattern │ Overview │ Definition │ -│ New Terms │ Custom query │ Overview │ Definition │ -│ New Terms │ Filters │ Overview │ Definition │ -│ ESQL │ ESQL query │ Overview │ Definition │ -│ ESQL │ Suppress alerts by │ Overview │ Definition │ -│ ESQL │ Suppress alerts for │ Overview │ Definition │ -│ ESQL │ If a suppression field is missing │ Overview │ Definition │ -``` +User should be able to upgrade prebuilt rules with and without previewing what updates they would apply (rule properties of target rule versions). + +User should be able to upgrade prebuilt rules with and without customizations. Where the following fields support customizations: + +| Rule type | Field name in UI | Diffable rule field | +| ---------------- | ------------------------- | ------------------------- | +| All rule types | Rule name | `name` | +| All rule types | Rule description | `description` | +| All rule types | Tags | `tags` | +| All rule types | Default severity | `severity` | +| All rule types | Severity Override | `severity_mapping` | +| All rule types | Default risk score | `risk_score` | +| All rule types | Risk score override | `risk_score_mapping` | +| All rule types | Reference URLs | `references` | +| All rule types | False positive examples | `false_positives` | +| All rule types | MITRE ATT&CK™ threats | `threat` | +| All rule types | Setup guide | `setup` | +| All rule types | Investigation guide | `note` | +| All rule types | Related integrations | `related_integrations` | +| All rule types | Required fields | `required_fields` | +| All rule types | Rule schedule | `rule_schedule` | +| All rule types | Max alerts per run | `max_signals` | +| All rule types | Rule name override | `rule_name_override` | +| All rule types | Timestamp override | `timestamp_override` | +| All rule types | Timeline template | `timeline_template` | +| All rule types | Building block `*` | `building_block` | +| All rule types | Investigation fields | `investigation_fields` | +| All rule types | Data source `**` | `data_source` | +| All rule types | Suppress alerts | `alert_suppression` | +| Custom Query | Custom query | `kql_query` | +| Saved Query | Custom query | `kql_query` | +| EQL | EQL query | `eql_query` | +| ESQL | ESQL query | `esql_query` | +| Threat Match | Custom query | `kql_query` | +| Threat Match | Indicator index patterns | `threat_index` | +| Threat Match | Indicator index query | `threat_query` | +| Threat Match | Indicator mapping | `threat_mapping` | +| Threat Match | Indicator prefix override | `threat_indicator_path` | +| Threshold | Custom query | `kql_query` | +| Threshold | Threshold config | `threshold` | +| Machine Learning | Machine Learning job | `machine_learning_job_id` | +| Machine Learning | Anomaly score threshold | `anomaly_threshold` | +| New Terms | Custom query | `kql_query` | +| New Terms | Fields | `new_terms_fields` | +| New Terms | History Window Size | `history_window_start` | + +- `*` Building block field is used to mark alerts as building block alerts. +- `**` Data Source represents index patterns or a data view. Machine Learning rules don't have data_source field. + +User should be able to upgrade prebuilt rules with updates in the following non-customizable fields: + +| Field name | Diffable rule field | +| --------------------- | ------------------- | +| Rule type | `type` | +| Rule version | `version` | ## Scenarios @@ -294,7 +288,7 @@ Examples: | all rules on the page, e.g. 12 | ``` -#### **Scenario: User cannot upgrade selected prebuilt rules with conflicts** +#### **Scenario: User cannot upgrade multiple prebuilt rules selected on the page when they have upgrade conflicts** **Automation**: 1 e2e test with mock rules @@ -333,13 +327,13 @@ And user should NOT see a number of rules available to upgrade #### **Scenario: User cannot upgrade all prebuilt rules at once if they have upgrade conflicts** -**Automation**: 1 e2e test with mock rules +**Automation**: 1 e2e test with mock rules ```Gherkin Given X prebuilt rules are installed in Kibana And for Y of the installed rules there are new versions available And all Y new versions have conflicts with the current versions -When user opens the Rule Updates table +When user opens the Rule Updates table Then Y rules available for upgrade should be displayed in the table Then user should see a CTA to upgrade all rules And the CTA to upgrade all rules should be disabled @@ -393,10 +387,9 @@ And the remaining M = Y - K rules should still be present in the table And user should see the number of rules available to upgrade decreased by K number of upgraded rules ``` +### Rule upgrade workflow: upgrading rules with rule type changes -### Rule upgrade workflow: upgrading rules with rule type change - -#### **Scenario: User can upgrade rule with rule type change individually** +#### **Scenario: User can upgrade rules with rule type changes one-by-one** **Automation**: 1 e2e test with mock rules @@ -410,8 +403,7 @@ And the user should not be able to upgrade them directly from the table And there should be a message/tooltip indicating why the rule cannot be upgraded directly ``` -#### **Scenario: User can bulk upgrade selected rules with rule type changes** - +#### **Scenario: User can NOT bulk upgrade rules with rule type changes when upgrading selected rules** **Automation**: 1 e2e test with mock rules @@ -426,7 +418,7 @@ And the user should not be able to upgrade them directly from the table And there should be a message/tooltip indicating why the rule cannot be upgraded directly ``` -#### **Scenario: User can bulk upgrade all rules with rule type changes** +#### **Scenario: User can NOT bulk upgrade rules with rule type changes when upgrading all rules** **Automation**: 1 e2e test with mock rules @@ -817,7 +809,6 @@ Examples: | upgrading individual | ``` - ### Rule upgrade via the Prebuilt rules API There's a legacy prebuilt rules API and a new one. Both should be tested against two types of the package: with and without historical rule versions. @@ -910,4 +901,4 @@ When user opens the Rule Management page And user opens the Rule Updates table Then user should see prebuilt rules available to upgrade But user should not be able to upgrade them -``` \ No newline at end of file +``` diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/package_installation_and_upgrade.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rules_package.md similarity index 90% rename from x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/package_installation_and_upgrade.md rename to x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rules_package.md index 57e16684facca..5d0bfee30d8b0 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/package_installation_and_upgrade.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/prebuilt_rules_package.md @@ -1,12 +1,19 @@ -# Prebuilt Rules Package Installation and Upgrade +# Test plan: prebuilt rules package -This is a test plan for the workflows of installing and updating the Prebuilt Rules package. +**Status**: `in progress`, matches [Milestone 3](https://github.com/elastic/kibana/issues/174168). -> For the test plans for installing and upgrading prebuilt rules, see [Installation of Prebuilt Rules](./installation.md) and [Upgrade of Prebuilt Rules](./upgrade.md). +## Summary -Status: `in progress`. The current test plan matches [Rule Immutability/Customization Milestone 3 epic](https://github.com/elastic/kibana/issues/174168). +This is a test plan for the workflow of installing and updating the Fleet package with prebuilt rules. -## Table of Contents +This workflow makes prebuilt rules available for installation and upgrade in the system by the user. + +## Table of contents + + - [Useful information](#useful-information) - [Tickets](#tickets) @@ -18,7 +25,7 @@ Status: `in progress`. The current test plan matches [Rule Immutability/Customiz - [Package installation](#package-installation) - [**Scenario: Package is installed via Fleet**](#scenario-package-is-installed-via-fleet) - [**Scenario: Package is installed via bundled Fleet package in Kibana**](#scenario-package-is-installed-via-bundled-fleet-package-in-kibana) - - [**Scenario: Large package can be installed on a small Kibana instance**](#scenario-large-package-can-be-installed-on-a-small-kibana-instance) + - [**Scenario: Large package can be installed on a memory restricted Kibana instance**](#scenario-large-package-can-be-installed-on-a-memory-restricted-kibana-instance) - [Scenarios for the real package](#scenarios-for-the-real-package) - [**Scenario: User can install prebuilt rules from scratch, then install new rules and upgrade existing rules from the new package**](#scenario-user-can-install-prebuilt-rules-from-scratch-then-install-new-rules-and-upgrade-existing-rules-from-the-new-package) - [Kibana upgrade](#kibana-upgrade) diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/customizable_rule_fields.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/customizable_rule_fields.md index 66459fd0de38b..f9b63b6de8165 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/customizable_rule_fields.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/customizable_rule_fields.md @@ -1,50 +1,48 @@ -### Customizable rule fields +# Customizable rule fields These are fields in the detection rule schema that are able to be customized on a prebuilt rule. -| field_name | -| name | -| description | -| interval | -| from | -| to | -| note | -| severity | -| tags | -| severity_mapping | -| risk_score | -| risk_score_mapping | -| references | -| false_positives | -| threat | -| note | -| setup | -| related_integrations | -| required_fields | -| max_signals | -| investigation_fields | -| rule_name_override | -| timestamp_override | -| timeline_template | -| building_block_type | -| query | -| language | -| filters | -| index | -| data_view_id | -| alert_suppression | -| event_category_override | -| timestamp_field | -| tiebreaker_field | -| threat_index | -| threat_mapping | -| threat_indicator_path | -| threat_query | -| threat_language | -| threat_filters | -| threshold | -| machine_learning_job_id | -| anomaly_threshold | -| new_terms_fields | -| history_window_start | -| type | +| Rule type | Field name in UI | Diffable rule field | +| ---------------- | ------------------------- | ------------------------- | +| All rule types | Rule name | `name` | +| All rule types | Rule description | `description` | +| All rule types | Tags | `tags` | +| All rule types | Default severity | `severity` | +| All rule types | Severity Override | `severity_mapping` | +| All rule types | Default risk score | `risk_score` | +| All rule types | Risk score override | `risk_score_mapping` | +| All rule types | Reference URLs | `references` | +| All rule types | False positive examples | `false_positives` | +| All rule types | MITRE ATT&CK™ threats | `threat` | +| All rule types | Setup guide | `setup` | +| All rule types | Investigation guide | `note` | +| All rule types | Related integrations | `related_integrations` | +| All rule types | Required fields | `required_fields` | +| All rule types | Rule schedule | `rule_schedule` | +| All rule types | Max alerts per run | `max_signals` | +| All rule types | Rule name override | `rule_name_override` | +| All rule types | Timestamp override | `timestamp_override` | +| All rule types | Timeline template | `timeline_template` | +| All rule types | Building block `*` | `building_block` | +| All rule types | Investigation fields | `investigation_fields` | +| All rule types | Data source `**` | `data_source` | +| All rule types | Suppress alerts | `alert_suppression` | +| Custom Query | Custom query | `kql_query` | +| Saved Query | Custom query | `kql_query` | +| EQL | EQL query | `eql_query` | +| ESQL | ESQL query | `esql_query` | +| Threat Match | Custom query | `kql_query` | +| Threat Match | Indicator index patterns | `threat_index` | +| Threat Match | Indicator index query | `threat_query` | +| Threat Match | Indicator mapping | `threat_mapping` | +| Threat Match | Indicator prefix override | `threat_indicator_path` | +| Threshold | Custom query | `kql_query` | +| Threshold | Threshold config | `threshold` | +| Machine Learning | Machine Learning job | `machine_learning_job_id` | +| Machine Learning | Anomaly score threshold | `anomaly_threshold` | +| New Terms | Custom query | `kql_query` | +| New Terms | Fields | `new_terms_fields` | +| New Terms | History Window Size | `history_window_start` | + +- `*` Building block field is used to mark alerts as building block alerts. +- `**` Data Source represents index patterns or a data view. Machine Learning rules don't have data_source field. diff --git a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/non_customizable_rule_fields.md b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/non_customizable_rule_fields.md index 8cb72a0368281..b408f1fab5698 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/non_customizable_rule_fields.md +++ b/x-pack/solutions/security/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/shared_assets/non_customizable_rule_fields.md @@ -1,8 +1,10 @@ -### Non-customizable rule fields +# Non-customizable rule fields These are fields in the detection rule schema that cannot be customized for a prebuilt rule. -| version | -| id | -| author | -| license | +| Field name | Diffable rule field | +| ------------ | ------------------- | +| Rule type | `type` | +| Rule version | `version` | +| Rule author | `author` | +| Rule license | `license` | diff --git a/x-pack/solutions/security/plugins/security_solution/package.json b/x-pack/solutions/security/plugins/security_solution/package.json index 70bae657557b7..f5f2658df70d8 100644 --- a/x-pack/solutions/security/plugins/security_solution/package.json +++ b/x-pack/solutions/security/plugins/security_solution/package.json @@ -7,16 +7,16 @@ "scripts": { "extract-mitre-attacks": "node scripts/extract_tactics_techniques_mitre.js && node ../../../../../scripts/eslint ./public/detections/mitre/mitre_tactics_techniques.ts --fix", "build-beat-doc": "node scripts/beat_docs/build.js && node ../../../../../scripts/eslint ../timelines/server/utils/beat_schema/fields.ts --fix", - "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../../../node_modules/.bin/cypress", + "cypress": "../../../../../node_modules/.bin/cypress", "cypress:burn": "yarn cypress:dw run --env burn=2 --headed", "cypress:changed-specs-only": "yarn cypress:dw run --changed-specs-only --env burn=2", - "cypress:dw": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file plugins/security_solution/public/management/cypress/cypress.config.ts --ftr-config-file ../../../../test/defend_workflows_cypress/cli_config", + "cypress:dw": "node ./scripts/start_cypress_parallel --config-file plugins/security_solution/public/management/cypress/cypress.config.ts --ftr-config-file ../../../../test/defend_workflows_cypress/cli_config", "cypress:dw:open": "yarn cypress:dw open", "cypress:dw:run": "yarn cypress:dw run", - "cypress:dw:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file plugins/security_solution/public/management/cypress/cypress_serverless.config.ts --ftr-config-file ../../../../test/defend_workflows_cypress/serverless_config", + "cypress:dw:serverless": "node ./scripts/start_cypress_parallel --config-file plugins/security_solution/public/management/cypress/cypress_serverless.config.ts --ftr-config-file ../../../../test/defend_workflows_cypress/serverless_config", "cypress:dw:serverless:open": "yarn cypress:dw:serverless open", "cypress:dw:serverless:run": "yarn cypress:dw:serverless run", - "cypress:dw:qa:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel_serverless --config-file plugins/security_solution/public/management/cypress/cypress_serverless_qa.config.ts", + "cypress:dw:qa:serverless": "node ./scripts/start_cypress_parallel_serverless --config-file plugins/security_solution/public/management/cypress/cypress_serverless_qa.config.ts", "cypress:dw:qa:serverless:run": "yarn cypress:dw:qa:serverless run", "cypress:dw:serverless:changed-specs-only": "yarn cypress:dw:serverless run --changed-specs-only --env burn=2", "cypress:dw:endpoint": "echo '\n** WARNING **: Run script `cypress:dw:endpoint` no longer valid! Use `cypress:dw` instead\n'", diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts index 5cfabe266eda8..326cf7287cb55 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/categories.ts @@ -70,6 +70,10 @@ export const FOOTER_CATEGORIES: Array> = [ defaultMessage: 'Management', }), iconType: 'gear', - linkIds: [ExternalPageName.management, ExternalPageName.integrationsSecurity], + linkIds: [ + ExternalPageName.management, + ExternalPageName.managementMonitoring, + ExternalPageName.integrationsSecurity, + ], }, ]; diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_links.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_links.ts index abe7cc68603bd..8e59adabec834 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_links.ts @@ -31,6 +31,11 @@ export const settingsNavLinks: SolutionNavLink[] = [ title: i18n.MANAGEMENT_TITLE, isFooterLink: true, }, + { + id: ExternalPageName.managementMonitoring, + title: i18n.MONITORING_TITLE, + isFooterLink: true, + }, { id: ExternalPageName.integrationsSecurity, title: i18n.INTEGRATIONS_TITLE, diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_translations.ts b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_translations.ts index dec17809971f3..ef4467aaf677e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/app/solution_navigation/links/sections/settings_translations.ts @@ -41,3 +41,6 @@ export const VISUALIZE_DESCRIPTION = i18n.translate( defaultMessage: 'Manage visualization library. Create, edit, and share visualizations.', } ); +export const MONITORING_TITLE = i18n.translate('xpack.securitySolution.navLinks.monitoring.title', { + defaultMessage: 'Stack Monitoring', +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.test.tsx index 01d9cd4f44dc6..0bd3e70b088ac 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.test.tsx @@ -5,13 +5,15 @@ * 2.0. */ -import type { ContentReferences } from '@kbn/elastic-assistant-common'; -import { contentReferenceComponentFactory } from './content_reference_component_factory'; +import type { ContentReference } from '@kbn/elastic-assistant-common'; +import { ContentReferenceComponentFactory } from './content_reference_component_factory'; import React from 'react'; import { render, screen } from '@testing-library/react'; -import type { ContentReferenceNode } from '../content_reference_parser'; - -const testContentReferenceNode = { contentReferenceId: '1' } as ContentReferenceNode; +import type { + InvalidContentReferenceNode, + ResolvedContentReferenceNode, + UnresolvedContentReferenceNode, +} from '../content_reference_parser'; jest.mock('../../../../common/lib/kibana', () => ({ useNavigation: jest.fn().mockReturnValue({ @@ -34,89 +36,80 @@ describe('contentReferenceComponentFactory', () => { [ 'EsqlQueryReference', { - '1': { - id: '1', - type: 'EsqlQuery', - query: '', - label: '', - }, - } as ContentReferences, - testContentReferenceNode, + id: '1', + type: 'EsqlQuery', + query: '', + label: '', + } as ContentReference, ], [ 'KnowledgeBaseEntryReference', { - '1': { - id: '1', - type: 'KnowledgeBaseEntry', - knowledgeBaseEntryId: '', - knowledgeBaseEntryName: '', - }, - } as ContentReferences, - testContentReferenceNode, + id: '1', + type: 'KnowledgeBaseEntry', + knowledgeBaseEntryId: '', + knowledgeBaseEntryName: '', + } as ContentReference, ], [ 'ProductDocumentationReference', { - '1': { - id: '1', - type: 'ProductDocumentation', - title: '', - url: '', - }, - } as ContentReferences, - testContentReferenceNode, + id: '1', + type: 'ProductDocumentation', + title: '', + url: '', + } as ContentReference, ], [ 'SecurityAlertReference', { - '1': { - id: '1', - type: 'SecurityAlert', - alertId: '', - }, - } as ContentReferences, - testContentReferenceNode, + id: '1', + type: 'SecurityAlert', + alertId: '', + } as ContentReference, ], [ 'SecurityAlertsPageReference', { - '1': { - id: '1', - type: 'SecurityAlertsPage', - }, - } as ContentReferences, - testContentReferenceNode, + id: '1', + type: 'SecurityAlertsPage', + } as ContentReference, ], ])( - "Renders component: '%s'", - async ( - testId: string, - contentReferences: ContentReferences, - contentReferenceNode: ContentReferenceNode - ) => { - const Component = contentReferenceComponentFactory({ - contentReferences, - contentReferencesVisible: true, - loading: false, - }); - - render(); + "Renders correct component for '%s'", + async (testId: string, contentReference: ContentReference) => { + const resolvedContentReferenceNode: ResolvedContentReferenceNode = { + contentReferenceId: '1', + contentReferenceCount: 1, + contentReferenceBlock: '{reference(123)}', + contentReference, + type: 'contentReference', + }; + + render( + + ); expect(screen.getByTestId(testId)).toBeInTheDocument(); } ); - it('renders nothing when specific contentReference is undefined', async () => { - const Component = contentReferenceComponentFactory({ - contentReferences: {}, - contentReferencesVisible: true, - loading: false, - }); + it('renders nothing when specific contentReferenceNode is invalid', () => { + const invalidContentReferenceNode: InvalidContentReferenceNode = { + contentReferenceId: '1', + contentReferenceCount: undefined, + contentReferenceBlock: '{reference(123)}', + contentReference: undefined, + type: 'contentReference', + }; const { container } = render( - ); @@ -124,59 +117,23 @@ describe('contentReferenceComponentFactory', () => { expect(screen.queryByText('[1]')).not.toBeInTheDocument(); }); - it('renders placeholder if contentReferences are undefined and is loading', async () => { - const Component = contentReferenceComponentFactory({ - contentReferences: undefined, - contentReferencesVisible: true, - loading: true, - }); + it('renders placeholder if contentReferenceNode is unresolved', () => { + const unresolvedContentReferenceNode: UnresolvedContentReferenceNode = { + contentReferenceId: '1', + contentReferenceCount: 1, + contentReferenceBlock: '{reference(123)}', + contentReference: undefined, + type: 'contentReference', + }; render( - ); expect(screen.getByTestId('ContentReferenceButton')).toBeInTheDocument(); expect(screen.getByText('[1]')).toBeInTheDocument(); }); - - it('renders nothing if contentReferences are undefined and is not loading', async () => { - const Component = contentReferenceComponentFactory({ - contentReferences: undefined, - contentReferencesVisible: true, - loading: false, - }); - - const { container } = render( - - ); - - expect(container).toBeEmptyDOMElement(); - expect(screen.queryByText('[1]')).not.toBeInTheDocument(); - }); - - it('renders nothing if contentReferenceId is empty string', async () => { - const Component = contentReferenceComponentFactory({ - contentReferences: { - '1': { - id: '1', - type: 'SecurityAlertsPage', - }, - } as ContentReferences, - contentReferencesVisible: true, - loading: false, - }); - - const { container } = render( - - ); - - expect(container).toBeEmptyDOMElement(); - expect(screen.queryByText('[-1]')).not.toBeInTheDocument(); - }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.tsx index 2aa1fddf985e1..6fe92c32a22fa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/content_reference_component_factory.tsx @@ -5,9 +5,19 @@ * 2.0. */ -import type { ContentReferences } from '@kbn/elastic-assistant-common'; +import type { + ContentReferences, + EsqlContentReference, + KnowledgeBaseEntryContentReference, + ProductDocumentationContentReference, + SecurityAlertContentReference, + SecurityAlertsPageContentReference, +} from '@kbn/elastic-assistant-common'; import React from 'react'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { + ContentReferenceNode, + ResolvedContentReferenceNode, +} from '../content_reference_parser'; import { KnowledgeBaseEntryReference } from './knowledge_base_entry_reference'; import { SecurityAlertReference } from './security_alert_reference'; import { SecurityAlertsPageReference } from './security_alerts_page_reference'; @@ -15,78 +25,75 @@ import { ContentReferenceButton } from './content_reference_button'; import { ProductDocumentationReference } from './product_documentation_reference'; import { EsqlQueryReference } from './esql_query_reference'; -export interface ContentReferenceComponentFactory { - contentReferences?: ContentReferences; +/** While a message is being streamed, content references are null. When a message has finished streaming, content references are either defined or undefined */ +export type StreamingOrFinalContentReferences = ContentReferences | undefined | null; + +export interface Props { contentReferencesVisible: boolean; - loading: boolean; + contentReferenceNode: ContentReferenceNode; } -export const contentReferenceComponentFactory = ({ - contentReferences, +export const ContentReferenceComponentFactory: React.FC = ({ contentReferencesVisible, - loading, -}: ContentReferenceComponentFactory) => { - const ContentReferenceComponent = ( - contentReferenceNode: ContentReferenceNode - ): React.ReactNode => { - if (!contentReferencesVisible) return null; - if (!contentReferenceNode.contentReferenceId) return null; + contentReferenceNode, +}: Props) => { + if (!contentReferencesVisible) return null; + + if (contentReferenceNode.contentReferenceCount === undefined) return null; - const defaultNode = ( + if (contentReferenceNode.contentReference === undefined) { + return ( ); + } - if (!contentReferences && loading) return defaultNode; - - const contentReference = contentReferences?.[contentReferenceNode.contentReferenceId]; - - if (!contentReference) return null; - - switch (contentReference.type) { - case 'KnowledgeBaseEntry': - return ( - - ); - case 'SecurityAlert': - return ( - - ); - case 'SecurityAlertsPage': - return ( - - ); - case 'ProductDocumentation': - return ( - - ); - case 'EsqlQuery': - return ( - - ); - default: - return defaultNode; + switch (contentReferenceNode.contentReference.type) { + case 'KnowledgeBaseEntry': { + return ( + + } + /> + ); } - }; - - ContentReferenceComponent.displayName = 'ContentReferenceComponent'; - - return ContentReferenceComponent; + case 'SecurityAlert': + return ( + + } + /> + ); + case 'SecurityAlertsPage': + return ( + + } + /> + ); + case 'ProductDocumentation': + return ( + + } + /> + ); + case 'EsqlQuery': { + return ( + + } + /> + ); + } + default: + return null; + } }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/esql_query_reference.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/esql_query_reference.tsx index 0241b8750882d..39b3fd74529d2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/esql_query_reference.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/esql_query_reference.tsx @@ -8,19 +8,15 @@ import type { EsqlContentReference } from '@kbn/elastic-assistant-common'; import React, { useCallback } from 'react'; import { EuiLink } from '@elastic/eui'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { ResolvedContentReferenceNode } from '../content_reference_parser'; import { PopoverReference } from './popover_reference'; import { useKibana } from '../../../../common/lib/kibana'; interface Props { - contentReferenceNode: ContentReferenceNode; - esqlContentReference: EsqlContentReference; + contentReferenceNode: ResolvedContentReferenceNode; } -export const EsqlQueryReference: React.FC = ({ - contentReferenceNode, - esqlContentReference, -}) => { +export const EsqlQueryReference: React.FC = ({ contentReferenceNode }) => { const { discover: { locator }, application: { navigateToApp }, @@ -34,8 +30,9 @@ export const EsqlQueryReference: React.FC = ({ } const url = await locator.getLocation({ query: { - esql: esqlContentReference.query, + esql: contentReferenceNode.contentReference.query, }, + timeRange: contentReferenceNode.contentReference.timerange, }); navigateToApp(url.app, { @@ -43,7 +40,7 @@ export const EsqlQueryReference: React.FC = ({ openInNewTab: true, }); }, - [locator, esqlContentReference.query, navigateToApp] + [locator, contentReferenceNode, navigateToApp] ); return ( @@ -51,7 +48,7 @@ export const EsqlQueryReference: React.FC = ({ contentReferenceCount={contentReferenceNode.contentReferenceCount} data-test-subj="EsqlQueryReference" > - {esqlContentReference.label} + {contentReferenceNode.contentReference.label} ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/knowledge_base_entry_reference.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/knowledge_base_entry_reference.tsx index c5b7e7586bdb6..c35a0ae8b506f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/knowledge_base_entry_reference.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/knowledge_base_entry_reference.tsx @@ -9,30 +9,26 @@ import type { KnowledgeBaseEntryContentReference } from '@kbn/elastic-assistant- import React, { useCallback } from 'react'; import { EuiLink } from '@elastic/eui'; import { KNOWLEDGE_BASE_ENTRY_REFERENCE_LABEL } from './translations'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { ResolvedContentReferenceNode } from '../content_reference_parser'; import { PopoverReference } from './popover_reference'; import { useKibana } from '../../../../common/lib/kibana'; interface Props { - contentReferenceNode: ContentReferenceNode; - knowledgeBaseEntryContentReference: KnowledgeBaseEntryContentReference; + contentReferenceNode: ResolvedContentReferenceNode; } -export const KnowledgeBaseEntryReference: React.FC = ({ - contentReferenceNode, - knowledgeBaseEntryContentReference, -}) => { +export const KnowledgeBaseEntryReference: React.FC = ({ contentReferenceNode }) => { const { navigateToApp } = useKibana().services.application; const onClick = useCallback( (e: React.MouseEvent) => { e.preventDefault(); navigateToApp('management', { - path: `kibana/securityAiAssistantManagement?tab=knowledge_base&entry_search_term=${knowledgeBaseEntryContentReference.knowledgeBaseEntryId}`, + path: `kibana/securityAiAssistantManagement?tab=knowledge_base&entry_search_term=${contentReferenceNode.contentReference.knowledgeBaseEntryId}`, openInNewTab: true, }); }, - [navigateToApp, knowledgeBaseEntryContentReference] + [navigateToApp, contentReferenceNode] ); return ( @@ -41,7 +37,7 @@ export const KnowledgeBaseEntryReference: React.FC = ({ data-test-subj="KnowledgeBaseEntryReference" > - {`${KNOWLEDGE_BASE_ENTRY_REFERENCE_LABEL}: ${knowledgeBaseEntryContentReference.knowledgeBaseEntryName}`} + {`${KNOWLEDGE_BASE_ENTRY_REFERENCE_LABEL}: ${contentReferenceNode.contentReference.knowledgeBaseEntryName}`} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/product_documentation_reference.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/product_documentation_reference.tsx index 215d2db00a46e..39009e4ecd05f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/product_documentation_reference.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/product_documentation_reference.tsx @@ -8,25 +8,21 @@ import type { ProductDocumentationContentReference } from '@kbn/elastic-assistant-common'; import React from 'react'; import { EuiLink } from '@elastic/eui'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { ResolvedContentReferenceNode } from '../content_reference_parser'; import { PopoverReference } from './popover_reference'; interface Props { - contentReferenceNode: ContentReferenceNode; - productDocumentationContentReference: ProductDocumentationContentReference; + contentReferenceNode: ResolvedContentReferenceNode; } -export const ProductDocumentationReference: React.FC = ({ - contentReferenceNode, - productDocumentationContentReference, -}) => { +export const ProductDocumentationReference: React.FC = ({ contentReferenceNode }) => { return ( - - {productDocumentationContentReference.title} + + {contentReferenceNode.contentReference.title} ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alert_reference.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alert_reference.tsx index 8accfd4fd0a2b..d507d0171e2c4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alert_reference.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alert_reference.tsx @@ -9,30 +9,26 @@ import type { SecurityAlertContentReference } from '@kbn/elastic-assistant-commo import React, { useCallback } from 'react'; import { EuiLink } from '@elastic/eui'; import { SECURITY_ALERT_REFERENCE_LABEL } from './translations'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { ResolvedContentReferenceNode } from '../content_reference_parser'; import { PopoverReference } from './popover_reference'; import { useKibana } from '../../../../common/lib/kibana'; interface Props { - contentReferenceNode: ContentReferenceNode; - securityAlertContentReference: SecurityAlertContentReference; + contentReferenceNode: ResolvedContentReferenceNode; } -export const SecurityAlertReference: React.FC = ({ - contentReferenceNode, - securityAlertContentReference, -}) => { +export const SecurityAlertReference: React.FC = ({ contentReferenceNode }) => { const { navigateToApp } = useKibana().services.application; const onClick = useCallback( (e: React.MouseEvent) => { e.preventDefault(); navigateToApp('security', { - path: `alerts/redirect/${securityAlertContentReference.alertId}`, + path: `alerts/redirect/${contentReferenceNode.contentReference.alertId}`, openInNewTab: true, }); }, - [navigateToApp, securityAlertContentReference] + [navigateToApp, contentReferenceNode] ); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alerts_page_reference.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alerts_page_reference.tsx index 54a31f97aba72..a402234c454bb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alerts_page_reference.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/components/security_alerts_page_reference.tsx @@ -8,21 +8,17 @@ import type { SecurityAlertsPageContentReference } from '@kbn/elastic-assistant-common'; import React, { useCallback } from 'react'; import { EuiLink } from '@elastic/eui'; -import type { ContentReferenceNode } from '../content_reference_parser'; +import type { ResolvedContentReferenceNode } from '../content_reference_parser'; import { PopoverReference } from './popover_reference'; import { SECURITY_ALERTS_PAGE_REFERENCE_LABEL } from './translations'; import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use_navigate_to_alerts_page_with_filters'; import { FILTER_OPEN, FILTER_ACKNOWLEDGED } from '../../../../../common/types'; interface Props { - contentReferenceNode: ContentReferenceNode; - securityAlertsPageContentReference: SecurityAlertsPageContentReference; + contentReferenceNode: ResolvedContentReferenceNode; } -export const SecurityAlertsPageReference: React.FC = ({ - contentReferenceNode, - securityAlertsPageContentReference, -}) => { +export const SecurityAlertsPageReference: React.FC = ({ contentReferenceNode }) => { const openAlertsPageWithFilters = useNavigateToAlertsPageWithFilters(); const onClick = useCallback( diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.test.ts b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.test.ts index 9b3acb5e4f4a1..7e76c383464be 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.test.ts @@ -8,12 +8,14 @@ import unified from 'unified'; import markdown from 'remark-parse-no-trim'; import type { Parent } from 'mdast'; -import { ContentReferenceParser } from './content_reference_parser'; +import { contentReferenceParser } from './content_reference_parser'; describe('ContentReferenceParser', () => { - it('extracts references from poem', async () => { - const file = unified().use([[markdown, {}], ContentReferenceParser]) - .parse(`With a wagging tail and a wet, cold nose,{reference(ccaSI)} + it('extracts references from poem', () => { + const file = unified().use([ + [markdown, {}], + contentReferenceParser({ contentReferences: null }), + ]).parse(`With a wagging tail and a wet, cold nose,{reference(ccaSI)} A furry friend, from head to toes.{reference(ccaSI)} Loyal companion, always near,{reference(ccaSI)} Chasing squirrels, full of cheer.{reference(ccaSI)} @@ -37,8 +39,11 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ); }); - it('extracts reference after linebreak', async () => { - const file = unified().use([[markdown, {}], ContentReferenceParser]).parse(`First line + it('extracts reference after linebreak', () => { + const file = unified().use([ + [markdown, {}], + contentReferenceParser({ contentReferences: null }), + ]).parse(`First line {reference(FTQJp)} `) as Parent; @@ -50,9 +55,9 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ); }); - it('eats empty content reference', async () => { + it('eats empty content reference', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('There is an empty content reference.{reference()}') as Parent; expect(file.children[0].children).toEqual( @@ -60,16 +65,51 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; expect.objectContaining({ type: 'text', value: 'There is an empty content reference.' }), expect.objectContaining({ type: 'contentReference', - contentReferenceCount: -1, - contentReferenceId: '', + contentReferenceCount: 1, }), ]) ); }); - it('eats space preceding content reference', async () => { + it('invalid content reference has correct contentReferenceCount', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([ + [markdown, {}], + contentReferenceParser({ + contentReferences: { + valid1: { id: 'valid1', type: 'SecurityAlertsPage' }, + valid2: { id: 'valid2', type: 'SecurityAlertsPage' }, + }, + }), + ]) + .parse( + 'There {reference(valid1)} is one invalid content reference {reference(invalid)} and two valid ones. {reference(valid2)}' + ) as Parent; + + expect(file.children[0].children).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + type: 'contentReference', + contentReferenceCount: 1, + contentReferenceId: 'valid1', + }), + expect.objectContaining({ + type: 'contentReference', + contentReferenceCount: undefined, + contentReferenceId: 'invalid', + }), + expect.objectContaining({ + type: 'contentReference', + contentReferenceCount: 2, + contentReferenceId: 'valid2', + }), + ]) + ); + }); + + it('eats space preceding content reference', () => { + const file = unified() + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('Delete space after punctuation. {reference(example)}') as Parent; expect(file.children[0].children).toEqual( @@ -80,22 +120,42 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ); }); - it('parses when there is no space preceding the content reference', async () => { + it('parses when there is no space preceding the content reference', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('No preceding space.{reference(example)}') as Parent; + expect(file.children[0].children).toEqual( + expect.arrayContaining([expect.objectContaining({ type: 'contentReference' })]) + ); + }); + + it('correct content reference count when contentReferences is null', () => { + const file = unified() + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) + .parse('No preceding space.{reference(example)} {reference(example2)}') as Parent; + expect(file.children[0].children).toEqual( expect.arrayContaining([ - expect.objectContaining({ type: 'text', value: 'No preceding space.' }), - expect.objectContaining({ type: 'contentReference' }), + expect.objectContaining({ + type: 'contentReference', + contentReferenceId: 'example', + contentReferenceCount: 1, + contentReference: undefined, + }), + expect.objectContaining({ + type: 'contentReference', + contentReferenceId: 'example2', + contentReferenceCount: 2, + contentReference: undefined, + }), ]) ); }); - it('handles single citation block', async () => { + it('handles single citation block', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('Hello world {reference(example)} hello wolrd') as Parent; expect(file.children[0].children).toEqual([ @@ -155,9 +215,9 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ]); }); - it('handles multiple citation blocks with different referenceIds', async () => { + it('handles multiple citation blocks with different referenceIds', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('Hello world {reference(example)} hello world {reference(example2)}') as Parent; expect(file.children[0].children).toEqual([ @@ -236,9 +296,9 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ]); }); - it('handles multiple citation blocks with same referenceIds', async () => { + it('handles multiple citation blocks with same referenceIds', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('Hello world {reference(example)} hello world {reference(example)}') as Parent; expect(file.children[0].children).toEqual([ @@ -317,9 +377,9 @@ Their love's a beacon, shining bright.{reference(ccaSI)}`) as Parent; ]); }); - it('handles partial citation blocks', async () => { + it('handles partial citation blocks', () => { const file = unified() - .use([[markdown, {}], ContentReferenceParser]) + .use([[markdown, {}], contentReferenceParser({ contentReferences: null })]) .parse('Hello world {reference(example)} hello world {reference(') as Parent; expect(file.children[0].children).toEqual([ diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.ts b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.ts index e64a96efa1360..7a5e64276b60d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/content_reference/content_reference_parser.ts @@ -6,122 +6,183 @@ */ import type { RemarkTokenizer } from '@elastic/eui'; -import type { ContentReferenceBlock } from '@kbn/elastic-assistant-common'; +import type { ContentReference, ContentReferenceBlock } from '@kbn/elastic-assistant-common'; import type { Plugin } from 'unified'; import type { Node } from 'unist'; +import type { StreamingOrFinalContentReferences } from './components/content_reference_component_factory'; -export interface ContentReferenceNode extends Node { +/** A ContentReferenceNode that has been extracted from the message and the content reference details are available. */ +export interface ResolvedContentReferenceNode extends Node { type: 'contentReference'; contentReferenceId: string; contentReferenceCount: number; contentReferenceBlock: ContentReferenceBlock; + contentReference: T; +} + +/** A ContentReferenceNode that has been extracted from the message but the content reference details are not available on the client **yet**. When the message finishes streaming, the details will become available. */ +export interface UnresolvedContentReferenceNode extends Node { + type: 'contentReference'; + contentReferenceId: string; + contentReferenceCount: number; + contentReferenceBlock: ContentReferenceBlock; + contentReference: undefined; +} + +/** A ContentReferenceNode that has been extracted from the message but the content reference details are erroneous. */ +export interface InvalidContentReferenceNode extends Node { + type: 'contentReference'; + contentReferenceId: string; + contentReferenceCount: undefined; + contentReferenceBlock: ContentReferenceBlock; + contentReference: undefined; +} + +export type ContentReferenceNode = + | ResolvedContentReferenceNode + | UnresolvedContentReferenceNode + | InvalidContentReferenceNode; + +interface Params { + contentReferences: StreamingOrFinalContentReferences; } /** Matches `{reference` and ` {reference(` */ const REFERENCE_START_PATTERN = '\\u0020?\\{reference'; -export const ContentReferenceParser: Plugin = function ContentReferenceParser() { - const Parser = this.Parser; - const tokenizers = Parser.prototype.inlineTokenizers; - const methods = Parser.prototype.inlineMethods; +export const contentReferenceParser: (params: Params) => Plugin = ({ contentReferences }) => + function ContentReferenceParser() { + const Parser = this.Parser; + const tokenizers = Parser.prototype.inlineTokenizers; + const methods = Parser.prototype.inlineMethods; - let currentContentReferenceCount = 1; - const contentReferenceCounts: Record = {}; + let currentContentReferenceCount = 1; + const contentReferenceCounts: Record = {}; - const tokenizeCustomCitation: RemarkTokenizer = function tokenizeCustomCitation( - eat, - value, - silent - ) { - const [match] = value.match(new RegExp(`^${REFERENCE_START_PATTERN}`)) || []; + const tokenizeCustomCitation: RemarkTokenizer = function tokenizeCustomCitation( + eat, + value, + silent + ) { + const [match] = value.match(new RegExp(`^${REFERENCE_START_PATTERN}`)) || []; - if (!match) return false; + if (!match) return false; - if (value[match.length] !== '(') return false; + if (value[match.length] !== '(') return false; - let index = match.length; + let index = match.length; - function readArg(open: string, close: string) { - if (value[index] !== open) return ''; - index++; + function readArg(open: string, close: string) { + if (value[index] !== open) return ''; + index++; - let body = ''; - let openBrackets = 0; + let body = ''; + let openBrackets = 0; - for (; index < value.length; index++) { - const char = value[index]; - if (char === close && openBrackets === 0) { - index++; + for (; index < value.length; index++) { + const char = value[index]; + if (char === close && openBrackets === 0) { + index++; - return body; - } else if (char === close) { - openBrackets--; - } else if (char === open) { - openBrackets++; + return body; + } else if (char === close) { + openBrackets--; + } else if (char === open) { + openBrackets++; + } + + body += char; } - body += char; + return ''; } - return ''; - } - - const contentReferenceId = readArg('(', ')'); + const contentReferenceId = readArg('(', ')'); - const closeChar = value[index]; - if (closeChar !== '}') return false; + const closeChar = value[index]; + if (closeChar !== '}') return false; - const now = eat.now(); + const now = eat.now(); - if (!contentReferenceId) { - this.file.info('No content reference id found', { - line: now.line, - column: now.column + match.length + 1, - }); - } + if (!contentReferenceId) { + this.file.info('No content reference id found', { + line: now.line, + column: now.column + match.length + 1, + }); + } - if (silent) { - return true; - } + if (silent) { + return true; + } - now.column += match.length + 1; - now.offset += match.length + 1; + now.column += match.length + 1; + now.offset += match.length + 1; - const contentReferenceBlock: ContentReferenceBlock = `{reference(${contentReferenceId})}`; + const contentReferenceBlock: ContentReferenceBlock = `{reference(${contentReferenceId})}`; + const contentReference = contentReferences?.[contentReferenceId]; - const getContentReferenceCount = (id: string) => { - if (!id) { - return -1; + const getContentReferenceCount = () => { + // If the content reference id is already in the contentReferenceCounts, return the existing count + if (contentReferenceId in contentReferenceCounts) { + return contentReferenceCounts[contentReferenceId]; + } + // If the content reference id is not in the contentReferenceCounts, increment the currentContentReferenceCount and return the new count + contentReferenceCounts[contentReferenceId] = currentContentReferenceCount++; + return contentReferenceCounts[contentReferenceId]; + }; + + const toEat = `${match.startsWith(' ') ? ' ' : ''}${contentReferenceBlock}`; + + if (contentReferences === null) { + // The message is still streaming, so the content reference details are not available yet + const contentReferenceNode: UnresolvedContentReferenceNode = { + type: 'contentReference', + contentReferenceId, + contentReferenceCount: getContentReferenceCount(), + contentReferenceBlock, + contentReference: undefined, + }; + + return eat(toEat)(contentReferenceNode); } - if (id in contentReferenceCounts) { - return contentReferenceCounts[id]; + + if (contentReference === undefined) { + // The message has finished streaming, but the content reference details were not found + const contentReferenceNode: InvalidContentReferenceNode = { + type: 'contentReference', + contentReferenceId, + contentReferenceCount: undefined, + contentReferenceBlock, + contentReference, + }; + + return eat(toEat)(contentReferenceNode); } - contentReferenceCounts[id] = currentContentReferenceCount++; - return contentReferenceCounts[id]; - }; - const toEat = `${match.startsWith(' ') ? ' ' : ''}${contentReferenceBlock}`; + // The message has finished streaming and the content reference details were found + const contentReferenceNode: ResolvedContentReferenceNode = { + type: 'contentReference', + contentReferenceId, + contentReferenceCount: getContentReferenceCount(), + contentReferenceBlock, + contentReference, + }; - const contentReferenceNode: ContentReferenceNode = { - type: 'contentReference', - contentReferenceId, - contentReferenceCount: getContentReferenceCount(contentReferenceId), - contentReferenceBlock, + return eat(toEat)(contentReferenceNode); }; - return eat(toEat)(contentReferenceNode); - }; + tokenizeCustomCitation.notInLink = true; - tokenizeCustomCitation.notInLink = true; + tokenizeCustomCitation.locator = (value, fromIndex) => { + const nextIndex = value + .substring(fromIndex) + .match(new RegExp(REFERENCE_START_PATTERN))?.index; + if (nextIndex === undefined) { + return -1; + } + return nextIndex + 1; + }; - tokenizeCustomCitation.locator = (value, fromIndex) => { - const nextIndex = value.substring(fromIndex).match(new RegExp(REFERENCE_START_PATTERN))?.index; - if (nextIndex === undefined) { - return -1; - } - return nextIndex + 1; + tokenizers.contentReference = tokenizeCustomCitation; + methods.splice(methods.indexOf('text'), 0, 'contentReference'); }; - - tokenizers.contentReference = tokenizeCustomCitation; - methods.splice(methods.indexOf('text'), 0, 'contentReference'); -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx index 58634c9c53d1c..45f6c4009f72b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/index.tsx @@ -88,6 +88,7 @@ export const getComments: GetAssistantMessages = ({ regenerateMessage={regenerateMessageOfConversation} setIsStreaming={setIsStreaming} transformMessage={() => ({ content: '' } as unknown as ContentMessage)} + contentReferences={null} isFetching // we never need to append to a code block in the loading comment, which is what this index is used for index={999} @@ -131,6 +132,7 @@ export const getComments: GetAssistantMessages = ({ refetchCurrentConversation={refetchCurrentConversation} regenerateMessage={regenerateMessageOfConversation} setIsStreaming={setIsStreaming} + contentReferences={null} transformMessage={() => ({ content: '' } as unknown as ContentMessage)} // we never need to append to a code block in the system comment, which is what this index is used for index={999} @@ -176,7 +178,7 @@ export const getComments: GetAssistantMessages = ({ children: ( ({ + useNavigation: jest.fn().mockReturnValue({ + navigateTo: jest.fn(), + }), + useKibana: jest.fn().mockReturnValue({ + services: { + discover: { + locator: jest.fn(), + }, + application: { + navigateToApp: jest.fn(), + }, + }, + }), +})); + const content = 'Test Content'; const mockAbortStream = jest.fn(); const testProps = { @@ -30,6 +47,7 @@ const testProps = { regenerateMessage: jest.fn(), setIsStreaming: jest.fn(), transformMessage: jest.fn(), + contentReferences: undefined, }; const mockReader = jest.fn() as unknown as ReadableStreamDefaultReader; @@ -61,6 +79,61 @@ describe('StreamComment', () => { expect(screen.getByText(content)).toBeInTheDocument(); }); + it('renders citations correctly when content references are defined', () => { + render( + + ); + + expect(screen.getByText('[1]')).toBeInTheDocument(); + expect(screen.getByTestId('ContentReferenceButton')).toBeEnabled(); + }); + + it('renders citations correctly when content references null', () => { + render( + + ); + + expect(screen.getByText('[1]')).toBeInTheDocument(); + expect(screen.getByTestId('ContentReferenceButton')).not.toBeEnabled(); + }); + + it('renders citations correctly when content references are undefined', () => { + render( + + ); + + expect(screen.queryByText('[1]')).not.toBeInTheDocument(); + }); + it('renders cursor when content is loading', () => { render(); expect(screen.getByTestId('cursor')).toBeInTheDocument(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/index.tsx index 93e52c275f242..fd49909ccda4f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/index.tsx @@ -7,18 +7,18 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { ContentReferences } from '@kbn/elastic-assistant-common'; import type { ContentMessage } from '..'; import { useStream } from './use_stream'; import { StopGeneratingButton } from './buttons/stop_generating_button'; import { RegenerateResponseButton } from './buttons/regenerate_response_button'; import { MessagePanel } from './message_panel'; import { MessageText } from './message_text'; +import type { StreamingOrFinalContentReferences } from '../content_reference/components/content_reference_component_factory'; interface Props { abortStream: () => void; content?: string; - contentReferences?: ContentReferences; + contentReferences: StreamingOrFinalContentReferences; contentReferencesVisible?: boolean; contentReferencesEnabled?: boolean; isError?: boolean; @@ -116,8 +116,8 @@ export const StreamComment = ({ contentReferences={contentReferences} contentReferencesEnabled={contentReferencesEnabled} index={index} - loading={isAnythingLoading} contentReferencesVisible={contentReferencesVisible} + loading={isAnythingLoading} /> } error={error ? new Error(error) : undefined} diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/message_text.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/message_text.tsx index e0aab7040ddd4..60020f8b1abff 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/message_text.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/get_comments/stream/message_text.tsx @@ -20,15 +20,15 @@ import { css } from '@emotion/react'; import type { Code, InlineCode, Parent, Text } from 'mdast'; import React, { useMemo } from 'react'; import type { Node } from 'unist'; -import type { ContentReferences } from '@kbn/elastic-assistant-common'; import { customCodeBlockLanguagePlugin } from '../custom_codeblock/custom_codeblock_markdown_plugin'; import { CustomCodeBlock } from '../custom_codeblock/custom_code_block'; -import { ContentReferenceParser } from '../content_reference/content_reference_parser'; -import { contentReferenceComponentFactory } from '../content_reference/components/content_reference_component_factory'; +import { contentReferenceParser } from '../content_reference/content_reference_parser'; +import type { StreamingOrFinalContentReferences } from '../content_reference/components/content_reference_component_factory'; +import { ContentReferenceComponentFactory } from '../content_reference/components/content_reference_component_factory'; interface Props { content: string; - contentReferences?: ContentReferences; + contentReferences: StreamingOrFinalContentReferences; contentReferencesVisible: boolean; contentReferencesEnabled: boolean; index: number; @@ -105,8 +105,7 @@ const loadingCursorPlugin = () => { }; interface GetPluginDependencies { - contentReferences?: ContentReferences; - loading: boolean; + contentReferences: StreamingOrFinalContentReferences; contentReferencesVisible: boolean; contentReferencesEnabled: boolean; } @@ -114,7 +113,6 @@ interface GetPluginDependencies { const getPluginDependencies = ({ contentReferences, contentReferencesVisible, - loading, contentReferencesEnabled, }: GetPluginDependencies) => { const parsingPlugins = getDefaultEuiMarkdownParsingPlugins(); @@ -127,11 +125,14 @@ const getPluginDependencies = ({ ...components, ...(contentReferencesEnabled ? { - contentReference: contentReferenceComponentFactory({ - contentReferences, - contentReferencesVisible, - loading, - }), + contentReference: (contentReferenceNode) => { + return ( + + ); + }, } : {}), cursor: Cursor, @@ -169,7 +170,7 @@ const getPluginDependencies = ({ loadingCursorPlugin, customCodeBlockLanguagePlugin, ...parsingPlugins, - ...(contentReferencesEnabled ? [ContentReferenceParser] : []), + ...(contentReferencesEnabled ? [contentReferenceParser({ contentReferences })] : []), ], processingPluginList: processingPlugins, }; @@ -194,9 +195,8 @@ export function MessageText({ contentReferences, contentReferencesVisible, contentReferencesEnabled, - loading, }), - [contentReferences, contentReferencesVisible, contentReferencesEnabled, loading] + [contentReferences, contentReferencesVisible, contentReferencesEnabled] ); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx index 526261d13bca6..42a98a0b743db 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/barchart.tsx @@ -13,7 +13,7 @@ import { Chart, BarSeries, Axis, Position, ScaleType, Settings } from '@elastic/ import { getOr, get, isNumber } from 'lodash/fp'; import deepmerge from 'deepmerge'; import { v4 as uuidv4 } from 'uuid'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import deepEqual from 'fast-deep-equal'; import { escapeDataProviderId } from '../drag_and_drop/helpers'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/chart_place_holder.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/chart_place_holder.tsx index bce7146d3c1db..a3938242c910e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/chart_place_holder.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/chart_place_holder.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiFlexItem, EuiText, EuiFlexGroup } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import type { ChartSeriesData } from './common'; import { checkIfAllValuesAreZero } from './common'; import * as i18n from './translation'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.test.tsx index f600eb501d189..5652d1337020c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.test.tsx @@ -5,9 +5,12 @@ * 2.0. */ -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; import React from 'react'; import { renderHook } from '@testing-library/react'; +import { matchers } from '@emotion/jest'; + +expect.extend(matchers); import { useDarkMode } from '../../lib/kibana'; import type { ChartSeriesData } from './common'; @@ -25,12 +28,12 @@ jest.mock('../../lib/kibana'); describe('WrappedByAutoSizer', () => { it('should render correct default height', () => { - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper).toHaveStyleRule('height', defaultChartHeight); }); it('should render correct given height', () => { - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper).toHaveStyleRule('height', '100px'); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.tsx index 120fb6977b0de..feb683c681418 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/common.tsx @@ -20,7 +20,7 @@ import type { import { LEGACY_DARK_THEME, LEGACY_LIGHT_THEME, Position } from '@elastic/charts'; import { EuiFlexGroup } from '@elastic/eui'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { useDarkMode } from '../../lib/kibana'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.tsx index 2d5dcafc77df5..de711b6d086b3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart.tsx @@ -5,11 +5,11 @@ * 2.0. */ -import type { EuiFlexGroupProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip, useEuiTheme } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import type { Datum, NodeColorAccessor, PartialTheme, ElementClickListener } from '@elastic/charts'; +import type { SerializedStyles } from '@emotion/react'; import { Chart, Partition, @@ -18,10 +18,9 @@ import { defaultPartitionValueFormatter, } from '@elastic/charts'; import { isEmpty } from 'lodash'; -import type { FlattenSimpleInterpolation } from 'styled-components'; -import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; import { useThemes } from './common'; import { DraggableLegend } from './draggable_legend'; import type { LegendItem } from './draggable_legend_item'; @@ -63,36 +62,34 @@ export interface DonutChartWrapperProps { children?: React.ReactElement; dataExists: boolean; donutTextWrapperClassName?: string; - donutTextWrapperStyles?: FlattenSimpleInterpolation; + donutTextWrapperStyles?: SerializedStyles; isChartEmbeddablesEnabled?: boolean; label?: React.ReactElement | string; title: React.ReactElement | string | number | null; } -/* Make this position absolute in order to overlap the text onto the donut */ -export const DonutTextWrapper = styled(EuiFlexGroup)< - EuiFlexGroupProps & { - $dataExists?: boolean; - $donutTextWrapperStyles?: FlattenSimpleInterpolation; - $isChartEmbeddablesEnabled?: boolean; - className?: string; - } ->` - top: ${({ $isChartEmbeddablesEnabled, $dataExists }) => - $isChartEmbeddablesEnabled && !$dataExists ? `66%` : `34%;`}; - width: 100%; - max-width: 77px; - position: absolute; - z-index: 1; - - ${({ className, $donutTextWrapperStyles }) => - className && $donutTextWrapperStyles ? `&.${className} {${$donutTextWrapperStyles}}` : ''} -`; - -export const StyledEuiFlexItem = styled(EuiFlexItem)` - position: relative; - align-items: center; -`; +const getStyles = ( + dataExists: boolean, + isChartEmbeddablesEnabled?: boolean, + donutTextWrapperStyles?: SerializedStyles, + className?: string +) => { + return { + donutTextWrapper: css` + top: ${isChartEmbeddablesEnabled && !dataExists ? '66%' : '34%'}; + width: 100%; + max-width: 77px; + position: absolute; // Make this position absolute in order to overlap the text onto the donut + z-index: 1; + + ${className && donutTextWrapperStyles ? `&.${className} {${donutTextWrapperStyles}}` : ''} + `, + flexItem: css` + position: relative; + align-items: center; + `, + }; +}; const DonutChartWrapperComponent: React.FC = ({ children, @@ -104,6 +101,12 @@ const DonutChartWrapperComponent: React.FC = ({ title, }) => { const { euiTheme } = useEuiTheme(); + const styles = getStyles( + dataExists, + isChartEmbeddablesEnabled, + donutTextWrapperStyles, + donutTextWrapperClassName + ); const emptyLabelStyle = useMemo( () => ({ color: euiTheme.colors.textSubdued, @@ -120,11 +123,9 @@ const DonutChartWrapperComponent: React.FC = ({ gutterSize="l" data-test-subj="donut-chart" > - - + = ({ )} - + {children} - +
); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx index be062ea0b1c33..2a3d302a7f01f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx @@ -5,9 +5,11 @@ * 2.0. */ -import type { ReactWrapper } from 'enzyme'; -import { mount } from 'enzyme'; +import { screen, render } from '@testing-library/react'; import React from 'react'; +import { matchers } from '@emotion/jest'; + +expect.extend(matchers); import '../../mock/react_beautiful_dnd'; import { TestProviders } from '../../mock'; @@ -57,102 +59,102 @@ const legendItems: LegendItem[] = [ describe('DraggableLegend', () => { const height = 400; - describe('rendering', () => { - let wrapper: ReactWrapper; - - beforeEach(() => { - wrapper = mount( - - - - ); - }); - - it(`renders a container with the specified non-zero 'height'`, () => { - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'height', - `${height}px` - ); - }); - - it(`renders a container with the default 'min-width'`, () => { - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'min-width', - `${DEFAULT_WIDTH}px` - ); - }); - - it(`renders a container with the specified 'min-width'`, () => { - const width = 1234; - - wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'min-width', - `${width}px` - ); - }); - - it('scrolls when necessary', () => { - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( - 'overflow', - 'auto' - ); - }); - - it('renders the legend items', () => { - legendItems.forEach((item) => - expect( - wrapper.find(`[data-test-subj="legend-item-${item.dataProviderId}"]`).first().text() - ).toEqual(item.value) - ); - }); - - it('renders a spacer for every legend item', () => { - expect(wrapper.find('[data-test-subj="draggable-legend-spacer"]').hostNodes().length).toEqual( - legendItems.length - ); - }); + + it(`renders a container with the specified non-zero 'height'`, () => { + render( + + + + ); + expect(screen.getByTestId('draggable-legend')).toHaveStyleRule('height', `${height}px`); + }); + + it("renders a container with the default 'min-width'", () => { + render( + + + + ); + expect(screen.getByTestId('draggable-legend')).toHaveStyleRule( + 'min-width', + `${DEFAULT_WIDTH}px` + ); + }); + + it(`renders a container with the specified 'min-width'`, () => { + const width = 1234; + + render( + + + + ); + + expect(screen.getByTestId('draggable-legend')).toHaveStyleRule('min-width', `${width}px`); }); - it('does NOT render the legend when an empty collection of legendItems is provided', () => { - const wrapper = mount( + it('scrolls when necessary', () => { + render( + + + + ); + expect(screen.getByTestId('draggable-legend')).toHaveStyleRule('overflow', 'auto'); + }); + + it('renders the legend items', () => { + const { container } = render( + + + + ); + + legendItems.forEach((item) => + expect( + container.querySelector(`[data-provider-id="draggableId.content.${item.dataProviderId}"]`) + ).toHaveTextContent(item.value.toString()) + ); + }); + + it('renders a spacer for every legend item', () => { + render( + + + + ); + expect(screen.getAllByTestId('draggable-legend-spacer').length).toEqual(legendItems.length); + }); + + it('does NOT render the legend when an empty collection of legendItems is provided', async () => { + render( ); - expect(wrapper.find('[data-test-subj="draggable-legend"]').exists()).toBe(false); + expect(screen.queryByTestId('draggable-legend')).toBeNull(); }); it(`renders a legend with the minimum height when 'height' is zero`, () => { - const wrapper = mount( + render( ); - expect(wrapper.find('[data-test-subj="draggable-legend"]').first()).toHaveStyleRule( + expect(screen.getByTestId('draggable-legend')).toHaveStyleRule( 'height', `${MIN_LEGEND_HEIGHT}px` ); }); it('renders a legend with specified class names', () => { - const wrapper = mount( + render( ); - expect(wrapper.find('[data-test-subj="draggable-legend"]').first().getDOMNode()).toHaveClass( - 'foo', - 'bar', - 'baz' - ); + expect(screen.getByTestId('draggable-legend')).toHaveClass('foo', 'bar', 'baz'); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx index df350aadf5883..6b0264ac75162 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme } from '@elastic/eui'; import { rgba } from 'polished'; import React from 'react'; -import styled from 'styled-components'; +import { css } from '@emotion/react'; import type { LegendItem } from './draggable_legend_item'; import { DraggableLegendItem } from './draggable_legend_item'; @@ -16,32 +16,40 @@ import { DraggableLegendItem } from './draggable_legend_item'; export const MIN_LEGEND_HEIGHT = 175; export const DEFAULT_WIDTH = 165; // px -const DraggableLegendContainer = styled.div<{ height: number; $minWidth: number }>` - height: ${({ height }) => `${height}px`}; - overflow: auto; - scrollbar-width: thin; - width: 100%; - @media only screen and (min-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { - width: 165px; - } - min-width: ${({ $minWidth }) => `${$minWidth}px`}; +const useStyles = (height: number, minWidth: number) => { + const { euiTheme } = useEuiTheme(); - &::-webkit-scrollbar { - height: ${({ theme }) => theme.eui.euiScrollBar}; - width: ${({ theme }) => theme.eui.euiScrollBar}; - } + return { + draggableLegendContainer: css` + height: ${height}px; + overflow: auto; + scrollbar-width: thin; + width: 100%; - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; - } + @media only screen and (min-width: ${euiTheme.breakpoint.m}) { + width: 165px; + } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } -`; + min-width: ${minWidth}px; + + &::-webkit-scrollbar { + height: ${euiTheme.size.base}; + width: ${euiTheme.size.base}; + } + + &::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: ${rgba(euiTheme.colors.darkShade, 0.5)}; + border: ${euiTheme.border.radius.small} solid transparent; + } + + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: transparent; + } + `, + }; +}; const DraggableLegendComponent: React.FC<{ className?: string; @@ -49,16 +57,17 @@ const DraggableLegendComponent: React.FC<{ legendItems: LegendItem[]; minWidth?: number; }> = ({ className, height = 0, legendItems, minWidth = DEFAULT_WIDTH }) => { + const styles = useStyles(height === 0 ? MIN_LEGEND_HEIGHT : height, minWidth); + if (legendItems.length === 0) { return null; } return ( - @@ -70,7 +79,7 @@ const DraggableLegendComponent: React.FC<{ ))} - +
); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx index d0175b92662a8..107840ec65d55 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/draggable_legend_item.tsx @@ -8,7 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui'; import numeral from '@elastic/numeral'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; import { DefaultDraggable } from '../draggables'; @@ -17,7 +17,7 @@ import { EMPTY_VALUE_LABEL } from './translation'; import { hasValueToDisplay } from '../../utils/validators'; const CountFlexItem = styled(EuiFlexItem)` - ${({ theme }) => `margin-right: ${theme.eui.euiSizeS};`} + ${({ theme }) => `margin-right: ${theme.euiTheme.size.s};`} `; export interface LegendItem { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/legend_item.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/legend_item.tsx index 45dbe5c7f7162..3104d121026c6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/legend_item.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/legend_item.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EMPTY_VALUE_LABEL } from './translation'; import { hasValueToDisplay } from '../../utils/validators'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/conditions_table/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/conditions_table/__snapshots__/index.test.tsx.snap index 9f25007a5cb90..6b8688994fbdb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/conditions_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/conditions_table/__snapshots__/index.test.tsx.snap @@ -13,14 +13,14 @@ exports[`conditions_table ConditionsTable should render multi item table with an ] } > - - + - - + theme.eui.euiSizeXL}; - padding-bottom: ${({ theme }) => theme.eui.euiSizeS}; + padding-top: ${({ theme }) => theme.euiTheme.size.xl}; + padding-bottom: ${({ theme }) => theme.euiTheme.size.s}; `; type ConditionsTableProps = EuiBasicTableProps & { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/empty_page/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/empty_page/index.tsx index 7a15e17bffc13..00abf7905b392 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/empty_page/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/empty_page/index.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import type { MouseEventHandler, ReactNode } from 'react'; import React, { useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; const EmptyPrompt = styled(EuiEmptyPrompt)` align-self: center; /* Corrects horizontal centering in IE11 */ diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/guided_onboarding_tour/tour_step.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/guided_onboarding_tour/tour_step.tsx index 8fec6e25f5169..1bf7c61d44825 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/guided_onboarding_tour/tour_step.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/guided_onboarding_tour/tour_step.tsx @@ -11,7 +11,7 @@ import type { EuiTourStepProps } from '@elastic/eui'; import { EuiButtonEmpty, EuiImage, EuiSpacer, EuiText, EuiTourStep } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { useShallowEqualSelector } from '../../hooks/use_selector'; import { TimelineId } from '../../../../common/types'; import { timelineDefaults } from '../../../timelines/store/defaults'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap index ba7e8f8ef4fce..8cd4da9a40747 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap @@ -5,7 +5,9 @@ exports[`HeaderPage it renders 1`] = ` - + - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.test.tsx index 4e95954e70dee..3adf4f79e263e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.test.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { euiDarkVars } from '@kbn/ui-theme'; import { shallow } from 'enzyme'; import React from 'react'; @@ -123,21 +122,6 @@ describe('HeaderPage', () => { expect(wrapper.find('[data-test-subj="header-page-supplements"]').first().exists()).toBe(false); }); - test('it DOES NOT apply border styles when border is false', () => { - const wrapper = mount( - - - - ); - const securitySolutionHeaderPage = wrapper.find('.securitySolutionHeaderPage').first(); - - expect(securitySolutionHeaderPage).not.toHaveStyleRule( - 'border-bottom', - euiDarkVars.euiBorderThin - ); - expect(securitySolutionHeaderPage).not.toHaveStyleRule('padding-bottom', euiDarkVars.euiSizeL); - }); - test('it renders the right side items', () => { const wrapper = mount( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.tsx index 21f310f5344c9..8027ff625ace6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/index.tsx @@ -11,10 +11,10 @@ import { EuiPageHeaderSection, EuiSpacer, useEuiTheme, + euiFontSize, } from '@elastic/eui'; import React from 'react'; import { css } from '@emotion/react'; -import styled, { css as styleCss } from 'styled-components'; import type { LinkIconProps } from '../link_icon'; import { LinkIcon } from '../link_icon'; @@ -30,25 +30,6 @@ interface HeaderProps { isLoading?: boolean; } -const LinkBack = styled.div.attrs({ - className: 'securitySolutionHeaderPage__linkBack', -})` - ${({ theme }) => styleCss` - font-size: ${theme.eui.euiFontSizeXS}; - line-height: ${theme.eui.euiLineHeight}; - margin-bottom: ${theme.eui.euiSizeS}; - `} -`; -LinkBack.displayName = 'LinkBack'; - -const HeaderSection = styled(EuiPageHeaderSection)` - // Without min-width: 0, as a flex child, it wouldn't shrink properly - // and could overflow its parent. - min-width: 0; - max-width: 100%; -`; -HeaderSection.displayName = 'HeaderSection'; - function Divider(): JSX.Element { const { euiTheme } = useEuiTheme(); @@ -81,14 +62,30 @@ export interface HeaderPageProps extends HeaderProps { titleNode?: React.ReactElement; } +const useHeaderLinkBackStyles = () => { + const euiThemeContext = useEuiTheme(); + const fontSizeXs = euiFontSize(euiThemeContext, 'xs').fontSize; + const lineHeightS = euiFontSize(euiThemeContext, 's').lineHeight; + const { euiTheme } = euiThemeContext; + + return { + linkBack: css` + font-size: ${fontSizeXs}; + line-height: ${lineHeightS}; + margin-bottom: ${euiTheme.size.s}; + `, + }; +}; + export const HeaderLinkBack: React.FC<{ backOptions: BackOptions }> = React.memo( ({ backOptions }) => { + const styles = useHeaderLinkBackStyles(); const { navigateToUrl } = useKibana().services.application; const { formatUrl } = useFormatUrl(backOptions.pageId); const backUrl = formatUrl(backOptions.path ?? ''); return ( - +
{ @@ -100,12 +97,21 @@ export const HeaderLinkBack: React.FC<{ backOptions: BackOptions }> = React.memo > {backOptions.text} - +
); } ); HeaderLinkBack.displayName = 'HeaderLinkBack'; +const headerPageStyles = { + // Without min-width: 0, as a flex child, it wouldn't shrink properly + // and could overflow its parent. + headerSection: css` + min-width: 0; + max-width: 100%; + `, +}; + const HeaderPageComponent: React.FC = ({ backOptions, backComponent, @@ -121,7 +127,7 @@ const HeaderPageComponent: React.FC = ({ }) => ( <> - + {backOptions && } {!backOptions && backComponent && <>{backComponent}} @@ -134,7 +140,7 @@ const HeaderPageComponent: React.FC = ({ )} {border && isLoading && } - +
{children && ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/title.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/title.tsx index 2da771d0163bd..14bf4dfe7fada 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/title.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_page/title.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiBetaBadge, EuiBadge, EuiTitle } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import type { BadgeOptions, TitleProp } from './types'; import { TruncatableText } from '../truncatable_text'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/__snapshots__/index.test.tsx.snap index 3ef2ecf88449b..24ce833a307c8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/__snapshots__/index.test.tsx.snap @@ -1,9 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`HeaderSection it renders 1`] = ` -
-
+ `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.test.tsx index 4f4a15695b216..5f4fa2528aba9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.test.tsx @@ -5,13 +5,17 @@ * 2.0. */ -import { euiDarkVars } from '@kbn/ui-theme'; import { mount, shallow } from 'enzyme'; import React from 'react'; +import { matchers } from '@emotion/jest'; + +expect.extend(matchers); import { TestProviders } from '../../mock'; import { getHeaderAlignment, HeaderSection } from '.'; import { ModalInspectQuery } from '../inspect/modal'; +import { renderHook } from '@testing-library/react'; +import { useEuiTheme } from '@elastic/eui'; jest.mock('../inspect/modal', () => { const actual = jest.requireActual('../inspect/modal'); @@ -118,8 +122,12 @@ describe('HeaderSection', () => { ); const siemHeaderSection = wrapper.find('.siemHeaderSection').first(); - expect(siemHeaderSection).toHaveStyleRule('border-bottom', euiDarkVars.euiBorderThin); - expect(siemHeaderSection).toHaveStyleRule('padding-bottom', euiDarkVars.euiSizeL); + expect(siemHeaderSection.exists()).toBe(true); + + const { result } = renderHook(() => useEuiTheme()); + + expect(siemHeaderSection).toHaveStyleRule('border-bottom', result.current.euiTheme.border.thin); + expect(siemHeaderSection).toHaveStyleRule('padding-bottom', result.current.euiTheme.size.l); }); test('it DOES NOT apply border styles when border is false', () => { @@ -130,8 +138,13 @@ describe('HeaderSection', () => { ); const siemHeaderSection = wrapper.find('.siemHeaderSection').first(); - expect(siemHeaderSection).not.toHaveStyleRule('border-bottom', euiDarkVars.euiBorderThin); - expect(siemHeaderSection).not.toHaveStyleRule('padding-bottom', euiDarkVars.euiSizeL); + const { result } = renderHook(() => useEuiTheme()); + + expect(siemHeaderSection).not.toHaveStyleRule( + 'border-bottom', + result.current.euiTheme.border.thin + ); + expect(siemHeaderSection).not.toHaveStyleRule('padding-bottom', result.current.euiTheme.size.l); }); test('it splits the title and supplement areas evenly when split is true', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.tsx index 75cd089a87e36..fd3854eb27a45 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/header_section/index.tsx @@ -6,9 +6,16 @@ */ import type { EuiTitleSize } from '@elastic/eui'; -import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle } from '@elastic/eui'; +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiIconTip, + EuiTitle, + useEuiTheme, +} from '@elastic/eui'; import React, { useCallback } from 'react'; -import styled, { css } from 'styled-components'; +import { css } from '@emotion/react'; import classnames from 'classnames'; import { InspectButton } from '../inspect'; @@ -16,46 +23,35 @@ import { InspectButton } from '../inspect'; import { Subtitle } from '../subtitle'; import * as i18n from '../../containers/query_toggle/translations'; -interface HeaderProps { - border?: boolean; - height?: number; - className?: string; // eslint-disable-line react/no-unused-prop-types - $hideSubtitle?: boolean; // eslint-disable-line react/no-unused-prop-types -} - -const Header = styled.header` - &.toggle-expand { - margin-bottom: ${({ theme }) => theme.eui.euiSizeL}; - } - - .no-margin { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - ${({ height }) => - height && - css` - height: ${height}px; - `} - margin-bottom: 0; - user-select: text; - - ${({ border }) => - border && - css` - border-bottom: ${({ theme }) => theme.eui.euiBorderThin}; - padding-bottom: ${({ theme }) => theme.eui.euiSizeL}; - `} -`; -Header.displayName = 'Header'; +const useStyles = (border?: boolean, height?: number) => { + const { euiTheme } = useEuiTheme(); + + return { + header: css` + margin-bottom: 0; + user-select: text; + ${height ? `height: ${height}px;` : ''} + ${border ? `border-bottom: ${euiTheme.border.thin}; padding-bottom: ${euiTheme.size.l};` : ''} + + &.toggle-expand { + margin-bottom: ${euiTheme.size.l}; + } + + .no-margin { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + `, + }; +}; -export interface HeaderSectionProps extends HeaderProps { +export interface HeaderSectionProps { alignHeader?: 'center' | 'baseline' | 'stretch' | 'flexStart' | 'flexEnd'; children?: React.ReactNode; outerDirection?: 'row' | 'rowReverse' | 'column' | 'columnReverse' | undefined; growLeftSplit?: boolean; headerFilters?: string | React.ReactNode; + border?: boolean; height?: number; hideSubtitle?: boolean; id?: string; @@ -114,6 +110,7 @@ const HeaderSectionComponent: React.FC = ({ tooltip, tooltipTitle, }) => { + const styles = useStyles(border, height); const toggle = useCallback(() => { if (toggleQuery) { toggleQuery(!toggleStatus); @@ -125,13 +122,7 @@ const HeaderSectionComponent: React.FC = ({ siemHeaderSection: true, }); return ( -
+
= ({ )} -
+
); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/inspect/modal.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/inspect/modal.tsx index bb0a20b7736b0..3598ec8ff33ab 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/inspect/modal.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/inspect/modal.tsx @@ -21,7 +21,7 @@ import { import numeral from '@elastic/numeral'; import type { ReactNode } from 'react'; import React, { useMemo, Fragment } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { useLocation } from 'react-router-dom'; import type { InputsModelId } from '../../store/inputs/constants'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/links/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/links/helpers.tsx index 5aed35ccb4b4c..9a7a4fd2038d7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/links/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/links/helpers.tsx @@ -21,7 +21,7 @@ import { EuiLink, EuiPopover, } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { FormattedMessage } from '@kbn/i18n-react'; import { defaultToEmptyTag } from '../empty_value'; export interface ReputationLinkSetting { diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/index.tsx index bcc98f089cf62..e773527a1b545 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/index.tsx @@ -6,7 +6,7 @@ */ import React, { useState, useEffect, useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiFlexGroup, EuiFlexItem, EuiSelect, EuiSpacer } from '@elastic/eui'; import type { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/types'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/matrix_loader.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/matrix_loader.tsx index 8eca508a4b74b..e8b703f34c7cc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/matrix_loader.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/matrix_histogram/matrix_loader.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; const StyledEuiFlexGroup = styled(EuiFlexGroup)` flex: 1; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/news_feed/post/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/news_feed/post/index.tsx index cc9332cb1c2a0..f2d910343b0ff 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/news_feed/post/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/news_feed/post/index.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { PreferenceFormattedP1DTDate } from '../../formatted_date'; import { showNewsItem } from '../helpers'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/page/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/page/index.tsx index dd0af06904ef9..cc5e30351df92 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/page/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/page/index.tsx @@ -5,8 +5,12 @@ * 2.0. */ -import { EuiBadge, EuiDescriptionList, EuiFlexGroup, EuiIcon } from '@elastic/eui'; -import styled, { createGlobalStyle, css } from 'styled-components'; +import React, { memo } from 'react'; +import type { ComponentProps, FC } from 'react'; +import type { UseEuiTheme } from '@elastic/eui'; +import { EuiBadge, EuiDescriptionList, EuiFlexGroup, EuiIcon, useEuiFontSize } from '@elastic/eui'; +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; export const SecuritySolutionAppWrapper = styled.div` display: flex; @@ -22,7 +26,7 @@ SecuritySolutionAppWrapper.displayName = 'SecuritySolutionAppWrapper'; * components, that position themselves just below the kibana header, are displayed correctly * when shown above content that is set to `full screen`. */ -export const FULL_SCREEN_CONTENT_OVERRIDES_CSS_STYLESHEET = () => css` +export const FULL_SCREEN_CONTENT_OVERRIDES_CSS_STYLESHEET = ` .euiOverlayMask[data-relative-to-header='below'] { top: 0 !important; } @@ -34,12 +38,10 @@ export const FULL_SCREEN_CONTENT_OVERRIDES_CSS_STYLESHEET = () => css` `; /* - SIDE EFFECT: the following `createGlobalStyle` overrides default styling in angular code that was not theme-friendly + SIDE EFFECT: the following `appGlobalStyles` overrides default styling in angular code that was not theme-friendly and `EuiPopover`, `EuiToolTip` global styles */ -export const AppGlobalStyle = createGlobalStyle<{ - theme: { eui: { euiColorPrimary: string; euiColorLightShade: string; euiSizeS: string } }; -}>` +export const appGlobalStyles = ({ euiTheme }: UseEuiTheme): string => ` /* overrides the default styling of EuiDataGrid expand popover footer to make it a column of actions instead of the default actions row @@ -69,8 +71,8 @@ export const AppGlobalStyle = createGlobalStyle<{ } .euiText + .euiPopoverFooter { - border-top: 1px solid ${({ theme }) => theme.eui.euiColorLightShade}; - margin-top: ${({ theme }) => theme.eui.euiSizeS}; + border-top: 1px solid ${euiTheme.colors.lightShade}; + margin-top: ${euiTheme.size.s}; } } @@ -107,20 +109,24 @@ export const AppGlobalStyle = createGlobalStyle<{ } `; -export const DescriptionListStyled = styled(EuiDescriptionList)` - ${({ theme }) => ` - word-break: break-word; - dt { - font-size: ${theme.eui.euiFontSizeXS} !important; - } - dd { - width: fit-content; - } - dd > div { - width: fit-content; - } - `} -`; +export const DescriptionListStyled: FC> = memo( + ({ css: cssProp, ...props }) => { + const baseStyles = css` + word-break: break-word; + dt { + font-size: ${useEuiFontSize('xs').fontSize} !important; + } + dd { + width: fit-content; + } + dd > div { + width: fit-content; + } + `; + + return ; + } +); DescriptionListStyled.displayName = 'DescriptionListStyled'; @@ -153,7 +159,7 @@ export const OverviewWrapper = styled(EuiFlexGroup)` .euiButtonIcon { position: absolute; - right: ${(props) => props.theme.eui.euiSizeM}; + right: ${({ theme }) => theme.euiTheme.size.m}; top: 6px; z-index: 2; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/page_wrapper/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/page_wrapper/index.tsx index acedbe669f36a..65b2ee7bdab59 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/page_wrapper/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/page_wrapper/index.tsx @@ -7,11 +7,12 @@ import classNames from 'classnames'; import React, { useEffect } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; +import { Global } from '@emotion/react'; import type { CommonProps } from '@elastic/eui'; import { useGlobalFullScreen } from '../../containers/use_full_screen'; -import { AppGlobalStyle } from '../page'; +import { appGlobalStyles } from '../page'; const Wrapper = styled.div` &.securitySolutionWrapper--fullHeight { @@ -55,7 +56,7 @@ const SecuritySolutionPageWrapperComponent: React.FC< return ( {children} - + ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap index c91ece7818df0..e3b4f43293c23 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/__snapshots__/helpers.test.tsx.snap @@ -23,11 +23,7 @@ exports[`Table Helpers #RowItemOverflow it returns correctly against snapshot 1` /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/helpers.tsx index 2c21ffa8cbd70..14edb569ca401 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/tables/helpers.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { euiThemeVars } from '@kbn/ui-theme'; +import { css } from '@emotion/react'; import { EuiLink, EuiPopover, @@ -15,18 +15,15 @@ import { EuiTextColor, EuiFlexGroup, EuiFlexItem, + useEuiFontSize, + useEuiTheme, } from '@elastic/eui'; -import styled from 'styled-components'; import { SecurityCellActions, CellActionsMode, SecurityCellActionsTrigger } from '../cell_actions'; import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { defaultToEmptyTag, getEmptyTagValue } from '../empty_value'; import { MoreRowItems } from '../page'; import { MoreContainer } from '../../../timelines/components/field_renderers/more_container'; -const Subtext = styled.div` - font-size: ${(props) => props.theme.eui.euiFontSizeXS}; -`; - interface GetRowItemsWithActionsParams { values: string[] | null | undefined; fieldName: string; @@ -98,6 +95,7 @@ export const RowItemOverflowComponent: React.FC = ({ overflowIndexStart = 5, maxOverflowItems = 5, }) => { + const { euiTheme } = useEuiTheme(); const maxVisibleValues = useMemo( () => values.slice(0, maxOverflowItems + 1), [values, maxOverflowItems] @@ -117,7 +115,7 @@ export const RowItemOverflowComponent: React.FC = ({ {values.length > overflowIndexStart + maxOverflowItems && ( @@ -148,14 +146,23 @@ interface PopoverComponentProps { idPrefix: string; } +const useStyles = () => { + return { + subtext: css` + font-size: ${useEuiFontSize('xs').fontSize}; + `, + }; +}; + const PopoverComponent: React.FC = ({ children, count, idPrefix }) => { + const styles = useStyles(); const [isOpen, setIsOpen] = useState(false); const onButtonClick = useCallback(() => { setIsOpen(!isOpen); }, [isOpen]); return ( - +
@@ -174,7 +181,7 @@ const PopoverComponent: React.FC = ({ children, count, id > {children} - +
); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx index 73086e2d584be..4067827e6de98 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx @@ -8,7 +8,7 @@ import type { ReactWrapper } from 'enzyme'; import { mount } from 'enzyme'; import React from 'react'; -import { waitFor } from '@testing-library/react'; +import { screen, render, waitFor, fireEvent } from '@testing-library/react'; import { TestProviders, mockDataViewSpec } from '../../mock'; @@ -116,9 +116,8 @@ describe('TopN', () => { toggleTopN, }; describe('common functionality', () => { - let wrapper: ReactWrapper; beforeEach(() => { - wrapper = mount( + render( @@ -126,8 +125,7 @@ describe('TopN', () => { }); test('it invokes the toggleTopN function when the close button is clicked', () => { - wrapper.find('[data-test-subj="close"]').first().simulate('click'); - wrapper.update(); + fireEvent.click(screen.getByTestId('close')); expect(toggleTopN).toHaveBeenCalled(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx index 5c3cecfe3fce3..7b21dcd945d8d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { EuiButtonIcon, EuiSuperSelect } from '@elastic/eui'; +import { EuiButtonIcon, EuiSuperSelect, useEuiTheme } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import styled from 'styled-components'; +import { css } from '@emotion/react'; import type { Filter, Query } from '@kbn/es-query'; import type { DataViewSpec } from '@kbn/data-plugin/common'; @@ -21,28 +21,31 @@ import { getSourcererScopeName, removeIgnoredAlertFilters } from './helpers'; import * as i18n from './translations'; import type { AlertsStackByField } from '../../../detections/components/alerts_kpis/common/types'; -const TopNContainer = styled.div` - min-width: 600px; -`; - -const CloseButton = styled(EuiButtonIcon)` - position: absolute; - right: 4px; - top: 4px; -`; - -const ViewSelect = styled(EuiSuperSelect)` - width: 170px; -`; - -const TopNContent = styled.div` - margin-top: 4px; - margin-right: ${({ theme }) => theme.eui.euiSizeXS}; - - .euiPanel { - border: none; - } -`; +const useStyles = () => { + const { euiTheme } = useEuiTheme(); + + return { + topNContainer: css` + min-width: 600px; + `, + closeButton: css` + position: absolute; + right: 4px; + top: 4px; + `, + viewSelect: css` + width: 170px; + `, + topNContent: css` + margin-top: 4px; + margin-right: ${euiTheme.size.xs}; + + .euiPanel { + border: none; + } + `, + }; +}; export interface Props extends Pick { filterQuery?: string; @@ -78,6 +81,7 @@ const TopNComponent: React.FC = ({ toggleTopN, applyGlobalQueriesAndFilters, }) => { + const styles = useStyles(); const [view, setView] = useState(defaultView); const onViewSelected = useCallback( (value: string) => setView(value as TimelineEventsType), @@ -91,7 +95,8 @@ const TopNComponent: React.FC = ({ const headerChildren = useMemo( () => ( - + css={styles.viewSelect} data-test-subj="view-select" disabled={options.length === 1} onChange={onViewSelected} @@ -99,7 +104,7 @@ const TopNComponent: React.FC = ({ valueOfSelected={view} /> ), - [onViewSelected, options, view] + [onViewSelected, options, styles.viewSelect, view] ); // alert workflow statuses (e.g. open | closed) and other alert-specific @@ -110,8 +115,8 @@ const TopNComponent: React.FC = ({ ); return ( - - +
+
{view === 'raw' || view === 'all' ? ( = ({ hideQueryToggle /> )} - +
- - +
); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx index 7557d4bc76820..f836484efb454 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.test.tsx @@ -29,7 +29,7 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - EuiContextMenu: jest.fn().mockReturnValue(
), + EuiContextMenu: jest.fn(() =>
), }; }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.tsx index bcdb9d163164c..61eea9fa57b94 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/actions.tsx @@ -8,7 +8,7 @@ import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui'; import { buildContextMenuForActions } from '@kbn/ui-actions-plugin/public'; import React, { useCallback, useMemo, useState } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import useAsync from 'react-use/lib/useAsync'; import { InputsModelId } from '../../store/inputs/constants'; @@ -31,7 +31,7 @@ const Wrapper = styled.div` z-index: 1; } &.histogram-viz-actions { - padding: ${({ theme }) => theme.eui.euiSizeS}; + padding: ${({ theme }) => theme.euiTheme.size.s}; } `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap index 4c5601ef3bdf7..22413142e4745 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap @@ -228,7 +228,7 @@ Object { "xAccessor": "b41a2958-650b-470a-84c4-c6fd8f0c6d37", "yConfig": Array [ Object { - "color": "#54B399", + "color": "#16C5C0", "forAccessor": "5417777d-d9d9-4268-9cdc-eb29b873bd65", }, ], @@ -243,7 +243,7 @@ Object { "xAccessor": "cded27f7-8ef8-458c-8d9b-70db48ae340d", "yConfig": Array [ Object { - "color": "#DA8B45", + "color": "#FFC9C2", "forAccessor": "a3bf9dc1-c8d2-42d6-9e60-31892a4c509e", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap index 73b57d04c823e..b84c279da18c2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap @@ -199,7 +199,7 @@ Object { "xAccessor": "a0cb6400-f708-46c3-ad96-24788f12dae4", "yConfig": Array [ Object { - "color": "#d36186", + "color": "#EE72A6", "forAccessor": "d9a6eb6b-8b78-439e-98e7-a718f8ffbebe", }, ], @@ -214,7 +214,7 @@ Object { "xAccessor": "95e74e6-99dd-4b11-8faf-439b4d959df9", "yConfig": Array [ Object { - "color": "#9170b8", + "color": "#61A2FF", "forAccessor": "e7052671-fb9e-481f-8df3-7724c98cfc6f", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap index 83135f5a4e4dd..b0e18a8502393 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap @@ -212,7 +212,7 @@ Object { "xAccessor": "f8bfa719-5c1c-4bf2-896e-c318d77fc08e", "yConfig": Array [ Object { - "color": "#d36186", + "color": "#EE72A6", "forAccessor": "32f66676-f4e1-48fd-b7f8-d4de38318601", }, ], @@ -227,7 +227,7 @@ Object { "xAccessor": "c72aad6a-fc9c-43dc-9194-e13ca3ee8aff", "yConfig": Array [ Object { - "color": "#9170b8", + "color": "#61A2FF", "forAccessor": "b7e59b08-96e6-40d1-84fd-e97b977d1c47", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap index 23dd658448ccc..d79e976d452fa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap @@ -223,7 +223,7 @@ Object { "xAccessor": "662cd5e5-82bf-4325-a703-273f84b97e09", "yConfig": Array [ Object { - "color": "#d36186", + "color": "#EE72A6", "forAccessor": "5f317308-cfbb-4ee5-bfb9-07653184fabf", }, ], @@ -238,7 +238,7 @@ Object { "xAccessor": "36444b8c-7e10-4069-8298-6c1b46912be2", "yConfig": Array [ Object { - "color": "#9170b8", + "color": "#61A2FF", "forAccessor": "ac1eb80c-ddde-46c4-a90c-400261926762", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap index 24b50ee3d6f61..7ccba37428a0a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap @@ -238,7 +238,7 @@ Object { "xAccessor": "d9c438c5-f776-4436-9d20-d62dc8c03be8", "yConfig": Array [ Object { - "color": "#d36186", + "color": "#EE72A6", "forAccessor": "5acd4c9d-dc3b-4b21-9632-e4407944c36d", }, ], @@ -253,7 +253,7 @@ Object { "xAccessor": "4607c585-3af3-43b9-804f-e49b27796d79", "yConfig": Array [ Object { - "color": "#9170b8", + "color": "#61A2FF", "forAccessor": "d27e0966-daf9-41f4-9033-230cf1e76dc9", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap index 70fb96a186640..16803a64eb2e5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap @@ -232,7 +232,7 @@ Object { "xAccessor": "49a42fe6-ebe8-4adb-8eed-1966a5297b7e", "yConfig": Array [ Object { - "color": "#54B399", + "color": "#16C5C0", "forAccessor": "0eb97c09-a351-4280-97da-944e4bd30dd7", }, ], @@ -247,7 +247,7 @@ Object { "xAccessor": "33a6163d-0c0a-451d-aa38-8ca6010dd5bf", "yConfig": Array [ Object { - "color": "#CA8EAE", + "color": "#EE72A6", "forAccessor": "2b27c80e-a20d-46f1-8fb2-79626ef4563c", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap index 1fe0fc602ca1f..95b63196046bd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap @@ -237,7 +237,7 @@ Object { "xAccessor": "430e690c-9992-414f-9bce-00812d99a5e7", "yConfig": Array [ Object { - "color": "#54B399", + "color": "#16C5C0", "forAccessor": "938b445a-a291-4bbc-84fe-4f47b69c20e4", }, ], @@ -252,7 +252,7 @@ Object { "xAccessor": "e959c351-a3a2-4525-b244-9623f215a8fd", "yConfig": Array [ Object { - "color": "#CA8EAE", + "color": "#EE72A6", "forAccessor": "c8165fc3-7180-4f1b-8c87-bc3ea04c6df7", }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx index 871750d5ad00f..e4124e826b083 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/lens_embeddable.tsx @@ -10,7 +10,6 @@ import { useDispatch } from 'react-redux'; import { FormattedMessage } from '@kbn/i18n-react'; import { ViewMode } from '@kbn/embeddable-plugin/public'; -import styled from 'styled-components'; import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import type { RangeFilterParams } from '@kbn/es-query'; import type { ClickTriggerEvent, MultiClickTriggerEvent } from '@kbn/charts-plugin/public'; @@ -19,6 +18,7 @@ import type { TypedLensByValueInput, XYState, } from '@kbn/lens-plugin/public'; +import { css } from '@emotion/react'; import { setAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { useKibana } from '../../lib/kibana'; import { useLensAttributes } from './use_lens_attributes'; @@ -35,20 +35,20 @@ import { useInspect } from '../inspect/use_inspect'; const DISABLED_ACTIONS = ['ACTION_CUSTOMIZE_PANEL']; -const LensComponentWrapper = styled.div<{ - $height?: number; - width?: string | number; -}>` - height: ${({ $height }) => ($height ? `${$height}px` : 'auto')}; - width: ${({ width }) => width ?? 'auto'}; - - .expExpressionRenderer__expression { - padding: 2px 0 0 0 !important; - } - .legacyMtrVis__container { - padding: 0; - } -`; +const getStyles = (width?: string | number, height?: number) => { + return { + lensComponentWrapper: css({ + height: height ? `${height}px` : 'auto', + width: width ?? 'auto', + '.expExpressionRenderer__expression': { + padding: '2px 0 0 0 !important', + }, + '.legacyMtrVis__container': { + padding: 0, + }, + }), + }; +}; const LensEmbeddableComponent: React.FC = ({ applyGlobalQueriesAndFilters = true, @@ -71,7 +71,12 @@ const LensEmbeddableComponent: React.FC = ({ disableOnClickFilter = false, casesAttachmentMetadata, }) => { - const style = useMemo( + const styles = useMemo( + () => getStyles(wrapperWidth, wrapperHeight), + [wrapperWidth, wrapperHeight] + ); + + const lensComponentStyle = useMemo( () => ({ height: wrapperHeight ?? '100%', minWidth: '100px', @@ -79,6 +84,7 @@ const LensEmbeddableComponent: React.FC = ({ }), [wrapperHeight, wrapperWidth] ); + const { lens, data: { @@ -240,7 +246,7 @@ const LensEmbeddableComponent: React.FC = ({ return ( <> {attributes && searchSessionId && ( - +
= ({ overrides={overrides} searchSessionId={searchSessionId} showInspector={false} - style={style} + style={lensComponentStyle} syncCursor={false} syncTooltips={false} timeRange={timerange} viewMode={ViewMode.VIEW} withDefaultActions={false} /> - +
)} {isShowingModal && request != null && response != null && ( /x-pack/solutions/security/plugins/security_solution/public/common/**/*.{ts,tsx}', ], moduleNameMapper: require('../../server/__mocks__/module_name_map'), + transform: { + ...rootConfig.transform, + '^.+\\.(js|tsx?)$': + '/x-pack/solutions/security/plugins/security_solution/jest/babel-transformer.js', + }, }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/index.tsx index ced56586f4f2f..0963fc0836471 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/index.tsx @@ -64,9 +64,9 @@ export const RulesWithGapsOverviewPanel = () => { ); - const handleShowRulesWithGapsFilterButtonClick = (value: boolean) => { + const handleShowRulesWithGapsFilterButtonClick = () => { setFilterOptions({ - showRulesWithGaps: value, + showRulesWithGaps: !showRulesWithGaps, }); }; @@ -119,16 +119,10 @@ export const RulesWithGapsOverviewPanel = () => { - handleShowRulesWithGapsFilterButtonClick(false)} - > - {i18n.RULE_GAPS_OVERVIEW_PANEL_SHOW_ALL_RULES_LABEL} - handleShowRulesWithGapsFilterButtonClick(true)} + onClick={handleShowRulesWithGapsFilterButtonClick} + iconType={showRulesWithGaps ? `checkInCircleFilled` : undefined} > {i18n.RULE_GAPS_OVERVIEW_PANEL_SHOW_RULES_WITH_GAPS_LABEL} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/translations.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/translations.tsx index fe9963eace3d1..04f29b2676917 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/translations.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/rules_with_gaps_overview_panel/translations.tsx @@ -13,18 +13,10 @@ export const RULE_GAPS_OVERVIEW_PANEL_LABEL = i18n.translate( defaultMessage: 'Total rules with gaps:', } ); - -export const RULE_GAPS_OVERVIEW_PANEL_SHOW_ALL_RULES_LABEL = i18n.translate( - 'xpack.securitySolution.ruleGapsOverviewPanel.showAllRulesLabel', - { - defaultMessage: 'Show all rules', - } -); - export const RULE_GAPS_OVERVIEW_PANEL_SHOW_RULES_WITH_GAPS_LABEL = i18n.translate( 'xpack.securitySolution.ruleGapsOverviewPanel.showRulesWithGapsLabel', { - defaultMessage: 'Show rules with gaps', + defaultMessage: 'Only rules with gaps', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts index e13a5ecf66c5e..7780f0a056b39 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts @@ -24,7 +24,7 @@ describe('getFillColor', () => { const expectedColorPalette = getRiskSeverityColors(euiTheme); it('returns the expected fill color', () => { - expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#F1D86F'); + expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#D6BF57'); }); it('returns the expected fill color when risk score is zero', () => { @@ -36,11 +36,11 @@ describe('getFillColor', () => { }); it('returns the expected fill color when risk score is 100', () => { - expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#bd271e'); + expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#E7664C'); }); it('returns the expected fill color when risk score is greater than 100', () => { - expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#bd271e'); + expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#E7664C'); }); it('returns the expected fill color when risk score is greater than RISK_SCORE_CRITICAL', () => { @@ -90,23 +90,23 @@ describe('getFillColor', () => { const colorPalette = euiPaletteWarm(RISK_SCORE_STEPS); it('returns the expected fill color', () => { - expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#efb685'); + expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#ffaea5'); }); it('returns the expected fill color when risk score is zero', () => { - expect(getFillColor({ riskScore: 0, colorPalette })).toEqual('#fbfada'); + expect(getFillColor({ riskScore: 0, colorPalette })).toEqual('#ffe7e4'); }); it('returns the expected fill color when risk score is less than zero', () => { - expect(getFillColor({ riskScore: -1, colorPalette })).toEqual('#fbfada'); + expect(getFillColor({ riskScore: -1, colorPalette })).toEqual('#ffe7e4'); }); it('returns the expected fill color when risk score is 100', () => { - expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#e7664c'); + expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#f6726a'); }); it('returns the expected fill color when risk score is greater than 100', () => { - expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#e7664c'); + expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#f6726a'); }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts index 14ac924287d43..c3b675b6d1bc1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts @@ -73,7 +73,7 @@ describe('layers', () => { const dataName = 'mimikatz process started'; expect( getLayersOneDimension({ colorPalette, maxRiskSubAggregations })[0].shape.fillColor(dataName) - ).toEqual('#bd271e'); + ).toEqual('#E7664C'); }); it('return the default fill color when dataName is not found in the maxRiskSubAggregations', () => { @@ -169,7 +169,7 @@ describe('layers', () => { { index: 0, value: 'Host-k8iyfzraq9' }, ], }) - ).toEqual('#bd271e'); + ).toEqual('#E7664C'); }); it('returns the default fillColor for layer 1 when the group from path is not found', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts index 107018011b91b..da50bb6e006f6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts @@ -20,6 +20,7 @@ describe('getFlattenedLegendItems', () => { it('returns the expected legend items', () => { const expected: Array> = [ { + color: undefined, count: 34, field: 'kibana.alert.rule.name', value: 'matches everything', @@ -49,93 +50,97 @@ describe('getFlattenedLegendItems', () => { value: 'Host-r4y6xi92ob', }, { + color: undefined, count: 28, field: 'kibana.alert.rule.name', value: 'EQL process sequence', }, { - color: '#FF7E62', + color: '#DA8B45', count: 10, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#FF7E62', + color: '#DA8B45', count: 7, field: 'host.name', value: 'Host-ao1a4wu7vn', }, { - color: '#FF7E62', + color: '#DA8B45', count: 5, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#FF7E62', + color: '#DA8B45', count: 3, field: 'host.name', value: 'Host-r4y6xi92ob', }, { + color: undefined, count: 19, field: 'kibana.alert.rule.name', value: 'Endpoint Security', }, { - color: '#F1D86F', + color: '#D6BF57', count: 11, field: 'host.name', value: 'Host-ao1a4wu7vn', }, { - color: '#F1D86F', + color: '#D6BF57', count: 6, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#F1D86F', + color: '#D6BF57', count: 1, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#F1D86F', + color: '#D6BF57', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', }, { + color: undefined, count: 5, field: 'kibana.alert.rule.name', value: 'mimikatz process started', }, { - color: '#bd271e', + color: '#E7664C', count: 3, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#bd271e', + color: '#E7664C', count: 1, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#bd271e', + color: '#E7664C', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', }, { + color: undefined, count: 1, field: 'kibana.alert.rule.name', value: 'Threshold rule', }, { - color: '#bd271e', + color: '#E7664C', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts index 1504ff5f6e7da..d7f0276afab6f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts @@ -223,28 +223,28 @@ describe('legend', () => { scopeId: TableId.alertsOnAlertsPage, }, { - color: '#FF7E62', + color: '#DA8B45', count: 28, field: 'kibana.alert.rule.name', value: 'EQL process sequence', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#F1D86F', + color: '#D6BF57', count: 19, field: 'kibana.alert.rule.name', value: 'Endpoint Security', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#bd271e', + color: '#E7664C', count: 5, field: 'kibana.alert.rule.name', value: 'mimikatz process started', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#bd271e', + color: '#E7664C', count: 1, field: 'kibana.alert.rule.name', value: 'Threshold rule', diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts index 93e5f9aa2bae9..89996b6db4551 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts @@ -17,7 +17,7 @@ const mockedUseKibana = mockUseKibana(); const mockedTelemetry = createTelemetryServiceMock(); jest.mock('../../../common/hooks/use_experimental_features', () => ({ - useEnableExperimental: () => ({ ...mockedExperimentalFeatures, serviceEntityStoreEnabled: true }), + useEnableExperimental: () => ({ ...mockedExperimentalFeatures }), })); jest.mock('../../../common/lib/kibana', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.test.tsx index 4a8bf9e895d85..3f98db09625e9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.test.tsx @@ -46,9 +46,9 @@ describe('useAnomaliesColumns', () => { }); expect(renderedComponent).toMatchInlineSnapshot(` - + test-job-name - + `); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.tsx index 1b3d54f61016c..ea35ca90a072b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/columns.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React, { useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import type { EuiTableFieldDataColumnType } from '@elastic/eui'; import * as i18n from './translations'; import type { SecurityJob } from '../../../common/components/ml_popover/types'; @@ -17,7 +17,7 @@ import type { AnomaliesCount } from '../../../common/components/ml/anomaly/use_a type AnomaliesColumns = Array>; const DarkShadeText = styled.span` - color: ${({ theme }) => theme.eui.euiColorDarkShade}; + color: ${({ theme: { euiTheme } }) => euiTheme.colors.darkShade}; `; export const useAnomaliesColumns = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_header/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_header/index.tsx index a902015483677..8d8c8a5c335b3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_header/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_header/index.tsx @@ -6,11 +6,10 @@ */ import React, { useMemo, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle, EuiLink } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { useDispatch } from 'react-redux'; import { capitalize, sumBy } from 'lodash/fp'; import { FormattedMessage } from '@kbn/i18n-react'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { SEVERITY_COLOR } from '../../../overview/components/detection_response/utils'; import { LinkAnchor, useGetSecuritySolutionLinkProps } from '../../../common/components/links'; import { @@ -45,7 +44,6 @@ const StyledEuiTitle = styled(EuiTitle)` // This is not used by the inspect feature but required by the refresh button const HOST_RISK_QUERY_ID = 'hostRiskScoreKpiQuery'; const USER_RISK_QUERY_ID = 'userRiskScoreKpiQuery'; -const SERVICE_RISK_QUERY_ID = 'serviceRiskScoreKpiQuery'; export const EntityAnalyticsHeader = () => { const { from, to } = useGlobalTime(); @@ -57,7 +55,6 @@ export const EntityAnalyticsHeader = () => { }), [from, to] ); - const isServiceEntityStoreEnabled = useIsExperimentalFeatureEnabled('serviceEntityStoreEnabled'); const { severityCount: hostsSeverityCount, @@ -81,17 +78,6 @@ export const EntityAnalyticsHeader = () => { riskEntity: EntityType.user, }); - const { - severityCount: servicesSeverityCount, - loading: serviceRiskLoading, - refetch: refetchServiceRiskScore, - inspect: inspectServiceRiskScore, - } = useRiskScoreKpi({ - filterQuery, - timerange, - riskEntity: EntityType.service, - }); - const { data } = useAggregatedAnomaliesByJob({ skip: false, from, to }); const dispatch = useDispatch(); @@ -163,15 +149,6 @@ export const EntityAnalyticsHeader = () => { inspect: inspectHostRiskScore, }); - useQueryInspector({ - queryId: SERVICE_RISK_QUERY_ID, - loading: serviceRiskLoading, - refetch: refetchServiceRiskScore, - setQuery, - deleteQuery, - inspect: inspectServiceRiskScore, - }); - // Anomaly jobs are enabled if at least one job is started or has data const areJobsEnabled = useMemo( () => @@ -216,15 +193,6 @@ export const EntityAnalyticsHeader = () => { href={userRiskTabUrl} /> - - {isServiceEntityStoreEnabled && ( - - - - )} )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/columns.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/columns.tsx index 88175bc049a4e..3a72ec19143bc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/columns.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/columns.tsx @@ -9,7 +9,7 @@ import type { SyntheticEvent } from 'react'; import React from 'react'; import type { EuiBasicTableColumn } from '@elastic/eui'; import { EuiLink } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { get } from 'lodash/fp'; import { EntityTypeToIdentifierField } from '../../../../common/entity_analytics/types'; @@ -40,7 +40,7 @@ import { FormattedRelativePreferenceDate } from '../../../common/components/form import { formatRiskScore } from '../../common'; const StyledCellActions = styled(SecurityCellActions)` - padding-left: ${({ theme }) => theme.eui.euiSizeS}; + padding-left: ${({ theme: { euiTheme } }) => euiTheme.size.s}; `; type OpenEntityOnAlertsPage = (entityName: string) => void; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx index 76c5b7be5f3bb..225aee1bfb34d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx @@ -231,7 +231,7 @@ const EntityAnalyticsRiskScoresComponent = ({ ({ - useEnableExperimental: () => ({ ...mockedExperimentalFeatures, serviceEntityStoreEnabled: true }), + useEnableExperimental: () => ({ ...mockedExperimentalFeatures }), })); jest.mock('../../../../common/hooks/use_global_filter_query'); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_details_tab_body/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_details_tab_body/index.tsx index 97f6e36bcca03..32fa82df0791d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_details_tab_body/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_details_tab_body/index.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { useUpsellingComponent } from '../../../common/hooks/use_upselling'; import { EnableRiskScore } from '../enable_risk_score'; @@ -28,7 +28,7 @@ import { RiskEnginePrivilegesCallOut } from '../risk_engine_privileges_callout'; import { RiskScoresNoDataDetected } from '../risk_score_no_data_detected'; const StyledEuiFlexGroup = styled(EuiFlexGroup)` - margin-top: ${({ theme }) => theme.eui.euiSizeL}; + margin-top: ${({ theme: { euiTheme } }) => euiTheme.size.l}; `; type ComponentsQueryProps = HostsComponentsQueryProps | UsersComponentsQueryProps; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx index b8e98c02dd06d..165d2fad541b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx @@ -6,7 +6,7 @@ */ import type { EuiBasicTableColumn } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiBasicTable, EuiButton, @@ -39,7 +39,7 @@ import { EntityAnalyticsLearnMoreLink } from '../entity_analytics_learn_more_lin const SpacedOrderedList = styled.ol` li { - margin-bottom: ${({ theme }) => theme.eui.euiSizeM}; + margin-bottom: ${({ theme: { euiTheme } }) => euiTheme.size.m}; } `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx index bc4a704b48655..334a7fff8d33b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { i18n } from '@kbn/i18n'; import { ChartLabel } from '../../../overview/components/detection_response/alerts_by_status/chart_label'; import { RISK_SEVERITY_COLOUR } from '../../common/utils'; @@ -22,8 +22,8 @@ import type { RiskSeverity } from '../../../../common/search_strategy'; const DONUT_HEIGHT = 120; const DonutContainer = styled(EuiFlexItem)` - padding-right: ${({ theme }) => theme.eui.euiSizeXXL}; - padding-left: ${({ theme }) => theme.eui.euiSizeM}; + padding-right: ${({ theme: { euiTheme } }) => euiTheme.size.xxl}; + padding-left: ${({ theme: { euiTheme } }) => euiTheme.size.m}; `; const StyledLegendItems = styled(EuiFlexItem)` diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.test.tsx index d53fb004295af..d6ee52667441b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.test.tsx @@ -5,18 +5,21 @@ * 2.0. */ -import { render } from '@testing-library/react'; +import { render, renderHook } from '@testing-library/react'; import React from 'react'; +import { matchers } from '@emotion/jest'; import { TestProviders } from '../../../../common/mock'; import type { EuiHealthProps } from '@elastic/eui'; -import { EuiHealth } from '@elastic/eui'; +import { EuiHealth, useEuiTheme } from '@elastic/eui'; import { RiskSeverity } from '../../../../../common/search_strategy'; import { RiskScoreLevel } from '.'; import { SEVERITY_COLOR } from '../../../../overview/components/detection_response/utils'; +expect.extend(matchers); + jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { @@ -109,6 +112,21 @@ describe('RiskScore', () => { ); - expect(queryByTestId('risk-score')).toHaveStyleRule('background-color', undefined); + expect(queryByTestId('risk-score')).not.toHaveStyleRule('background-color'); + }); + + it('renders background-color when hideBackgroundColor is false', () => { + const { queryByTestId } = render( + + + + ); + + const { result } = renderHook(() => useEuiTheme()); + + expect(queryByTestId('risk-score')).toHaveStyleRule( + 'background-color', + result.current.euiTheme.colors.backgroundBaseDanger + ); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx index 123027fd81da9..e754189feff8e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx @@ -6,34 +6,36 @@ */ import React from 'react'; - import { EuiHealth, EuiTextColor, useEuiTheme } from '@elastic/eui'; - -import styled, { css } from 'styled-components'; +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; import { RISK_SEVERITY_COLOUR } from '../../../common/utils'; import { HoverPopover } from '../../../../common/components/hover_popover'; import type { RiskSeverity } from '../../../../../common/search_strategy'; -const RiskBadge = styled.div<{ - $severity: RiskSeverity; - $hideBackgroundColor: boolean; +const RiskBadge = styled('div', { + shouldForwardProp: (prop) => !['severity', 'hideBackgroundColor'].includes(prop), +})<{ + severity: RiskSeverity; + hideBackgroundColor: boolean; }>` - ${({ theme, color, $severity, $hideBackgroundColor }) => css` + ${({ theme: { euiTheme }, color, severity, hideBackgroundColor }) => css` width: fit-content; - padding-right: ${theme.eui.euiSizeS}; - padding-left: ${theme.eui.euiSizeXS}; + padding-right: ${euiTheme.size.s}; + padding-left: ${euiTheme.size.xs}; - ${($severity === 'Critical' || $severity === 'High') && - !$hideBackgroundColor && + ${(severity === 'Critical' || severity === 'High') && + !hideBackgroundColor && css` background-color: ${color}; border-radius: 999px; // pill shaped `}; `} `; + const TooltipContainer = styled.div` - padding: ${({ theme }) => theme.euiSizeS}; + padding: ${({ theme: { euiTheme } }) => euiTheme.size.s}; `; export const RiskScoreLevel: React.FC<{ @@ -77,8 +79,8 @@ const RiskScoreBadge: React.FC<{ return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx index e643407cde5f4..9877ee22dbc40 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiColorPaletteDisplay } from '@elastic/eui'; import React, { useMemo } from 'react'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/styled_basic_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/styled_basic_table.tsx index 9b150aade8b99..505f87acba1b9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/styled_basic_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/styled_basic_table.tsx @@ -4,11 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiBasicTable } from '@elastic/eui'; // @ts-expect-error TS2769 -export const StyledBasicTable = styled(EuiBasicTable)` +export const StyledBasicTable: typeof EuiBasicTable = styled(EuiBasicTable)` .euiTableRow { .euiTableRowCell { border-bottom: none !important; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts index a11ba6f8c5d8c..c36179a44a8b3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/translations.ts @@ -176,7 +176,7 @@ export const RISK_SCORE_ENGINE_RUN_SUCCESS = i18n.translate( export const RISK_ENGINE_SAVED_OBJECT_CONFIGURATION_SUCCESS = i18n.translate( 'xpack.securitySolution.riskScore.savedObject.configurationSuccess', { - defaultMessage: 'Risk engine Saved Object configuration updated successfully', + defaultMessage: 'Your configuration was updated.', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/components/authentication/__snapshots__/authentications_host_table.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/components/authentication/__snapshots__/authentications_host_table.test.tsx.snap index 45a1e70d9ba81..fe13a71198890 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/components/authentication/__snapshots__/authentications_host_table.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/components/authentication/__snapshots__/authentications_host_table.test.tsx.snap @@ -1,53 +1,36 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Authentication Host Table Component rendering it renders the host authentication table 1`] = ` -.c2 .siemSubtitle__item { +.c1 .siemSubtitle__item { color: #7a7f89; font-size: 12px; line-height: 1.5; } -.c1 { - margin-bottom: 0; - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; -} - -.c1.toggle-expand { - margin-bottom: 24px; -} - -.c1 .no-margin { - margin-top: 0 !important; - margin-bottom: 0 !important; -} - .c0 { position: relative; } -.c3 tbody th, -.c3 tbody td { +.c2 tbody th, +.c2 tbody td { vertical-align: top; } -.c3 tbody .euiTableCellContent { +.c2 tbody .euiTableCellContent { display: block; } -.c4 { +.c3 { margin-top: 4px; } @media only screen and (min-width:575px) { - .c2 .siemSubtitle__item { + .c1 .siemSubtitle__item { display: inline-block; margin-right: 16px; } - .c2 .siemSubtitle__item:last-child { + .c1 .siemSubtitle__item:last-child { margin-right: 0; } } @@ -57,7 +40,8 @@ exports[`Authentication Host Table Component rendering it renders the host authe data-test-subj="authentications-host-table-loading-false" >

= ({ detailName, hostDeta hostName={detailName} indexNames={selectedPatterns} jobNameById={jobNameById} + scopeId={SourcererScopeName.default} /> )} diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap index 848c0ec895cda..49e00e866c68f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/arrows/__snapshots__/index.test.tsx.snap @@ -10,15 +10,15 @@ exports[`arrows ArrowBody renders correctly against snapshot 1`] = ` "compat": true, "insert": [Function], "inserted": Object { - "4ieeuw-euiColorMode-LIGHT": true, - "4rtwwc": true, + "10uvw04": true, + "vzhe8z-euiColorMode-LIGHT": true, }, "key": "css", "nonce": undefined, "registered": Object { - "css-4ieeuw-euiColorMode-LIGHT": " + "css-vzhe8z-euiColorMode-LIGHT": " label: euiColorMode-LIGHT; - color: #343741; + color: #1D2A3E; ", }, "sheet": StyleSheet { @@ -199,7 +199,7 @@ exports[`arrows ArrowBody renders correctly against snapshot 1`] = ` data-s="" > - html{scrollbar-width:auto;scrollbar-color:rgba(105,112,125,0.5) #f0f1f4;font-family:'Inter',BlinkMacSystemFont,Helvetica,Arial,sans-serif;font-size:0.875rem;line-height:1.1428571428571428;font-weight:400;-webkit-text-size-adjust:100%;text-size-adjust:100%;font-kerning:normal;block-size:100%;background-color:#f7f8fc;color:#343741;} + html{scrollbar-width:auto;scrollbar-color:rgba(90,109,140,0.5) #ECF1F9;font-family:'Inter',BlinkMacSystemFont,Helvetica,Arial,sans-serif;font-size:0.875rem;line-height:1.1428571428571428;font-weight:400;-webkit-text-size-adjust:100%;text-size-adjust:100%;font-kerning:normal;block-size:100%;background-color:#F6F9FC;color:#1D2A3E;} , , ], }, @@ -1070,10 +1070,10 @@ exports[`arrows ArrowBody renders correctly against snapshot 1`] = ` serialized={ Object { "map": undefined, - "name": "4rtwwc", + "name": "10uvw04", "next": undefined, "styles": " - background-color: #D3DAE6; + background-color: #CAD3E2; height: 3px; width: 25px; ", @@ -1082,7 +1082,7 @@ exports[`arrows ArrowBody renders correctly against snapshot 1`] = ` } /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap index e8707480b1c66..678f9ccb94812 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/__snapshots__/index.test.tsx.snap @@ -147,6 +147,7 @@ exports[`IP Overview Component rendering it renders the default IP Overview 1`] jobNameById={Object {}} loading={false} narrowDateRange={[MockFunction]} + scopeId="default" startDate="2019-06-15T06:00:00.000Z" type="details" updateFlowTargetAction={[MockFunction]} @@ -300,6 +301,7 @@ exports[`IP Overview Component rendering it renders the side panel IP overview 1 jobNameById={Object {}} loading={false} narrowDateRange={[MockFunction]} + scopeId="default" startDate="2019-06-15T06:00:00.000Z" type="details" updateFlowTargetAction={[MockFunction]} diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.test.tsx index 6f2c748d7f54a..3295a1e1a92a9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.test.tsx @@ -17,6 +17,7 @@ import { mockData } from './mock'; import { mockAnomalies } from '../../../../common/components/ml/mock'; import type { NarrowDateRange } from '../../../../common/components/ml/types'; import { FlowTargetSourceDest } from '../../../../../common/search_strategy'; +import { SourcererScopeName } from '../../../../sourcerer/store/model'; describe('IP Overview Component', () => { describe('rendering', () => { @@ -38,6 +39,7 @@ describe('IP Overview Component', () => { }>, indexPatterns: [], jobNameById: {}, + scopeId: SourcererScopeName.default, }; test('it renders the default IP Overview', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.tsx index 1c909a8eff31b..d7720b9d6a947 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/details/index.tsx @@ -38,6 +38,7 @@ import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions'; import { InspectButton, InspectButtonContainer } from '../../../../common/components/inspect'; import { OverviewDescriptionList } from '../../../../common/components/overview_description_list'; +import type { SourcererScopeName } from '../../../../sourcerer/store/model'; export interface IpOverviewProps { anomaliesData: Anomalies | null; @@ -52,6 +53,7 @@ export interface IpOverviewProps { isLoadingAnomaliesData: boolean; loading: boolean; narrowDateRange: NarrowDateRange; + scopeId: SourcererScopeName; startDate: string; type: networkModel.NetworkType; indexPatterns: string[]; @@ -73,6 +75,7 @@ export const IpOverview = React.memo( isLoadingAnomaliesData, anomaliesData, narrowDateRange, + scopeId, indexPatterns, jobNameById, }) => { @@ -148,14 +151,14 @@ export const IpOverview = React.memo( title: i18n.HOST_ID, description: typeData && data.host - ? hostIdRenderer({ host: data.host, isDraggable, ipFilter: ip, contextID }) + ? hostIdRenderer({ host: data.host, isDraggable, ipFilter: ip, contextID, scopeId }) : getEmptyTagValue(), }, { title: i18n.HOST_NAME, description: typeData && data.host - ? hostNameRenderer(data.host, ip, contextID, isDraggable) + ? hostNameRenderer(scopeId, data.host, ip, contextID, isDraggable) : getEmptyTagValue(), }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/__mocks__/mock.ts b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/__mocks__/mock.ts index 02889acb04866..ed7970d95e237 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/__mocks__/mock.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/__mocks__/mock.ts @@ -50,7 +50,7 @@ export const mockSourceLayer = { properties: { fillColor: { type: 'STATIC', - options: { color: '#6092C0' }, + options: { color: '#A6EDEA' }, }, lineColor: { type: 'STATIC', @@ -108,7 +108,7 @@ export const mockDestinationLayer = { properties: { fillColor: { type: 'STATIC', - options: { color: '#D36086' }, + options: { color: '#61A2FF' }, }, lineColor: { type: 'STATIC', @@ -164,7 +164,7 @@ export const mockClientLayer = { properties: { fillColor: { type: 'STATIC', - options: { color: '#6092C0' }, + options: { color: '#A6EDEA' }, }, lineColor: { type: 'STATIC', @@ -227,7 +227,7 @@ export const mockServerLayer = { properties: { fillColor: { type: 'STATIC', - options: { color: '#D36086' }, + options: { color: '#61A2FF' }, }, lineColor: { type: 'STATIC', @@ -286,7 +286,7 @@ export const mockLineLayer = { }, lineColor: { type: 'STATIC', - options: { color: '#6092C0' }, + options: { color: '#A6EDEA' }, }, lineWidth: { type: 'DYNAMIC', @@ -351,7 +351,7 @@ export const mockClientServerLineLayer = { }, lineColor: { type: 'STATIC', - options: { color: '#6092C0' }, + options: { color: '#A6EDEA' }, }, lineWidth: { type: 'DYNAMIC', diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/map_tool_tip.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/map_tool_tip.test.tsx.snap deleted file mode 100644 index dc94b1039dfc5..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/__snapshots__/map_tool_tip.test.tsx.snap +++ /dev/null @@ -1,37 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MapToolTip full component renders correctly against snapshot 1`] = ` - - - - - - - -`; - -exports[`MapToolTip placeholder component renders correctly against snapshot 1`] = ` - - - - - - - -`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.test.tsx index fb8b0ec79b961..7ca325330b5a5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.test.tsx @@ -5,43 +5,107 @@ * 2.0. */ -import { shallow } from 'enzyme'; import React from 'react'; -import { MapToolTipComponent } from './map_tool_tip'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import type { TooltipFeature } from '@kbn/maps-plugin/common'; +import { MapToolTipComponent } from './map_tool_tip'; +import * as i18n from '../translations'; +import { TestProviders } from '../../../../../common/mock'; -describe('MapToolTip', () => { - test('placeholder component renders correctly against snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); - }); +jest.mock('./line_tool_tip_content', () => ({ + LineToolTipContent: jest.fn(() =>
), +})); - test('full component renders correctly against snapshot', () => { - const addFilters = jest.fn(); - const closeTooltip = jest.fn(); - const features: TooltipFeature[] = [ - { - id: 1, - layerId: 'layerId', - mbProperties: {}, - actions: [], - }, - ]; - const getLayerName = jest.fn(); - const loadFeatureProperties = jest.fn(); - const loadFeatureGeometry = jest.fn(); - - const wrapper = shallow( +jest.mock('./point_tool_tip_content', () => ({ + PointToolTipContent: jest.fn(() =>
), +})); + +describe('MapToolTipComponent', () => { + const mockCloseTooltip = jest.fn(); + const mockGetLayerName = jest.fn(); + const mockLoadFeatureProperties = jest.fn(); + const mockLoadFeatureGeometry = jest.fn(); + const features = [ + { layerId: 'layer1', id: 'feature1', mbProperties: {} }, + { layerId: 'layer2', id: 'feature2', mbProperties: {} }, + ] as TooltipFeature[]; + + const renderComponent = (props = {}) => { + return render( + getLayerName={mockGetLayerName} + loadFeatureProperties={mockLoadFeatureProperties} + loadFeatureGeometry={mockLoadFeatureGeometry} + {...props} + />, + { wrapper: TestProviders } ); - expect(wrapper).toMatchSnapshot(); + }; + + beforeEach(() => { + jest.clearAllMocks(); + mockGetLayerName.mockResolvedValue('Layer Name'); + mockLoadFeatureProperties.mockResolvedValue([{ name: 'property1', value: 'value1' }]); + mockLoadFeatureGeometry.mockResolvedValue({ type: 'Point' }); + }); + + it('should not render tooltips when features is empty', () => { + renderComponent({ features: [] }); + expect(screen.queryByTestId('point-tool-tip-content')).toBeNull(); + }); + + it('shows a loading spinner initially', () => { + renderComponent(); + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + }); + + it('displays an error message when isError is true', async () => { + mockLoadFeatureProperties.mockRejectedValue(new Error('Load error')); + renderComponent(); + + await waitFor(() => { + expect(screen.getByText(i18n.MAP_TOOL_TIP_ERROR)).toBeInTheDocument(); + }); + }); + + it('displays PointToolTipContent and ToolTipFooter when feature geometry is Point', async () => { + renderComponent(); + + await waitFor(() => { + expect(screen.getByTestId('point-tool-tip-content')).toBeInTheDocument(); + expect(screen.getByTestId('previous-feature-button')).toBeInTheDocument(); + expect(screen.getByTestId('next-feature-button')).toBeInTheDocument(); + }); + }); + + it('navigates to the next and previous features correctly', async () => { + renderComponent(); + + await waitFor(() => { + expect(screen.getByTestId('previous-feature-button')).toBeInTheDocument(); + expect(screen.getByTestId('next-feature-button')).toBeInTheDocument(); + }); + + const nextButton = screen.getByTestId('next-feature-button'); + fireEvent.click(nextButton); + + await waitFor(() => { + expect(mockLoadFeatureProperties).toHaveBeenCalledWith({ + layerId: 'layer2', + properties: {}, + }); + }); + + const previousButton = screen.getByTestId('previous-feature-button'); + fireEvent.click(previousButton); + + await waitFor(() => { + expect(mockLoadFeatureProperties).toHaveBeenCalledWith({ + layerId: 'layer1', + properties: {}, + }); + }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.tsx index d82bf1ce18051..54fc4bc5efe49 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -14,6 +14,7 @@ import { } from '@elastic/eui'; import type { Geometry } from 'geojson'; import type { ITooltipProperty } from '@kbn/maps-plugin/public/classes/tooltips/tooltip_property'; +import type { TooltipFeature } from '@kbn/maps-plugin/common'; import type { MapToolTipProps } from '../types'; import { ToolTipFooter } from './tooltip_footer'; import { LineToolTipContent } from './line_tool_tip_content'; @@ -21,9 +22,11 @@ import { PointToolTipContent } from './point_tool_tip_content'; import { Loader } from '../../../../../common/components/loader'; import * as i18n from '../translations'; +const DEFAULT_FEATURE: TooltipFeature[] = []; + export const MapToolTipComponent = ({ closeTooltip, - features = [], + features = DEFAULT_FEATURE, getLayerName, loadFeatureProperties, loadFeatureGeometry, @@ -35,7 +38,6 @@ export const MapToolTipComponent = ({ const [featureProps, setFeatureProps] = useState([]); const [featureGeometry, setFeatureGeometry] = useState(null); const [, setLayerName] = useState(''); - const handleCloseTooltip = useCallback(() => { if (closeTooltip != null) { closeTooltip(); @@ -74,24 +76,28 @@ export const MapToolTipComponent = ({ return (
- {featureGeometry != null && featureGeometry.type === 'LineString' ? ( - - ) : ( - - )} {features.length > 1 && ( - + <> + {featureGeometry != null && featureGeometry.type === 'LineString' ? ( + + ) : ( + + )} + + )} {isLoadingNextFeature && }
diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx index 43f874dec5215..4ad664b73d9d9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx @@ -16,6 +16,7 @@ import { DescriptionListStyled } from '../../../../../common/components/page'; import { HostDetailsLink, NetworkDetailsLink } from '../../../../../common/components/links'; import { DefaultFieldRenderer } from '../../../../../timelines/components/field_renderers/default_renderer'; import type { FlowTarget } from '../../../../../../common/search_strategy'; +import { SourcererScopeName } from '../../../../../sourcerer/store/model'; interface PointToolTipContentProps { contextId: string; @@ -42,6 +43,7 @@ export const PointToolTipContentComponent = ({ attrName={key} idPrefix={`map-point-tooltip-${contextId}-${key}-${value}`} render={(item) => getRenderedFieldValue(key, item)} + scopeId={SourcererScopeName.default} /> ) : ( getEmptyTagValue() diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/tooltip_footer.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/tooltip_footer.tsx index 7d5e55a0172a7..4faa7d50aa8ad 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/tooltip_footer.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/components/embeddables/map_tool_tip/tooltip_footer.tsx @@ -6,24 +6,9 @@ */ import React from 'react'; -import { - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiIcon, - EuiText, -} from '@elastic/eui'; -import { euiLightVars as theme } from '@kbn/ui-theme'; -import styled from '@emotion/styled'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText } from '@elastic/eui'; import * as i18n from '../translations'; -export const Icon = styled(EuiIcon)` - margin-right: ${theme.euiSizeS}; -`; - -Icon.displayName = 'Icon'; - interface MapToolTipFooterProps { featureIndex: number; totalFeatures: number; diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx index 0eb3fb36638b8..74dc6e39dc5d0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx @@ -59,6 +59,7 @@ import { CellActionsMode, SecurityCellActionsTrigger, } from '../../../../common/components/cell_actions'; +import { SourcererScopeName } from '../../../../sourcerer/store/model'; const NetworkDetailsManage = manageQuery(IpOverview); @@ -224,6 +225,7 @@ const NetworkDetailsComponent: React.FC = () => { narrowDateRange={narrowDateRange} indexPatterns={selectedPatterns} jobNameById={jobNameById} + scopeId={SourcererScopeName.default} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx index e00d0ebd31b4f..32cada93fb791 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.test.tsx @@ -173,10 +173,10 @@ describe('getFormattedAlertStats', () => { it('should return alert stats', () => { const alertStats = getFormattedAlertStats(mockAlertData, euiTheme); expect(alertStats).toEqual([ - { key: 'High', count: 2, color: '#FF7E62' }, + { key: 'High', count: 2, color: '#DA8B45' }, { key: 'Low', count: 2, color: '#54B399' }, - { key: 'Medium', count: 2, color: '#F1D86F' }, - { key: 'Critical', count: 2, color: '#bd271e' }, + { key: 'Medium', count: 2, color: '#D6BF57' }, + { key: 'Critical', count: 2, color: '#E7664C' }, ]); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx index 715f6dfa43589..1f3750c86863a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx @@ -27,6 +27,7 @@ import { useAnomaliesTableData } from '../../../common/components/ml/anomaly/use import { useInstalledSecurityJobNameById } from '../../../common/components/ml/hooks/use_installed_security_jobs'; import { EmptyPrompt } from '../../../common/components/empty_prompt'; import type { NarrowDateRange } from '../../../common/components/ml/types'; +import { SourcererScopeName } from '../../../sourcerer/store/model'; export interface NetworkDetailsProps { /** @@ -121,6 +122,7 @@ export const NetworkDetails = ({ narrowDateRange={narrowDateRange} indexPatterns={selectedPatterns} jobNameById={jobNameById} + scopeId={SourcererScopeName.default} /> ) : ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.test.tsx new file mode 100644 index 0000000000000..85aacdb478d44 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.test.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { render } from '@testing-library/react'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { PreviewPanelFooter } from './footer'; +import { PREVIEW_FOOTER_LINK_TEST_ID, PREVIEW_FOOTER_TEST_ID } from './test_ids'; +import { NetworkPanelKey } from '.'; +import { FlowTargetSourceDest } from '../../../common/search_strategy'; +import { mockFlyoutApi } from '../document_details/shared/mocks/mock_flyout_context'; + +jest.mock('@kbn/expandable-flyout'); + +const ip = 'ip'; +const flowTarget = FlowTargetSourceDest.destination; +const scopeId = 'scopeId'; + +describe('', () => { + beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue(mockFlyoutApi); + }); + + it('should open network details flyout when clicked', () => { + const { getByTestId } = render( + + ); + + expect(getByTestId(PREVIEW_FOOTER_TEST_ID)).toBeInTheDocument(); + + getByTestId(PREVIEW_FOOTER_LINK_TEST_ID).click(); + expect(mockFlyoutApi.openFlyout).toHaveBeenCalledWith({ + right: { + id: NetworkPanelKey, + params: { + ip, + flowTarget, + scopeId, + }, + }, + }); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.tsx new file mode 100644 index 0000000000000..25c7ec8ea8c1b --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/footer.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FC } from 'react'; +import React, { useCallback, useMemo } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiFlyoutFooter, EuiLink, EuiPanel } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { PREVIEW_FOOTER_LINK_TEST_ID, PREVIEW_FOOTER_TEST_ID } from './test_ids'; +import type { FlowTargetSourceDest } from '../../../common/search_strategy'; +import { NetworkPanelKey } from '.'; + +export interface PreviewPanelFooterProps { + /** + * IP value + */ + ip: string; + /** + * Destination or source information + */ + flowTarget: FlowTargetSourceDest; + /** + * Scope ID + */ + scopeId: string; +} + +/** + * Footer at the bottom of preview panel with a link to open network details flyout + */ +export const PreviewPanelFooter: FC = ({ ip, flowTarget, scopeId }) => { + const { openFlyout } = useExpandableFlyoutApi(); + + const openNetworkFlyout = useCallback(() => { + openFlyout({ + right: { + id: NetworkPanelKey, + params: { + ip, + flowTarget, + scopeId, + }, + }, + }); + }, [openFlyout, flowTarget, ip, scopeId]); + + const fullDetailsLink = useMemo( + () => ( + + <> + {i18n.translate('xpack.securitySolution.flyout.network.preview.openFlyoutLabel', { + defaultMessage: 'Show full network details', + })} + + + ), + [openNetworkFlyout] + ); + + return ( + + + + {fullDetailsLink} + + + + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.test.tsx new file mode 100644 index 0000000000000..5161771e86e78 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.test.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { render } from '@testing-library/react'; +import { + useExpandableFlyoutApi, + useExpandableFlyoutHistory, + useExpandableFlyoutState, +} from '@kbn/expandable-flyout'; +import { PREVIEW_FOOTER_TEST_ID } from './test_ids'; +import { NetworkPanel } from '.'; +import { FlowTargetSourceDest } from '../../../common/search_strategy'; +import { mockFlyoutApi } from '../document_details/shared/mocks/mock_flyout_context'; +import { TestProviders } from '../../common/mock'; + +jest.mock('@kbn/expandable-flyout'); +jest.mock('../../common/hooks/use_experimental_features'); + +const ip = 'ip'; +const flowTarget = FlowTargetSourceDest.destination; +const scopeId = 'scopeId'; + +describe('', () => { + beforeEach(() => { + jest.mocked(useExpandableFlyoutApi).mockReturnValue(mockFlyoutApi); + jest.mocked(useExpandableFlyoutHistory).mockReturnValue([]); + (useExpandableFlyoutState as jest.Mock).mockReturnValue({}); + }); + + it('should not show footer if non-preview mode', () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId(PREVIEW_FOOTER_TEST_ID)).not.toBeInTheDocument(); + }); + + it('should show footer if preview mode', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId(PREVIEW_FOOTER_TEST_ID)).toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.tsx index 37727e8074f0b..19a24ed02f49d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/index.tsx @@ -10,6 +10,7 @@ import React, { memo } from 'react'; import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; import { i18n } from '@kbn/i18n'; import { TableId } from '@kbn/securitysolution-data-table'; +import { PreviewPanelFooter } from './footer'; import type { FlowTargetSourceDest } from '../../../common/search_strategy'; import { PanelHeader } from './header'; import { PanelContent } from './content'; @@ -64,6 +65,7 @@ export const NetworkPanel: FC = memo( /> + {isPreviewMode && } ); } diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/test_ids.ts b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/test_ids.ts new file mode 100644 index 0000000000000..91bf92a12c935 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/test_ids.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PREFIX } from '../shared/test_ids'; + +export const PREVIEW_FOOTER_TEST_ID = `${PREFIX}NetworkPreviewFooter` as const; +export const PREVIEW_FOOTER_LINK_TEST_ID = `${PREVIEW_FOOTER_TEST_ID}Link` as const; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts index 93fbc7ef76f27..3dbea89c49dc3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/rbac/endpoint_role_rbac_with_space_awareness.cy.ts @@ -107,6 +107,7 @@ describe( 'Host Isolation ExceptionsNone', 'BlocklistNone', 'Event FiltersNone', + 'Global Artifact ManagementNone', 'Elastic Defend Policy ManagementNone', 'Response Actions HistoryNone', 'Host IsolationAll', @@ -124,5 +125,9 @@ describe( ); }); }); + + it('should include new Global Artifact Management privilege', () => { + cy.getByTestSubj('securitySolution_siemV2_global_artifact_management').should('exist'); + }); } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_cloud_topic_id.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_cloud_topic_id.ts new file mode 100644 index 0000000000000..ea493319cdb87 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_cloud_topic_id.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback, useState } from 'react'; +import type { CloudDataAttributes } from '@kbn/cloud-plugin/common/types'; +import { useKibana } from '../../../common/lib/kibana/kibana_react'; +import { OnboardingTopicId } from '../../constants'; + +const URL = '/internal/cloud/solution'; + +interface UseCloudTopicIdParams { + onComplete: (topicId: OnboardingTopicId | null) => void; +} + +export const useCloudTopicId = ({ onComplete }: UseCloudTopicIdParams) => { + const { http } = useKibana().services; + const [isLoading, setIsLoading] = useState(false); + + const start = useCallback(async () => { + setIsLoading(true); + try { + const data = await http.get(URL, { version: '1' }); + if (isSiemMigrationsCloudOnboarding(data)) { + onComplete(OnboardingTopicId.siemMigrations); + } else { + onComplete(null); + } + } catch (_) { + // ignore the error, we will just show the default topic + onComplete(null); + } + setIsLoading(false); + }, [onComplete, http]); + + return { start, isLoading }; +}; + +const isSiemMigrationsCloudOnboarding = (data: CloudDataAttributes) => { + const { security } = data.onboardingData ?? {}; + return ( + security?.useCase === 'siem' && + security?.migration?.value && + security?.migration?.type === 'splunk' + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_stored_state.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_stored_state.ts index 86ef735d13703..2e382929c39e5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_stored_state.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_stored_state.ts @@ -46,7 +46,7 @@ export const useStoredCompletedCardIds = (spaceId: string) => * Stores the selected topic ID per space */ export const useStoredUrlDetails = (spaceId: string) => - useDefinedLocalStorage(`${LocalStorageKey.urlDetails}.${spaceId}`, null); + useLocalStorage(`${LocalStorageKey.urlDetails}.${spaceId}`); /** * Stores the selected selectable card ID per space diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_topic_id.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_topic_id.ts index b20e8ae392b62..6c56ddb41eed1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_topic_id.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_topic_id.ts @@ -5,11 +5,9 @@ * 2.0. */ -import { useCallback } from 'react'; import { useParams } from 'react-router-dom'; import { OnboardingTopicId } from '../../constants'; import type { OnboardingRouteParams } from '../../types'; -import { useUrlDetail } from './use_url_detail'; /** * Hook that returns the topic id from the URL, or the default topic id if none is present @@ -19,17 +17,3 @@ export const useTopicId = (): OnboardingTopicId => { const { topicId = OnboardingTopicId.default } = useParams(); return topicId; }; - -export const useTopic = (): [OnboardingTopicId, (topicId: OnboardingTopicId) => void] => { - const topicId = useTopicId(); - const { setTopicDetail } = useUrlDetail(); - - const setTopicId = useCallback( - (newTopicId: OnboardingTopicId) => { - setTopicDetail(newTopicId); - }, - [setTopicDetail] - ); - - return [topicId, setTopicId]; -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.test.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.test.ts new file mode 100644 index 0000000000000..b202e87d489af --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.test.ts @@ -0,0 +1,255 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { renderHook, act } from '@testing-library/react'; +import { useUrlDetail, useSyncUrlDetails, getCardIdFromHash } from './use_url_detail'; + +// --- Mocks for dependencies --- +jest.mock('@kbn/security-solution-navigation', () => ({ + ...jest.requireActual('@kbn/security-solution-navigation'), + useNavigateTo: jest.fn(), + SecurityPageName: { landing: 'landing' }, +})); + +jest.mock('./use_stored_state', () => ({ + ...jest.requireActual('./use_stored_state'), + useStoredUrlDetails: jest.fn(), +})); + +jest.mock('./use_topic_id', () => ({ + ...jest.requireActual('./use_topic_id'), + useTopicId: jest.fn(), +})); + +jest.mock('./use_cloud_topic_id', () => ({ + ...jest.requireActual('./use_cloud_topic_id'), + useCloudTopicId: jest.fn(), +})); + +jest.mock('../onboarding_context', () => ({ + ...jest.requireActual('../onboarding_context'), + useOnboardingContext: jest.fn(), +})); + +// Import the mocked modules for type-checking and setting implementations +import { useStoredUrlDetails } from './use_stored_state'; +import { useTopicId } from './use_topic_id'; +import { useCloudTopicId } from './use_cloud_topic_id'; +import { useNavigateTo, SecurityPageName } from '@kbn/security-solution-navigation'; +import { useOnboardingContext } from '../onboarding_context'; +import type { OnboardingCardId } from '../../constants'; +import { OnboardingTopicId } from '../../constants'; + +// --- Tests for useUrlDetail --- +describe('useUrlDetail', () => { + let mockSetStoredUrlDetail: jest.Mock; + let mockNavigateTo: jest.Mock; + let mockReportCardOpen: jest.Mock; + + beforeEach(() => { + mockSetStoredUrlDetail = jest.fn(); + mockNavigateTo = jest.fn(); + mockReportCardOpen = jest.fn(); + + // By default, no stored detail + (useStoredUrlDetails as jest.Mock).mockReturnValue([null, mockSetStoredUrlDetail]); + (useNavigateTo as jest.Mock).mockReturnValue({ navigateTo: mockNavigateTo }); + (useTopicId as jest.Mock).mockReturnValue(OnboardingTopicId.default); + (useOnboardingContext as jest.Mock).mockReturnValue({ + spaceId: 'test-space', + telemetry: { reportCardOpen: mockReportCardOpen }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('returns the expected initial values', () => { + const { result } = renderHook(() => useUrlDetail()); + expect(result.current.topicId).toBe(OnboardingTopicId.default); + expect(typeof result.current.setTopic).toBe('function'); + expect(typeof result.current.setCard).toBe('function'); + expect(typeof result.current.navigateToDetail).toBe('function'); + expect(result.current.storedUrlDetail).toBe(null); + }); + + it('setTopic updates stored detail and navigates (default topic)', () => { + const { result } = renderHook(() => useUrlDetail()); + + act(() => { + result.current.setTopic(OnboardingTopicId.default); + }); + + // When topic is "default", the detail is null + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith(null); + expect(mockNavigateTo).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.landing, + path: undefined, + }); + }); + + it('setTopic updates stored detail and navigates (non-default topic)', () => { + const { result } = renderHook(() => useUrlDetail()); + + act(() => { + result.current.setTopic('customTopic' as OnboardingTopicId); + }); + + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith('customTopic'); + expect(mockNavigateTo).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.landing, + path: 'customTopic', + }); + }); + + it('setCard updates the URL hash, stored detail and reports telemetry when a cardId is provided', () => { + // Spy on history.replaceState (used in setHash) + const replaceStateSpy = jest.spyOn(history, 'replaceState').mockImplementation(() => {}); + (useTopicId as jest.Mock).mockReturnValue(OnboardingTopicId.default); + const { result } = renderHook(() => useUrlDetail()); + const cardId = 'card1'; + + act(() => { + result.current.setCard(cardId as OnboardingCardId); + }); + + // Expect the URL hash to be updated to "#card1" + expect(replaceStateSpy).toHaveBeenCalledWith(null, '', `#${cardId}`); + // For topic "default", getUrlDetail produces `#card1` + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith(`#${cardId}`); + expect(mockReportCardOpen).toHaveBeenCalledWith(cardId); + replaceStateSpy.mockRestore(); + }); + + it('setCard updates the URL hash and stored detail without reporting telemetry when cardId is null', () => { + const replaceStateSpy = jest.spyOn(history, 'replaceState').mockImplementation(() => {}); + const { result } = renderHook(() => useUrlDetail()); + + act(() => { + result.current.setCard(null); + }); + + expect(replaceStateSpy).toHaveBeenCalledWith(null, '', ' '); + // For a null cardId, getUrlDetail returns an empty string (falsy) so stored detail becomes null + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith(null); + expect(mockReportCardOpen).not.toHaveBeenCalled(); + replaceStateSpy.mockRestore(); + }); + + it('navigateToDetail calls navigateTo with the correct parameters', () => { + const { result } = renderHook(() => useUrlDetail()); + + act(() => { + result.current.navigateToDetail('detail-path'); + }); + + expect(mockNavigateTo).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.landing, + path: 'detail-path', + }); + }); +}); + +// --- Tests for getCardIdFromHash --- +describe('getCardIdFromHash', () => { + it('extracts the card id from a hash with query parameters', () => { + const cardId = getCardIdFromHash('#card1?foo=bar'); + expect(cardId).toBe('card1'); + }); + + it('returns null if no card id is present', () => { + const cardId = getCardIdFromHash('#?foo=bar'); + expect(cardId).toBeNull(); + }); +}); + +// --- Tests for useSyncUrlDetails --- +describe('useSyncUrlDetails', () => { + let mockSetStoredUrlDetail: jest.Mock; + let mockNavigateTo: jest.Mock; + let mockReportCardOpen: jest.Mock; + let mockStartGetCloudTopicId: jest.Mock; + let mockConfigHas: jest.Mock; + + beforeEach(() => { + mockSetStoredUrlDetail = jest.fn(); + mockNavigateTo = jest.fn(); + mockReportCardOpen = jest.fn(); + mockStartGetCloudTopicId = jest.fn(); + mockConfigHas = jest.fn().mockReturnValue(true); + + // Provide default values for the dependencies used inside useUrlDetail + (useStoredUrlDetails as jest.Mock).mockReturnValue([null, mockSetStoredUrlDetail]); + (useNavigateTo as jest.Mock).mockReturnValue({ navigateTo: mockNavigateTo }); + (useTopicId as jest.Mock).mockReturnValue(OnboardingTopicId.default); + (useCloudTopicId as jest.Mock).mockReturnValue({ + start: mockStartGetCloudTopicId, + isLoading: false, + }); + (useOnboardingContext as jest.Mock).mockReturnValue({ + config: { has: mockConfigHas }, + telemetry: { reportCardOpen: mockReportCardOpen }, + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('updates stored detail and reports telemetry when URL detail differs from stored detail', () => { + const pathTopicId = 'customTopic' as OnboardingTopicId; + const hashCardId = 'card1' as OnboardingCardId; + const expectedUrlDetail = `${pathTopicId}#${hashCardId}`; + + // Render the hook with URL detail (via path and hash) + renderHook(() => useSyncUrlDetails({ pathTopicId, hashCardId })); + + // useEffect should run immediately after mount: + expect(mockReportCardOpen).toHaveBeenCalledWith(hashCardId, { auto: true }); + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith(expectedUrlDetail); + }); + + it('navigates to the stored detail when URL is empty and a stored detail exists', () => { + // Simulate that a stored detail already exists + (useStoredUrlDetails as jest.Mock).mockReturnValue([ + 'customTopic#card1', + mockSetStoredUrlDetail, + ]); + + renderHook(() => useSyncUrlDetails({ pathTopicId: null, hashCardId: null })); + + expect(mockNavigateTo).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.landing, + path: 'customTopic#card1', + }); + }); + + it('calls startGetCloudTopicId when URL is empty and stored detail is undefined', () => { + // Simulate no stored detail (undefined) – e.g. first time onboarding + (useStoredUrlDetails as jest.Mock).mockReturnValue([undefined, mockSetStoredUrlDetail]); + + renderHook(() => useSyncUrlDetails({ pathTopicId: null, hashCardId: null })); + + expect(mockStartGetCloudTopicId).toHaveBeenCalled(); + }); + + it('clears stored detail if the stored topic is invalid', () => { + // Simulate a stored detail with an invalid topic + (useStoredUrlDetails as jest.Mock).mockReturnValue([ + 'invalidTopic#card1', + mockSetStoredUrlDetail, + ]); + // Simulate config.has returning false for an invalid topic + mockConfigHas.mockReturnValue(false); + + renderHook(() => useSyncUrlDetails({ pathTopicId: null, hashCardId: null })); + + expect(mockSetStoredUrlDetail).toHaveBeenCalledWith(null); + // In this case, navigation should not be triggered + expect(mockNavigateTo).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.ts index 444aa7831802d..7f4d6d57e1acf 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/hooks/use_url_detail.ts @@ -5,12 +5,13 @@ * 2.0. */ -import { useCallback } from 'react'; +import { useCallback, useEffect } from 'react'; import { SecurityPageName, useNavigateTo } from '@kbn/security-solution-navigation'; import { useStoredUrlDetails } from './use_stored_state'; import { OnboardingTopicId, type OnboardingCardId } from '../../constants'; import { useOnboardingContext } from '../onboarding_context'; import { useTopicId } from './use_topic_id'; +import { useCloudTopicId } from './use_cloud_topic_id'; export const getCardIdFromHash = (hash: string): OnboardingCardId | null => (hash.split('?')[0].replace('#', '') as OnboardingCardId) || null; @@ -19,34 +20,41 @@ const setHash = (cardId: OnboardingCardId | null) => { history.replaceState(null, '', cardId == null ? ' ' : `#${cardId}`); }; -const getTopicPath = (topicId: OnboardingTopicId) => - topicId !== OnboardingTopicId.default ? topicId : ''; - -const getCardHash = (cardId: OnboardingCardId | null) => (cardId ? `#${cardId}` : ''); +const getUrlDetail = (topicId: OnboardingTopicId, cardId: OnboardingCardId | null): string => { + return `${topicId !== OnboardingTopicId.default ? topicId : ''}${cardId ? `#${cardId}` : ''}`; +}; /** * This hook manages the expanded card id state in the LocalStorage and the hash in the URL. + * The "urlDetail" is the combination of the topicId as the path fragment followed cardId in the hash (#) parameter, in the URL */ export const useUrlDetail = () => { - const { config, spaceId, telemetry } = useOnboardingContext(); + const { spaceId, telemetry } = useOnboardingContext(); const topicId = useTopicId(); const [storedUrlDetail, setStoredUrlDetail] = useStoredUrlDetails(spaceId); const { navigateTo } = useNavigateTo(); - const setTopicDetail = useCallback( + const navigateToDetail = useCallback( + (detail?: string | null) => { + navigateTo({ deepLinkId: SecurityPageName.landing, path: detail || undefined }); + }, + [navigateTo] + ); + + const setTopic = useCallback( (newTopicId: OnboardingTopicId) => { - const path = newTopicId === OnboardingTopicId.default ? undefined : newTopicId; - setStoredUrlDetail(path ?? null); - navigateTo({ deepLinkId: SecurityPageName.landing, path }); + const detail = newTopicId === OnboardingTopicId.default ? null : newTopicId; + setStoredUrlDetail(detail); + navigateToDetail(detail); }, - [setStoredUrlDetail, navigateTo] + [setStoredUrlDetail, navigateToDetail] ); - const setCardDetail = useCallback( + const setCard = useCallback( (newCardId: OnboardingCardId | null) => { setHash(newCardId); - setStoredUrlDetail(`${getTopicPath(topicId)}${getCardHash(newCardId)}` || null); + setStoredUrlDetail(getUrlDetail(topicId, newCardId) || null); if (newCardId != null) { telemetry.reportCardOpen(newCardId); } @@ -54,29 +62,59 @@ export const useUrlDetail = () => { [setStoredUrlDetail, topicId, telemetry] ); - const syncUrlDetails = useCallback( - (pathTopicId: OnboardingTopicId | null, hashCardId: OnboardingCardId | null) => { - if (storedUrlDetail) { - // If the stored topic is not valid, clear it - const [storedTopicId] = storedUrlDetail.split('#'); - if (storedTopicId && !config.has(storedTopicId as OnboardingTopicId)) { - setStoredUrlDetail(null); - return; - } - } - const urlDetail = `${pathTopicId || ''}${hashCardId ? `#${hashCardId}` : ''}`; - if (urlDetail && urlDetail !== storedUrlDetail) { - if (hashCardId) { - telemetry.reportCardOpen(hashCardId, { auto: true }); - } - setStoredUrlDetail(urlDetail); + return { topicId, setTopic, setCard, navigateToDetail, storedUrlDetail, setStoredUrlDetail }; +}; + +interface UseSyncUrlDetailsParams { + pathTopicId: OnboardingTopicId | null; + hashCardId: OnboardingCardId | null; +} +/** + * This hook manages the expanded card id state in the LocalStorage and the hash in the URL. + */ +export const useSyncUrlDetails = ({ pathTopicId, hashCardId }: UseSyncUrlDetailsParams) => { + const { config, telemetry } = useOnboardingContext(); + const { storedUrlDetail, setStoredUrlDetail, navigateToDetail, setTopic } = useUrlDetail(); + + const onComplete = useCallback((cloudTopicId: OnboardingTopicId | null) => { + if (cloudTopicId && config.has(cloudTopicId)) { + setTopic(cloudTopicId); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const { start: startGetCloudTopicId, isLoading } = useCloudTopicId({ onComplete }); + + useEffect(() => { + // Create the URL detail + const urlDetail = `${pathTopicId || ''}${hashCardId ? `#${hashCardId}` : ''}`; + + // If the URL has a topic it has prevalence, we need to set it to the local storage + if (urlDetail && urlDetail !== storedUrlDetail) { + if (hashCardId) { + telemetry.reportCardOpen(hashCardId, { auto: true }); } - if (!urlDetail && storedUrlDetail) { - navigateTo({ deepLinkId: SecurityPageName.landing, path: storedUrlDetail }); + setStoredUrlDetail(urlDetail); + return; + } + + // If the URL has no topic, but the local storage has a topic, we need to navigate to the topic + if (!urlDetail && storedUrlDetail) { + // Check if the stored topic is not valid, if so clear it to prevent inconsistencies + const [storedTopicId] = storedUrlDetail.split('#'); + if (storedTopicId && !config.has(storedTopicId as OnboardingTopicId)) { + setStoredUrlDetail(null); + return; } - }, - [config, navigateTo, setStoredUrlDetail, storedUrlDetail, telemetry] - ); + navigateToDetail(storedUrlDetail); + } + + // If nothing is stored and nothing is in the URL, let's see if we have a cloud topic (first time onboarding) + if (!urlDetail && storedUrlDetail === undefined) { + startGetCloudTopicId(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - return { setTopicDetail, setCardDetail, syncUrlDetails }; + return { isLoading }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.test.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.test.ts index b60642093b651..2c2383138efa7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.test.ts @@ -9,10 +9,10 @@ import { useExpandedCard } from './use_expanded_card'; import type { OnboardingCardId } from '../../../constants'; import { waitFor, renderHook, act } from '@testing-library/react'; -const mockSetCardDetail = jest.fn(); +const mockSetCard = jest.fn(); jest.mock('../../hooks/use_url_detail', () => ({ ...jest.requireActual('../../hooks/use_url_detail'), - useUrlDetail: () => ({ setCardDetail: mockSetCardDetail }), + useUrlDetail: () => ({ setCard: mockSetCard }), })); jest.mock('react-router-dom', () => ({ @@ -67,7 +67,7 @@ describe('useExpandedCard Hook', () => { }); it('should set the expanded card id', () => { - expect(mockSetCardDetail).toHaveBeenCalledWith(mockCardId); + expect(mockSetCard).toHaveBeenCalledWith(mockCardId); }); it('should not scroll', async () => { @@ -88,7 +88,7 @@ describe('useExpandedCard Hook', () => { }); it('should set the expanded card id', () => { - expect(mockSetCardDetail).toHaveBeenCalledWith(mockCardId); + expect(mockSetCard).toHaveBeenCalledWith(mockCardId); }); it('should scroll', async () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.ts index 514618390695c..065c4f6ce6c38 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_expanded_card.ts @@ -28,16 +28,16 @@ const scrollToCard = (cardId: OnboardingCardId) => { * This hook manages the expanded card id state in the LocalStorage and the hash in the URL. */ export const useExpandedCard = () => { - const { setCardDetail } = useUrlDetail(); + const { setCard } = useUrlDetail(); const { hash } = useLocation(); const cardIdFromHash = useMemo(() => getCardIdFromHash(hash), [hash]); - const [cardId, setCardId] = useState(null); + const [expandedCardId, _setExpandedCardId] = useState(null); // This effect implements auto-scroll in the initial render. useEffect(() => { if (cardIdFromHash) { - setCardId(cardIdFromHash); + _setExpandedCardId(cardIdFromHash); scrollToCard(cardIdFromHash); } // cardIdFromHash is only defined once on page load @@ -46,14 +46,14 @@ export const useExpandedCard = () => { const setExpandedCardId = useCallback( (newCardId, options) => { - setCardId(newCardId); - setCardDetail(newCardId); + _setExpandedCardId(newCardId); + setCard(newCardId); if (newCardId != null && options?.scroll) { scrollToCard(newCardId); } }, - [setCardDetail] + [setCard] ); - return { expandedCardId: cardId, setExpandedCardId }; + return { expandedCardId, setExpandedCardId }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx index 00e2353b66e29..d67e6ea9aa007 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx @@ -9,9 +9,9 @@ import React, { useMemo } from 'react'; import { EuiButtonGroup } from '@elastic/eui'; import { OnboardingTopicId } from '../../constants'; import { useOnboardingContext } from '../onboarding_context'; -import { useTopic } from '../hooks/use_topic_id'; import type { TopicConfig } from '../../types'; import { SiemMigrationSetupTour } from '../../../siem_migrations/rules/components/tours/setup_guide'; +import { useUrlDetail } from '../hooks/use_url_detail'; const getLabel = (topicConfig: TopicConfig) => { if (topicConfig.id === OnboardingTopicId.siemMigrations) { @@ -26,7 +26,7 @@ const getLabel = (topicConfig: TopicConfig) => { export const OnboardingHeaderTopicSelector = React.memo(() => { const { config } = useOnboardingContext(); - const [topicId, setTopicId] = useTopic(); + const { topicId, setTopic } = useUrlDetail(); const selectorOptions = useMemo( () => @@ -49,7 +49,7 @@ export const OnboardingHeaderTopicSelector = React.memo(() => { legend="Topic selector" options={selectorOptions} idSelected={topicId} - onChange={(id) => setTopicId(id as OnboardingTopicId)} + onChange={(id) => setTopic(id as OnboardingTopicId)} isFullWidth /> ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx index 31d51b9427d46..0470e3ea147ab 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useEffect, useMemo } from 'react'; +import React, { useMemo } from 'react'; import type { RouteComponentProps } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; @@ -13,10 +13,11 @@ import { Redirect } from 'react-router-dom'; import { ONBOARDING_PATH } from '../../../common/constants'; import type { OnboardingRouteParams } from '../types'; import { OnboardingTopicId } from '../constants'; -import { getCardIdFromHash, useUrlDetail } from './hooks/use_url_detail'; +import { getCardIdFromHash, useSyncUrlDetails } from './hooks/use_url_detail'; import { useOnboardingContext } from './onboarding_context'; import { OnboardingHeader } from './onboarding_header'; import { OnboardingBody } from './onboarding_body'; +import { CenteredLoadingSpinner } from '../../common/components/centered_loading_spinner'; export const OnboardingRouter = React.memo(() => { const { config } = useOnboardingContext(); @@ -24,7 +25,7 @@ export const OnboardingRouter = React.memo(() => { const topicPathParam = useMemo(() => { const availableTopics = [...config.values()] .map(({ id }) => id) // available topic ids - .filter((val) => val !== OnboardingTopicId.default) // except "default" + .filter((id) => id !== OnboardingTopicId.default) // except "default" .join('|'); if (availableTopics) { return `/:topicId(${availableTopics})?`; // optional parameter} @@ -43,18 +44,15 @@ OnboardingRouter.displayName = 'OnboardingRouter'; type OnboardingRouteProps = RouteComponentProps; -const OnboardingRoute = React.memo(({ match, location }) => { - const { syncUrlDetails } = useUrlDetail(); +const OnboardingRoute = React.memo(({ match: { params }, location }) => { + const { isLoading } = useSyncUrlDetails({ + pathTopicId: params.topicId || null, + hashCardId: getCardIdFromHash(location.hash), + }); - /** - * This effect syncs the URL details with the stored state, it only needs to be executed once per page load. - */ - useEffect(() => { - const pathTopicId = match.params.topicId || null; - const hashCardId = getCardIdFromHash(location.hash); - syncUrlDetails(pathTopicId, hashCardId); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + if (isLoading) { + return ; + } return ( <> diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index b8df2ea6df517..bbdd8b129d737 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -18,7 +18,7 @@ import { useIsWithinMinBreakpoint, } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { ALERT_WORKFLOW_STATUS, ALERT_SEVERITY } from '@kbn/rule-data-utils'; import { FILTER_OPEN, FILTER_ACKNOWLEDGED, FILTER_CLOSED } from '../../../../../common/types'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/chart_label.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/chart_label.tsx index 12dce8053bf59..6c00ef6c0e686 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/chart_label.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/chart_label.tsx @@ -6,7 +6,7 @@ */ import { EuiLink } from '@elastic/eui'; import React, { useCallback } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { FormattedCount } from '../../../../common/components/formatted_number'; interface ChartLabelProps { @@ -15,7 +15,7 @@ interface ChartLabelProps { } const PlaceHolder = styled.div` - padding: ${(props) => props.theme.eui.euiSizeS}; + padding: ${(props) => props.theme.euiTheme.size.s}; `; const ChartLabelComponent: React.FC = ({ count, onClick }) => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx index 1993247674c3f..a41bd1e1c6616 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText, useEuiTheme } from '@elastic/eui'; import type { AxisStyle, Rotation } from '@elastic/charts'; import { ScaleType } from '@elastic/charts'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { FormattedNumber } from '@kbn/i18n-react'; import numeral from '@elastic/numeral'; import { BarChart } from '../../../../common/components/charts/barchart'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/soc_trends/soc_trends.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/soc_trends/soc_trends.tsx index 6c69a038b45fe..7ba5d4d1f067e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/soc_trends/soc_trends.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/soc_trends/soc_trends.tsx @@ -17,7 +17,7 @@ import { EuiText, EuiToolTip, } from '@elastic/eui'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { InputsModelId } from '../../../../common/store/inputs/constants'; import { SocTrendsDatePickerLock } from './date_picker_lock'; import { SuperDatePicker } from '../../../../common/components/super_date_picker'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index a30ae72ed9b00..4e4892bfc152e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -10,7 +10,7 @@ import numeral from '@elastic/numeral'; import React, { useEffect, useMemo, useCallback } from 'react'; import type { Filter, Query } from '@kbn/es-query'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiButton } from '@elastic/eui'; import type { DataViewSpec } from '@kbn/data-plugin/common'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; @@ -67,8 +67,8 @@ const getHistogramOption = (fieldName: string): MatrixHistogramOption => ({ const StyledLinkButton = styled(EuiButton)` margin-left: 0; - @media only screen and (min-width: ${(props) => props.theme.eui.euiBreakpoints.m}) { - margin-left: ${({ theme }) => theme.eui.euiSizeL}; + @media only screen and (min-width: ${(props) => props.theme.euiTheme.breakpoint.m}) { + margin-left: ${({ theme }) => theme.euiTheme.size.l}; } `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/index.tsx index 84b56a43a2023..8fc03416d2882 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/host_overview/index.tsx @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { euiDarkVars as darkTheme, euiLightVars as lightTheme } from '@kbn/ui-theme'; import { getOr } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { RiskScoreHeaderTitle } from '../../../entity_analytics/components/risk_score_header_title'; import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useQueryInspector } from '../../../common/components/page/manage_query'; @@ -59,7 +59,7 @@ interface HostSummaryProps { } const HostRiskOverviewWrapper = styled(EuiFlexGroup)` - padding-top: ${({ theme }) => theme.eui.euiSizeM}; + padding-top: ${({ theme: { euiTheme } }) => euiTheme.size.m}; width: ${({ $width }: { $width: string }) => $width}; `; @@ -179,7 +179,7 @@ export const HostOverview = React.memo( title: i18n.HOST_ID, description: data && data.host - ? hostIdRenderer({ host: data.host, isDraggable, noLink: true }) + ? hostIdRenderer({ host: data.host, isDraggable, noLink: true, scopeId }) : getEmptyTagValue(), }, { @@ -205,7 +205,7 @@ export const HostOverview = React.memo( ), }, ], - [data, indexNames, hostName, isDraggable] + [data, indexNames, hostName, isDraggable, scopeId] ); const firstColumn = useMemo( () => diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx index f76b446ac72e8..5e6b4e0a33ab6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx @@ -6,29 +6,29 @@ */ import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink, EuiSplitPanel, EuiText } from '@elastic/eui'; import * as i18n from './translations'; const ButtonContainer = styled(EuiFlexGroup)` - padding: ${({ theme }) => theme.eui.euiSizeS}; + padding: ${({ theme: { euiTheme } }) => euiTheme.size.s}; `; const Icon = styled(EuiIcon)` padding: 0; - margin-top: ${({ theme }) => theme.eui.euiSizeM}; + margin-top: ${({ theme: { euiTheme } }) => euiTheme.size.m}; margin-left: 12px; transform: scale(${({ color }) => (color === 'primary' ? 1.4 : 1)}); `; const PanelContainer = styled(EuiSplitPanel.Inner)` - margin-bottom: ${({ theme }) => theme.eui.euiSizeM}; + margin-bottom: ${({ theme: { euiTheme } }) => euiTheme.size.m}; `; const Title = styled(EuiText)<{ textcolor: 'primary' | 'warning' }>` - color: ${({ theme, textcolor }) => - textcolor === 'primary' ? theme.eui.euiColorPrimary : theme.eui.euiColorWarningText}; - margin-bottom: ${({ theme }) => theme.eui.euiSizeM}; + color: ${({ theme: { euiTheme }, textcolor }) => + textcolor === 'primary' ? euiTheme.colors.primary : euiTheme.colors.textWarning}; + margin-bottom: ${({ theme: { euiTheme } }) => euiTheme.size.m}; `; export const InnerLinkPanel = ({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/link_panel.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/link_panel.tsx index 07a7634d62b39..79ad1b25770fb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/link_panel.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/link_panel/link_panel.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React, { useMemo, useState } from 'react'; -import styled from 'styled-components'; +import { css } from '@emotion/react'; import { chunk } from 'lodash'; import type { EuiTableFieldDataColumnType, CriteriaWithPagination } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiBasicTable, EuiPanel, EuiSpacer } from '@elastic/eui'; @@ -13,20 +13,6 @@ import { InspectButtonContainer } from '../../../common/components/inspect'; import { HeaderSection } from '../../../common/components/header_section'; import type { LinkPanelListItem } from './types'; -// @ts-expect-error TS2769 -const StyledTable = styled(EuiBasicTable)` - [data-test-subj='panel-link'], - [data-test-subj='panel-no-link'] { - opacity: 0; - } - tr:hover { - [data-test-subj='panel-link'], - [data-test-subj='panel-no-link'] { - opacity: 1; - } - } -`; - const PAGE_SIZE = 5; const sortAndChunkItems = ( @@ -128,7 +114,19 @@ const LinkPanelComponent = ({ {splitPanel} {infoPanel} {chunkedItems.length > 0 && ( - - - + } buttonContentClassName="accordion-button" id="host-stat-accordion-groupauditbeat" > - + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - - + } buttonContentClassName="accordion-button" id="host-stat-accordion-groupendgame" > - + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - - + } buttonContentClassName="accordion-button" id="host-stat-accordion-groupfilebeat" > - + - + - + - - + - - + + - + - - + } buttonContentClassName="accordion-button" id="host-stat-accordion-groupwinlogbeat" > - + - + - + - - + - - + + - + - + - - + - - + + - + - + `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx index e6e3fd730a895..4687be2914304 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_host_stats/index.tsx @@ -8,7 +8,7 @@ import { EuiAccordion, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import type { HostsOverviewStrategyResponse } from '../../../../common/search_strategy'; import type { FormattedStat, StatGroup } from '../types'; @@ -247,7 +247,7 @@ const hostStatGroups: StatGroup[] = [ const MoveItLeftTitle = styled.div` margin-left: 24px; - @media only screen and (min-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + @media only screen and (min-width: ${({ theme: { euiTheme } }) => euiTheme.breakpoint.m}) { max-width: 40px; } `; @@ -256,7 +256,7 @@ const MoveItLeft = styled.div` `; const NoMarginTopFlexItem = styled(EuiFlexItem)` - @media only screen and (max-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + @media only screen and (max-width: ${({ theme: { euiTheme } }) => euiTheme.breakpoint.m}) { margin-top: -10px !important; } `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap index b59b29db68031..acca9a5ed4a7c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Overview Network Stat Data rendering it renders the default OverviewNetworkStats 1`] = ` - - + - + - + - - + - - + + - + - + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + - + - + - - + - - + + - + - + - - + - - + + - + - + - - + - - + + - + - + `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx index e461bf3241b2a..89111562c089e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/overview_network_stats/index.tsx @@ -8,7 +8,7 @@ import { EuiAccordion, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import type { NetworkOverviewStrategyResponse } from '../../../../common/search_strategy'; import type { FormattedStat, StatGroup } from '../types'; @@ -160,7 +160,7 @@ const NetworkStatsContainer = styled.div` `; const MoveItLeftTitle = styled.div` margin-left: 24px; - @media only screen and (min-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + @media only screen and (min-width: ${({ theme: { euiTheme } }) => euiTheme.breakpoint.m}) { max-width: 40px; } `; @@ -169,7 +169,7 @@ const MoveItLeft = styled.div` `; const NoMarginTopFlexItem = styled(EuiFlexItem)` - @media only screen and (max-width: ${({ theme }) => theme.eui.euiBreakpoints.m}) { + @media only screen and (max-width: ${({ theme: { euiTheme } }) => euiTheme.breakpoint.m}) { margin-top: -10px !important; } `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/counts/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/counts/index.tsx index f75ed58010c6e..6137f470e2992 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/counts/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/counts/index.tsx @@ -7,7 +7,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiToolTip } from '@elastic/eui'; import React from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { getPinnedEventCount, diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/recent_timelines.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/recent_timelines.tsx index 5f73a38f86d92..6887e3283dff2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/recent_timelines.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/recent_timelines/recent_timelines.tsx @@ -8,7 +8,7 @@ import { EuiSpacer, EuiText, EuiToolTip, EuiButtonIcon } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { RecentTimelineHeader } from './header'; import type { OnOpenTimeline, diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/stat_value.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/stat_value.tsx index 7b00ef7ff4cd7..c540ce38a8aa5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/stat_value.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/stat_value.tsx @@ -8,7 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSkeletonText, EuiProgress, EuiText } from '@elastic/eui'; import numeral from '@elastic/numeral'; import React, { useEffect, useState } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { DEFAULT_NUMBER_FORMAT } from '../../../common/constants'; import { useUiSetting$ } from '../../common/lib/kibana'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/user_overview/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/user_overview/index.tsx index ba4016c49f522..d5aa5b7bed136 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/user_overview/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/user_overview/index.tsx @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { euiDarkVars as darkTheme, euiLightVars as lightTheme } from '@kbn/ui-theme'; import { getOr } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { buildUserNamesFilter } from '../../../../common/search_strategy'; import { RiskScoreHeaderTitle } from '../../../entity_analytics/components/risk_score_header_title'; import { useGlobalTime } from '../../../common/containers/use_global_time'; @@ -60,7 +60,7 @@ export interface UserSummaryProps { } const UserRiskOverviewWrapper = styled(EuiFlexGroup)` - padding-top: ${({ theme }) => theme.eui.euiSizeM}; + padding-top: ${({ theme: { euiTheme } }) => euiTheme.size.m}; width: ${({ $width }: { $width: string }) => $width}; `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/links.ts b/x-pack/solutions/security/plugins/security_solution/public/overview/links.ts index bfa2064f672e5..4e2fdeace3a5b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/links.ts @@ -29,6 +29,7 @@ export const overviewLinks: LinkItem = { defaultMessage: 'Summary of your security environment activity, including alerts, events, recent items, and a news feed!', }), + path: OVERVIEW_PATH, capabilities: [`${SECURITY_FEATURE_ID}.show`], globalSearchKeywords: [ diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts index e149804630dc9..e4b976a51ab3f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/api/index.ts @@ -52,7 +52,7 @@ export interface GetRuleMigrationStatsParams { /** Optional AbortSignal for cancelling request */ signal?: AbortSignal; } -/** Retrieves the stats for all the existing migrations, aggregated by `migration_id`. */ +/** Retrieves the stats for the specific migration. */ export const getRuleMigrationStats = async ({ migrationId, signal, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index dc867b61ecfe7..87f849b3638c6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -21,6 +21,7 @@ import type { AutonomousSystem } from '../../../../common/search_strategy'; import { FlowTarget } from '../../../../common/search_strategy'; import type { HostEcs } from '@kbn/securitysolution-ecs'; import { mockGetUrlForApp } from '@kbn/security-solution-navigation/mocks/context'; +import { SourcererScopeName } from '../../../sourcerer/store/model'; jest.mock('../../../common/lib/kibana'); jest.mock('@kbn/security-solution-navigation/src/context'); @@ -32,6 +33,8 @@ mockGetUrlForApp.mockImplementation( jest.mock('../../../common/hooks/use_get_field_spec'); describe('Field Renderers', () => { + const scopeId = SourcererScopeName.default; + describe('#locationRenderer', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( @@ -104,24 +107,32 @@ describe('Field Renderers', () => { describe('#hostIdRenderer', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - {hostNameRenderer(mockData.complete.host, '10.10.10.10')} + + {hostNameRenderer(scopeId, mockData.complete.host, '10.10.10.10')} + ); expect(asFragment()).toMatchSnapshot(); }); test('it renders emptyTagValue when non-matching IP is provided', () => { render( - {hostNameRenderer(mockData.complete.host, '10.10.10.11')} + + {hostNameRenderer(scopeId, mockData.complete.host, '10.10.10.11')} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when no host.id is provided', () => { - render({hostNameRenderer(emptyIdHost, FlowTarget.source)}); + render( + {hostNameRenderer(scopeId, emptyIdHost, FlowTarget.source)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when no host.ip is provided', () => { - render({hostNameRenderer(emptyIpHost, FlowTarget.source)}); + render( + {hostNameRenderer(scopeId, emptyIpHost, FlowTarget.source)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); }); @@ -129,7 +140,9 @@ describe('Field Renderers', () => { describe('#hostNameRenderer', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - {hostNameRenderer(mockData.complete.host, '10.10.10.10')} + + {hostNameRenderer(scopeId, mockData.complete.host, '10.10.10.10')} + ); expect(asFragment()).toMatchSnapshot(); @@ -137,21 +150,29 @@ describe('Field Renderers', () => { test('it renders emptyTagValue when non-matching IP is provided', () => { render( - {hostNameRenderer(mockData.complete.host, '10.10.10.11')} + + {hostNameRenderer(scopeId, mockData.complete.host, '10.10.10.11')} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when no host.id is provided', () => { - render({hostNameRenderer(emptyIdHost, FlowTarget.source)}); + render( + {hostNameRenderer(scopeId, emptyIdHost, FlowTarget.source)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when no host.ip is provided', () => { - render({hostNameRenderer(emptyIpHost, FlowTarget.source)}); + render( + {hostNameRenderer(scopeId, emptyIpHost, FlowTarget.source)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); test('it renders emptyTagValue when no host.name is provided', () => { - render({hostNameRenderer(emptyNameHost, FlowTarget.source)}); + render( + {hostNameRenderer(scopeId, emptyNameHost, FlowTarget.source)} + ); expect(screen.getByText(getEmptyValue())).toBeInTheDocument(); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx index 1cb30270fb4f7..45968add49f95 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx @@ -19,6 +19,7 @@ import { DefaultDraggable } from '../../../common/components/draggables'; import { getEmptyTagValue } from '../../../common/components/empty_value'; import { HostDetailsLink, ReputationLink, WhoIsLink } from '../../../common/components/links'; import * as i18n from '../../../explore/network/components/details/translations'; +import type { SourcererScopeName } from '../../../sourcerer/store/model'; export const IpOverviewId = 'ip-overview'; @@ -97,6 +98,7 @@ interface HostIdRendererTypes { ipFilter?: string; isDraggable?: boolean; noLink?: boolean; + scopeId: string | undefined; } export const hostIdRenderer = ({ @@ -105,6 +107,7 @@ export const hostIdRenderer = ({ isDraggable = false, ipFilter, noLink, + scopeId, }: HostIdRendererTypes): React.ReactElement => host.id && host.ip && (ipFilter == null || host.ip.includes(ipFilter)) ? ( <> @@ -118,6 +121,7 @@ export const hostIdRenderer = ({ value={host.id[0]} isAggregatable={true} fieldType={'keyword'} + scopeId={scopeId} > {noLink ? ( <>{host.id} @@ -134,6 +138,7 @@ export const hostIdRenderer = ({ ); export const hostNameRenderer = ( + scopeId: SourcererScopeName, host?: HostEcs, ipFilter?: string, contextID?: string, @@ -153,6 +158,7 @@ export const hostNameRenderer = ( value={host.name[0]} isAggregatable={true} fieldType={'keyword'} + scopeId={scopeId} > {host.name ? host.name : getEmptyTagValue()} diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap index 2b9b8e4675ced..ffadec2c625dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap @@ -106,16 +106,11 @@ tr:hover .c3:focus::before { vertical-align: top; } -.c8 svg { - position: relative; - top: -1px; -} - -.c10 { +.c9 { margin-right: 5px; } -.c9 { +.c8 { margin-right: 5px; } @@ -937,7 +932,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1325,7 +1320,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -1383,7 +1378,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -1417,7 +1412,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -1492,7 +1487,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -1550,7 +1545,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1675,7 +1670,7 @@ tr:hover .c3:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1658,7 +1653,7 @@ tr:hover .c5:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1692,7 +1687,7 @@ tr:hover .c5:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1777,7 +1772,7 @@ tr:hover .c5:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -1845,7 +1840,7 @@ tr:hover .c5:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" > @@ -2026,7 +2021,7 @@ tr:hover .c5:focus::before { class="euiToolTipAnchor emotion-euiToolTipAnchor-inlineBlock" >
ja3 @@ -2568,7 +2563,7 @@ tr:hover .c5:focus::before { class="euiBadge__text emotion-euiBadge__text" > client cert @@ -2663,7 +2658,7 @@ tr:hover .c5:focus::before { class="euiBadge__text emotion-euiBadge__text" > server cert diff --git a/x-pack/solutions/security/plugins/security_solution/public/value_list/components/list_item_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/value_list/components/list_item_table.tsx index 11ecd486aa452..b469c958e565d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/value_list/components/list_item_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/value_list/components/list_item_table.tsx @@ -39,7 +39,7 @@ export const ListItemTable = ({ name: COLUMN_VALUE, render: (value, item) => canWriteIndex ? : value, - sortable: list.type !== 'text', + sortable: list.type !== 'text' && list.type !== 'ip_range', }, { field: LIST_ITEM_FIELDS.updatedAt, diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.test.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.test.ts index 126a7c4192fc3..969cc71bce3f3 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.test.ts @@ -9,6 +9,7 @@ import { httpServerMock, httpServiceMock } from '@kbn/core/server/mocks'; import { registerUpdateInsightsRoute } from './update_insight'; import { createMockEndpointAppContext, getRegisteredVersionedRouteMock } from '../../mocks'; import { WORKFLOW_INSIGHTS_UPDATE_ROUTE } from '../../../../common/endpoint/constants'; +import type { EndpointAppContext } from '../../types'; jest.mock('../../services', () => ({ securityWorkflowInsightsService: { @@ -21,52 +22,55 @@ const updateMock = jest.requireMock('../../services').securityWorkflowInsightsSe describe('Update Insights Route Handler', () => { let mockResponse: ReturnType; - let callRoute: ( - params: Record, - body: Record, - authz?: Record - ) => Promise; - beforeEach(() => { + const callRoute = async ( + params: Record, + body: Record, + authz: Record = { + canWriteWorkflowInsights: true, + canReadWorkflowInsights: true, + } + ) => { mockResponse = httpServerMock.createResponseFactory(); const mockEndpointContext = createMockEndpointAppContext(); const router = httpServiceMock.createRouter(); - registerUpdateInsightsRoute(router, mockEndpointContext); - - callRoute = async (params, body, authz = { canWriteWorkflowInsights: true }) => { - const mockContext = { - core: { - security: { - authc: { - getCurrentUser: jest - .fn() - .mockReturnValue({ username: 'test-user', roles: ['admin'] }), - }, + const mockContext = { + ...mockEndpointContext, + service: { + ...mockEndpointContext.service, + getEndpointAuthz: jest.fn().mockResolvedValue(authz), + }, + securitySolution: { + getEndpointAuthz: jest.fn().mockResolvedValue(authz), + }, + core: { + security: { + authc: { + getCurrentUser: jest.fn().mockReturnValue({ username: 'test-user', roles: ['admin'] }), }, }, - securitySolution: { - getEndpointAuthz: jest.fn().mockResolvedValue(authz), - }, - }; + }, + }; - const request = httpServerMock.createKibanaRequest({ - method: 'put', - path: WORKFLOW_INSIGHTS_UPDATE_ROUTE, - params, - body, - }); + registerUpdateInsightsRoute(router, mockContext as unknown as EndpointAppContext); - const { routeHandler } = getRegisteredVersionedRouteMock( - router, - 'put', - WORKFLOW_INSIGHTS_UPDATE_ROUTE, - '1' - )!; - await routeHandler(mockContext, request, mockResponse); - }; - }); + const request = httpServerMock.createKibanaRequest({ + method: 'put', + path: WORKFLOW_INSIGHTS_UPDATE_ROUTE, + params, + body, + }); + + const { routeHandler } = getRegisteredVersionedRouteMock( + router, + 'put', + WORKFLOW_INSIGHTS_UPDATE_ROUTE, + '1' + )!; + await routeHandler(mockContext, request, mockResponse); + }; describe('with valid privileges', () => { it('should update insight and return the updated data', async () => { @@ -98,14 +102,38 @@ describe('Update Insights Route Handler', () => { }); describe('with invalid privileges', () => { - it('should return forbidden if user lacks read privileges', async () => { + it('should return forbidden if user lacks write and read privileges', async () => { await callRoute( { insightId: '1' }, - { name: 'Updated Insight' }, - { canWriteWorkflowInsights: false } + { action: { type: 'remediated' } }, + { canWriteWorkflowInsights: false, canReadWorkflowInsights: false } ); expect(mockResponse.forbidden).toHaveBeenCalled(); }); + + it('should allow update if user has no write privileges but read and the body only contains action.type', async () => { + const updateBody = { action: { type: 'remediated' } }; // Only action.type in the body + updateMock.mockResolvedValue({ id: 1, ...updateBody }); + await callRoute({ insightId: '1' }, updateBody, { + canWriteWorkflowInsights: false, + canReadWorkflowInsights: true, + }); + + expect(updateMock).toHaveBeenCalledWith('1', updateBody); + expect(mockResponse.ok).toHaveBeenCalledWith({ + body: { id: 1, action: { type: 'remediated' } }, + }); + }); + + it('should return forbidden if user has no write privileges but read and the body contains more than action.type', async () => { + const updateBody = { action: { type: 'remediated' }, value: 'changeme' }; + await callRoute({ insightId: '1' }, updateBody, { + canWriteWorkflowInsights: false, + canReadWorkflowInsights: true, + }); + + expect(mockResponse.forbidden).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.ts b/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.ts index a1f1813b5e710..d1584cf083b9b 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/endpoint/routes/workflow_insights/update_insight.ts @@ -46,7 +46,7 @@ export const registerUpdateInsightsRoute = ( }, }, withEndpointAuthz( - { all: ['canWriteWorkflowInsights'] }, + { all: ['canReadWorkflowInsights'] }, endpointContext.logFactory.get('workflowInsights'), updateInsightsRouteHandler(endpointContext) ) @@ -63,9 +63,19 @@ const updateInsightsRouteHandler = ( > => { const logger = endpointContext.logFactory.get('workflowInsights'); + const isOnlyActionTypeUpdate = (body: Partial): boolean => { + // Type guard is done by schema validation + if (!body?.action?.type) return false; + // Make sure the body only contains the action.type field + return Object.keys(body).length === 1 && Object.keys(body.action).length === 1; + }; + return async (_, request, response) => { const { insightId } = request.params; - + const { canWriteWorkflowInsights } = await endpointContext.service.getEndpointAuthz(request); + if (!canWriteWorkflowInsights && !isOnlyActionTypeUpdate(request.body)) { + return response.forbidden({ body: 'Unauthorized to update workflow insights' }); + } logger.debug(`Updating insight ${insightId}`); try { const body = await securityWorkflowInsightsService.update( diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts index 25dc49cadf9df..2a7b73511234e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_create_rules/route.ts @@ -42,6 +42,8 @@ export const bulkCreateRulesRoute = ( logger: Logger, docLinks: DocLinksServiceSetup ) => { + const securityDocLinks = docLinks.links.securitySolution; + router.versioned .post({ access: 'public', @@ -67,8 +69,8 @@ export const bulkCreateRulesRoute = ( }, options: { deprecated: { - documentationUrl: docLinks.links.securitySolution.legacyBulkApiDeprecations, - severity: 'critical', + documentationUrl: securityDocLinks.legacyRuleManagementBulkApiDeprecations, + severity: 'warning', reason: { type: 'migrate', newApiMethod: 'POST', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts index ec7a195141ce4..592851b714f2f 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_delete_rules/route.ts @@ -132,6 +132,9 @@ export const bulkDeleteRulesRoute = ( authz: { requiredPrivileges: ['securitySolution'] }, }, }; + + const securityDocLinks = docLinks.links.securitySolution; + router.versioned.delete(routeConfig).addVersion( { version: '2023-10-31', @@ -142,8 +145,8 @@ export const bulkDeleteRulesRoute = ( }, options: { deprecated: { - documentationUrl: docLinks.links.securitySolution.legacyBulkApiDeprecations, - severity: 'critical', + documentationUrl: securityDocLinks.legacyRuleManagementBulkApiDeprecations, + severity: 'warning', reason: { type: 'migrate', newApiMethod: 'POST', @@ -154,6 +157,7 @@ export const bulkDeleteRulesRoute = ( }, handler ); + router.versioned.post(routeConfig).addVersion( { version: '2023-10-31', @@ -164,8 +168,8 @@ export const bulkDeleteRulesRoute = ( }, options: { deprecated: { - documentationUrl: docLinks.links.securitySolution.legacyBulkApiDeprecations, - severity: 'critical', + documentationUrl: securityDocLinks.legacyRuleManagementBulkApiDeprecations, + severity: 'warning', reason: { type: 'migrate', newApiMethod: 'POST', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts index 197b6675e9b91..a89c687b8d92c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_patch_rules/route.ts @@ -36,6 +36,8 @@ export const bulkPatchRulesRoute = ( logger: Logger, docLinks: DocLinksServiceSetup ) => { + const securityDocLinks = docLinks.links.securitySolution; + router.versioned .patch({ access: 'public', @@ -61,8 +63,8 @@ export const bulkPatchRulesRoute = ( }, options: { deprecated: { - documentationUrl: docLinks.links.securitySolution.legacyBulkApiDeprecations, - severity: 'critical', + documentationUrl: securityDocLinks.legacyRuleManagementBulkApiDeprecations, + severity: 'warning', reason: { type: 'migrate', newApiMethod: 'POST', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts index 516006342c19c..54bae2977c679 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/bulk_update_rules/route.ts @@ -40,6 +40,8 @@ export const bulkUpdateRulesRoute = ( logger: Logger, docLinks: DocLinksServiceSetup ) => { + const securityDocLinks = docLinks.links.securitySolution; + router.versioned .put({ access: 'public', @@ -65,8 +67,8 @@ export const bulkUpdateRulesRoute = ( }, options: { deprecated: { - documentationUrl: docLinks.links.securitySolution.legacyBulkApiDeprecations, - severity: 'critical', + documentationUrl: securityDocLinks.legacyRuleManagementBulkApiDeprecations, + severity: 'warning', reason: { type: 'migrate', newApiMethod: 'POST', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts index 32f61c2836ecb..11de1de5780d9 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts @@ -19,7 +19,7 @@ import type { LogLevel, } from '../../../../../../../common/api/detection_engine/rule_monitoring'; import { - logLevelFromExecutionStatus, + consoleLogLevelFromExecutionStatus, LogLevelSetting, logLevelToNumber, RuleExecutionStatusEnum, @@ -159,7 +159,7 @@ export const createRuleExecutionLogClientForExecutors = ( const writeStatusChangeToConsole = (args: NormalizedStatusChangeArgs, logMeta: ExtMeta): void => { const messageParts: string[] = [`Changing rule status to "${args.newStatus}"`, args.message]; const logMessage = messageParts.filter(Boolean).join('. '); - const logLevel = logLevelFromExecutionStatus(args.newStatus); + const logLevel = consoleLogLevelFromExecutionStatus(args.newStatus, args.userError); writeMessageToConsole(logMessage, logLevel, logMeta); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/event_log/event_log_writer.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/event_log/event_log_writer.ts index b0963546100e2..f0cc2ed9ae3b8 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/event_log/event_log_writer.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/event_log/event_log_writer.ts @@ -10,7 +10,7 @@ import type { IEventLogService } from '@kbn/event-log-plugin/server'; import { SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/server'; import type { LogLevel } from '../../../../../../../common/api/detection_engine/rule_monitoring'; import { - logLevelFromExecutionStatus, + eventLogLevelFromExecutionStatus, logLevelToNumber, ruleExecutionStatusToNumber, } from '../../../../../../../common/api/detection_engine/rule_monitoring'; @@ -107,7 +107,7 @@ export const createEventLogWriter = (eventLogService: IEventLogService): IEventL }, logStatusChange: (args: StatusChangeArgs): void => { - const logLevel = logLevelFromExecutionStatus(args.newStatus); + const logLevel = eventLogLevelFromExecutionStatus(args.newStatus); eventLogger.logEvent({ '@timestamp': nowISO(), message: args.message, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts index 073296dd2bd06..5c863d356a3a1 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_store_data_client.ts @@ -316,10 +316,6 @@ export class EntityStoreDataClient { throw new Error('Universal entity store is not enabled'); } - if (entityType === EntityType.service && !experimentalFeatures.serviceEntityStoreEnabled) { - throw new Error('Service entity store is not enabled'); - } - if (!this.options.taskManager) { throw new Error('Task Manager is not available'); } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts index 5829d190fb2bb..5408501ae0e38 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts @@ -204,30 +204,6 @@ describe('calculateRiskScores()', () => { expect(response.scores.service).toHaveLength(2); }); - it('calculates risk score for service when the experimental flag is enabled', async () => { - const response = await calculateRiskScores({ - ...params, - experimentalFeatures: { - ...mockGlobalState.app.enableExperimental, - serviceEntityStoreEnabled: true, - }, - }); - - expect(response.scores.service).toHaveLength(2); - }); - - it('does NOT calculates risk score for service when the experimental flag is disabled', async () => { - const response = await calculateRiskScores({ - ...params, - experimentalFeatures: { - ...mockGlobalState.app.enableExperimental, - serviceEntityStoreEnabled: false, - }, - }); - - expect(response.scores.service).toHaveLength(0); - }); - it('returns scores in the expected format', async () => { const { scores: { host: hostScores }, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts index d6685a04b6c33..267a05a23b7f5 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts @@ -311,9 +311,7 @@ export const calculateRiskScores = async ({ const userBuckets = response.aggregations.user?.buckets ?? []; const hostBuckets = response.aggregations.host?.buckets ?? []; - const serviceBuckets = experimentalFeatures.serviceEntityStoreEnabled - ? response.aggregations.service?.buckets ?? [] - : []; + const serviceBuckets = response.aggregations.service?.buckets ?? []; const afterKeys = { host: response.aggregations.host?.after_key, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts index 28b6ce0214bab..20035065746bc 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts @@ -348,10 +348,16 @@ describe('Risk Scoring Task', () => { // add additional mock responses for the additional identifier calls mockRiskScoreService.calculateAndPersistScores .mockResolvedValueOnce({ + // first call - host entity type after_keys: { host: { 'user.name': 'value' } }, scores_written: 5, errors: [], - }) + }) // second call - user entity type + .mockResolvedValueOnce({ + after_keys: {}, + scores_written: 5, + errors: [], + }) // third call - service entity type .mockResolvedValueOnce({ after_keys: {}, scores_written: 5, @@ -369,7 +375,7 @@ describe('Risk Scoring Task', () => { entityAnalyticsConfig, experimentalFeatures: mockExperimentalFeatures, }); - expect(mockRiskScoreService.calculateAndPersistScores).toHaveBeenCalledTimes(4); + expect(mockRiskScoreService.calculateAndPersistScores).toHaveBeenCalledTimes(5); expect(mockRiskScoreService.calculateAndPersistScores).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/update.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/update.ts index 1c288578748a6..a1d93eee2c55e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/update.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/api/update.ts @@ -44,6 +44,9 @@ export const registerSiemRuleMigrationsUpdateRoute = ( const { migration_id: migrationId } = req.params; const rulesToUpdate = req.body; + if (rulesToUpdate.length === 0) { + return res.noContent(); + } const ids = rulesToUpdate.map((rule) => rule.id); const siemMigrationAuditLogger = new SiemMigrationAuditLogger(context.securitySolution); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts index 974fe85dda5c1..7e72a3cb0884e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/siem_migrations/rules/data/rule_migrations_data_base_client.ts @@ -41,11 +41,16 @@ export class RuleMigrationsDataBaseClient { return this.currentUser.profile_uid; } const username = this.currentUser.username; - const users = await this.esScopedClient.asCurrentUser.security.getUser({ - username, - with_profile_uid: true, - }); - return users[username].profile_uid; + try { + const users = await this.esScopedClient.asCurrentUser.security.getUser({ + username, + with_profile_uid: true, + }); + return users[username].profile_uid; + } catch (error) { + this.logger.error(`Error getting profile_uid for user ${username}: ${error}`); + return username; + } } protected processResponseHits( diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index e43c76d42adfa..ff0f9ab4b8f18 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -38,7 +38,7 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi serverArgs: [ ...xPackFunctionalTestsConfig.get('esTestCluster.serverArgs'), 'node.attr.name=apiIntegrationTestNode', - 'path.repo=/tmp/repo,/tmp/repo_1,/tmp/repo_2,/tmp/cloud-snapshots/', + `path.repo=/tmp/repo,/tmp/repo_1,/tmp/repo_2,/tmp/cloud-snapshots/`, ], }, }; diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/.gitignore b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/.gitignore new file mode 100644 index 0000000000000..d555c9d94945b --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/.gitignore @@ -0,0 +1,2 @@ +# unzipped snapshot folder +knowledge_base/snapshot_kb_8.10/ \ No newline at end of file diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/chat/chat.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/chat/chat.spec.ts index 67ec6e4a4693e..0f602dd836d51 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/chat/chat.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/chat/chat.spec.ts @@ -20,13 +20,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); const messages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'You are a helpful assistant', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -63,6 +56,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon params: { body: { name: 'my_api_call', + systemMessage: 'You are a helpful assistant', messages, connectorId: 'does not exist', functions: [], @@ -98,6 +92,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon .on('error', reject) .send({ name: 'my_api_call', + systemMessage: 'You are a helpful assistant', messages, connectorId, functions: [], @@ -154,6 +149,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon params: { body: { name: 'my_api_call', + systemMessage: 'You are a helpful assistant', messages, connectorId, functions: [], diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts index 1cca90f96ab83..5d77326cdc49b 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/complete/complete.spec.ts @@ -36,13 +36,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); const messages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'You are a helpful assistant', - }, - }, { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/connectors/connectors.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/connectors/connectors.spec.ts index 43b3a4c824957..012bbcfb899ba 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/connectors/connectors.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/connectors/connectors.spec.ts @@ -10,6 +10,7 @@ import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provi export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); + describe('List connectors', () => { before(async () => { await observabilityAIAssistantAPIClient.deleteAllActionConnectors(); @@ -32,7 +33,10 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon endpoint: 'GET /internal/observability_ai_assistant/connectors', }); - expect(res.body.length).to.be(0); + const connectorsExcludingPreconfiguredInference = res.body.filter( + (c) => c.actionTypeId !== '.inference' + ); + expect(connectorsExcludingPreconfiguredInference.length).to.be(0); }); it("returns the gen ai connector if it's been created", async () => { @@ -44,7 +48,10 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon endpoint: 'GET /internal/observability_ai_assistant/connectors', }); - expect(res.body.length).to.be(1); + const connectorsExcludingPreconfiguredInference = res.body.filter( + (c) => c.actionTypeId !== '.inference' + ); + expect(connectorsExcludingPreconfiguredInference.length).to.be(1); await observabilityAIAssistantAPIClient.deleteActionConnector({ actionId: connectorId }); }); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/conversations/conversations.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/conversations/conversations.spec.ts index a7e6772c7761f..9fe2f83b35a2e 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/conversations/conversations.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/conversations/conversations.spec.ts @@ -25,6 +25,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }, labels: {}, numeric_labels: {}, + systemMessage: 'this is a system message', messages: [ { '@timestamp': new Date().toISOString(), @@ -135,6 +136,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }, labels: conversationCreate.labels, numeric_labels: conversationCreate.numeric_labels, + systemMessage: conversationCreate.systemMessage, messages: conversationCreate.messages, namespace: 'default', public: conversationCreate.public, diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/index.ts index 3f756ecd11247..1d3d41ddb4400 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/index.ts @@ -20,7 +20,10 @@ export default function aiAssistantApiIntegrationTests({ loadTestFile(require.resolve('./complete/functions/summarize.spec.ts')); loadTestFile(require.resolve('./public_complete/public_complete.spec.ts')); loadTestFile(require.resolve('./knowledge_base/knowledge_base_setup.spec.ts')); - loadTestFile(require.resolve('./knowledge_base/knowledge_base_migration.spec.ts')); + loadTestFile( + require.resolve('./knowledge_base/knowledge_base_add_semantic_text_field_migration.spec.ts') + ); + loadTestFile(require.resolve('./knowledge_base/knowledge_base_reindex.spec.ts')); loadTestFile(require.resolve('./knowledge_base/knowledge_base_status.spec.ts')); loadTestFile(require.resolve('./knowledge_base/knowledge_base.spec.ts')); loadTestFile(require.resolve('./knowledge_base/knowledge_base_user_instructions.spec.ts')); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_add_semantic_text_field_migration.spec.ts similarity index 98% rename from x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_add_semantic_text_field_migration.spec.ts index b1d6f82345ca7..3390cd3ef35c4 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_migration.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_add_semantic_text_field_migration.spec.ts @@ -98,7 +98,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon describe('after migrating', () => { before(async () => { const { status } = await observabilityAIAssistantAPIClient.editor({ - endpoint: 'POST /internal/observability_ai_assistant/kb/semantic_text_migration', + endpoint: 'POST /internal/observability_ai_assistant/kb/migrations/kb_semantic_text', }); expect(status).to.be(200); }); @@ -137,7 +137,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon it('returns entries correctly via API', async () => { const { status } = await observabilityAIAssistantAPIClient.editor({ - endpoint: 'POST /internal/observability_ai_assistant/kb/semantic_text_migration', + endpoint: 'POST /internal/observability_ai_assistant/kb/migrations/kb_semantic_text', }); expect(status).to.be(200); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_reindex.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_reindex.spec.ts new file mode 100644 index 0000000000000..79c6b963a852e --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_reindex.spec.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { resourceNames } from '@kbn/observability-ai-assistant-plugin/server/service'; +import AdmZip from 'adm-zip'; +import path from 'path'; +import { AI_ASSISTANT_SNAPSHOT_REPO_PATH } from '../../../../default_configs/stateful.config.base'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; +import { + deleteKnowledgeBaseModel, + importTinyElserModel, + deleteInferenceEndpoint, + setupKnowledgeBase, + waitForKnowledgeBaseReady, +} from './helpers'; + +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); + const es = getService('es'); + const ml = getService('ml'); + const retry = getService('retry'); + const log = getService('log'); + + describe('when the knowledge base index was created before 8.11', function () { + // Intentionally skipped in all serverless environnments (local and MKI) + // because the migration scenario being tested is not relevant to MKI and Serverless. + this.tags(['skipServerless']); + + before(async () => { + const zipFilePath = `${AI_ASSISTANT_SNAPSHOT_REPO_PATH}.zip`; + log.debug(`Unzipping ${zipFilePath} to ${AI_ASSISTANT_SNAPSHOT_REPO_PATH}`); + new AdmZip(zipFilePath).extractAllTo(path.dirname(AI_ASSISTANT_SNAPSHOT_REPO_PATH), true); + + await importTinyElserModel(ml); + await setupKnowledgeBase(observabilityAIAssistantAPIClient); + await waitForKnowledgeBaseReady({ observabilityAIAssistantAPIClient, log, retry }); + }); + + beforeEach(async () => { + await deleteKbIndex(); + await restoreKbSnapshot(); + await createOrUpdateIndexAssets(); + }); + + after(async () => { + await deleteKbIndex(); + await createOrUpdateIndexAssets(); + await deleteKnowledgeBaseModel(ml); + await deleteInferenceEndpoint({ es }); + }); + + it('has an index created version earlier than 8.11', async () => { + await retry.try(async () => { + expect(await getKbIndexCreatedVersion()).to.be.lessThan(8110000); + }); + }); + + function createKnowledgeBaseEntry() { + const knowledgeBaseEntry = { + id: 'my-doc-id-1', + title: 'My title', + text: 'My content', + }; + + return observabilityAIAssistantAPIClient.editor({ + endpoint: 'POST /internal/observability_ai_assistant/kb/entries/save', + params: { body: knowledgeBaseEntry }, + }); + } + + it('cannot add new entries to KB', async () => { + const { status, body } = await createKnowledgeBaseEntry(); + + // @ts-expect-error + expect(body.message).to.eql( + 'The knowledge base is currently being re-indexed. Please try again later' + ); + + expect(status).to.be(503); + }); + + it('can add new entries after re-indexing', async () => { + await runKbSemanticTextMigration(); + + await retry.try(async () => { + const { status } = await createKnowledgeBaseEntry(); + expect(status).to.be(200); + }); + }); + }); + + async function getKbIndexCreatedVersion() { + const indexSettings = await es.indices.getSettings({ + index: resourceNames.concreteIndexName.kb, + }); + + const { settings } = Object.values(indexSettings)[0]; + return parseInt(settings?.index?.version?.created ?? '', 10); + } + + async function deleteKbIndex() { + log.debug('Deleting KB index'); + + await es.indices.delete( + { index: resourceNames.concreteIndexName.kb, ignore_unavailable: true }, + { ignore: [404] } + ); + } + + async function restoreKbSnapshot() { + log.debug( + `Restoring snapshot of ${resourceNames.concreteIndexName.kb} from ${AI_ASSISTANT_SNAPSHOT_REPO_PATH}` + ); + const snapshotRepoName = 'snapshot-repo-8-10'; + const snapshotName = 'my_snapshot'; + await es.snapshot.createRepository({ + name: snapshotRepoName, + repository: { + type: 'fs', + settings: { location: AI_ASSISTANT_SNAPSHOT_REPO_PATH }, + }, + }); + + await es.snapshot.restore({ + repository: snapshotRepoName, + snapshot: snapshotName, + wait_for_completion: true, + body: { + indices: resourceNames.concreteIndexName.kb, + }, + }); + + await es.snapshot.deleteRepository({ name: snapshotRepoName }); + } + + async function createOrUpdateIndexAssets() { + const { status } = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'POST /internal/observability_ai_assistant/index_assets', + }); + expect(status).to.be(200); + } + + async function runKbSemanticTextMigration() { + const { status } = await observabilityAIAssistantAPIClient.editor({ + endpoint: 'POST /internal/observability_ai_assistant/kb/migrations/kb_semantic_text', + }); + expect(status).to.be(200); + } +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts index a1068a1a66ccf..5f9092d338af0 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/knowledge_base_user_instructions.spec.ts @@ -286,13 +286,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon .completeAfterIntercept(); const messages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'You are a helpful assistant', - }, - }, { '@timestamp': new Date().toISOString(), message: { @@ -353,10 +346,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon it('adds the instruction to the system prompt', async () => { const conversation = await getConversationForUser('editor'); - const systemMessage = conversation.messages.find( - (message) => message.message.role === MessageRole.System - )!; - expect(systemMessage.message.content).to.contain(userInstructionText); + expect(conversation.systemMessage).to.contain(userInstructionText); }); it('does not add the instruction to the context', async () => { @@ -375,12 +365,9 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon it('does not add the instruction conversation for other users', async () => { const conversation = await getConversationForUser('admin'); - const systemMessage = conversation.messages.find( - (message) => message.message.role === MessageRole.System - )!; - expect(systemMessage.message.content).to.not.contain(userInstructionText); - expect(conversation.messages.length).to.be(5); + expect(conversation.systemMessage).to.not.contain(userInstructionText); + expect(conversation.messages.length).to.be(4); }); }); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/snapshot_kb_8.10.zip b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/snapshot_kb_8.10.zip new file mode 100644 index 0000000000000..0e65dd1848246 Binary files /dev/null and b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/snapshot_kb_8.10.zip differ diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/public_complete/public_complete.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/public_complete/public_complete.spec.ts index cc0ed3e3f40aa..6dabb460bf599 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/public_complete/public_complete.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/public_complete/public_complete.spec.ts @@ -27,13 +27,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantApi'); const messages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: 'You are a helpful assistant', - }, - }, { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/test/api_integration/deployment_agnostic/default_configs/stateful.config.base.ts b/x-pack/test/api_integration/deployment_agnostic/default_configs/stateful.config.base.ts index 1668c3d634671..5b65152aea809 100644 --- a/x-pack/test/api_integration/deployment_agnostic/default_configs/stateful.config.base.ts +++ b/x-pack/test/api_integration/deployment_agnostic/default_configs/stateful.config.base.ts @@ -34,6 +34,11 @@ interface CreateTestConfigOptions { suiteTags?: { include?: string[]; exclude?: string[] }; } +export const AI_ASSISTANT_SNAPSHOT_REPO_PATH = path.resolve( + REPO_ROOT, + 'x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/knowledge_base/snapshot_kb_8.10' +); + export function createStatefulTestConfig( options: CreateTestConfigOptions ) { @@ -121,6 +126,7 @@ export function createStatefulTestConfig { + const radioGroup = await testSubjects.find(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR); + return await radioGroup.findByCssSelector(`input[value='${setupTechnology}']`); + }; + const showSetupTechnologyComponent = async () => { return await testSubjects.exists(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR); }; const selectAwsCredentials = async (credentialType: 'direct' | 'temporary') => { - await clickOptionButton(AWS_CREDENTIAL_SELECTOR); await selectValue( AWS_CREDENTIAL_SELECTOR, credentialType === 'direct' ? 'direct_access_keys' : 'temporary_keys' @@ -415,7 +419,7 @@ export function AddCisIntegrationFormPageProvider({ await clickOptionButton(testSubjectIds.CIS_AWS_OPTION_TEST_ID); - await clickOptionButton(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR_AGENTLESS_RADIO); + await selectSetupTechnology('agentless'); await selectValue(testSubjectIds.AWS_CREDENTIAL_SELECTOR, 'direct_access_keys'); await fillInTextField(testSubjectIds.DIRECT_ACCESS_KEY_ID_TEST_ID, directAccessKeyId); await fillInTextField(testSubjectIds.DIRECT_ACCESS_SECRET_KEY_TEST_ID, directAccessSecretKey); @@ -427,7 +431,7 @@ export function AddCisIntegrationFormPageProvider({ await clickOptionButton(testSubjectIds.CIS_GCP_OPTION_TEST_ID); await clickOptionButton(testSubjectIds.GCP_SINGLE_ACCOUNT_TEST_ID); - await clickOptionButton(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR_AGENTLESS_RADIO); + await selectSetupTechnology('agentless'); await fillInTextField(testSubjectIds.PRJ_ID_TEST_ID, projectId); await fillInTextField(testSubjectIds.CREDENTIALS_JSON_TEST_ID, credentialJson); }; @@ -452,6 +456,8 @@ export function AddCisIntegrationFormPageProvider({ await navigateToAddIntegrationCspmPage(); await PageObjects.header.waitUntilLoadingHasFinished(); + await inputIntegrationName(`cloud_security_posture-${new Date().toISOString()}`); + await fillOutForm(cloudProvider); // Click Save Button to create the Integration then navigate to Integration Policies Tab Page @@ -469,6 +475,12 @@ export function AddCisIntegrationFormPageProvider({ // Fill out form to edit an agentless integration await fillInTextField(testSubjectId, value); + // TechDebt: This is a workaround to ensure the form is saved + // const agentlessRadio = await getSetupTechnologyRadio('agentless'); + // const agentBasedRadio = await getSetupTechnologyRadio('agent-based'); + // expect(await agentlessRadio.isEnabled()).to.be(true); + // expect(agentBasedRadio.isEnabled()).to.be(true); + // Clicking Save Button updates and navigates to Integration Policies Tab Page await clickSaveIntegrationButton(); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -559,6 +571,7 @@ export function AddCisIntegrationFormPageProvider({ clickOptionButton, selectAwsCredentials, selectSetupTechnology, + getSetupTechnologyRadio, clickSaveButton, clickSaveIntegrationButton, clickAccordianButton, diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index e49d006a817ed..8e78baef8c8f6 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -991,18 +991,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { before(async () => { await setCustomDashboardsEnabled(true); await loginWithReadOnlyUser(); - await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); - await pageObjects.header.waitUntilLoadingHasFinished(); - - await pageObjects.timePicker.setAbsoluteRange( - START_SYNTHTRACE_DATE.format(DATE_PICKER_FORMAT), - END_SYNTHTRACE_DATE.format(DATE_PICKER_FORMAT) - ); + // Setting the params directly will help us reduce flakiness (and clicking the wrong tab) + // as we already test the flow (in #Single Host Flyout) here we can directly navigate to test the permissions + const dashboardsTabSearchParams = `?_a=(dateRange:(from:%27${DATE_WITH_HOSTS_DATA_FROM}%27,to:%27${DATE_WITH_HOSTS_DATA_TO}%27),filters:!(),limit:100,panelFilters:!(),query:(language:kuery,query:%27%27))&tableProperties=(detailsItemId:host-1-Linux,pagination:(pageIndex:0,pageSize:10),sorting:(direction:desc,field:alertsCount))&assetDetails=(dateRange:(from:%27${DATE_WITH_HOSTS_DATA_FROM}%27,to:%27${DATE_WITH_HOSTS_DATA_TO}%27),name:host-1,tabId:dashboards)`; - await waitForPageToLoad(); - - await pageObjects.infraHostsView.clickTableOpenFlyoutButton(); - await browser.scrollTop(); + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH, { + search: dashboardsTabSearchParams, + }); + await pageObjects.header.waitUntilLoadingHasFinished(); }); after(async () => { diff --git a/x-pack/test/functional/apps/lens/group2/table.ts b/x-pack/test/functional/apps/lens/group2/table.ts index 45833cc94d91e..386efcd520ca2 100644 --- a/x-pack/test/functional/apps/lens/group2/table.ts +++ b/x-pack/test/functional/apps/lens/group2/table.ts @@ -160,7 +160,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await lens.changePaletteTo('temperature'); await lens.waitForVisualization(); const styleObj = await lens.getDatatableCellStyle(0, 2); - expect(styleObj['background-color']).to.be('rgb(246, 249, 252)'); + expect(styleObj['background-color']).to.be('rgb(232, 241, 255)'); }); it('should keep the coloring consistent when changing mode', async () => { @@ -169,7 +169,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await lens.waitForVisualization(); // check that all remained the same const styleObj = await lens.getDatatableCellStyle(0, 2); - expect(styleObj['background-color']).to.be('rgb(246, 249, 252)'); + expect(styleObj['background-color']).to.be('rgb(232, 241, 255)'); }); it('should keep the coloring consistent when moving to custom palette from default', async () => { @@ -177,7 +177,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await lens.waitForVisualization(); // check that all remained the same const styleObj = await lens.getDatatableCellStyle(0, 2); - expect(styleObj['background-color']).to.be('rgb(246, 249, 252)'); + expect(styleObj['background-color']).to.be('rgb(232, 241, 255)'); }); it('tweak the color stops numeric value', async () => { @@ -202,7 +202,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('lnsPalettePanel_dynamicColoring_reverseColors'); await lens.waitForVisualization(); const styleObj = await lens.getDatatableCellStyle(1, 1); - expect(styleObj['background-color']).to.be('rgb(200, 222, 255)'); + expect(styleObj['background-color']).to.be('rgb(168, 202, 255)'); // should also set text color when in cell mode expect(styleObj.color).to.be('rgb(0, 0, 0)'); await lens.closePalettePanel(); diff --git a/x-pack/test/functional/apps/lens/group4/chart_data.ts b/x-pack/test/functional/apps/lens/group4/chart_data.ts index 197cf1b2c43f8..9123e0a49888e 100644 --- a/x-pack/test/functional/apps/lens/group4/chart_data.ts +++ b/x-pack/test/functional/apps/lens/group4/chart_data.ts @@ -115,9 +115,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // assert legend expect(debugState?.legend!.items).to.eql([ { key: '5,722.775 - 8,529.22', name: '5,722.775 - 8,529.22', color: '#61a2ff' }, - { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#c8deff' }, - { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#f6f9fc' }, - { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffccc6' }, + { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#a8caff' }, + { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#e8f1ff' }, + { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffafa6' }, { key: '≥ 16,948.555', name: '≥ 16,948.555', color: '#f6726a' }, ]); }); diff --git a/x-pack/test/functional/apps/lens/group5/heatmap.ts b/x-pack/test/functional/apps/lens/group5/heatmap.ts index 574f3711eb0ee..635d283075aae 100644 --- a/x-pack/test/functional/apps/lens/group5/heatmap.ts +++ b/x-pack/test/functional/apps/lens/group5/heatmap.ts @@ -56,9 +56,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // assert legend expect(debugState?.legend!.items).to.eql([ { key: '5,722.775 - 8,529.22', name: '5,722.775 - 8,529.22', color: '#61a2ff' }, - { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#c8deff' }, - { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#f6f9fc' }, - { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffccc6' }, + { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#a8caff' }, + { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#e8f1ff' }, + { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffafa6' }, { key: '≥ 16,948.555', name: '≥ 16,948.555', color: '#f6726a' }, ]); @@ -71,19 +71,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await lens.openPalettePanel(); await common.sleep(1000); await retry.try(async () => { - await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '10', { - clearWithKeyboard: true, - typeCharByChar: true, - }); + await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '10'); }); const debugState = await lens.getCurrentChartDebugState('heatmapChart'); // assert legend has changed expect(debugState?.legend!.items).to.eql([ { key: '7,125.997 - 8,529.22', name: '7,125.997 - 8,529.22', color: '#61a2ff' }, - { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#c8deff' }, - { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#f6f9fc' }, - { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffccc6' }, + { key: '8,529.22 - 11,335.665', name: '8,529.22 - 11,335.665', color: '#a8caff' }, + { key: '11,335.665 - 14,142.11', name: '11,335.665 - 14,142.11', color: '#e8f1ff' }, + { key: '14,142.11 - 16,948.555', name: '14,142.11 - 16,948.555', color: '#ffafa6' }, { key: '≥ 16,948.555', name: '≥ 16,948.555', color: '#f6726a' }, ]); }); @@ -95,9 +92,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // assert legend has changed expect(debugState?.legend!.items).to.eql([ { key: '7,125.99 - 8,529.2', name: '7,125.99 - 8,529.2', color: '#61a2ff' }, - { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#c8deff' }, - { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#f6f9fc' }, - { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffccc6' }, + { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#a8caff' }, + { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#e8f1ff' }, + { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffafa6' }, { color: '#f6726a', key: '≥ 16,948.55', @@ -107,18 +104,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should reflect stop changes when in number to the chart', async () => { - await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '0', { - clearWithKeyboard: true, - }); + await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '0'); const debugState = await lens.getCurrentChartDebugState('heatmapChart'); // assert legend has changed expect(debugState?.legend!.items).to.eql([ { key: '0 - 8,529.2', name: '0 - 8,529.2', color: '#61a2ff' }, - { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#c8deff' }, - { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#f6f9fc' }, - { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffccc6' }, + { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#a8caff' }, + { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#e8f1ff' }, + { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffafa6' }, { key: '≥ 16,948.55', name: '≥ 16,948.55', color: '#f6726a' }, ]); }); @@ -126,17 +121,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should reflect the apply stop value without rounding', async () => { // target item is 5722.774804505345 // so set a value slightly lower which can be rounded - await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '5722.7747', { - clearWithKeyboard: true, - }); + await testSubjects.setValue('lnsPalettePanel_dynamicColoring_range_value_0', '5722.7747'); const debugState = await lens.getCurrentChartDebugState('heatmapChart'); // assert legend has a rounded value expect(debugState?.legend!.items).to.eql([ { key: '5,722.775 - 8,529.2', name: '5,722.775 - 8,529.2', color: '#61a2ff' }, - { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#c8deff' }, - { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#f6f9fc' }, - { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffccc6' }, + { key: '8,529.2 - 11,335.66', name: '8,529.2 - 11,335.66', color: '#a8caff' }, + { key: '11,335.66 - 14,142.1', name: '11,335.66 - 14,142.1', color: '#e8f1ff' }, + { key: '14,142.1 - 16,948.55', name: '14,142.1 - 16,948.55', color: '#ffafa6' }, { key: '≥ 16,948.55', name: '≥ 16,948.55', color: '#f6726a' }, ]); // assert the cell has the correct coloring despite the legend rounding diff --git a/x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js b/x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js index c1d40776df94f..bb5fed5d28edc 100644 --- a/x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js +++ b/x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js @@ -14,7 +14,8 @@ export default function ({ getPageObjects, getService }) { const security = getService('security'); const retry = getService('retry'); - describe('shapefile upload', () => { + // Failing: See https://github.com/elastic/kibana/issues/209228 + describe.skip('shapefile upload', () => { let indexName = ''; before(async () => { await security.testUser.setRoles([ diff --git a/x-pack/test/functional/apps/maps/group4/mapbox_styles.js b/x-pack/test/functional/apps/maps/group4/mapbox_styles.js index e1bce36d2be89..2d9de1095fb5e 100644 --- a/x-pack/test/functional/apps/maps/group4/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/group4/mapbox_styles.js @@ -83,19 +83,19 @@ export default function ({ getPageObjects, getService }) { 2, 'rgba(0,0,0,0)', 3, - '#d8e7ff', + '#e4eefd', 4.125, - '#c8ddff', + '#d3e3fe', 5.25, - '#b8d4ff', + '#c1d8fe', 6.375, - '#a8caff', + '#afceff', 7.5, - '#98c0ff', + '#9dc3ff', 8.625, - '#87b6ff', + '#8bb8ff', 9.75, - '#75acff', + '#77adff', 10.875, '#61a2ff', ], @@ -162,19 +162,19 @@ export default function ({ getPageObjects, getService }) { 2, 'rgba(0,0,0,0)', 3, - '#d8e7ff', + '#e4eefd', 4.125, - '#c8ddff', + '#d3e3fe', 5.25, - '#b8d4ff', + '#c1d8fe', 6.375, - '#a8caff', + '#afceff', 7.5, - '#98c0ff', + '#9dc3ff', 8.625, - '#87b6ff', + '#8bb8ff', 9.75, - '#75acff', + '#77adff', 10.875, '#61a2ff', ], diff --git a/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js b/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js index 8b292ba7ce3d4..58787f3d059cd 100644 --- a/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js +++ b/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js @@ -78,19 +78,19 @@ export default function ({ getPageObjects, getService }) { 1622, 'rgba(0,0,0,0)', 1623, - '#d8e7ff', + '#e4eefd', 2643.875, - '#c8ddff', + '#d3e3fe', 3664.75, - '#b8d4ff', + '#c1d8fe', 4685.625, - '#a8caff', + '#afceff', 5706.5, - '#98c0ff', + '#9dc3ff', 6727.375, - '#87b6ff', + '#8bb8ff', 7748.25, - '#75acff', + '#77adff', 8769.125, '#61a2ff', ], @@ -123,19 +123,19 @@ export default function ({ getPageObjects, getService }) { 0, 'rgba(0,0,0,0)', 1, - '#d8e7ff', + '#e4eefd', 1.875, - '#c8ddff', + '#d3e3fe', 2.75, - '#b8d4ff', + '#c1d8fe', 3.625, - '#a8caff', + '#afceff', 4.5, - '#98c0ff', + '#9dc3ff', 5.375, - '#87b6ff', + '#8bb8ff', 6.25, - '#75acff', + '#77adff', 7.125, '#61a2ff', ], @@ -168,19 +168,19 @@ export default function ({ getPageObjects, getService }) { -1, 'rgba(0,0,0,0)', 0, - '#d8e7ff', + '#e4eefd', 1867.625, - '#c8ddff', + '#d3e3fe', 3735.25, - '#b8d4ff', + '#c1d8fe', 5602.875, - '#a8caff', + '#afceff', 7470.5, - '#98c0ff', + '#9dc3ff', 9338.125, - '#87b6ff', + '#8bb8ff', 11205.75, - '#75acff', + '#77adff', 13073.375, '#61a2ff', ], diff --git a/x-pack/test/functional/apps/maps/group4/mvt_scaling.js b/x-pack/test/functional/apps/maps/group4/mvt_scaling.js index fd7d0204feed0..03d6caf5ebdb5 100644 --- a/x-pack/test/functional/apps/maps/group4/mvt_scaling.js +++ b/x-pack/test/functional/apps/maps/group4/mvt_scaling.js @@ -85,19 +85,19 @@ export default function ({ getPageObjects, getService }) { 0.3819660112501051, 'rgba(0,0,0,0)', 1.381966011250105, - '#d8e7ff', + '#e4eefd', 1.6614745084375788, - '#c8ddff', + '#d3e3fe', 1.9409830056250525, - '#b8d4ff', + '#c1d8fe', 2.2204915028125263, - '#a8caff', + '#afceff', 2.5, - '#98c0ff', + '#9dc3ff', 2.7795084971874737, - '#87b6ff', + '#8bb8ff', 3.0590169943749475, - '#75acff', + '#77adff', 3.338525491562421, '#61a2ff', ], @@ -124,7 +124,7 @@ export default function ({ getPageObjects, getService }) { ], layout: { visibility: 'visible' }, paint: { - 'line-color': '#98c0ff', + 'line-color': '#9dc3ff', 'line-width': 3, 'line-dasharray': [2, 1], 'line-opacity': 1, diff --git a/x-pack/test/functional_search/tests/solution_navigation.ts b/x-pack/test/functional_search/tests/solution_navigation.ts index b9bd403b43b4a..0a3b92521b5de 100644 --- a/x-pack/test/functional_search/tests/solution_navigation.ts +++ b/x-pack/test/functional_search/tests/solution_navigation.ts @@ -277,6 +277,7 @@ export default function searchSolutionNavigation({ 'project_settings_project_nav', 'ml:modelManagement', 'stack_management', + 'monitoring', ]); }); }); diff --git a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts index c87e0d76dff3a..c6fcf5dfc471a 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/conversations/index.spec.ts @@ -93,14 +93,6 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte body: { conversation: { messages: [ - { - '@timestamp': '2024-04-18T14:28:50.118Z', - message: { - role: MessageRole.System, - content: - 'You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities.\n\nIt\'s very important to not assume what the user is meaning. Ask them for clarification if needed.\n\nIf you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation.\n\nIn KQL ("kqlFilter")) escaping happens with double quotes, not single quotes. Some characters that need escaping are: \':()\\ /". Always put a field value in double quotes. Best: service.name:"opbeans-go". Wrong: service.name:opbeans-go. This is very important!\n\nYou can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response.\n\nNote that ES|QL (the Elasticsearch Query Language which is a new piped language) is the preferred query language.\n\nYou MUST use the "query" function when the user wants to:\n- visualize data\n- run any arbitrary query\n- breakdown or filter ES|QL queries that are displayed on the current page\n- convert queries from another language to ES|QL\n- asks general questions about ES|QL\n\nDO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries or explain anything about the ES|QL query language yourself.\nDO NOT UNDER ANY CIRCUMSTANCES try to correct an ES|QL query yourself - always use the "query" function for this.\n\nDO NOT UNDER ANY CIRCUMSTANCES USE ES|QL syntax (`service.name == "foo"`) with "kqlFilter" (`service.name:"foo"`).\n\nEven if the "context" function was used before that, follow it up with the "query" function. If a query fails, do not attempt to correct it yourself. Again you should call the "query" function,\neven if it has been called before.\n\nWhen the "visualize_query" function has been called, a visualization has been displayed to the user. DO NOT UNDER ANY CIRCUMSTANCES follow up a "visualize_query" function call with your own visualization attempt.\nIf the "execute_query" function has been called, summarize these results for the user. The user does not see a visualization in this case.\n\nYou MUST use the get_dataset_info function function before calling the "query" or "changes" function.\n\nIf a function requires an index, you MUST use the results from the dataset info functions.\n\n\n\nThe user is able to change the language which they want you to reply in on the settings page of the AI Assistant for Observability, which can be found in the Stack Management app under the option AI Assistants.\nIf the user asks how to change the language, reply in the same language the user asked in.You do not have a working memory. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base.', - }, - }, { '@timestamp': '2024-04-18T14:29:01.615Z', message: { @@ -308,19 +300,17 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte expect(response.body.conversations[0].conversation.title).to.be('My title'); - const { messages } = response.body.conversations[0]; + const { messages, systemMessage } = response.body.conversations[0]; + + expect(messages.length).to.eql(4); - expect(messages.length).to.eql(5); + const [firstUserMessage, contextRequest, contextResponse, assistantResponse] = + messages.map((msg) => msg.message); - const [ - systemMessage, - firstUserMessage, - contextRequest, - contextResponse, - assistantResponse, - ] = messages.map((msg) => msg.message); + const systemMessageContent = + 'You are a helpful assistant for Elastic Observability. Your goal is to help the Elastic Observability users to quickly assess what is happening in their observed systems. You can help them visualise and analyze data, investigate their systems, perform root cause analysis or identify optimisation opportunities.\n\n It\'s very important to not assume what the user is meaning. Ask them for clarification if needed.\n\n If you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation.\n\n In KQL ("kqlFilter")) escaping happens with double quotes, not single quotes. Some characters that need escaping are: \':()\\ /". Always put a field value in double quotes. Best: service.name:"opbeans-go". Wrong: service.name:opbeans-go. This is very important!\n\n You can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response.\n\n Note that ES|QL (the Elasticsearch Query Language which is a new piped language) is the preferred query language.\n\n If you want to call a function or tool, only call it a single time per message. Wait until the function has been executed and its results\n returned to you, before executing the same tool or another tool again if needed.\n\n DO NOT UNDER ANY CIRCUMSTANCES USE ES|QL syntax (`service.name == "foo"`) with "kqlFilter" (`service.name:"foo"`).\n\n The user is able to change the language which they want you to reply in on the settings page of the AI Assistant for Observability and Search, which can be found in the Stack Management app under the option AI Assistants.\n If the user asks how to change the language, reply in the same language the user asked in.\n\nYou MUST use the "query" function when the user wants to:\n - visualize data\n - run any arbitrary query\n - breakdown or filter ES|QL queries that are displayed on the current page\n - convert queries from another language to ES|QL\n - asks general questions about ES|QL\n\n DO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries or explain anything about the ES|QL query language yourself.\n DO NOT UNDER ANY CIRCUMSTANCES try to correct an ES|QL query yourself - always use the "query" function for this.\n\n If the user asks for a query, and one of the dataset info functions was called and returned no results, you should still call the query function to generate an example query.\n\n Even if the "query" function was used before that, follow it up with the "query" function. If a query fails, do not attempt to correct it yourself. Again you should call the "query" function,\n even if it has been called before.\n\n When the "visualize_query" function has been called, a visualization has been displayed to the user. DO NOT UNDER ANY CIRCUMSTANCES follow up a "visualize_query" function call with your own visualization attempt.\n If the "execute_query" function has been called, summarize these results for the user. The user does not see a visualization in this case.\n\nYou MUST use the "get_dataset_info" function before calling the "query" or the "changes" functions.\n\nIf a function requires an index, you MUST use the results from the dataset info functions.\n\nYou do not have a working memory. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base.\n\nWhen asked questions about the Elastic stack or products, You should use the retrieve_elastic_doc function before answering,\n to retrieve documentation related to the question. Consider that the documentation returned by the function\n is always more up to date and accurate than any own internal knowledge you might have.'; - expect(systemMessage.role).to.eql('system'); + expect(systemMessage).to.eql(systemMessageContent); expect(firstUserMessage.content).to.eql('hello'); @@ -380,7 +370,7 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte endpoint: 'POST /internal/observability_ai_assistant/conversations', }); - const messages = response.body.conversations[0].messages.slice(5); + const messages = response.body.conversations[0].messages.slice(4); expect(messages.length).to.eql(4); @@ -400,7 +390,7 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte content: 'My second response', }); - expect(response.body.conversations[0].messages.length).to.eql(9); + expect(response.body.conversations[0].messages.length).to.eql(8); }); }); diff --git a/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png b/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png index 8ef70d4bf357a..cdef4e39c8854 100644 Binary files a/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png and b/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png differ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/alert_status/alert_status.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/alert_status/alert_status.ts index bf2e5831c10f7..888810e914a3d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/alert_status/alert_status.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/alert_status/alert_status.ts @@ -44,7 +44,6 @@ export default ({ getService }: FtrProviderContext) => { const path = dataPathBuilder.getPath('auditbeat/hosts'); describe('@ess @serverless change alert status endpoints', () => { - // Flakey: See https://github.com/elastic/kibana/issues/179704 describe('validation checks', () => { describe('update by ids', () => { it('should not give errors when querying and the alerts index does not exist yet', async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/ess.config.ts index a7617f75514d1..73492f96f3b31 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/ess.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/ess.config.ts @@ -15,12 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.getAll(), kbnTestServer: { ...functionalConfig.get('kbnTestServer'), - serverArgs: [ - ...functionalConfig.get('kbnTestServer.serverArgs'), - `--xpack.securitySolution.enableExperimental=${JSON.stringify([ - 'serviceEntityStoreEnabled', - ])}`, - ], + serverArgs: [...functionalConfig.get('kbnTestServer.serverArgs')], }, testFiles: [require.resolve('..')], junit: { diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/serverless.config.ts index 66045b8005c61..70bb6197364eb 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/serverless.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/configs/serverless.config.ts @@ -9,7 +9,6 @@ import { createTestConfig } from '../../../../../config/serverless/config.base'; export default createTestConfig({ kbnTestServerArgs: [ - `--xpack.securitySolution.enableExperimental=${JSON.stringify(['serviceEntityStoreEnabled'])}`, `--xpack.securitySolutionServerless.productTypes=${JSON.stringify([ { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/create.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/create.ts new file mode 100644 index 0000000000000..f6aa2b66459a1 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/create.ts @@ -0,0 +1,198 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { v4 as uuidv4 } from 'uuid'; +import { SiemMigrationStatus } from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { + defaultOriginalRule, + deleteAllMigrationRules, + migrationResourcesRouteHelpersFactory, + migrationRulesRouteHelpersFactory, + splunkRuleWithResources, +} from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const supertest = getService('supertest'); + const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest); + const migrationResourcesRoutes = migrationResourcesRouteHelpersFactory(supertest); + + describe('@ess @serverless @serverlessQA Create API', () => { + beforeEach(async () => { + await deleteAllMigrationRules(es); + }); + + describe('Happy path', () => { + it('should create migrations with provided id', async () => { + const migrationId = uuidv4(); + await migrationRulesRoutes.create({ migrationId, payload: [defaultOriginalRule] }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + + const migrationRule = response.body.data[0]; + expect(migrationRule).toEqual( + expect.objectContaining({ + migration_id: migrationId, + original_rule: defaultOriginalRule, + status: SiemMigrationStatus.PENDING, + }) + ); + }); + + it('should create migrations without provided id', async () => { + const { + body: { migration_id: migrationId }, + } = await migrationRulesRoutes.create({ payload: [defaultOriginalRule] }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + + const migrationRule = response.body.data[0]; + expect(migrationRule).toEqual( + expect.objectContaining({ + migration_id: migrationId, + original_rule: defaultOriginalRule, + status: SiemMigrationStatus.PENDING, + }) + ); + }); + + it('should create migrations with the rules that have resources', async () => { + const migrationId = uuidv4(); + await migrationRulesRoutes.create({ migrationId, payload: [splunkRuleWithResources] }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + + const migrationRule = response.body.data[0]; + expect(migrationRule).toEqual( + expect.objectContaining({ + migration_id: migrationId, + original_rule: splunkRuleWithResources, + status: SiemMigrationStatus.PENDING, + }) + ); + + // fetch missing resources + const resourcesResponse = await migrationResourcesRoutes.getMissingResources({ + migrationId, + }); + expect(resourcesResponse.body).toEqual([ + { type: 'macro', name: 'summariesonly' }, + { type: 'macro', name: 'drop_dm_object_name(1)' }, + { type: 'lookup', name: 'malware_tracker' }, + ]); + }); + }); + + describe('Error handling', () => { + it('should return no content error', async () => { + const migrationId = uuidv4(); + await migrationRulesRoutes.create({ migrationId, payload: [], expectStatusCode: 204 }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(0); + }); + + it(`should return an error when undefined payload has been passed`, async () => { + const migrationId = uuidv4(); + const response = await migrationRulesRoutes.create({ migrationId, expectStatusCode: 400 }); + + expect(response.body).toEqual({ + error: 'Bad Request', + message: '[request body]: Expected array, received null', + statusCode: 400, + }); + }); + + it('should return an error when original rule id is not specified', async () => { + const { id, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.id: Required', + }); + }); + + it('should return an error when original rule vendor is not specified', async () => { + const { vendor, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.vendor: Invalid literal value, expected "splunk"', + }); + }); + + it('should return an error when original rule title is not specified', async () => { + const { title, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.title: Required', + }); + }); + + it('should return an error when original rule description is not specified', async () => { + const { description, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.description: Required', + }); + }); + + it('should return an error when original rule query is not specified', async () => { + const { query, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.query: Required', + }); + }); + + it('should return an error when original rule query_language is not specified', async () => { + const { query_language: _, ...restOfOriginalRule } = defaultOriginalRule; + const response = await migrationRulesRoutes.create({ + payload: [restOfOriginalRule], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: 0.query_language: Required', + }); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get.ts index 4b7fc75f0bdf9..80544899d6d18 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get.ts @@ -8,9 +8,17 @@ import expect from 'expect'; import { v4 as uuidv4 } from 'uuid'; import { + RuleTranslationResult, + SiemMigrationStatus, +} from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { + RuleMigrationDocument, createMigrationRules, + defaultElasticRule, + defaultOriginalRule, deleteAllMigrationRules, getMigrationRuleDocument, + getMigrationRuleDocuments, migrationRulesRouteHelpersFactory, } from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -25,18 +33,639 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllMigrationRules(es); }); - it('should fetch existing rules within specified migration', async () => { - // create a document - const migrationId = uuidv4(); - const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); - await createMigrationRules(es, [migrationRuleDocument]); + describe('Basic', () => { + it('should fetch existing rules within specified migration', async () => { + // create a document + const migrationId = uuidv4(); + const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); + await createMigrationRules(es, [migrationRuleDocument]); + + const { '@timestamp': timestamp, updated_at: updatedAt, ...rest } = migrationRuleDocument; + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + expect(response.body.data).toEqual(expect.arrayContaining([expect.objectContaining(rest)])); + }); + }); + + describe('Filtering', () => { + it('should fetch rules filtered by `searchTerm`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const title = `${index < 5 ? 'Elastic' : 'Splunk'} rule - ${index}`; + const originalRule = { ...defaultOriginalRule, title }; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + original_rule: originalRule, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // Search by word `Elastic` + let expectedRuleDocuments = expect.arrayContaining( + migrationRuleDocuments + .slice(0, 5) + .map(({ '@timestamp': timestamp, updated_at: updatedAt, ...rest }) => + expect.objectContaining(rest) + ) + ); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { search_term: 'Elastic' }, + }); + expect(response.body.total).toEqual(5); + expect(response.body.data).toEqual(expectedRuleDocuments); + + // Search by word `Splunk` + expectedRuleDocuments = expect.arrayContaining( + migrationRuleDocuments + .slice(5) + .map(({ '@timestamp': timestamp, updated_at: updatedAt, ...rest }) => + expect.objectContaining(rest) + ) + ); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { search_term: 'Splunk' }, + }); + expect(response.body.total).toEqual(5); + expect(response.body.data).toEqual(expectedRuleDocuments); + }); + + it('should fetch rules filtered by `ids`', async () => { + // create a document + const migrationId = uuidv4(); + + const migrationRuleDocuments = getMigrationRuleDocuments(10, () => ({ + migration_id: migrationId, + })); + const createdDocumentIds = await createMigrationRules(es, migrationRuleDocuments); + + const expectedIds = createdDocumentIds.slice(0, 3).sort(); + + // fetch migration rules by existing ids + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { ids: expectedIds }, + }); + expect(response.body.total).toEqual(3); + expect(response.body.data.map(({ id }) => id).sort()).toEqual(expectedIds); + + // fetch migration rules by non-existing id + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { ids: [uuidv4()] }, + }); + expect(response.body.total).toEqual(0); + }); + + it('should fetch rules filtered by `prebuilt`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const prebuiltRuleId = index < 3 ? uuidv4() : undefined; + const elasticRule = { ...defaultElasticRule, prebuilt_rule_id: prebuiltRuleId }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules matched Elastic prebuilt rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_prebuilt: true }, + }); + expect(response.body.total).toEqual(3); + + // fetch custom translated migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_prebuilt: false }, + }); + expect(response.body.total).toEqual(7); + }); + + it('should fetch rules filtered by `installed`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const installedRuleId = index < 2 ? uuidv4() : undefined; + const elasticRule = { ...defaultElasticRule, id: installedRuleId }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch installed migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_installed: true }, + }); + expect(response.body.total).toEqual(2); + + // fetch non-installed migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_installed: false }, + }); + expect(response.body.total).toEqual(8); + }); + + it('should fetch rules filtered by `failed`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const status = index < 4 ? SiemMigrationStatus.FAILED : SiemMigrationStatus.COMPLETED; + return { + migration_id: migrationId, + status, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch failed migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_failed: true }, + }); + expect(response.body.total).toEqual(4); + + // fetch non-failed migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_failed: false }, + }); + expect(response.body.total).toEqual(6); + }); + + it('should fetch rules filtered by `fullyTranslated`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const translationResult = + index < 6 + ? RuleTranslationResult.FULL + : index < 8 + ? RuleTranslationResult.PARTIAL + : RuleTranslationResult.UNTRANSLATABLE; + return { + migration_id: migrationId, + translation_result: translationResult, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch failed migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_fully_translated: true }, + }); + expect(response.body.total).toEqual(6); + + // fetch non-failed migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_fully_translated: false }, + }); + expect(response.body.total).toEqual(4); + }); + + it('should fetch rules filtered by `partiallyTranslated`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const translationResult = + index < 4 + ? RuleTranslationResult.FULL + : index < 8 + ? RuleTranslationResult.PARTIAL + : RuleTranslationResult.UNTRANSLATABLE; + return { + migration_id: migrationId, + translation_result: translationResult, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch failed migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_partially_translated: true }, + }); + expect(response.body.total).toEqual(4); + + // fetch non-failed migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_partially_translated: false }, + }); + expect(response.body.total).toEqual(6); + }); + + it('should fetch rules filtered by `untranslatable`', async () => { + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const translationResult = + index < 3 + ? RuleTranslationResult.FULL + : index < 5 + ? RuleTranslationResult.PARTIAL + : RuleTranslationResult.UNTRANSLATABLE; + return { + migration_id: migrationId, + translation_result: translationResult, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(10, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch failed migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_untranslatable: true }, + }); + expect(response.body.total).toEqual(5); + + // fetch non-failed migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { is_untranslatable: false }, + }); + expect(response.body.total).toEqual(5); + }); + }); + + describe('Sorting', () => { + it('should fetch rules sorted by `title`', async () => { + const titles = ['Elastic 1', 'Windows', 'Linux', 'Elastic 2']; + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const title = titles[index]; + const originalRule = { ...defaultOriginalRule, title }; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + original_rule: originalRule, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(titles.length, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.title', sort_direction: 'asc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.title)).toEqual(titles.sort()); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.title', sort_direction: 'desc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.title)).toEqual( + titles.sort().reverse() + ); + }); + + it('should fetch rules sorted by `severity`', async () => { + const severities = ['critical', 'low', 'medium', 'low', 'critical']; + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const severity = severities[index]; + const elasticRule = { ...defaultElasticRule, severity }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments( + severities.length, + overrideCallback + ); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.severity', sort_direction: 'asc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.severity)).toEqual([ + 'low', + 'low', + 'medium', + 'critical', + 'critical', + ]); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.severity', sort_direction: 'desc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.severity)).toEqual([ + 'critical', + 'critical', + 'medium', + 'low', + 'low', + ]); + }); + + it('should fetch rules sorted by `risk_score`', async () => { + const riskScores = [55, 0, 100, 23]; + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const riskScore = riskScores[index]; + const elasticRule = { ...defaultElasticRule, risk_score: riskScore }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments( + riskScores.length, + overrideCallback + ); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.risk_score', sort_direction: 'asc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.risk_score)).toEqual( + riskScores.sort((a, b) => { + return a - b; + }) + ); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.risk_score', sort_direction: 'desc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.risk_score)).toEqual( + riskScores + .sort((a, b) => { + return a - b; + }) + .reverse() + ); + }); + + it('should fetch rules sorted by `prebuilt_rule_id`', async () => { + const prebuiltRuleIds = ['rule-1', undefined, undefined, 'rule-2', undefined]; + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const prebuiltRuleId = prebuiltRuleIds[index]; + const elasticRule = { ...defaultElasticRule, prebuilt_rule_id: prebuiltRuleId }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments( + prebuiltRuleIds.length, + overrideCallback + ); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.prebuilt_rule_id', sort_direction: 'asc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.prebuilt_rule_id)).toEqual([ + undefined, + undefined, + undefined, + 'rule-1', + 'rule-2', + ]); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'elastic_rule.prebuilt_rule_id', sort_direction: 'desc' }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.prebuilt_rule_id)).toEqual([ + 'rule-2', + 'rule-1', + undefined, + undefined, + undefined, + ]); + }); + + it('should fetch rules sorted by `translation_result`', async () => { + const translationResults = [ + RuleTranslationResult.UNTRANSLATABLE, + RuleTranslationResult.FULL, + RuleTranslationResult.PARTIAL, + ]; + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + return { + migration_id: migrationId, + translation_result: translationResults[index], + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments( + translationResults.length, + overrideCallback + ); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'translation_result', sort_direction: 'asc' }, + }); + expect(response.body.data.map((rule) => rule.translation_result)).toEqual([ + RuleTranslationResult.UNTRANSLATABLE, + RuleTranslationResult.PARTIAL, + RuleTranslationResult.FULL, + ]); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'translation_result', sort_direction: 'desc' }, + }); + expect(response.body.data.map((rule) => rule.translation_result)).toEqual([ + RuleTranslationResult.FULL, + RuleTranslationResult.PARTIAL, + RuleTranslationResult.UNTRANSLATABLE, + ]); + }); + + it('should fetch rules sorted by `updated_at`', async () => { + // create a document + const migrationId = uuidv4(); + + // Creating documents separately to have different `update_at` timestamps + await createMigrationRules(es, [getMigrationRuleDocument({ migration_id: migrationId })]); + await createMigrationRules(es, [getMigrationRuleDocument({ migration_id: migrationId })]); + await createMigrationRules(es, [getMigrationRuleDocument({ migration_id: migrationId })]); + await createMigrationRules(es, [getMigrationRuleDocument({ migration_id: migrationId })]); + await createMigrationRules(es, [getMigrationRuleDocument({ migration_id: migrationId })]); + + // fetch migration rules + let response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'updated_at', sort_direction: 'asc' }, + }); + const ascSorted = response.body.data.map((rule) => rule.updated_at); + + // fetch migration rules + response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { sort_field: 'updated_at', sort_direction: 'desc' }, + }); + const descSorted = response.body.data.map((rule) => rule.updated_at); + + expect(ascSorted).toEqual(descSorted.reverse()); + }); + }); + + describe('Pagination', () => { + it('should fetch rules within specific page', async () => { + const titles = Array.from({ length: 50 }, (_, index) => `Migration rule - ${index}`); + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const title = titles[index]; + const originalRule = { ...defaultOriginalRule, title }; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + original_rule: originalRule, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(titles.length, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + const response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { page: 3, per_page: 7 }, + }); + const start = 3 * 7; + expect(response.body.data.map((rule) => rule.elastic_rule?.title)).toEqual( + titles.slice(start, start + 7) + ); + }); + + it('should fetch rules within very first page if `perPage` is not specified', async () => { + const titles = Array.from({ length: 50 }, (_, index) => `Migration rule - ${index}`); + + // create a document + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const title = titles[index]; + const originalRule = { ...defaultOriginalRule, title }; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + original_rule: originalRule, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(titles.length, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + // fetch migration rules + const response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { page: 3 }, + }); + const defaultSize = 10; + expect(response.body.data.map((rule) => rule.elastic_rule?.title)).toEqual( + titles.slice(0, defaultSize) + ); + }); + + it('should fetch rules within very first page of a specified size if `perPage` is specified', async () => { + const titles = Array.from({ length: 50 }, (_, index) => `Migration rule - ${index}`); + + // create a document + const migrationId = uuidv4(); - const { '@timestamp': timestamp, updated_at: updatedAt, ...rest } = migrationRuleDocument; + const overrideCallback = (index: number): Partial => { + const title = titles[index]; + const originalRule = { ...defaultOriginalRule, title }; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + original_rule: originalRule, + elastic_rule: elasticRule, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(titles.length, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); - // fetch migration rule - const response = await migrationRulesRoutes.get(migrationId); - expect(response.body.total).toEqual(1); - expect(response.body.data).toEqual(expect.arrayContaining([expect.objectContaining(rest)])); + // fetch migration rules + const response = await migrationRulesRoutes.get({ + migrationId, + queryParams: { per_page: 18 }, + }); + expect(response.body.data.map((rule) => rule.elastic_rule?.title)).toEqual( + titles.slice(0, 18) + ); + }); }); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get_prebuilt_rules.ts new file mode 100644 index 0000000000000..aa73189eca4cd --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/get_prebuilt_rules.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { v4 as uuidv4 } from 'uuid'; +import { RuleTranslationResult } from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { deleteAllRules } from '../../../../../common/utils/security_solution'; +import { + RuleMigrationDocument, + createMigrationRules, + defaultElasticRule, + deleteAllMigrationRules, + getMigrationRuleDocuments, + migrationRulesRouteHelpersFactory, +} from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { + createPrebuiltRuleAssetSavedObjects, + createRuleAssetSavedObject, + deleteAllPrebuiltRuleAssets, + deleteAllTimelines, +} from '../../../detections_response/utils'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const log = getService('log'); + const supertest = getService('supertest'); + const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest); + + describe('@ess @serverless @serverlessQA Get Prebuilt Rules API', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllTimelines(es, log); + await deleteAllPrebuiltRuleAssets(es, log); + await deleteAllMigrationRules(es); + + // Add some prebuilt rules + const ruleAssetSavedObjects = [ + createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }), + createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }), + createRuleAssetSavedObject({ rule_id: 'rule-3', version: 1 }), + createRuleAssetSavedObject({ rule_id: 'rule-4', version: 1 }), + createRuleAssetSavedObject({ rule_id: 'rule-5', version: 1 }), + ]; + await createPrebuiltRuleAssetSavedObjects(es, ruleAssetSavedObjects); + }); + + it('should return all prebuilt rules matched by migration rules', async () => { + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const { query_language: queryLanguage, query, ...rest } = defaultElasticRule; + return { + migration_id: migrationId, + elastic_rule: index < 2 ? { ...rest, prebuilt_rule_id: `rule-${index + 1}` } : undefined, + translation_result: index < 2 ? RuleTranslationResult.FULL : undefined, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(4, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const response = await migrationRulesRoutes.getPrebuiltRules({ migrationId }); + + const prebuiltRulesIds = Object.keys(response.body).sort(); + expect(prebuiltRulesIds).toEqual(['rule-1', 'rule-2']); + }); + + it('should return empty response when migration rules did not match prebuilt rules', async () => { + const migrationId = uuidv4(); + + const migrationRuleDocuments = getMigrationRuleDocuments(10, () => ({ + migration_id: migrationId, + })); + await createMigrationRules(es, migrationRuleDocuments); + + const response = await migrationRulesRoutes.getPrebuiltRules({ migrationId }); + expect(response.body).toEqual({}); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/index.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/index.ts index b9ca65861b971..afce2e4e03ec4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/index.ts @@ -8,6 +8,11 @@ import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('@ess SecuritySolution SIEM Migrations', () => { + loadTestFile(require.resolve('./create')); + loadTestFile(require.resolve('./get_prebuilt_rules')); loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./install')); + loadTestFile(require.resolve('./stats')); + loadTestFile(require.resolve('./update')); }); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/install.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/install.ts new file mode 100644 index 0000000000000..684db1939e279 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/install.ts @@ -0,0 +1,216 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { v4 as uuidv4 } from 'uuid'; +import { ElasticRule } from '@kbn/security-solution-plugin/common/siem_migrations/model/rule_migration.gen'; +import { RuleTranslationResult } from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { deleteAllRules } from '../../../../../common/utils/security_solution'; +import { + RuleMigrationDocument, + createMigrationRules, + defaultElasticRule, + deleteAllMigrationRules, + getMigrationRuleDocuments, + migrationRulesRouteHelpersFactory, + statsOverrideCallbackFactory, +} from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { + createPrebuiltRuleAssetSavedObjects, + createRuleAssetSavedObject, + deleteAllPrebuiltRuleAssets, + deleteAllTimelines, +} from '../../../detections_response/utils'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const log = getService('log'); + const supertest = getService('supertest'); + const securitySolutionApi = getService('securitySolutionApi'); + const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest); + + describe('@ess @serverless @serverlessQA Install API', () => { + beforeEach(async () => { + await deleteAllRules(supertest, log); + await deleteAllTimelines(es, log); + await deleteAllPrebuiltRuleAssets(es, log); + await deleteAllMigrationRules(es); + }); + + it('should install all installable custom migration rules', async () => { + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const title = `Rule - ${index}`; + const elasticRule = { ...defaultElasticRule, title }; + return { + migration_id: migrationId, + elastic_rule: elasticRule, + translation_result: index < 2 ? RuleTranslationResult.FULL : undefined, + }; + }; + + const migrationRuleDocuments = getMigrationRuleDocuments(5, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} }); + expect(installResponse.body).toEqual({ installed: 2 }); + + // fetch installed migration rules information + const response = await migrationRulesRoutes.get({ migrationId }); + const installedMigrationRules = response.body.data.reduce((acc, item) => { + if (item.elastic_rule?.id) { + acc.push(item.elastic_rule); + } + return acc; + }, [] as ElasticRule[]); + expect(installedMigrationRules.length).toEqual(2); + + // fetch installed rules + const { body: rulesResponse } = await securitySolutionApi + .findRules({ query: {} }) + .expect(200); + + const expectedRulesData = expect.arrayContaining( + installedMigrationRules.map((migrationRule) => + expect.objectContaining({ + id: migrationRule.id, + name: migrationRule.title, + }) + ) + ); + + expect(rulesResponse.data).toEqual(expectedRulesData); + + // Installed rules should be disabled + rulesResponse.data.forEach((rule: RuleResponse) => { + expect(rule.enabled).toEqual(false); + }); + }); + + it('should install all installable migration rules matched with prebuilt rules', async () => { + const ruleAssetSavedObject = createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }); + await createPrebuiltRuleAssetSavedObjects(es, [ruleAssetSavedObject]); + + const migrationId = uuidv4(); + + const overrideCallback = (index: number): Partial => { + const { query_language: queryLanguage, query, ...rest } = defaultElasticRule; + return { + migration_id: migrationId, + elastic_rule: index < 2 ? { ...rest, prebuilt_rule_id: 'rule-1' } : undefined, + translation_result: index < 2 ? RuleTranslationResult.FULL : undefined, + }; + }; + const migrationRuleDocuments = getMigrationRuleDocuments(4, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} }); + expect(installResponse.body).toEqual({ installed: 2 }); + + // fetch installed rules + const { body: rulesResponse } = await securitySolutionApi + .findRules({ query: {} }) + .expect(200); + + const expectedInstalledRules = expect.arrayContaining([ + expect.objectContaining(ruleAssetSavedObject['security-rule']), + ]); + expect(rulesResponse.data.length).toEqual(1); + expect(rulesResponse.data).toEqual(expectedInstalledRules); + + // Installed rules should be disabled + rulesResponse.data.forEach((rule: RuleResponse) => { + expect(rule.enabled).toEqual(false); + }); + }); + + it('should install and enable all installable migration rules', async () => { + const migrationId = uuidv4(); + + const overrideCallback = statsOverrideCallbackFactory({ + migrationId, + completed: 2, + fullyTranslated: 2, + }); + const migrationRuleDocuments = getMigrationRuleDocuments(2, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const installResponse = await migrationRulesRoutes.install({ + migrationId, + payload: { enabled: true }, + }); + expect(installResponse.body).toEqual({ installed: 2 }); + + // fetch installed rules + const { body: rulesResponse } = await securitySolutionApi + .findRules({ query: {} }) + .expect(200); + + expect(rulesResponse.data.length).toEqual(2); + + // Installed rules should be enabled + rulesResponse.data.forEach((rule: RuleResponse) => { + expect(rule.enabled).toEqual(true); + }); + }); + + it('should install migration rules by ids', async () => { + const migrationId = uuidv4(); + + const overrideCallback = statsOverrideCallbackFactory({ + migrationId, + completed: 5, + fullyTranslated: 5, + }); + const migrationRuleDocuments = getMigrationRuleDocuments(5, overrideCallback); + const createdDocumentIds = await createMigrationRules(es, migrationRuleDocuments); + + // Migration rules to install by ids + const ids = createdDocumentIds.slice(0, 3); + + const installResponse = await migrationRulesRoutes.install({ + migrationId, + payload: { ids, enabled: true }, + }); + expect(installResponse.body).toEqual({ installed: 3 }); + + // fetch installed rules + const { body: rulesResponse } = await securitySolutionApi + .findRules({ query: {} }) + .expect(200); + + expect(rulesResponse.data.length).toEqual(3); + + // Installed rules should be enabled + rulesResponse.data.forEach((rule: RuleResponse) => { + expect(rule.enabled).toEqual(true); + }); + }); + + it('should return zero installed rules as a response for the non-existing migration', async () => { + const migrationId = uuidv4(); + const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} }); + expect(installResponse.body).toEqual({ installed: 0 }); + }); + + it('should return an error if body payload is not passed', async () => { + const migrationId = uuidv4(); + const installResponse = await migrationRulesRoutes.install({ + migrationId, + expectStatusCode: 400, + }); + expect(installResponse.body).toEqual({ + statusCode: 400, + error: 'Bad Request', + message: '[request body]: Expected object, received null', + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/stats.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/stats.ts new file mode 100644 index 0000000000000..42c6d4f097150 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/stats.ts @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { v4 as uuidv4 } from 'uuid'; +import { + createMigrationRules, + deleteAllMigrationRules, + getMigrationRuleDocuments, + migrationRulesRouteHelpersFactory, + statsOverrideCallbackFactory, +} from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const supertest = getService('supertest'); + const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest); + + describe('@ess @serverless @serverlessQA Stats API', () => { + beforeEach(async () => { + await deleteAllMigrationRules(es); + }); + + it('should return stats for the specific migration', async () => { + const migrationId = uuidv4(); + + const failed = 3; + const pending = 5; + const processing = 7; + const completed = 10; + const total = failed + pending + processing + completed; + const overrideCallback = statsOverrideCallbackFactory({ + migrationId, + failed, + pending, + processing, + completed, // 4 - full, 5 - partial, 1 - untranslated + fullyTranslated: 4, + partiallyTranslated: 5, + }); + const migrationRuleDocuments = getMigrationRuleDocuments(total, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const response = await migrationRulesRoutes.stats({ migrationId }); + expect(response.body).toEqual( + expect.objectContaining({ + status: 'stopped', + id: migrationId, + rules: { + total, + pending, + processing, + completed, + failed, + }, + }) + ); + }); + + it('should return stats for the existing migrations', async () => { + const migrationId1 = uuidv4(); + const migrationId2 = uuidv4(); + + const overrideCallback1 = statsOverrideCallbackFactory({ + migrationId: migrationId1, + failed: 2, + pending: 4, + processing: 3, + completed: 33, + fullyTranslated: 10, + partiallyTranslated: 10, + }); + const migrationRuleDocuments1 = getMigrationRuleDocuments(42, overrideCallback1); + const overrideCallback2 = statsOverrideCallbackFactory({ + migrationId: migrationId2, + failed: 7, + pending: 2, + processing: 5, + completed: 14, + fullyTranslated: 3, + partiallyTranslated: 5, + }); + const migrationRuleDocuments2 = getMigrationRuleDocuments(28, overrideCallback2); + await createMigrationRules(es, [...migrationRuleDocuments1, ...migrationRuleDocuments2]); + + const response = await migrationRulesRoutes.statsAll({}); + const expectedStats = expect.arrayContaining([ + expect.objectContaining({ + status: 'stopped', + id: migrationId1, + rules: { total: 42, pending: 4, processing: 3, completed: 33, failed: 2 }, + }), + expect.objectContaining({ + status: 'stopped', + id: migrationId2, + rules: { total: 28, pending: 2, processing: 5, completed: 14, failed: 7 }, + }), + ]); + expect(response.body).toEqual(expectedStats); + }); + + it('should return translation stats for the specific migration', async () => { + const migrationId = uuidv4(); + + const failed = 3; + const pending = 5; + const processing = 7; + const completed = 10; + const total = failed + pending + processing + completed; + const overrideCallback = statsOverrideCallbackFactory({ + migrationId, + failed, + pending, + processing, + completed, // 4 - full, 5 - partial, 1 - untranslated + fullyTranslated: 4, + partiallyTranslated: 5, + }); + const migrationRuleDocuments = getMigrationRuleDocuments(total, overrideCallback); + await createMigrationRules(es, migrationRuleDocuments); + + const response = await migrationRulesRoutes.translationStats({ migrationId }); + expect(response.body).toEqual( + expect.objectContaining({ + id: migrationId, + rules: { + total, + success: { + total: completed, + result: { full: 4, partial: 5, untranslatable: 1 }, + installable: 4, + prebuilt: 0, + }, + failed, + }, + }) + ); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/update.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/update.ts new file mode 100644 index 0000000000000..f114af2de519a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/rules/trial_license_complete_tier/update.ts @@ -0,0 +1,156 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from 'expect'; +import { v4 as uuidv4 } from 'uuid'; +import { + createMigrationRules, + deleteAllMigrationRules, + getMigrationRuleDocument, + migrationRulesRouteHelpersFactory, +} from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const es = getService('es'); + const supertest = getService('supertest'); + const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest); + + describe('@ess @serverless @serverlessQA Update API', () => { + beforeEach(async () => { + await deleteAllMigrationRules(es); + }); + + describe('Happy path', () => { + it('should update migration rules', async () => { + const migrationId = uuidv4(); + const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); + const [createdDocumentId] = await createMigrationRules(es, [migrationRuleDocument]); + + const now = new Date().toISOString(); + await migrationRulesRoutes.update({ + migrationId, + payload: [ + { + id: createdDocumentId, + elastic_rule: { title: 'Updated title' }, + comments: [{ message: 'Update comment', created_by: 'ftr test', created_at: now }], + }, + ], + }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + + const { + '@timestamp': timestamp, + updated_at: updatedAt, + updated_by: updatedBy, + elastic_rule: elasticRule, + ...rest + } = migrationRuleDocument; + + const migrationRule = response.body.data[0]; + expect(migrationRule).toEqual( + expect.objectContaining({ + ...rest, + elastic_rule: { ...elasticRule, title: 'Updated title' }, + comments: [{ message: 'Update comment', created_by: 'ftr test', created_at: now }], + }) + ); + }); + + it('should ignore attributes that are not eligible for update', async () => { + const migrationId = uuidv4(); + const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); + const [createdDocumentId] = await createMigrationRules(es, [migrationRuleDocument]); + + const now = new Date().toISOString(); + await migrationRulesRoutes.update({ + migrationId, + payload: [ + { + id: createdDocumentId, + elastic_rule: { title: 'Updated title' }, + comments: [{ message: 'Update comment', created_by: 'ftr test', created_at: now }], + // Should be ignored + migration_id: 'fake_migration_id_1', + original_rule: { description: 'Ignore this description' }, + translation_result: 'ignore this translation result', + status: 'ignore this status', + }, + ], + }); + + const { + '@timestamp': timestamp, + updated_at: updatedAt, + updated_by: updatedBy, + elastic_rule: elasticRule, + ...rest + } = migrationRuleDocument; + const expectedMigrationRule = expect.objectContaining({ + ...rest, + elastic_rule: { ...elasticRule, title: 'Updated title' }, + comments: [{ message: 'Update comment', created_by: 'ftr test', created_at: now }], + }); + + // fetch migration rule + const response = await migrationRulesRoutes.get({ migrationId }); + expect(response.body.total).toEqual(1); + + const migrationRule = response.body.data[0]; + expect(migrationRule).toEqual(expectedMigrationRule); + }); + }); + + describe('Error handling', () => { + it('should return empty content response when no rules passed', async () => { + const migrationId = uuidv4(); + await migrationRulesRoutes.update({ + migrationId, + payload: [], + expectStatusCode: 204, + }); + }); + + it(`should return an error when rule's id is not specified`, async () => { + const migrationId = uuidv4(); + const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); + await createMigrationRules(es, [migrationRuleDocument]); + + const response = await migrationRulesRoutes.update({ + migrationId, + payload: [{ elastic_rule: { title: 'Updated title' } }], + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + error: 'Bad Request', + message: '[request body]: 0.id: Required', + statusCode: 400, + }); + }); + + it(`should return an error when undefined payload has been passed`, async () => { + const migrationId = uuidv4(); + const migrationRuleDocument = getMigrationRuleDocument({ migration_id: migrationId }); + await createMigrationRules(es, [migrationRuleDocument]); + + const response = await migrationRulesRoutes.update({ + migrationId, + expectStatusCode: 400, + }); + expect(response.body).toEqual({ + error: 'Bad Request', + message: '[request body]: Expected array, received null', + statusCode: 400, + }); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/asserts.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/asserts.ts new file mode 100644 index 0000000000000..47b94ecda6816 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/asserts.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import SuperTest from 'supertest'; + +export const assertStatusCode = (statusCode: number, response: SuperTest.Response) => { + if (response.status !== statusCode) { + throw new Error( + `Expected status code ${statusCode}, but got ${response.statusCode} \n` + response.text + ); + } +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/index.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/index.ts index 3d500f4a1383b..2140c100f4e5a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/index.ts @@ -5,4 +5,6 @@ * 2.0. */ +export * from './mocks'; +export * from './resources'; export * from './rules'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/mocks.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/mocks.ts new file mode 100644 index 0000000000000..184e19f8d0c9c --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/mocks.ts @@ -0,0 +1,190 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Client } from '@elastic/elasticsearch'; +import { + RuleTranslationResult, + SiemMigrationStatus, +} from '@kbn/security-solution-plugin/common/siem_migrations/constants'; + +import { + ElasticRule, + OriginalRule, + RuleMigration, +} from '@kbn/security-solution-plugin/common/siem_migrations/model/rule_migration.gen'; +import { INDEX_PATTERN as SIEM_MIGRATIONS_INDEX_PATTERN } from '@kbn/security-solution-plugin/server/lib/siem_migrations/rules/data/rule_migrations_data_service'; +import { generateAssistantComment } from '@kbn/security-solution-plugin/server/lib/siem_migrations/rules/task/util/comments'; + +const SIEM_MIGRATIONS_RULES_INDEX_PATTERN = `${SIEM_MIGRATIONS_INDEX_PATTERN}-rules-default`; + +export type RuleMigrationDocument = Omit; + +export const defaultOriginalRule: OriginalRule = { + id: 'https://127.0.0.1:8089/servicesNS/nobody/SA-AccessProtection/saved/searches/Access%20-%20Default%20Account%20Usage%20-%20Rule', + vendor: 'splunk', + title: 'Access - Default Account Usage - Rule', + description: + 'Discovers use of default accounts (such as admin, administrator, etc.). Default accounts have default passwords and are therefore commonly targeted by attackers using brute force attack tools.', + query: + '| from datamodel:"Authentication"."Successful_Default_Authentication" | stats max("_time") as "lastTime",values("tag") as "tag",count by "dest","user","app"', + query_language: 'spl', + annotations: { + mitre_attack: ['T1078'], + }, +}; + +export const splunkRuleWithResources: OriginalRule = { + id: 'https://127.0.0.1:8089/servicesNS/nobody/DA-ESS-EndpointProtection/saved/searches/Endpoint%20-%20Old%20Malware%20Infection%20-%20Rule', + vendor: 'splunk', + title: 'Endpoint - Old Malware Infection - Rule', + query: + '| tstats `summariesonly` max(_time) as lastTime from datamodel=Malware.Malware_Attacks by Malware_Attacks.signature,Malware_Attacks.dest | `drop_dm_object_name("Malware_Attacks")` | lookup local=true malware_tracker dest,signature OUTPUT firstTime | eval dayDiff=round((lastTime-firstTime)/86400,1) | search dayDiff>30', + query_language: 'spl', + description: 'Alerts when a host with an old infection is discovered (likely a re-infection).', +}; + +export const defaultElasticRule: ElasticRule = { + severity: 'low', + risk_score: 21, + integration_ids: [''], + query: + 'FROM [indexPattern]\n| STATS lastTime = max(_time), tag = values(tag), count BY dest, user, app', + description: + 'Discovers use of default accounts (such as admin, administrator, etc.). Default accounts have default passwords and are therefore commonly targeted by attackers using brute force attack tools.', + query_language: 'esql', + title: 'Access - Default Account Usage - Rule', +}; + +const defaultMigrationRuleDocument: RuleMigrationDocument = { + '@timestamp': '2025-01-13T15:17:43.571Z', + migration_id: '25a24356-3aab-401b-a73c-905cb8bf7a6d', + original_rule: defaultOriginalRule, + status: 'completed', + created_by: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + updated_by: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + updated_at: '2025-01-13T15:39:48.729Z', + comments: [ + generateAssistantComment( + '## Prebuilt Rule Matching Summary\nThe Splunk rule "Access - Default Account Usage - Rule" is intended to discover the use of default accounts, which are commonly targeted by attackers using brute force attack tools. However, none of the provided Elastic Prebuilt Rules specifically address the detection of default account usage. The closest matches involve brute force attacks in general, but they do not specifically focus on default accounts. Therefore, no suitable match was found.' + ), + generateAssistantComment('## Integration Matching Summary\nNo related integration found.'), + generateAssistantComment( + '## Translation Summary\n\nThe provided Splunk SPL query was analyzed and translated into the equivalent ES|QL query. Here is a breakdown of the process:\n\n### Original SPL Query\n```splunk-spl\n| from datamodel:"Authentication"."Successful_Default_Authentication" \n| stats max("_time") as "lastTime",\nvalues("tag") as "tag",\ncount by "dest","user","app"\n```\n\n### Key SPL Components and Their ES|QL Equivalents:\n1. **Data Model**: `from datamodel:"Authentication"."Successful_Default_Authentication"` is not directly translatable to ES|QL. Instead, we use `FROM logs-*` to define the data source.\n2. **Stats Aggregation**: The `stats max("_time") as "lastTime", values("tag") as "tag", count by "dest","user","app"` was translated as follows:\n - `max(_time) as lastTime` to find the latest time.\n - `values(tag) as tag` to collect all values in the `tag` field.\n - `count by dest, user, app` to count the occurrences grouped by `dest`, `user`, and `app`.\n\nBy analyzing these key components and their ES|QL equivalents, the translated query achieves the same results as the SPL query while adhering to the ES|QL syntax and structure.' + ), + ], + translation_result: 'partial', + elastic_rule: defaultElasticRule, +}; + +export const getMigrationRuleDocument = ( + overrideParams: Partial +): RuleMigrationDocument => ({ + ...defaultMigrationRuleDocument, + ...overrideParams, +}); + +export const getMigrationRuleDocuments = ( + count: number, + overrideCallback: (index: number) => Partial +): RuleMigrationDocument[] => { + const docs: RuleMigrationDocument[] = []; + for (let i = 0; i < count; i++) { + const overrideParams = overrideCallback(i); + docs.push(getMigrationRuleDocument(overrideParams)); + } + return docs; +}; + +export const statsOverrideCallbackFactory = ({ + migrationId, + failed = 0, + pending = 0, + processing = 0, + completed = 0, + fullyTranslated = 0, + partiallyTranslated = 0, +}: { + migrationId: string; + failed?: number; + pending?: number; + processing?: number; + completed?: number; + fullyTranslated?: number; + partiallyTranslated?: number; +}) => { + const overrideCallback = (index: number): Partial => { + let translationResult; + let status = SiemMigrationStatus.PENDING; + + const pendingEndIndex = failed + pending; + const processingEndIndex = failed + pending + processing; + const completedEndIndex = failed + pending + processing + completed; + if (index < failed) { + status = SiemMigrationStatus.FAILED; + } else if (index < pendingEndIndex) { + status = SiemMigrationStatus.PENDING; + } else if (index < processingEndIndex) { + status = SiemMigrationStatus.PROCESSING; + } else if (index < completedEndIndex) { + status = SiemMigrationStatus.COMPLETED; + const fullyTranslatedEndIndex = completedEndIndex - completed + fullyTranslated; + const partiallyTranslatedEndIndex = + completedEndIndex - completed + fullyTranslated + partiallyTranslated; + if (index < fullyTranslatedEndIndex) { + translationResult = RuleTranslationResult.FULL; + } else if (index < partiallyTranslatedEndIndex) { + translationResult = RuleTranslationResult.PARTIAL; + } else { + translationResult = RuleTranslationResult.UNTRANSLATABLE; + } + } + return { + migration_id: migrationId, + translation_result: translationResult, + status, + }; + }; + return overrideCallback; +}; + +export const createMigrationRules = async ( + es: Client, + rules: RuleMigrationDocument[] +): Promise => { + const createdAt = new Date().toISOString(); + const res = await es.bulk({ + refresh: 'wait_for', + operations: rules.flatMap((ruleMigration) => [ + { create: { _index: SIEM_MIGRATIONS_RULES_INDEX_PATTERN } }, + { + ...ruleMigration, + '@timestamp': createdAt, + updated_at: createdAt, + }, + ]), + }); + const ids = res.items.reduce((acc, item) => { + if (item.create?._id) { + acc.push(item.create._id); + } + return acc; + }, [] as string[]); + return ids; +}; + +export const deleteAllMigrationRules = async (es: Client): Promise => { + await es.deleteByQuery({ + index: [SIEM_MIGRATIONS_RULES_INDEX_PATTERN], + body: { + query: { + match_all: {}, + }, + }, + ignore_unavailable: true, + refresh: true, + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/resources.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/resources.ts new file mode 100644 index 0000000000000..3bfbb55c8cac1 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/resources.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import SuperTest from 'supertest'; +import { + ELASTIC_HTTP_VERSION_HEADER, + X_ELASTIC_INTERNAL_ORIGIN_REQUEST, +} from '@kbn/core-http-common'; +import { replaceParams } from '@kbn/openapi-common/shared'; + +import { SIEM_RULE_MIGRATION_RESOURCES_MISSING_PATH } from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { GetRuleMigrationResourcesMissingResponse } from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen'; +import { API_VERSIONS } from '@kbn/security-solution-plugin/common/constants'; +import { assertStatusCode } from './asserts'; + +export interface GetRuleMigrationMissingResourcesParams { + /** `id` of the migration to get missing resources for */ + migrationId: string; + /** Optional expected status code parameter */ + expectStatusCode?: number; +} + +export const migrationResourcesRouteHelpersFactory = (supertest: SuperTest.Agent) => { + return { + getMissingResources: async ({ + migrationId, + expectStatusCode = 200, + }: GetRuleMigrationMissingResourcesParams): Promise<{ + body: GetRuleMigrationResourcesMissingResponse; + }> => { + const response = await supertest + .get( + replaceParams(SIEM_RULE_MIGRATION_RESOURCES_MISSING_PATH, { migration_id: migrationId }) + ) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + }; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts index 25789dd382589..35836af0116d5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/siem_migrations/utils/rules.ts @@ -6,119 +6,195 @@ */ import SuperTest from 'supertest'; -import type { Client } from '@elastic/elasticsearch'; -import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common'; +import { + ELASTIC_HTTP_VERSION_HEADER, + X_ELASTIC_INTERNAL_ORIGIN_REQUEST, +} from '@kbn/core-http-common'; import { replaceParams } from '@kbn/openapi-common/shared'; -import { RuleMigration } from '@kbn/security-solution-plugin/common/siem_migrations/model/rule_migration.gen'; -import { INDEX_PATTERN as SIEM_MIGRATIONS_INDEX_PATTERN } from '@kbn/security-solution-plugin/server/lib/siem_migrations/rules/data/rule_migrations_data_service'; -import { SIEM_RULE_MIGRATION_PATH } from '@kbn/security-solution-plugin/common/siem_migrations/constants'; -import { GetRuleMigrationResponse } from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen'; -import { generateAssistantComment } from '@kbn/security-solution-plugin/server/lib/siem_migrations/rules/task/util/comments'; - -const SIEM_MIGRATIONS_RULES_INDEX_PATTERN = `${SIEM_MIGRATIONS_INDEX_PATTERN}-rules-default`; - -export type RuleMigrationDocument = Omit; - -const migrationRuleDocument: RuleMigrationDocument = { - '@timestamp': '2025-01-13T15:17:43.571Z', - migration_id: '25a24356-3aab-401b-a73c-905cb8bf7a6d', - original_rule: { - id: 'https://127.0.0.1:8089/servicesNS/nobody/SA-AccessProtection/saved/searches/Access%20-%20Default%20Account%20Usage%20-%20Rule', - vendor: 'splunk', - title: 'Access - Default Account Usage - Rule', - description: - 'Discovers use of default accounts (such as admin, administrator, etc.). Default accounts have default passwords and are therefore commonly targeted by attackers using brute force attack tools.', - query: - '| from datamodel:"Authentication"."Successful_Default_Authentication" | stats max("_time") as "lastTime",values("tag") as "tag",count by "dest","user","app"', - query_language: 'spl', - annotations: { - mitre_attack: ['T1078'], - }, - }, - status: 'completed', - created_by: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', - updated_by: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', - updated_at: '2025-01-13T15:39:48.729Z', - comments: [ - generateAssistantComment( - '## Prebuilt Rule Matching Summary\nThe Splunk rule "Access - Default Account Usage - Rule" is intended to discover the use of default accounts, which are commonly targeted by attackers using brute force attack tools. However, none of the provided Elastic Prebuilt Rules specifically address the detection of default account usage. The closest matches involve brute force attacks in general, but they do not specifically focus on default accounts. Therefore, no suitable match was found.' - ), - generateAssistantComment('## Integration Matching Summary\nNo related integration found.'), - generateAssistantComment( - '## Translation Summary\n\nThe provided Splunk SPL query was analyzed and translated into the equivalent ES|QL query. Here is a breakdown of the process:\n\n### Original SPL Query\n```splunk-spl\n| from datamodel:"Authentication"."Successful_Default_Authentication" \n| stats max("_time") as "lastTime",\nvalues("tag") as "tag",\ncount by "dest","user","app"\n```\n\n### Key SPL Components and Their ES|QL Equivalents:\n1. **Data Model**: `from datamodel:"Authentication"."Successful_Default_Authentication"` is not directly translatable to ES|QL. Instead, we use `FROM logs-*` to define the data source.\n2. **Stats Aggregation**: The `stats max("_time") as "lastTime", values("tag") as "tag", count by "dest","user","app"` was translated as follows:\n - `max(_time) as lastTime` to find the latest time.\n - `values(tag) as tag` to collect all values in the `tag` field.\n - `count by dest, user, app` to count the occurrences grouped by `dest`, `user`, and `app`.\n\nBy analyzing these key components and their ES|QL equivalents, the translated query achieves the same results as the SPL query while adhering to the ES|QL syntax and structure.' - ), - ], - translation_result: 'partial', - elastic_rule: { - severity: 'low', - risk_score: 21, - integration_ids: [''], - query: - 'FROM [indexPattern]\n| STATS lastTime = max(_time), tag = values(tag), count BY dest, user, app', - description: - 'Discovers use of default accounts (such as admin, administrator, etc.). Default accounts have default passwords and are therefore commonly targeted by attackers using brute force attack tools.', - query_language: 'esql', - title: 'Access - Default Account Usage - Rule', - }, -}; +import { + SIEM_RULE_MIGRATIONS_ALL_STATS_PATH, + SIEM_RULE_MIGRATIONS_PATH, + SIEM_RULE_MIGRATIONS_PREBUILT_RULES_PATH, + SIEM_RULE_MIGRATION_INSTALL_PATH, + SIEM_RULE_MIGRATION_PATH, + SIEM_RULE_MIGRATION_STATS_PATH, + SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH, +} from '@kbn/security-solution-plugin/common/siem_migrations/constants'; +import { + CreateRuleMigrationResponse, + GetAllStatsRuleMigrationResponse, + GetRuleMigrationPrebuiltRulesResponse, + GetRuleMigrationRequestQuery, + GetRuleMigrationResponse, + GetRuleMigrationStatsResponse, + InstallMigrationRulesResponse, + UpdateRuleMigrationResponse, +} from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen'; +import { API_VERSIONS } from '@kbn/security-solution-plugin/common/constants'; +import { assertStatusCode } from './asserts'; -export const getMigrationRuleDocument = ( - overrideParams: Partial -): RuleMigrationDocument => ({ - ...migrationRuleDocument, - ...overrideParams, -}); - -export const createMigrationRules = async ( - es: Client, - rules: RuleMigrationDocument[] -): Promise => { - const createdAt = new Date().toISOString(); - await es.bulk({ - refresh: 'wait_for', - operations: rules.flatMap((ruleMigration) => [ - { create: { _index: SIEM_MIGRATIONS_RULES_INDEX_PATTERN } }, - { - ...ruleMigration, - '@timestamp': createdAt, - updated_at: createdAt, - }, - ]), - }); -}; +export interface RequestParams { + /** Optional expected status code parameter */ + expectStatusCode?: number; +} -export const deleteAllMigrationRules = async (es: Client): Promise => { - await es.deleteByQuery({ - index: [SIEM_MIGRATIONS_RULES_INDEX_PATTERN], - body: { - query: { - match_all: {}, - }, - }, - ignore_unavailable: true, - refresh: true, - }); -}; +export interface MigrationRequestParams extends RequestParams { + /** `id` of the migration to get rules documents for */ + migrationId: string; +} -const assertStatusCode = (statusCode: number, response: SuperTest.Response) => { - if (response.status !== statusCode) { - throw new Error( - `Expected status code ${statusCode}, but got ${response.statusCode} \n` + response.text - ); - } -}; +export interface GetRuleMigrationParams extends MigrationRequestParams { + /** Optional query parameters */ + queryParams?: GetRuleMigrationRequestQuery; +} + +export interface CreateRuleMigrationParams extends RequestParams { + /** Optional `id` of migration to add the rules to. + * The id is necessary only for batching the migration creation in multiple requests */ + migrationId?: string; + /** Optional payload to send */ + payload?: any; +} + +export interface UpdateRulesParams extends MigrationRequestParams { + /** Optional payload to send */ + payload?: any; +} + +export interface InstallRulesParams extends MigrationRequestParams { + /** Optional payload to send */ + payload?: any; +} export const migrationRulesRouteHelpersFactory = (supertest: SuperTest.Agent) => { return { - get: async ( - migrationId: string, - expectStatusCode: number = 200 - ): Promise<{ body: GetRuleMigrationResponse }> => { + get: async ({ + migrationId, + queryParams = {}, + expectStatusCode = 200, + }: GetRuleMigrationParams): Promise<{ body: GetRuleMigrationResponse }> => { const response = await supertest .get(replaceParams(SIEM_RULE_MIGRATION_PATH, { migration_id: migrationId })) + .query(queryParams) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + create: async ({ + migrationId, + payload, + expectStatusCode = 200, + }: CreateRuleMigrationParams): Promise<{ body: CreateRuleMigrationResponse }> => { + const response = await supertest + .post(`${SIEM_RULE_MIGRATIONS_PATH}${migrationId ? `/${migrationId}` : ''}`) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(payload); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + update: async ({ + migrationId, + payload, + expectStatusCode = 200, + }: UpdateRulesParams): Promise<{ body: UpdateRuleMigrationResponse }> => { + const response = await supertest + .put(replaceParams(SIEM_RULE_MIGRATION_PATH, { migration_id: migrationId })) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(payload); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + install: async ({ + migrationId, + payload, + expectStatusCode = 200, + }: InstallRulesParams): Promise<{ body: InstallMigrationRulesResponse }> => { + const response = await supertest + .post(replaceParams(SIEM_RULE_MIGRATION_INSTALL_PATH, { migration_id: migrationId })) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(payload); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + stats: async ({ + migrationId, + expectStatusCode = 200, + }: MigrationRequestParams): Promise<{ body: GetRuleMigrationStatsResponse }> => { + const response = await supertest + .get(replaceParams(SIEM_RULE_MIGRATION_STATS_PATH, { migration_id: migrationId })) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + statsAll: async ({ + expectStatusCode = 200, + }: RequestParams): Promise<{ body: GetAllStatsRuleMigrationResponse }> => { + const response = await supertest + .get(SIEM_RULE_MIGRATIONS_ALL_STATS_PATH) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + translationStats: async ({ + migrationId, + expectStatusCode = 200, + }: MigrationRequestParams): Promise<{ body: GetRuleMigrationStatsResponse }> => { + const response = await supertest + .get( + replaceParams(SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH, { migration_id: migrationId }) + ) + .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') + .send(); + + assertStatusCode(expectStatusCode, response); + + return response; + }, + + getPrebuiltRules: async ({ + migrationId, + expectStatusCode = 200, + }: MigrationRequestParams): Promise<{ body: GetRuleMigrationPrebuiltRulesResponse }> => { + const response = await supertest + .get(replaceParams(SIEM_RULE_MIGRATIONS_PREBUILT_RULES_PATH, { migration_id: migrationId })) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '1') + .set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1) .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/notifications.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/notifications.cy.ts index 989e68425daf4..d14d41e6f39cc 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/notifications.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/notifications.cy.ts @@ -20,6 +20,7 @@ import { installAllPrebuiltRulesRequest, installPrebuiltRuleAssets, createAndInstallMockedPrebuiltRules, + preventPrebuiltRulesPackageInstallation, } from '../../../../tasks/api_calls/prebuilt_rules'; import { resetRulesTableState } from '../../../../tasks/common'; import { login } from '../../../../tasks/login'; @@ -35,6 +36,8 @@ describe( { tags: ['@ess', '@serverless', '@skipInServerlessMKI'] }, () => { beforeEach(() => { + preventPrebuiltRulesPackageInstallation(); + login(); /* Make sure persisted rules table state is cleared */ resetRulesTableState(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts index 72bb79302537e..fe27c4d76f22f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts @@ -26,6 +26,7 @@ import { RULE_MANAGEMENT_PAGE_BREADCRUMB } from '../../../../screens/breadcrumbs import { installPrebuiltRuleAssets, createAndInstallMockedPrebuiltRules, + preventPrebuiltRulesPackageInstallation, } from '../../../../tasks/api_calls/prebuilt_rules'; import { createSavedQuery, deleteSavedQueries } from '../../../../tasks/api_calls/saved_queries'; import { fetchMachineLearningModules } from '../../../../tasks/api_calls/machine_learning'; @@ -374,6 +375,8 @@ describe( }; beforeEach(() => { + preventPrebuiltRulesPackageInstallation(); + login(); resetRulesTableState(); deleteAlertsAndRules(); diff --git a/x-pack/test/security_solution_cypress/package.json b/x-pack/test/security_solution_cypress/package.json index ab7f8ef31e680..617dcb73e6e77 100644 --- a/x-pack/test/security_solution_cypress/package.json +++ b/x-pack/test/security_solution_cypress/package.json @@ -5,12 +5,12 @@ "private": true, "license": "Elastic License 2.0", "scripts": { - "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../node_modules/.bin/cypress", - "cypress:open:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../test/security_solution_cypress/cypress/cypress.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", + "cypress": "../../../node_modules/.bin/cypress", + "cypress:open:ess": "TZ=UTC node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../test/security_solution_cypress/cypress/cypress.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", "cypress:asset_inventory:run:ess": "yarn cypress:ess --spec './cypress/e2e/asset_inventory/**/*.cy.ts'", "cypress:entity_analytics:run:ess": "yarn cypress:ess --spec './cypress/e2e/entity_analytics/**/*.cy.ts'", "cypress:run:cases:ess": "yarn cypress:ess --spec './cypress/e2e/explore/cases/*.cy.ts'", - "cypress:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", + "cypress:ess": "TZ=UTC node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", "cypress:rule_management:run:ess": "yarn cypress:ess --spec './cypress/e2e/detection_response/rule_management/!(prebuilt_rules)/**/*.cy.ts'", "cypress:rule_management:prebuilt_rules:run:ess": "yarn cypress:ess --spec './cypress/e2e/detection_response/rule_management/prebuilt_rules/**/*.cy.ts'", "cypress:detection_engine:run:ess": "yarn cypress:ess --spec './cypress/e2e/detection_response/detection_engine/!(exceptions)/**/*.cy.ts'", @@ -24,8 +24,8 @@ "cypress:burn:ess": "yarn cypress:ess --env burn=5", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/", "junit:transform": "node ../../solutions/security/plugins/security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-security-solution/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Security Solution Cypress' --writeInPlace", - "cypress:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts --ftr-config-file ../../test/security_solution_cypress/serverless_config", - "cypress:cloud:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider NODE_TLS_REJECT_UNAUTHORIZED=0 ../../../node_modules/.bin/cypress", + "cypress:serverless": "TZ=UTC node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts --ftr-config-file ../../test/security_solution_cypress/serverless_config", + "cypress:cloud:serverless": "TZ=UTC NODE_TLS_REJECT_UNAUTHORIZED=0 ../../../node_modules/.bin/cypress", "cypress:open:cloud:serverless": "yarn cypress:cloud:serverless open --config-file ./cypress/cypress_serverless.config.ts --env CLOUD_SERVERLESS=true", "cypress:open:serverless": "yarn cypress:serverless open --config-file ../../test/security_solution_cypress/cypress/cypress_serverless.config.ts --spec './cypress/e2e/**/*.cy.ts'", "cypress:entity_analytics:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/entity_analytics/**/*.cy.ts'", @@ -40,7 +40,7 @@ "cypress:changed-specs-only:serverless": "yarn cypress:serverless --changed-specs-only --env burn=5", "cypress:cloud_security_posture:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/cloud_security_posture/**/*.cy.ts'", "cypress:burn:serverless": "yarn cypress:serverless --env burn=2", - "cypress:qa:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel_serverless --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts", + "cypress:qa:serverless": "TZ=UTC node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel_serverless --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts", "cypress:open:qa:serverless": "yarn cypress:qa:serverless open", "cypress:run:qa:serverless:entity_analytics": "yarn cypress:qa:serverless --spec './cypress/e2e/entity_analytics/**/*.cy.ts'", "cypress:run:qa:serverless:investigations": "yarn cypress:qa:serverless --spec './cypress/e2e/investigations/**/*.cy.ts'", @@ -52,4 +52,4 @@ "cypress:run:qa:serverless:ai_assistant": "yarn cypress:qa:serverless --spec './cypress/e2e/ai_assistant/**/*.cy.ts'", "cypress:run:qa:serverless:cloud_security_posture": "yarn cypress:qa:serverless --spec './cypress/e2e/cloud_security_posture/**/*.cy.ts" } -} +} \ No newline at end of file diff --git a/x-pack/test_serverless/functional/test_suites/observability/cypress/package.json b/x-pack/test_serverless/functional/test_suites/observability/cypress/package.json index bf0dad8dd01e6..d50d6e5ab8a36 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/cypress/package.json +++ b/x-pack/test_serverless/functional/test_suites/observability/cypress/package.json @@ -5,9 +5,9 @@ "private": true, "license": "Elastic License 2.0", "scripts": { - "cypress:open": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../../node_modules/.bin/cypress open --config-file ./cypress.config.ts", - "cypress:run": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../../node_modules/.bin/cypress run --browser chrome --config-file ./cypress.config.ts", - "cypress:serverless:open": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../../scripts/functional_tests --config ./config_runner.ts", - "cypress:serverless:run": "NODE_OPTIONS=--openssl-legacy-provider node ../../../../../../scripts/functional_tests --config ./config_server.ts" + "cypress:open": "node ../../../../../../node_modules/.bin/cypress open --config-file ./cypress.config.ts", + "cypress:run": "node ../../../../../../node_modules/.bin/cypress run --browser chrome --config-file ./cypress.config.ts", + "cypress:serverless:open": "node ../../../../../../scripts/functional_tests --config ./config_runner.ts", + "cypress:serverless:run": "node ../../../../../../scripts/functional_tests --config ./config_server.ts" } } \ No newline at end of file diff --git a/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/_get_cell_renderers.ts b/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/_get_cell_renderers.ts index 19845d332a73d..7db9ee6b5fec5 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/_get_cell_renderers.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/_get_cell_renderers.ts @@ -58,7 +58,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const logLevelBadge = await firstCell.findByTestSubject('*logLevelBadgeCell-'); expect(await logLevelBadge.getVisibleText()).to.be('debug'); expect(await logLevelBadge.getComputedStyle('background-color')).to.be( - 'rgba(190, 207, 227, 1)' + 'rgba(232, 241, 255, 1)' ); }); @@ -199,7 +199,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { logLevelBadge = await firstCell.findByTestSubject('*logLevelBadgeCell-'); expect(await logLevelBadge.getVisibleText()).to.be('debug'); expect(await logLevelBadge.getComputedStyle('background-color')).to.be( - 'rgba(190, 207, 227, 1)' + 'rgba(232, 241, 255, 1)' ); }); @@ -216,7 +216,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { logLevelBadge = await firstCell.findByTestSubject('*logLevelBadgeCell-'); expect(await logLevelBadge.getVisibleText()).to.be('debug'); expect(await logLevelBadge.getComputedStyle('background-color')).to.be( - 'rgba(190, 207, 227, 1)' + 'rgba(232, 241, 255, 1)' ); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.agentless.ts b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.agentless.ts index b203bc6427ed2..8b49343a57323 100644 --- a/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.agentless.ts +++ b/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.agentless.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import { CA_CERT_PATH, KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; +import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from './constants'; import { createTestConfig } from '../../config.base'; // TODO: Remove the agentless default config once Serverless API is merged and default policy is deleted @@ -19,7 +19,7 @@ export default createTestConfig({ `--xpack.cloud.serverless.project_id=some_fake_project_id`, `--xpack.fleet.packages.0.name=cloud_security_posture`, - `--xpack.fleet.packages.0.version=${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, + `--xpack.fleet.packages.0.version=${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}`, `--xpack.fleet.agentless.enabled=true`, `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, `--xpack.fleet.internal.fleetServerStandalone=true`, diff --git a/x-pack/test_serverless/functional/test_suites/security/constants.ts b/x-pack/test_serverless/functional/test_suites/security/constants.ts index 53aea092cf8f6..477797ca0fd95 100644 --- a/x-pack/test_serverless/functional/test_suites/security/constants.ts +++ b/x-pack/test_serverless/functional/test_suites/security/constants.ts @@ -6,3 +6,4 @@ */ export const SECURITY_ES_ARCHIVES_DIR = 'x-pack/test/security_solution_cypress/es_archives'; +export const AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION = '1.13.0-preview02'; diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_aws.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_aws.ts index ea499f96da585..c4971aa90d0ce 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_aws.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_aws.ts @@ -4,9 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import expect from '@kbn/expect'; import * as http from 'http'; +import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../../../constants'; import type { FtrProviderContext } from '../../../../../ftr_provider_context'; import { setupMockServer } from './mock_agentless_api'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -39,7 +39,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { after(async () => { await supertest .delete( - `/api/fleet/epm/packages/cloud_security_posture/${CLOUD_CREDENTIALS_PACKAGE_VERSION}` + `/api/fleet/epm/packages/cloud_security_posture/${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}` ) .set('kbn-xsrf', 'xxxx') .send({ force: true }) @@ -48,18 +48,22 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); describe('Serverless - Agentless CIS_AWS Single Account Launch Cloud formation', () => { - it(`should show CIS_AWS Launch Cloud formation button when credentials selector is direct access keys and package version is ${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, async () => { + it(`should show CIS_AWS Launch Cloud formation button when credentials selector is direct access keys and package version is ${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}`, async () => { await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); + await pageObjects.header.waitUntilLoadingHasFinished(); await cisIntegration.clickOptionButton(testSubjectIds.CIS_AWS_OPTION_TEST_ID); await cisIntegration.clickOptionButton(testSubjectIds.AWS_SINGLE_ACCOUNT_TEST_ID); + await cisIntegration.inputIntegrationName( + `cloud_security_posture-${new Date().toISOString()}` + ); + await cisIntegration.selectSetupTechnology('agentless'); - await cisIntegration.selectAwsCredentials('direct'); - await pageObjects.header.waitUntilLoadingHasFinished(); + await cisIntegration.selectAwsCredentials('direct'); expect( (await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()) !== undefined @@ -68,27 +72,22 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); describe('Serverless - Agentless CIS_AWS ORG Account Launch Cloud formation', () => { - // tech debt: this test is failing because the credentials select is not working as expected - // https://github.com/orgs/elastic/projects/705/views/92?sliceBy%5Bvalue%5D=Agentless+-+API+-+ESS&pane=issue&itemId=73261952 - it.skip(`should show CIS_AWS Launch Cloud formation button when credentials selector is direct access keys and package version is ${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, async () => { + it(`should show CIS_AWS Launch Cloud formation button when credentials selector is direct access keys and package version is ${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}`, async () => { await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); + await pageObjects.header.waitUntilLoadingHasFinished(); await cisIntegration.clickOptionButton(testSubjectIds.CIS_AWS_OPTION_TEST_ID); - await cisIntegration.selectSetupTechnology('agentless'); await cisIntegration.selectAwsCredentials('direct'); - await pageObjects.header.waitUntilLoadingHasFinished(); - expect(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()).to.be(true); }); }); - // TODO: Migrate test after Serverless default agentless policy is deleted. - describe.skip('Serverless - Agentless CIS_AWS edit flow', () => { + describe('Serverless - Agentless CIS_AWS edit flow', () => { it(`user should save and edit agentless integration policy`, async () => { const newDirectAccessKeyId = `newDirectAccessKey`; @@ -109,15 +108,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ) ).to.be(newDirectAccessKeyId); expect(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()).to.be(true); - expect(await cisIntegration.getElementText(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR)).to.be( - 'Agentless\nBETA' - ); - expect( - await cisIntegration.getFieldAttributeValue( - testSubjectIds.SETUP_TECHNOLOGY_SELECTOR, - 'disabled' - ) - ).to.be('true'); }); }); // FLAKY: https://github.com/elastic/kibana/issues/191017 diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_gcp.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_gcp.ts index 58d36fcb608fb..d6b7e056e29d7 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_gcp.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/cis_integration_gcp.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import * as http from 'http'; +import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../../../constants'; import type { FtrProviderContext } from '../../../../../ftr_provider_context'; import { setupMockServer } from './mock_agentless_api'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -36,7 +36,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { after(async () => { await supertest .delete( - `/api/fleet/epm/packages/cloud_security_posture/${CLOUD_CREDENTIALS_PACKAGE_VERSION}` + `/api/fleet/epm/packages/cloud_security_posture/${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}` ) .set('kbn-xsrf', 'xxxx') .send({ force: true }) @@ -44,10 +44,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { mockApiServer.close(); }); - describe.skip('Agentless CIS_GCP Single Account Launch Cloud shell', () => { - it(`should show CIS_GCP Launch Cloud Shell button when package version is ${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, async () => { + describe('Agentless CIS_GCP Single Account Launch Cloud shell', () => { + it(`should show CIS_GCP Launch Cloud Shell button when package version is ${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}`, async () => { await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); await cisIntegration.clickOptionButton(testSubjectIds.CIS_GCP_OPTION_TEST_ID); @@ -61,10 +61,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe.skip('Agentless CIS_GCP ORG Account Launch Cloud Shell', () => { - it(`should show CIS_GCP Launch Cloud Shell button when package version is ${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, async () => { + describe('Agentless CIS_GCP ORG Account Launch Cloud Shell', () => { + it(`should show CIS_GCP Launch Cloud Shell button when package version is ${AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION}`, async () => { await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); await cisIntegration.clickOptionButton(testSubjectIds.CIS_GCP_OPTION_TEST_ID); @@ -97,16 +97,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'value' ) ).to.be(newCredentialsJSON); - expect(await cisIntegrationGcp.showLaunchCloudShellAgentlessButton()).to.be(true); - expect(await cisIntegration.getElementText(testSubjectIds.SETUP_TECHNOLOGY_SELECTOR)).to.be( - 'Agentless\nBETA' - ); - expect( - await cisIntegration.getFieldAttributeValue( - testSubjectIds.SETUP_TECHNOLOGY_SELECTOR, - 'disabled' - ) - ).to.be('true'); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/create_agent.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/create_agent.ts index 14351439ac68f..0fc6744df94c4 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/create_agent.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/agentless/create_agent.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import * as http from 'http'; import expect from '@kbn/expect'; +import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../../../constants'; import { setupMockServer } from './mock_agentless_api'; import type { FtrProviderContext } from '../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -21,8 +21,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ]); const CIS_AWS_OPTION_TEST_ID = 'cisAwsTestId'; - const AWS_SINGLE_ACCOUNT_TEST_ID = 'awsSingleTestId'; + const AWS_MANUAL_TEST_ID = 'aws-manual-setup-option'; + const DIRECT_ACCESS_KEY_ID_TEST_ID = 'awsDirectAccessKeyId'; + const DIRECT_ACCESS_SECRET_KEY_TEST_ID = 'passwordInput-secret-access-key'; describe('Agentless API Serverless', function () { this.tags(['skipMKI', 'cloud_security_posture_agentless']); @@ -42,7 +44,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`should create agentless-agent`, async () => { const integrationPolicyName = `cloud_security_posture-${new Date().toISOString()}`; await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); await cisIntegration.clickOptionButton(CIS_AWS_OPTION_TEST_ID); @@ -50,8 +52,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await cisIntegration.inputIntegrationName(integrationPolicyName); - await cisIntegration.selectSetupTechnology('agentless'); await cisIntegration.selectAwsCredentials('direct'); + await cisIntegration.fillInTextField(DIRECT_ACCESS_KEY_ID_TEST_ID, 'test'); + await cisIntegration.fillInTextField(DIRECT_ACCESS_SECRET_KEY_TEST_ID, 'test'); await pageObjects.header.waitUntilLoadingHasFinished(); @@ -74,13 +77,24 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const integrationPolicyName = `cloud_security_posture-${new Date().toISOString()}`; await cisIntegration.navigateToAddIntegrationCspmWithVersionPage( - CLOUD_CREDENTIALS_PACKAGE_VERSION + AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION ); + await pageObjects.header.waitUntilLoadingHasFinished(); await cisIntegration.clickOptionButton(CIS_AWS_OPTION_TEST_ID); await cisIntegration.clickOptionButton(AWS_SINGLE_ACCOUNT_TEST_ID); + await pageObjects.header.waitUntilLoadingHasFinished(); await cisIntegration.inputIntegrationName(integrationPolicyName); + await pageObjects.header.waitUntilLoadingHasFinished(); + + await cisIntegration.selectSetupTechnology('agent-based'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + await cisIntegration.clickOptionButton(AWS_MANUAL_TEST_ID); + await cisIntegration.selectAwsCredentials('direct'); + await cisIntegration.fillInTextField(DIRECT_ACCESS_KEY_ID_TEST_ID, 'test'); + await cisIntegration.fillInTextField(DIRECT_ACCESS_SECRET_KEY_TEST_ID, 'test'); await cisIntegration.clickSaveButton(); await pageObjects.header.waitUntilLoadingHasFinished(); diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/agentless/mki_create_agent.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/agentless/mki_create_agent.ts index 629e007dd7f52..07ed747ddcc34 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/agentless/mki_create_agent.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/agentless/mki_create_agent.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../constants'; +import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../../../../constants'; import type { FtrProviderContext } from '../../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); diff --git a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/constants.ts b/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/constants.ts deleted file mode 100644 index e1ac04d4ee8cf..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/mki_only/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION = '1.13.0-preview02'; diff --git a/yarn.lock b/yarn.lock index 9c4a1fb0b3be1..f7fbbcf24f2b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2104,10 +2104,10 @@ tunnel-agent "^0.6.0" uuid "^8.3.2" -"@cypress/webpack-preprocessor@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-6.0.1.tgz#5369527c063b2f4718a125ddbd163c5775086e06" - integrity sha512-WVNeFVSnFKxE3WZNRIriduTgqJRpevaiJIPlfqYTTzfXRD7X1Pv4woDE+G4caPV9bJqVKmVFiwzrXMRNeJxpxA== +"@cypress/webpack-preprocessor@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-6.0.2.tgz#58a96aa4dbff7433dd37d24ed47e413aa3d3fabb" + integrity sha512-0+1+4iy4W9PE6R5ywBNKAZoFp8Sf//w3UJ+CKTqkcAjA29b+dtsD0iFT70DsYE0BMqUM1PO7HXFGbXllQ+bRAA== dependencies: bluebird "3.7.1" debug "^4.3.4" @@ -2150,7 +2150,7 @@ gonzales-pe "^4.3.0" node-source-walk "^6.0.1" -"@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3", "@discoveryjs/json-ext@^0.5.7": +"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3", "@discoveryjs/json-ext@^0.5.7": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== @@ -2321,10 +2321,10 @@ resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314" integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ== -"@elastic/eui-theme-borealis@0.0.9": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@elastic/eui-theme-borealis/-/eui-theme-borealis-0.0.9.tgz#6aea79b15091e84235555236726f1bb1fc0da2bf" - integrity sha512-56tzAX5Go4RuSD1fuKvHiLPumGll1NYK1dG4E9OPe7xfLXBGdLjhdXabkJfUlc5OVX2xK9RI3TOmUiimqm8SJg== +"@elastic/eui-theme-borealis@0.0.10": + version "0.0.10" + resolved "https://registry.yarnpkg.com/@elastic/eui-theme-borealis/-/eui-theme-borealis-0.0.10.tgz#ebc317c135220b2f17529fe4e7b235a66614006e" + integrity sha512-9VFpUfxtHLjChd7Q1HZry71+o1vEOaUnCSOJiJT6zi/sbt+J114k+GCukOChScK6xaX8ypYD4/I0olCBwZV5Vw== "@elastic/eui-theme-common@0.0.9": version "0.0.9" @@ -2334,10 +2334,10 @@ "@types/lodash" "^4.14.202" lodash "^4.17.21" -"@elastic/eui@99.1.0-borealis.0": - version "99.1.0-borealis.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-99.1.0-borealis.0.tgz#b5b34c749ac56b8ecd290fb715f56ba2e5f255ab" - integrity sha512-akDYl5ScBNwBm1sIsPHQVPq5rJpkgjg5Qtb2F1T36eWFp9ux5EVAqoFylsLBIaUnXiwVDkDAVH604IOrR46COg== +"@elastic/eui@99.2.0-borealis.0": + version "99.2.0-borealis.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-99.2.0-borealis.0.tgz#44b22bd4b2177bdf860e7d5ca5f00cea123f044a" + integrity sha512-cjd7+awwWoBzdqFju0v3Q6Pl/GB1Y9C+3j9nNj3u5JgK62E2z9AkQvRdL6Tv8jusFwoSR9OhC3H0bmYOKLx8mg== dependencies: "@elastic/eui-theme-common" "0.0.9" "@hello-pangea/dnd" "^16.6.0" @@ -3845,6 +3845,26 @@ resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== +"@jsonjoy.com/base64@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" + integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== + +"@jsonjoy.com/json-pack@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz#33ca57ee29d12feef540f2139225597469dec894" + integrity sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg== + dependencies: + "@jsonjoy.com/base64" "^1.1.1" + "@jsonjoy.com/util" "^1.1.2" + hyperdyperid "^1.2.0" + thingies "^1.20.0" + +"@jsonjoy.com/util@^1.1.2", "@jsonjoy.com/util@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-1.3.0.tgz#e5623885bb5e0c48c1151e4dae422fb03a5887a1" + integrity sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw== + "@juggle/resize-observer@^3.3.1": version "3.4.0" resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" @@ -3945,7 +3965,7 @@ version "0.0.0" uid "" -"@kbn/alerting-rule-utils@link:x-pack/platform/packages/shared/alerting_rule_utils": +"@kbn/alerting-rule-utils@link:x-pack/platform/packages/shared/alerting-rule-utils": version "0.0.0" uid "" @@ -6225,7 +6245,7 @@ version "0.0.0" uid "" -"@kbn/logs-overview@link:x-pack/platform/packages/shared/logs_overview": +"@kbn/logs-overview@link:x-pack/platform/packages/shared/logs-overview": version "0.0.0" uid "" @@ -6497,6 +6517,10 @@ version "0.0.0" uid "" +"@kbn/node-libs-browser-webpack-plugin@link:packages/kbn-node-libs-browser-webpack-plugin": + version "0.0.0" + uid "" + "@kbn/notifications-plugin@link:x-pack/platform/plugins/shared/notifications": version "0.0.0" uid "" @@ -6525,19 +6549,19 @@ version "0.0.0" uid "" -"@kbn/observability-ai-common@link:x-pack/solutions/observability/packages/observability_ai/observability_ai_common": +"@kbn/observability-ai-common@link:x-pack/solutions/observability/packages/observability-ai/observability-ai-common": version "0.0.0" uid "" -"@kbn/observability-ai-server@link:x-pack/solutions/observability/packages/observability_ai/observability_ai_server": +"@kbn/observability-ai-server@link:x-pack/solutions/observability/packages/observability-ai/observability-ai-server": version "0.0.0" uid "" -"@kbn/observability-alert-details@link:x-pack/solutions/observability/packages/alert_details": +"@kbn/observability-alert-details@link:x-pack/solutions/observability/packages/alert-details": version "0.0.0" uid "" -"@kbn/observability-alerting-test-data@link:x-pack/solutions/observability/packages/alerting_test_data": +"@kbn/observability-alerting-test-data@link:x-pack/solutions/observability/packages/alerting-test-data": version "0.0.0" uid "" @@ -6545,7 +6569,7 @@ version "0.0.0" uid "" -"@kbn/observability-get-padded-alert-time-range-util@link:x-pack/solutions/observability/packages/get_padded_alert_time_range_util": +"@kbn/observability-get-padded-alert-time-range-util@link:x-pack/solutions/observability/packages/get-padded-alert-time-range-util": version "0.0.0" uid "" @@ -6569,15 +6593,15 @@ version "0.0.0" uid "" -"@kbn/observability-utils-browser@link:x-pack/solutions/observability/packages/utils_browser": +"@kbn/observability-utils-browser@link:x-pack/solutions/observability/packages/utils-browser": version "0.0.0" uid "" -"@kbn/observability-utils-common@link:x-pack/solutions/observability/packages/utils_common": +"@kbn/observability-utils-common@link:x-pack/solutions/observability/packages/utils-common": version "0.0.0" uid "" -"@kbn/observability-utils-server@link:x-pack/solutions/observability/packages/utils_server": +"@kbn/observability-utils-server@link:x-pack/solutions/observability/packages/utils-server": version "0.0.0" uid "" @@ -7073,7 +7097,7 @@ version "0.0.0" uid "" -"@kbn/search-shared-ui@link:x-pack/solutions/search/packages/shared_ui": +"@kbn/search-shared-ui@link:x-pack/solutions/search/packages/shared-ui": version "0.0.0" uid "" @@ -7141,7 +7165,7 @@ version "0.0.0" uid "" -"@kbn/security-solution-distribution-bar@link:x-pack/solutions/security/packages/distribution_bar": +"@kbn/security-solution-distribution-bar@link:x-pack/solutions/security/packages/distribution-bar": version "0.0.0" uid "" @@ -8181,25 +8205,25 @@ ncp "^2.0.0" typescript "^5.5.3" -"@launchdarkly/js-sdk-common@2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@launchdarkly/js-sdk-common/-/js-sdk-common-2.12.0.tgz#c22eb9fead687260d916a75f693c7d399f085b05" - integrity sha512-HIDxvgo1vksC9hsYy3517sgW0Ql+iW3fgwlq/CEigeBNmaa9/J1Pxo7LrKPzezEA0kaGedmt/DCzVVxVBmxSsQ== +"@launchdarkly/js-sdk-common@2.13.0": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@launchdarkly/js-sdk-common/-/js-sdk-common-2.13.0.tgz#5fd767ec2369b8efb90d457f6d8b80856baba6a2" + integrity sha512-cRoOQWBEOOynY3YDHIF4am1ZxiGu6MFK4v8WyNR0zN+nVjdQiuuyfAbHB//1Q0nrc1aB0flOy6e8C51eHy+VeA== -"@launchdarkly/js-server-sdk-common@2.10.0": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@launchdarkly/js-server-sdk-common/-/js-server-sdk-common-2.10.0.tgz#5bb0de97d86d66ffb0a92018bab7def289af1b46" - integrity sha512-zbqpmEFQW/ZElZnRYX6N4gMZMpviE0F75/IyxcifLAFsjGNouxllpOOPbdtrLiJnJ0ixzt5vbtnem4tbhlYNOw== +"@launchdarkly/js-server-sdk-common@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@launchdarkly/js-server-sdk-common/-/js-server-sdk-common-2.11.0.tgz#bf0de806b5398dfbda1e5e0d051f63b3b9c4da35" + integrity sha512-0MAe0iHYhdye68Yuiq6183KhG53z3gXxtOJVuVbIF+wd6VsHXCnpDnrljbvT4yFVaY9R2YMIC5dIXALqUiXCpw== dependencies: - "@launchdarkly/js-sdk-common" "2.12.0" + "@launchdarkly/js-sdk-common" "2.13.0" semver "7.5.4" -"@launchdarkly/node-server-sdk@^9.7.2": - version "9.7.2" - resolved "https://registry.yarnpkg.com/@launchdarkly/node-server-sdk/-/node-server-sdk-9.7.2.tgz#23929639f4b09da1f4c5bb77ca858d32c56505a4" - integrity sha512-gcRarEh0yQrlwbWDORwbfTk19M/FtZje60EIo/c4298D/sqJ906MYq0J2MmyklEuIdQx/V4qPK+ss9LCCLpm/Q== +"@launchdarkly/node-server-sdk@^9.7.3": + version "9.7.3" + resolved "https://registry.yarnpkg.com/@launchdarkly/node-server-sdk/-/node-server-sdk-9.7.3.tgz#e6072a16626184ae89920b5b655106805ddd59d4" + integrity sha512-z8mAdncXVwfKsK9LdcBp2BXbm5CfS9zJ2ZrabnYTNJpF2L14mZY2CG4z40CzM6v5bYxn8mxTPtOXeX1d2xPLTg== dependencies: - "@launchdarkly/js-server-sdk-common" "2.10.0" + "@launchdarkly/js-server-sdk-common" "2.11.0" https-proxy-agent "^5.0.1" launchdarkly-eventsource "2.0.3" @@ -9139,10 +9163,10 @@ schema-utils "^3.0.0" source-map "^0.7.3" -"@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.28" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73" + integrity sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw== "@popperjs/core@^2.11.5", "@popperjs/core@^2.11.8": version "2.11.8" @@ -10378,6 +10402,50 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" +"@storybook/builder-webpack5@^6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-6.5.16.tgz#2f260e29fbc87f6f3bb3212459048ce37f3fb54e" + integrity sha512-kh8Sofm1sbijaHDWtm0sXabqACHVFjikU/fIkkW786kpjoPIPIec1a+hrLgDsZxMU3I7XapSOaCFzWt6FjVXjg== + dependencies: + "@babel/core" "^7.12.10" + "@storybook/addons" "6.5.16" + "@storybook/api" "6.5.16" + "@storybook/channel-postmessage" "6.5.16" + "@storybook/channels" "6.5.16" + "@storybook/client-api" "6.5.16" + "@storybook/client-logger" "6.5.16" + "@storybook/components" "6.5.16" + "@storybook/core-common" "6.5.16" + "@storybook/core-events" "6.5.16" + "@storybook/node-logger" "6.5.16" + "@storybook/preview-web" "6.5.16" + "@storybook/router" "6.5.16" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.5.16" + "@storybook/theming" "6.5.16" + "@types/node" "^14.0.10 || ^16.0.0" + babel-loader "^8.0.0" + babel-plugin-named-exports-order "^0.0.2" + browser-assert "^1.2.1" + case-sensitive-paths-webpack-plugin "^2.3.0" + core-js "^3.8.2" + css-loader "^5.0.1" + fork-ts-checker-webpack-plugin "^6.0.4" + glob "^7.1.6" + glob-promise "^3.4.0" + html-webpack-plugin "^5.0.0" + path-browserify "^1.0.1" + process "^0.11.10" + stable "^0.1.8" + style-loader "^2.0.0" + terser-webpack-plugin "^5.0.3" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "^5.9.0" + webpack-dev-middleware "^4.1.0" + webpack-hot-middleware "^2.25.1" + webpack-virtual-modules "^0.4.1" + "@storybook/channel-postmessage@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.5.16.tgz#06167c0a66c06b2b5f8ff01d1dd436fff8119a15" @@ -10695,6 +10763,44 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" +"@storybook/manager-webpack5@^6.5.16": + version "6.5.16" + resolved "https://registry.yarnpkg.com/@storybook/manager-webpack5/-/manager-webpack5-6.5.16.tgz#48b223557d9633614ff8c6e3227c01a57ab4eb55" + integrity sha512-OtxXv8JCe0r/0rE5HxaFicsNsXA+fqZxzokxquFFgrYf/1Jg4d7QX6/pG5wINF+5qInJfVkRG6xhPzv1s5bk9Q== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@storybook/addons" "6.5.16" + "@storybook/core-client" "6.5.16" + "@storybook/core-common" "6.5.16" + "@storybook/node-logger" "6.5.16" + "@storybook/theming" "6.5.16" + "@storybook/ui" "6.5.16" + "@types/node" "^14.0.10 || ^16.0.0" + babel-loader "^8.0.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + chalk "^4.1.0" + core-js "^3.8.2" + css-loader "^5.0.1" + express "^4.17.1" + find-up "^5.0.0" + fs-extra "^9.0.1" + html-webpack-plugin "^5.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + style-loader "^2.0.0" + telejson "^6.0.8" + terser-webpack-plugin "^5.0.3" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "^5.9.0" + webpack-dev-middleware "^4.1.0" + webpack-virtual-modules "^0.4.1" + "@storybook/mdx1-csf@^0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz#d4184e3f6486fade9f7a6bfaf934d9bc07718d5b" @@ -11293,10 +11399,10 @@ "@types/connect" "*" "@types/node" "*" -"@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== +"@types/bonjour@^3.5.13": + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" @@ -11390,10 +11496,10 @@ resolved "https://registry.yarnpkg.com/@types/command-line-usage/-/command-line-usage-5.0.4.tgz#374e4c62d78fbc5a670a0f36da10235af879a0d5" integrity sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg== -"@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== +"@types/connect-history-api-fallback@^1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" @@ -11619,7 +11725,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@*", "@types/express@^4.17.13", "@types/express@^4.17.21": +"@types/express@*", "@types/express@^4.17.21": version "4.17.21" resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -11752,11 +11858,21 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA== +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "@types/http-cache-semantics@*": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + "@types/http-proxy@^1.17.4", "@types/http-proxy@^1.17.8": version "1.17.9" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" @@ -12069,7 +12185,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node-forge@^1.3.11": +"@types/node-forge@^1.3.0", "@types/node-forge@^1.3.11": version "1.3.11" resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== @@ -12384,6 +12500,11 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== +"@types/retry@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + "@types/seedrandom@>=2.0.0 <4.0.0": version "2.4.28" resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" @@ -12415,14 +12536,14 @@ "@types/mime" "^1" "@types/node" "*" -"@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== +"@types/serve-index@^1.9.4": + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" -"@types/serve-static@*", "@types/serve-static@^1.13.10": +"@types/serve-static@*": version "1.13.10" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== @@ -12430,6 +12551,15 @@ "@types/mime" "^1" "@types/node" "*" +"@types/serve-static@^1.15.5": + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/set-value@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/set-value/-/set-value-4.0.3.tgz#ac7f5f9715c95c7351e02832df672a112428e587" @@ -12450,10 +12580,10 @@ resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== -"@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== +"@types/sockjs@^0.3.36": + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" @@ -12637,19 +12767,17 @@ tapable "^2.2.0" webpack "^5" -"@types/webpack-env@^1.15.3", "@types/webpack-env@^1.16.0": +"@types/webpack-env@^1.16.0": version "1.16.3" resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a" integrity sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw== -"@types/webpack-merge@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/webpack-merge/-/webpack-merge-4.1.5.tgz#265fbee4810474860d0f4c17e0107032881eed47" - integrity sha512-cbDo592ljSHeaVe5Q39JKN6Z4vMhmo4+C3JbksOIg+kjhKQYN2keGN7dvr/i18+dughij98Qrsfn1mU9NgVoCA== - dependencies: - "@types/webpack" "*" +"@types/webpack-env@^1.18.5": + version "1.18.5" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.5.tgz#eccda0b04fe024bed505881e2e532f9c119169bf" + integrity sha512-wz7kjjRRj8/Lty4B+Kr0LN6Ypc/3SymeCCGSbaXp2leH0ZVg/PriNiOwNj4bD4uphI7A8NXS4b6Gl373sfO5mA== -"@types/webpack-sources@*", "@types/webpack-sources@^0.1.4": +"@types/webpack-sources@*": version "0.1.5" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.5.tgz#be47c10f783d3d6efe1471ff7f042611bd464a92" integrity sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w== @@ -12658,7 +12786,16 @@ "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@*", "@types/webpack@^4", "@types/webpack@^4.4.31", "@types/webpack@^4.41.26", "@types/webpack@^4.41.3", "@types/webpack@^4.41.8": +"@types/webpack-sources@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.3.tgz#b667bd13e9fa15a9c26603dce502c7985418c3d8" + integrity sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.7.3" + +"@types/webpack@^4", "@types/webpack@^4.41.26", "@types/webpack@^4.41.8": version "4.41.32" resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.32.tgz#a7bab03b72904070162b2f169415492209e94212" integrity sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg== @@ -12670,7 +12807,7 @@ anymatch "^3.0.0" source-map "^0.6.0" -"@types/webpack@^5.0.0": +"@types/webpack@^5.0.0", "@types/webpack@^5.28.5": version "5.28.5" resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-5.28.5.tgz#0e9d9a15efa09bbda2cef41356ca4ac2031ea9a2" integrity sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw== @@ -12679,13 +12816,20 @@ tapable "^2.2.0" webpack "^5" -"@types/ws@*", "@types/ws@^8.5.1": +"@types/ws@*": version "8.5.3" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== dependencies: "@types/node" "*" +"@types/ws@^8.5.10": + version "8.5.12" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" + integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ== + dependencies: + "@types/node" "*" + "@types/xml2js@^0.4.11": version "0.4.11" resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.11.tgz#bf46a84ecc12c41159a7bd9cf51ae84129af0e79" @@ -13091,22 +13235,20 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" - integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== -"@webpack-cli/info@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" - integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== - dependencies: - envinfo "^7.7.3" +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== -"@webpack-cli/serve@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" - integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== "@wojtekmaj/enzyme-adapter-react-17@^0.6.7": version "0.6.7" @@ -13408,7 +13550,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== @@ -13425,7 +13567,7 @@ ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.0.1, ajv@^8.17.1, ajv@^8.8.0: +ajv@^8.0.0, ajv@^8.0.1, ajv@^8.17.1, ajv@^8.9.0: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -13752,11 +13894,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - array-from@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195" @@ -14091,7 +14228,7 @@ babel-jest@^29.7.0: graceful-fs "^4.2.9" slash "^3.0.0" -babel-loader@^8.0.0, babel-loader@^8.2.5: +babel-loader@^8.0.0: version "8.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== @@ -14101,6 +14238,14 @@ babel-loader@^8.0.0, babel-loader@^8.2.5: make-dir "^3.1.0" schema-utils "^2.6.5" +babel-loader@^9.1.3: + version "9.1.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" + integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== + dependencies: + find-cache-dir "^4.0.0" + schema-utils "^4.0.0" + babel-plugin-add-module-exports@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz#6caa4ddbe1f578c6a5264d4d3e6c8a2720a7ca2b" @@ -14181,6 +14326,11 @@ babel-plugin-macros@^3.0.1, babel-plugin-macros@^3.1.0: cosmiconfig "^7.0.0" resolve "^1.19.0" +babel-plugin-named-exports-order@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz#ae14909521cf9606094a2048239d69847540cb09" + integrity sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw== + babel-plugin-polyfill-corejs2@^0.4.10: version "0.4.10" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" @@ -14248,6 +14398,11 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24: resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== +babel-plugin-transform-require-default@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-require-default/-/babel-plugin-transform-require-default-0.1.7.tgz#fa97c97e52c30d70f8a505b7fffc5503dfa84a88" + integrity sha512-eoH8Tm/fVtkRluI6UDc8B/TdsbjuvQwd5BPaw4yShHV0USsKoFHgGJsVCcFPhsPVyoBKbTlisiEc4sBpbtUldA== + babel-plugin-transform-typescript-metadata@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz#7a327842d8c36ffe07ee1b5276434e56c297c9b7" @@ -14289,10 +14444,10 @@ babel-runtime@6.x: core-js "^2.4.0" regenerator-runtime "^0.11.0" -backport@^9.6.4: - version "9.6.4" - resolved "https://registry.yarnpkg.com/backport/-/backport-9.6.4.tgz#ea45ab97f32ebca1564269f92a6fc56eda703cdc" - integrity sha512-cTaItWSGoO33vOD/br/Di2KFesgHyE6UWuc0GN0IiFk13UqEadeURq3UOQptARyQC3Nz56Us5QYNJ3E5L61zYg== +backport@^9.6.6: + version "9.6.6" + resolved "https://registry.yarnpkg.com/backport/-/backport-9.6.6.tgz#ab7d0a1720eb5cd3ccef51cd79f1872bb9ed409c" + integrity sha512-X/2vWZNZP5wvbfWaxtLsXSbnOxANgoCh84IZavTS2X2/6X/si3cpUL0ky1fh+70bK5O8PI+3Fopp5srmeqHB1g== dependencies: "@octokit/rest" "^19.0.7" axios "^1.6.2" @@ -14549,13 +14704,11 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" -bonjour-service@^1.0.11: - version "1.0.13" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.13.tgz#4ac003dc1626023252d58adf2946f57e5da450c1" - integrity sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA== +bonjour-service@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -14673,6 +14826,11 @@ brotli@^1.2.0: dependencies: base64-js "^1.1.2" +browser-assert@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/browser-assert/-/browser-assert-1.2.1.tgz#9aaa5a2a8c74685c2ae05bfe46efd606f068c200" + integrity sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ== + browser-stdout@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -14831,6 +14989,13 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +bundle-name@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" + integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== + dependencies: + run-applescript "^7.0.0" + byte-size@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-9.0.1.tgz#7014b9f0e11ea732a8f2c21bef1cb8a78c6c55ff" @@ -14985,13 +15150,13 @@ callsites@^3.0.0, callsites@^3.1.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" - integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== +camel-case@^4.1.1, camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== dependencies: - pascal-case "^3.1.1" - tslib "^1.10.0" + pascal-case "^3.1.2" + tslib "^2.0.3" camelcase-css@2.0.1: version "2.0.1" @@ -15224,7 +15389,7 @@ cheerio@^1.0.0-rc.12, cheerio@^1.0.0-rc.3: parse5 "^7.0.0" parse5-htmlparser2-tree-adapter "^7.0.0" -chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.1, chokidar@^3.5.3: +chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.1, chokidar@^3.5.3, chokidar@^3.6.0: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -15360,17 +15525,23 @@ clean-css@^4.2.3: dependencies: source-map "~0.6.0" +clean-css@^5.2.2, clean-css@~5.3.2: + version "5.3.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== + dependencies: + source-map "~0.6.0" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -clean-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz#a99d8ec34c1c628a4541567aa7b457446460c62b" - integrity sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A== +clean-webpack-plugin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz#72947d4403d452f38ed61a9ff0ada8122aacd729" + integrity sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w== dependencies: - "@types/webpack" "^4.4.31" del "^4.1.1" cli-boxes@^2.2.1: @@ -15714,12 +15885,12 @@ commander@6.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== -commander@7, commander@^7.0.0, commander@^7.2.0: +commander@7, commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^10.0.1: +commander@^10.0.0, commander@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== @@ -15749,6 +15920,11 @@ commander@^6.2.0, commander@^6.2.1: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -16213,7 +16389,7 @@ css-in-js-utils@^2.0.0: hyphenate-style-name "^1.0.2" isobject "^3.0.1" -css-loader@^3.4.2, css-loader@^3.6.0: +css-loader@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== @@ -16232,6 +16408,36 @@ css-loader@^3.4.2, css-loader@^3.6.0: schema-utils "^2.7.0" semver "^6.3.0" +css-loader@^5.0.1: + version "5.2.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" + integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== + dependencies: + icss-utils "^5.1.0" + loader-utils "^2.0.0" + postcss "^8.2.15" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^3.0.0" + semver "^7.3.5" + +css-loader@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-7.1.2.tgz#64671541c6efe06b0e22e750503106bdd86880f8" + integrity sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.5.4" + css-select@^4.1.3: version "4.3.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" @@ -16769,7 +16975,7 @@ d3-zoom@^3.0.0: d3-selection "2 - 3" d3-transition "2 - 3" -d3@3.5.17, d3@^3.5.6: +d3@3.5.17: version "3.5.17" resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8" integrity sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g= @@ -16868,6 +17074,11 @@ dayjs@^1.10.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== +debounce@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -17033,6 +17244,19 @@ default-browser-id@^1.0.4: meow "^3.1.0" untildify "^2.0.0" +default-browser-id@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" + integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== + +default-browser@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" + integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== + dependencies: + bundle-name "^4.1.0" + default-browser-id "^5.0.0" + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -17073,6 +17297,11 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" @@ -17455,11 +17684,6 @@ discontinuous-range@1.0.0: resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo= -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - dns-packet@^5.2.2: version "5.4.0" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" @@ -17546,13 +17770,6 @@ domexception@^4.0.0: dependencies: webidl-conversions "^7.0.0" -domhandler@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" - integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw== - dependencies: - domelementtype "^2.0.1" - domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" @@ -17572,7 +17789,7 @@ dompurify@^3.0.6: resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.5.tgz#2c6a113fc728682a0f55684b1388c58ddb79dc38" integrity sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA== -domutils@^2.0.0, domutils@^2.5.2, domutils@^2.8.0: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -17590,7 +17807,7 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.1" -dot-case@^3.0.3, dot-case@^3.0.4: +dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== @@ -17766,9 +17983,9 @@ element-resize-detector@^1.2.2: batch-processor "1.0.0" elliptic@^6.0.0, elliptic@^6.5.4: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -18399,6 +18616,13 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" +eslint-plugin-playwright@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz#d7eda21e670274fc0c006e11ba5cc2c8417b2a6e" + integrity sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg== + dependencies: + globals "^13.23.0" + eslint-plugin-prettier@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" @@ -18791,10 +19015,10 @@ exponential-backoff@^3.1.1: resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== -expose-loader@^0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.5.tgz#e29ea2d9aeeed3254a3faa1b35f502db9f9c3f6f" - integrity sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw== +expose-loader@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-5.0.0.tgz#41368903eb1246b7c09fecf32c5cb3f67d0260e6" + integrity sha512-BtUqYRmvx1bEY5HN6eK2I9URUZgNmN0x5UANuocaNjXSgfoDlkXt+wyEMe7i5DzDNh2BKJHPc5F4rBwEdSQX6w== expr-eval@^2.0.2: version "2.0.2" @@ -19224,6 +19448,14 @@ find-cache-dir@^3.2.0, find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-cache-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" + integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== + dependencies: + common-path-prefix "^3.0.0" + pkg-dir "^7.0.0" + find-cypress-specs@^1.41.4: version "1.41.4" resolved "https://registry.yarnpkg.com/find-cypress-specs/-/find-cypress-specs-1.41.4.tgz#583595c502e785f7bb44dbb5a9ba2f09caf59e94" @@ -19302,6 +19534,14 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -19599,10 +19839,10 @@ fs-mkdirp-stream@^2.0.1: graceful-fs "^4.2.8" streamx "^2.12.0" -fs-monkey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" + integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== fs-readdir-recursive@^1.1.0: version "1.1.0" @@ -20044,10 +20284,10 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0, globals@^13.20.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== +globals@^13.19.0, globals@^13.20.0, globals@^13.23.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" @@ -20694,27 +20934,25 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" -html-entities@^2.1.0, html-entities@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" - integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== +html-entities@^2.1.0, html-entities@^2.4.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== -html-escaper@^2.0.0: +html-escaper@^2.0.0, html-escaper@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-loader@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.3.2.tgz#5a72ebba420d337083497c9aba7866c9e1aee340" - integrity sha512-DEkUwSd0sijK5PF3kRWspYi56XP7bTNkyg5YWSzBdjaSDmvCufep5c4Vpb3PBf6lUL0YPtLwBfy9fL0t5hBAGA== +html-loader@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-5.1.0.tgz#85c13e0abc3b5f3aa6e7f664eee6e44d00718d95" + integrity sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA== dependencies: - html-minifier-terser "^5.1.1" - htmlparser2 "^4.1.0" - loader-utils "^2.0.0" - schema-utils "^3.0.0" + html-minifier-terser "^7.2.0" + parse5 "^7.1.2" -html-minifier-terser@^5.0.1, html-minifier-terser@^5.1.1: +html-minifier-terser@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== @@ -20727,6 +20965,32 @@ html-minifier-terser@^5.0.1, html-minifier-terser@^5.1.1: relateurl "^0.2.7" terser "^4.6.3" +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-minifier-terser@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz#18752e23a2f0ed4b0f550f217bb41693e975b942" + integrity sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA== + dependencies: + camel-case "^4.1.2" + clean-css "~5.3.2" + commander "^10.0.0" + entities "^4.4.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.15.1" + html-tags@^3.1.0, html-tags@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" @@ -20763,15 +21027,16 @@ html-webpack-plugin@^4.0.0: tapable "^1.1.3" util.promisify "1.0.0" -htmlparser2@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" - integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== +html-webpack-plugin@^5.0.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" + integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== dependencies: - domelementtype "^2.0.1" - domhandler "^3.0.0" - domutils "^2.0.0" - entities "^2.0.0" + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" htmlparser2@^6.1.0: version "6.1.0" @@ -20956,6 +21221,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +hyperdyperid@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hyperdyperid/-/hyperdyperid-1.2.0.tgz#59668d323ada92228d2a869d3e474d5a33b69e6b" + integrity sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A== + hyphenate-style-name@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" @@ -20994,6 +21264,11 @@ icss-utils@^4.0.0, icss-utils@^4.1.1: dependencies: postcss "^7.0.14" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + ieee754@^1.1.12, ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -21272,10 +21547,10 @@ ipaddr.js@2.0.0: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.0.tgz#77ccccc8063ae71ab65c55f21b090698e763fc6e" integrity sha512-S54H9mIj0rbxRIyrDMEuuER86LdlgUg9FSeZ8duQb6CUG2iRrA36MYVQBSprTF/ZeAwvyQ5mDGuNvIPM0BIl3w== -ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== irregular-plurals@^3.2.0: version "3.2.0" @@ -21449,6 +21724,11 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + is-dom@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.1.0.tgz#af1fced292742443bb59ca3f76ab5e80907b4e8a" @@ -21534,6 +21814,13 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.1.tgz#6e084bbc92061fbb0971ec58b6ce6d404e24da69" integrity sha1-bghLvJIGH7sJcexYts5tQE4k2mk= +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-installed-globally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" @@ -21577,6 +21864,11 @@ is-negative-zero@^2.0.3: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== +is-network-error@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" + integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + is-node-process@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" @@ -21863,6 +22155,13 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +is-wsl@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" + integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== + dependencies: + is-inside-container "^1.0.0" + is2@^2.0.6: version "2.0.9" resolved "https://registry.yarnpkg.com/is2/-/is2-2.0.9.tgz#ff63b441f90de343fa8fac2125ee170da8e8240d" @@ -22588,6 +22887,11 @@ jest@^29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" +jiti@^1.20.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + joi-to-json@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/joi-to-json/-/joi-to-json-4.3.0.tgz#c56131ecf8a772fce89fd98b7f81d7b0fac31dbc" @@ -22928,9 +23232,9 @@ jsonify@~0.0.0: integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsonpath-plus@^10.0.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-10.2.0.tgz#84d680544d9868579cc7c8f59bbe153a5aad54c4" - integrity sha512-T9V+8iNYKFL2n2rF+w02LBOT2JjDnTjioaNFrxRy0Bv1y/hNsqR/EBK7Ojy2ythRHwmz2cRIls+9JitQGZC/sw== + version "10.3.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz#59e22e4fa2298c68dfcd70659bb47f0cad525238" + integrity sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA== dependencies: "@jsep-plugin/assignment" "^1.3.0" "@jsep-plugin/regex" "^1.0.4" @@ -23161,6 +23465,14 @@ language-tags@=1.0.5: dependencies: language-subtag-registry "~0.3.2" +launch-editor@^2.6.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.1.tgz#3bda72af213ec9b46b170e39661916ec66c2f463" + integrity sha512-elBx2l/tp9z99X5H/qev8uyDywVh0VXAwEbjk8kJhnc5grOFkGh7aW6q55me9xnYbss261XtnUrysZ+XvGbhQA== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + launchdarkly-eventsource@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/launchdarkly-eventsource/-/launchdarkly-eventsource-2.0.3.tgz#8a7b8da5538153f438f7d452b1c87643d900f984" @@ -23362,7 +23674,7 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^1.0.0, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@^1.2.3: version "1.4.2" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3" integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg== @@ -23402,6 +23714,13 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +locate-path@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + dependencies: + p-locate "^6.0.0" + lodash-es@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" @@ -23741,6 +24060,13 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +map-age-cleaner@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -24042,12 +24368,30 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memfs@^3.1.2, memfs@^3.4.3: - version "3.4.7" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" - integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== +mem@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" + integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== + dependencies: + map-age-cleaner "^0.1.3" + mimic-fn "^3.1.0" + +memfs@^3.1.2, memfs@^3.2.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - fs-monkey "^1.0.3" + fs-monkey "^1.0.4" + +memfs@^4.6.0: + version "4.11.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-4.11.1.tgz#9c9c8e65bf8ac72c0db8d0fbbbe29248cf51d56a" + integrity sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ== + dependencies: + "@jsonjoy.com/json-pack" "^1.0.3" + "@jsonjoy.com/util" "^1.3.0" + tree-dump "^1.0.1" + tslib "^2.0.0" "memoize-one@>=3.1.1 <6", memoize-one@^5.0.0: version "5.1.1" @@ -24260,22 +24604,22 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== "mime-db@>= 1.40.0 < 2", mime-db@^1.52.0: version "1.53.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.30, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.51.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" @@ -24292,6 +24636,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== + mimic-function@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" @@ -24319,14 +24668,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= -mini-css-extract-plugin@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.1.0.tgz#dcc2f0bfbec660c0bd1200ff7c8f82deec2cc8a6" - integrity sha512-0bTS+Fg2tGe3dFAgfiN7+YRO37oyQM7/vjFvZF1nXSCJ/sy0tGpeme8MbT4BCpUuUphKwTh9LH/uuTcWRr9DPA== +mini-css-extract-plugin@2.9.1: + version "2.9.1" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz#4d184f12ce90582e983ccef0f6f9db637b4be758" + integrity sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ== dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" + schema-utils "^4.0.0" + tapable "^2.2.1" minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -24740,10 +25088,10 @@ mri@1.1.4: resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== -mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== ms-chromium-edge-driver@^0.5.1: version "0.5.1" @@ -25000,7 +25348,7 @@ nise@^1.5.2: lolex "^5.0.1" path-to-regexp "^1.7.0" -no-case@^3.0.3, no-case@^3.0.4: +no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== @@ -25277,14 +25625,6 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -null-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-3.0.0.tgz#3e2b6c663c5bda8c73a54357d8fa0708dc61b245" - integrity sha512-hf5sNLl8xdRho4UPBOOeoIwT3WhjYcMUQm0zj44EhD6UscMAz72o2udpoDFBgykucdEDGIcd6SXbc/G6zssbzw== - dependencies: - loader-utils "^1.2.3" - schema-utils "^1.0.0" - num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -25573,7 +25913,7 @@ on-exit-leak-free@^2.1.0: resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -25613,6 +25953,16 @@ onetime@^7.0.0: dependencies: mimic-function "^5.0.0" +open@^10.0.3: + version "10.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.1.0.tgz#a7795e6e5d519abe4286d9937bb24b51122598e1" + integrity sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^3.1.0" + open@^7.0.3: version "7.4.2" resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" @@ -25621,7 +25971,7 @@ open@^7.0.3: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.0.9, open@^8.4.0, open@~8.4.0: +open@^8.4.0, open@~8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -25798,6 +26148,11 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== + p-event@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.1.0.tgz#e92bb866d7e8e5b732293b1c8269d38e9982bf8e" @@ -25831,6 +26186,13 @@ p-limit@^3.0.1, p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -25852,6 +26214,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -25884,7 +26253,7 @@ p-reflect@2.1.0, p-reflect@^2.1.0: resolved "https://registry.yarnpkg.com/p-reflect/-/p-reflect-2.1.0.tgz#5d67c7b3c577c4e780b9451fc9129675bd99fe67" integrity sha512-paHV8NUz8zDHu5lhr/ngGWQiW067DK/+IbJ+RfZ4k+s8y4EKyYCz8pGYWjxCg35eHztpJAt+NUgvN4L+GCbPlg== -p-retry@4, p-retry@^4.2.0, p-retry@^4.5.0: +p-retry@4, p-retry@^4.2.0: version "4.6.2" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== @@ -25892,6 +26261,15 @@ p-retry@4, p-retry@^4.2.0, p-retry@^4.5.0: "@types/retry" "0.12.0" retry "^0.13.1" +p-retry@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-6.2.0.tgz#8d6df01af298750009691ce2f9b3ad2d5968f3bd" + integrity sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA== + dependencies: + "@types/retry" "0.12.2" + is-network-error "^1.0.0" + retry "^0.13.1" + p-settle@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/p-settle/-/p-settle-4.1.1.tgz#37fbceb2b02c9efc28658fc8d36949922266035f" @@ -25985,13 +26363,13 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" - integrity sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA== +param-case@^3.0.3, param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== dependencies: - dot-case "^3.0.3" - tslib "^1.10.0" + dot-case "^3.0.4" + tslib "^2.0.3" parent-module@^1.0.0: version "1.0.0" @@ -26063,10 +26441,10 @@ parse5@^6.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parse5@^7.0.0, parse5@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.1.tgz#4649f940ccfb95d8754f37f73078ea20afe0c746" - integrity sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg== +parse5@^7.0.0, parse5@^7.1.1, parse5@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== dependencies: entities "^4.4.0" @@ -26075,13 +26453,13 @@ parseurl@~1.3.2, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -pascal-case@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" - integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== dependencies: - no-case "^3.0.3" - tslib "^1.10.0" + no-case "^3.0.4" + tslib "^2.0.3" pascalcase@^0.1.1: version "0.1.1" @@ -26120,6 +26498,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -26366,6 +26749,13 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" +pkg-dir@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" + integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== + dependencies: + find-up "^6.3.0" + pkg-up@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" @@ -26558,6 +26948,15 @@ postcss-loader@^4.2.0: schema-utils "^3.0.0" semver "^7.3.4" +postcss-loader@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-8.1.1.tgz#2822589e7522927344954acb55bbf26e8b195dfe" + integrity sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ== + dependencies: + cosmiconfig "^9.0.0" + jiti "^1.20.0" + semver "^7.5.4" + postcss-media-query-parser@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" @@ -26620,6 +27019,11 @@ postcss-modules-extract-imports@^2.0.0: dependencies: postcss "^7.0.5" +postcss-modules-extract-imports@^3.0.0, postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + postcss-modules-local-by-default@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" @@ -26630,6 +27034,15 @@ postcss-modules-local-by-default@^3.0.2: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.0" +postcss-modules-local-by-default@^4.0.0, postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + postcss-modules-scope@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" @@ -26638,6 +27051,13 @@ postcss-modules-scope@^2.2.0: postcss "^7.0.6" postcss-selector-parser "^6.0.0" +postcss-modules-scope@^3.0.0, postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" + postcss-modules-values@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" @@ -26646,6 +27066,13 @@ postcss-modules-values@^3.0.0: icss-utils "^4.0.0" postcss "^7.0.6" +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + postcss-normalize-charset@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" @@ -26806,7 +27233,7 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0 picocolors "^0.2.1" source-map "^0.6.1" -postcss@^8.4.19, postcss@^8.4.23, postcss@^8.4.31: +postcss@^8.2.15, postcss@^8.4.19, postcss@^8.4.23, postcss@^8.4.31, postcss@^8.4.33: version "8.4.49" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== @@ -26903,6 +27330,14 @@ pretty-error@^2.1.1: lodash "^4.17.20" renderkid "^2.0.4" +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" @@ -27381,14 +27816,6 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" -raw-loader@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-3.1.0.tgz#5e9d399a5a222cc0de18f42c3bc5e49677532b3f" - integrity sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA== - dependencies: - loader-utils "^1.1.0" - schema-utils "^2.0.1" - raw-loader@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" @@ -27504,7 +27931,7 @@ react-docgen@^5.0.0: dependencies: scheduler "^0.25.0" -react-dom@^17.0.1, react-dom@^17.0.2: +react-dom@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== @@ -27953,7 +28380,7 @@ react-window@^1.8.10: resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== -react@^17.0.1, react@^17.0.2: +react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== @@ -28124,13 +28551,6 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== - dependencies: - resolve "^1.9.0" - rechoir@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" @@ -28563,6 +28983,17 @@ renderkid@^2.0.4: lodash "^4.17.21" strip-ansi "^3.0.1" +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + repeat-element@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" @@ -28724,7 +29155,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.22.3, resolve@^1.22.8, resolve@^1.3.2, resolve@^1.9.0: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.22.3, resolve@^1.22.8, resolve@^1.3.2: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -28859,6 +29290,11 @@ rtl-css-js@^1.9.0: dependencies: "@babel/runtime" "^7.1.2" +run-applescript@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" + integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== + run-async@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" @@ -29141,10 +29577,10 @@ sass-embedded@^1.78.0: sass-embedded-win32-ia32 "1.78.0" sass-embedded-win32-x64 "1.78.0" -sass-loader@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.5.1.tgz#4cfb9cd17e09afc7d8787fdb57d665254c3aadcb" - integrity sha512-P8BGIW6OxYLJWaWG8DROibc98Uw/B90oHPYOjPQ5/tF572OTTwkhxSxpaQzD5lYam36zQd0cxjh24b4rcdNIZQ== +sass-loader@^10.5.2: + version "10.5.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.5.2.tgz#1ca30534fff296417b853c7597ca3b0bbe8c37d0" + integrity sha512-vMUoSNOUKJILHpcNCCyD23X34gve1TS7Rjd9uXHeKqhvBG39x6XbswFDtpbTElj6XdMFezoWhkh5vtKudf2cgQ== dependencies: klona "^2.0.4" loader-utils "^2.0.0" @@ -29191,7 +29627,7 @@ scheduler@^0.25.0: resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== -schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0: +schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== @@ -29200,14 +29636,6 @@ schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5. ajv "^6.12.2" ajv-keywords "^3.4.1" -schema-utils@^0.4.5: - version "0.4.7" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" - integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -29226,15 +29654,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== +schema-utils@^4.0.0, schema-utils@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" + ajv "^8.9.0" ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + ajv-keywords "^5.1.0" screenfull@^5.0.0: version "5.0.0" @@ -29271,11 +29699,12 @@ self-signed-cert@^1.0.1: resolved "https://registry.yarnpkg.com/self-signed-cert/-/self-signed-cert-1.0.1.tgz#9e2fae07503f84fb910f4a87c5c5c6becc207bf6" integrity sha512-86d1jYydqaRdUEyR9tj5nQ0d059RUWB9gdZrzDy2MJaUHii1h9EyzbAepkV1rOLO2AkSkQbXtUrqWRH4FDYWHA== -selfsigned@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56" - integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ== +selfsigned@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: + "@types/node-forge" "^1.3.0" node-forge "^1" semver-compare@^1.0.0: @@ -29524,6 +29953,11 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" @@ -29661,14 +30095,14 @@ sinon@^7.4.2: nise "^1.5.2" supports-color "^5.5.0" -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== +sirv@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== dependencies: - "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" sisteransi@^1.0.5: version "1.0.5" @@ -30319,13 +30753,13 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-replace-loader@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-2.2.0.tgz#0a0e6543fcec783d85c353a3e96a23872d45a94f" - integrity sha512-Ukt4ZC8+xVWdBRut3/iwnPJCNL1yV8AbVKXn8UcWdYrHgtuW4UDDAbBSi/J/CQDEWQBt824AJvPYahF23eJLRg== +string-replace-loader@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-3.1.0.tgz#11ac6ee76bab80316a86af358ab773193dd57a4f" + integrity sha512-5AOMUZeX5HE/ylKDnEa/KKBqvlnFmRZudSOjVJHxhoJg9QYTwl1rECx7SLR8BBH7tfxb4Rp7EM2XVfQFxIhsbQ== dependencies: - loader-utils "^1.2.3" - schema-utils "^1.0.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" "string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" @@ -30532,7 +30966,7 @@ strnum@^1.0.5: resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== -style-loader@^1.1.3, style-loader@^1.3.0: +style-loader@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== @@ -30540,6 +30974,19 @@ style-loader@^1.1.3, style-loader@^1.3.0: loader-utils "^2.0.0" schema-utils "^2.7.0" +style-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" + integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +style-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-4.0.0.tgz#0ea96e468f43c69600011e0589cb05c44f3b17a5" + integrity sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA== + style-search@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" @@ -30901,7 +31348,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -31083,7 +31530,7 @@ terser-webpack-plugin@^4.2.3: terser "^5.3.4" webpack-sources "^1.4.3" -terser-webpack-plugin@^5.3.10: +terser-webpack-plugin@^5.0.3, terser-webpack-plugin@^5.3.10: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== @@ -31103,7 +31550,7 @@ terser@^4.1.2, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^5.26.0, terser@^5.3.4, terser@^5.36.0, terser@^5.9.0: +terser@^5.10.0, terser@^5.15.1, terser@^5.26.0, terser@^5.3.4, terser@^5.36.0, terser@^5.9.0: version "5.36.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e" integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w== @@ -31142,6 +31589,11 @@ textarea-caret@^3.1.0: resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.1.0.tgz#5d5a35bb035fd06b2ff0e25d5359e97f2655087f" integrity sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q== +thingies@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.21.0.tgz#e80fbe58fd6fdaaab8fad9b67bd0a5c943c445c1" + integrity sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g== + thread-stream@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33" @@ -31384,10 +31836,10 @@ topojson-client@^3.1.0: dependencies: commander "2" -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== tough-cookie@^4.1.2, tough-cookie@^4.1.4: version "4.1.4" @@ -31437,6 +31889,11 @@ traverse@~0.6.6: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= +tree-dump@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tree-dump/-/tree-dump-1.0.2.tgz#c460d5921caeb197bde71d0e9a7b479848c5b8ac" + integrity sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ== + tree-kill@1.2.2, tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -31586,7 +32043,7 @@ tslib@2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -32138,15 +32595,6 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-loader@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-2.3.0.tgz#e0e2ef658f003efb8ca41b0f3ffbf76bab88658b" - integrity sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog== - dependencies: - loader-utils "^1.2.3" - mime "^2.4.4" - schema-utils "^2.5.0" - url-loader@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" @@ -32319,13 +32767,10 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -val-loader@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/val-loader/-/val-loader-1.1.1.tgz#32ba8ed5c3607504134977251db2966499e15ef7" - integrity sha512-JLqLXJWCVLXTxbUeHhLpWkgl3+X3U8Bl0vY7rTFZgFSbLJaEtAxuD2ixy/cM8w/gzC7sS3NE5IDSzClDt332sw== - dependencies: - loader-utils "^1.0.0" - schema-utils "^0.4.5" +val-loader@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/val-loader/-/val-loader-6.0.0.tgz#88078512fdb66e04deab659fec05e281105e4d81" + integrity sha512-NHi81ow+/mVBRuFRNxp8tfTSnAIFsq/wzZGqxv/a82Y722GQSOQi9yP0GuenSBiuw4+zGjmW/H9sLTbP3bewrw== validate-npm-package-license@^3.0.1: version "3.0.1" @@ -33000,37 +33445,41 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== +webpack-bundle-analyzer@^4.10.2: + version "4.10.2" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz#633af2862c213730be3dbdf40456db171b60d5bd" + integrity sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw== dependencies: + "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" acorn-walk "^8.0.0" - chalk "^4.1.0" commander "^7.2.0" + debounce "^1.2.1" + escape-string-regexp "^4.0.0" gzip-size "^6.0.0" - lodash "^4.17.20" + html-escaper "^2.0.2" opener "^1.5.2" - sirv "^1.0.7" + picocolors "^1.0.0" + sirv "^2.0.3" ws "^7.3.1" -webpack-cli@^4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" - integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.2.0" - "@webpack-cli/info" "^1.5.0" - "@webpack-cli/serve" "^1.7.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" colorette "^2.0.14" - commander "^7.0.0" + commander "^10.0.1" cross-spawn "^7.0.3" + envinfo "^7.7.3" fastest-levenshtein "^1.0.12" import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" + interpret "^3.1.1" + rechoir "^0.8.0" webpack-merge "^5.7.3" webpack-dev-middleware@^3.7.3: @@ -33044,51 +33493,65 @@ webpack-dev-middleware@^3.7.3: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-middleware@^5.3.1: - version "5.3.4" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" - integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== +webpack-dev-middleware@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e" + integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w== + dependencies: + colorette "^1.2.2" + mem "^8.1.1" + memfs "^3.2.2" + mime-types "^2.1.30" + range-parser "^1.2.1" + schema-utils "^3.0.0" + +webpack-dev-middleware@^7.1.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-7.4.1.tgz#5fafc609c44b0fcda27bb4444376eb1dc9fc1fe3" + integrity sha512-/t6KpZw/bnmCR0VKILjJT05mWecbf1aIM2VxCJUvBbg0iXqaQJFxbJ4PCrsY4iBH7PGwnccm4BYyoP1G+lGfAA== dependencies: colorette "^2.0.10" - memfs "^3.4.3" + memfs "^4.6.0" mime-types "^2.1.31" + on-finished "^2.4.1" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.9.3: - version "4.9.3" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9" - integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw== - dependencies: - "@types/bonjour" "^3.5.9" - "@types/connect-history-api-fallback" "^1.3.5" - "@types/express" "^4.17.13" - "@types/serve-index" "^1.9.1" - "@types/serve-static" "^1.13.10" - "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.1" +webpack-dev-server@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz#cb6ea47ff796b9251ec49a94f24a425e12e3c9b8" + integrity sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA== + dependencies: + "@types/bonjour" "^3.5.13" + "@types/connect-history-api-fallback" "^1.5.4" + "@types/express" "^4.17.21" + "@types/serve-index" "^1.9.4" + "@types/serve-static" "^1.15.5" + "@types/sockjs" "^0.3.36" + "@types/ws" "^8.5.10" ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" + bonjour-service "^1.2.1" + chokidar "^3.6.0" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" express "^4.17.3" graceful-fs "^4.2.6" - html-entities "^2.3.2" + html-entities "^2.4.0" http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.0.1" + ipaddr.js "^2.1.0" + launch-editor "^2.6.1" + open "^10.0.3" + p-retry "^6.2.0" + rimraf "^5.0.5" + schema-utils "^4.2.0" + selfsigned "^2.4.1" serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + webpack-dev-middleware "^7.1.0" + ws "^8.16.0" webpack-filter-warnings-plugin@^1.2.1: version "1.2.1" @@ -33113,13 +33576,6 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" -webpack-merge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== - dependencies: - lodash "^4.17.15" - webpack-merge@^5.7.3: version "5.8.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" @@ -33128,7 +33584,16 @@ webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: +webpack-merge@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-6.0.1.tgz#50c776868e080574725abc5869bd6e4ef0a16c6a" + integrity sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.1" + +webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== @@ -33148,18 +33613,12 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack-visualizer-plugin2@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/webpack-visualizer-plugin2/-/webpack-visualizer-plugin2-1.1.0.tgz#247256978c12ee2a0ec22e5d170f7d0b1ef98146" - integrity sha512-pB2Z9a12m+LwjrfptyR4ReEPc0llOjsb2lXVLEJ4yOnRCBtLeWW+TZrZihUZhJDSW9tc60UXnj9/orgyagLOkg== - dependencies: - d3 "^3.5.6" - mkdirp "^0.5.1" - prop-types "^15.7.2" - react "^17.0.1" - react-dom "^17.0.1" +webpack-virtual-modules@^0.4.1: + version "0.4.6" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz#3e4008230731f1db078d9cb6f68baf8571182b45" + integrity sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA== -webpack@4, webpack@^4.41.5: +webpack@4: version "4.46.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== @@ -33188,7 +33647,7 @@ webpack@4, webpack@^4.41.5: watchpack "^1.7.4" webpack-sources "^1.4.1" -"webpack@>=4.43.0 <6.0.0", webpack@^5: +"webpack@>=4.43.0 <6.0.0", webpack@^5, webpack@^5.9.0, webpack@^5.95.0: version "5.96.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.1.tgz#3676d1626d8312b6b10d0c18cc049fba7ac01f0c" integrity sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA== @@ -33358,10 +33817,10 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== +wildcard@^2.0.0, wildcard@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== window-size@^0.1.4: version "0.1.4" @@ -33507,7 +33966,7 @@ ws@^7.3.1, ws@^7.4.2: resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@^8.18.0, ws@^8.2.3, ws@^8.4.2, ws@^8.9.0: +ws@^8.16.0, ws@^8.18.0, ws@^8.2.3, ws@^8.9.0: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== @@ -33805,6 +34264,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yocto-queue@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== + yoctocolors-cjs@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242"