diff --git a/.backportrc.json b/.backportrc.json index ea135907bd807..8c673a14a80da 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -3,6 +3,7 @@ "repoName": "kibana", "targetBranchChoices": [ "main", + "8.12", "8.11", "8.10", "8.9", @@ -48,7 +49,7 @@ "backport" ], "branchLabelMapping": { - "^v8.12.0$": "main", + "^v8.13.0$": "main", "^v(\\d+).(\\d+).\\d+$": "$1.$2" }, "autoMerge": true, diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 662ebbe522ebd..788bbc2df8d4e 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -307,6 +307,7 @@ enabled: - x-pack/test/functional/apps/ml/stack_management_jobs/config.ts - x-pack/test/functional/apps/monitoring/config.ts - x-pack/test/functional/apps/observability_log_explorer/config.ts + - x-pack/test/functional/apps/painless_lab/config.ts - x-pack/test/functional/apps/remote_clusters/config.ts - x-pack/test/functional/apps/reporting_management/config.ts - x-pack/test/functional/apps/rollup_job/config.ts diff --git a/.buildkite/pipelines/pull_request/cypress_burn.yml b/.buildkite/pipelines/pull_request/cypress_burn.yml index 20dc2fd7a13b9..e65659a6e038b 100644 --- a/.buildkite/pipelines/pull_request/cypress_burn.yml +++ b/.buildkite/pipelines/pull_request/cypress_burn.yml @@ -1,6 +1,6 @@ steps: - command: .buildkite/scripts/steps/functional/defend_workflows_burn.sh - label: 'Defend Workflows Cypress Tests, burning changed specs' + label: '[Soft fail] Defend Workflows Cypress Tests, burning changed specs' agents: queue: n2-4-virt depends_on: build @@ -11,7 +11,7 @@ steps: automatic: false - command: .buildkite/scripts/steps/functional/defend_workflows_serverless_burn.sh - label: 'Defend Workflows Cypress Tests on Serverless, burning changed specs' + label: '[Soft fail] Defend Workflows Cypress Tests on Serverless, burning changed specs' agents: queue: n2-4-virt depends_on: build @@ -22,7 +22,7 @@ steps: automatic: false - command: .buildkite/scripts/steps/functional/security_solution_burn.sh - label: 'Security Solution Cypress tests, burning changed specs' + label: '[Soft fail] Security Solution Cypress tests, burning changed specs' agents: queue: n2-4-spot depends_on: build @@ -33,7 +33,7 @@ steps: soft_fail: true - command: .buildkite/scripts/steps/functional/osquery_cypress_burn.sh - label: 'Osquery Cypress Tests, burning changed specs' + label: '[Soft fail] Osquery Cypress Tests, burning changed specs' agents: queue: n2-4-spot depends_on: build diff --git a/.buildkite/pull_requests.json b/.buildkite/pull_requests.json index ebe7bafe9f3d5..f8b255ccf78cc 100644 --- a/.buildkite/pull_requests.json +++ b/.buildkite/pull_requests.json @@ -13,8 +13,9 @@ "commit_status_context": "kibana-ci", "build_on_commit": true, "build_on_comment": true, - "trigger_comment_regex": "^(?:(?:buildkite\\W+)?(?:build|test)\\W+(?:this|it))", - "always_trigger_comment_regex": "^(?:(?:buildkite\\W+)?(?:build|test)\\W+(?:this|it))", + "build_drafts": false, + "trigger_comment_regex": "^(?:(?:buildkite\\W+)?(?:build|test)\\W+(?:this|it))|^\\/ci$", + "always_trigger_comment_regex": "^(?:(?:buildkite\\W+)?(?:build|test)\\W+(?:this|it))|^\\/ci$", "skip_ci_labels": ["skip-ci", "jenkins-ci"], "skip_target_branches": ["6.8", "7.11", "7.12"], "enable_skippable_commits": true, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ba5860f1bbe14..0cce7fe8e5568 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -56,6 +56,7 @@ packages/kbn-babel-register @elastic/kibana-operations packages/kbn-babel-transform @elastic/kibana-operations x-pack/plugins/banners @elastic/appex-sharedux packages/kbn-bazel-runner @elastic/kibana-operations +packages/kbn-bfetch-error @elastic/appex-sharedux examples/bfetch_explorer @elastic/appex-sharedux src/plugins/bfetch @elastic/appex-sharedux packages/kbn-calculate-auto @elastic/obs-ux-management-team @@ -650,6 +651,7 @@ x-pack/examples/screenshotting_example @elastic/appex-sharedux x-pack/plugins/screenshotting @elastic/kibana-reporting-services packages/kbn-search-api-panels @elastic/enterprise-search-frontend packages/kbn-search-connectors @elastic/enterprise-search-frontend +packages/kbn-search-errors @elastic/kibana-data-discovery examples/search_examples @elastic/kibana-data-discovery packages/kbn-search-index-documents @elastic/enterprise-search-frontend packages/kbn-search-response-warnings @elastic/kibana-data-discovery diff --git a/.i18nrc.json b/.i18nrc.json index 2869094e7e152..1af130820cd36 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -9,6 +9,7 @@ "apmOss": "src/plugins/apm_oss", "autocomplete": "packages/kbn-securitysolution-autocomplete/src", "bfetch": "src/plugins/bfetch", + "bfetchError": "packages/kbn-bfetch-error", "cases": ["packages/kbn-cases-components"], "cellActions": "packages/kbn-cell-actions", "charts": "src/plugins/charts", @@ -102,6 +103,7 @@ "share": "src/plugins/share", "sharedUXPackages": "packages/shared-ux", "searchApiPanels": "packages/kbn-search-api-panels/", + "searchErrors": "packages/kbn-search-errors", "searchIndexDocuments": "packages/kbn-search-index-documents", "searchResponseWarnings": "packages/kbn-search-response-warnings", "securitySolutionPackages": "x-pack/packages/security-solution", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 5d8edf115f9ca..6729551a6342f 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 90d281c4e9f4c..4ea1908461e56 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_observability.mdx b/api_docs/ai_assistant_management_observability.mdx index 99ead7eef17fe..32d0d431ded16 100644 --- a/api_docs/ai_assistant_management_observability.mdx +++ b/api_docs/ai_assistant_management_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementObservability title: "aiAssistantManagementObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementObservability plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementObservability'] --- import aiAssistantManagementObservabilityObj from './ai_assistant_management_observability.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index b9bc5d05c9b93..427f771d2dbad 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index faa3ba01ce406..fcc2a1d8e29d3 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 051f27903fcba..d1ddfd443baf0 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 7421f2fdbe837..cb2e8177677d4 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 04c54fdbb9bb0..8a7a7a251eb08 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 163804bf946e7..9b926af3bd426 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 5261ed8e4f2dd..10405b26dcf75 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 26f41ede6025a..57be9d35d890a 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 69db21ab19476..b07651e936154 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index afd1d4b2224b4..2cc277c821630 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index b7eb12534cfb7..c5e55314d96b6 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index cf5fe72bb4704..e2c25ad3cd335 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 94c53ca52b62e..23d056c2ce302 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 6d97a919cc3d8..80195a7c29fb1 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index f15c8b4270f47..c30bb5cd1af77 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 265f6f8dac133..d0a6cffd96bcb 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 2f2cbfcfcd667..1d6f786af3da1 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 45a736a118568..45c617bdb1dfa 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 4e36e5cd0c1f6..071268a678c9b 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 3335fa73bf47a..d0134cb132342 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index a6f8c9dbf1c6d..28d3684c1795e 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 440b8d60f512f..88f2b8718dd53 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index fb9e09b27683a..372c6e967a4bc 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index dc4f33df821d5..305cb4db12abd 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 82a534845b0fa..ee4ecbd575a8d 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index b4b56a66a34a5..26c5720325a5d 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index f614afa9369e0..691417d77569d 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 62430d70fd068..c0677deb889d0 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 139aff2ca7754..046df838498ae 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 914125c81886b..54d234be2c6d6 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 071b9494793ce..60d509f9a12f5 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index af1947c646d7f..68f845960e8f2 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -18,7 +18,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | ---------------|-----------|-----------| | | ml, stackAlerts | - | | | ruleRegistry, observability, ml, infra, monitoring, securitySolution, stackAlerts, synthetics, transform, uptime | - | -| | share, uiActions, guidedOnboarding, home, serverless, management, spaces, savedObjects, indexManagement, visualizations, controls, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, advancedSettings, exploratoryView, fleet, metricsDataAccess, licenseManagement, maps, dataVisualizer, ml, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, crossClusterReplication, enterpriseSearch, globalSearchBar, graph, grokdebugger, indexLifecycleManagement, infra, ingestPipelines, logstash, monitoring, observabilityOnboarding, osquery, devTools, painlessLab, remoteClusters, rollup, searchprofiler, newsfeed, securitySolution, snapshotRestore, synthetics, transform, upgradeAssistant, uptime, ux, watcher, cloudDataMigration, console, filesManagement, kibanaOverview, visDefaultEditor, expressionHeatmap, expressionLegacyMetricVis, expressionPartitionVis, expressionTagcloud, visTypeTable, visTypeTimelion, visTypeTimeseries, visTypeVega, visTypeVislib | - | +| | share, uiActions, guidedOnboarding, home, serverless, management, spaces, savedObjects, indexManagement, visualizations, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, advancedSettings, exploratoryView, fleet, metricsDataAccess, licenseManagement, maps, dataVisualizer, ml, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, crossClusterReplication, enterpriseSearch, globalSearchBar, graph, grokdebugger, indexLifecycleManagement, infra, ingestPipelines, logstash, monitoring, observabilityOnboarding, osquery, devTools, painlessLab, remoteClusters, rollup, searchprofiler, newsfeed, securitySolution, snapshotRestore, synthetics, transform, upgradeAssistant, uptime, ux, watcher, cloudDataMigration, console, filesManagement, kibanaOverview, visDefaultEditor, expressionHeatmap, expressionLegacyMetricVis, expressionPartitionVis, expressionTagcloud, visTypeTable, visTypeTimelion, visTypeTimeseries, visTypeVega, visTypeVislib | - | | | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, visualizations, aiops, ml, dataVisualizer, dashboardEnhanced, graph, lens, securitySolution, eventAnnotation, @kbn/core-saved-objects-browser-mocks | - | @@ -28,7 +28,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | dashboard, dataVisualizer, stackAlerts, expressionPartitionVis | - | | | stackAlerts, alerting, securitySolution, inputControlVis | - | | | triggersActionsUi | - | -| | inspector, data, savedObjects, runtimeFields, indexManagement, dataViewEditor, unifiedSearch, embeddable, visualizations, controls, dashboard, licensing, savedObjectsTagging, dataViewFieldEditor, lens, security, triggersActionsUi, cases, observabilityShared, advancedSettings, exploratoryView, fleet, telemetry, maps, banners, reporting, timelines, cloudSecurityPosture, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, uptime, cloudLinks, console, dataViewManagement, eventAnnotationListing, filesManagement, uiActions, visTypeVislib | - | +| | inspector, data, savedObjects, runtimeFields, indexManagement, dataViewEditor, unifiedSearch, embeddable, visualizations, dashboard, licensing, savedObjectsTagging, dataViewFieldEditor, lens, security, triggersActionsUi, cases, observabilityShared, advancedSettings, exploratoryView, fleet, telemetry, maps, banners, reporting, timelines, cloudSecurityPosture, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, uptime, cloudLinks, console, dataViewManagement, eventAnnotationListing, filesManagement, uiActions, visTypeVislib | - | | | @kbn/core, visualizations, triggersActionsUi, advancedSettings | - | | | observability, @kbn/securitysolution-data-table, securitySolution | - | | | monitoring | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 70feaef0dd13c..6c221f8e405d6 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -484,8 +484,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [open_add_data_control_flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx#:~:text=toMountPoint), [open_add_data_control_flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx#:~:text=toMountPoint), [open_edit_control_group_flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx#:~:text=toMountPoint), [open_edit_control_group_flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx#:~:text=toMountPoint), [edit_control_action.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/actions/edit_control_action.tsx#:~:text=toMountPoint), [edit_control_action.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/actions/edit_control_action.tsx#:~:text=toMountPoint) | - | -| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx#:~:text=KibanaThemeProvider), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx#:~:text=KibanaThemeProvider), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx#:~:text=KibanaThemeProvider), [range_slider_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx#:~:text=KibanaThemeProvider), [range_slider_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx#:~:text=KibanaThemeProvider), [range_slider_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx#:~:text=KibanaThemeProvider), [control_group_container.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx#:~:text=KibanaThemeProvider), [control_group_container.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx#:~:text=KibanaThemeProvider), [control_group_container.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx#:~:text=KibanaThemeProvider), [time_slider_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx#:~:text=KibanaThemeProvider)+ 2 more | - | | | [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [options_list_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/options_list/options_list_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [range_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/range_slider/range_slider_persistable_state.ts#:~:text=SavedObjectReference), [time_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/time_slider/time_slider_persistable_state.ts#:~:text=SavedObjectReference), [time_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/time_slider/time_slider_persistable_state.ts#:~:text=SavedObjectReference), [time_slider_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/time_slider/time_slider_persistable_state.ts#:~:text=SavedObjectReference), [control_group_persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/common/control_group/control_group_persistable_state.ts#:~:text=SavedObjectReference)+ 2 more | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 1034f7d7a7913..1947c8fe6e20d 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 09a928cf60480..d1aa270bd8261 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 82b7eaaa113b5..2da6fbce53210 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index db477e06bc2ca..68c2929f3cf10 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 165de38235513..b524857396558 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index fa5e7b37b54cd..42c88ecc800be 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 9cd4ba6b861bf..21fc416f58388 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 920d942760938..217876c63a06f 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 267a10395a001..f23a0ff794e1b 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index aa6d18edb850e..bc72f744050f7 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index c574ee0bd4b23..ced26f3c33230 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index a1cdfae4cc8b8..469fe1017e538 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 400cf4f60baa5..5b7feefd74a7e 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index cad5c55189d3a..55f4cd2b47aed 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 4ff160e9bac43..51e02c64905a3 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index cfcc84223e7d2..be7e7a3dbb45c 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 5645468112e68..2f4770825b858 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 9a356e1c44ae8..b2c668dbd23d0 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index cb2404b25d172..e506bd1226c21 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index dfabf1c7600be..5683557ef766b 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 48bae08fb0dac..0f543ba997773 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 86443fa86b713..f4ad9e9cadcab 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 77c66a111e8c9..710a5186fddbf 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 985a84c89e9aa..99caac9c64df0 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index f17f44938cd61..c7bf1942fe83a 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 89006a1fc5e71..8e6e21a45e3cc 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index d152fd3d33e51..e2e793375e6ac 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index f08db602f77a7..d7e0209e36a5f 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index f005e710d9047..c5cd1c9ab35a7 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 2cf8a8dcc9e62..6fba5e391f66c 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index aa2c080a0101d..ff6a2fb085044 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index f07e0ba16937c..c58caac8ebdad 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 477297b1e424a..8c18aded00e1a 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index fd3593edfabdd..034a41cb43622 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 655dc0fc6fb41..4120272c20605 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 6c78f3b021631..a525ab8925586 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 132f0a719b81b..186e3389c89f1 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index f7a7cb9902051..bc0e89d32db64 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 89690b050449e..cf7218d19a33f 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 1d44292f093c8..6193ef343c1a9 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 50160805079ef..65d46c86d6837 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index e5518f72e6b60..48765721c2066 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 0ee4cd9ca8007..7f50ee6f36b23 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 282c9446b8891..1f2dab6b2cd95 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 05607b208d333..d9bba9990128e 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index 21262556ffd87..12366cbe61374 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index debe7b20aa1aa..9989367583833 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index b1028674a5561..8af936205f92a 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 9137920b999a3..9fc630743f3e7 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 73ae31061984d..5cecf6ef26877 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index 8858014b04c5f..e9486f8e755d0 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 3101ea6e7c868..3d1b783cb46a5 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 0f7475abc1fb0..cc2027bd867d7 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index b3751189f89e2..4838d9f52cd47 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 5379de10291c0..f3624a2d6d53b 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 370405df86446..108c51d06c621 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index c053c77554d70..09c2c983afc16 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 54e3c6c9c539c..d1ffbc80df85b 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 1b71efe4cce60..cfd55dfe7ffbb 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 4cd88cec4af67..73a0ebc5c3852 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 9ab1f3cdef257..b154f5d2ee476 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 46bd4b704b386..9f32a3cf39d0b 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 5a2fe2f2fefcd..93fb26924273e 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 7aef74b4d15ec..d7802c05f7e7e 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 096137b9f5ce4..ba2436348cc40 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index ab48174ca30d0..2effc54fd78e4 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 4ff354dd1e20f..b3b70f12ed5b3 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index cbabc1173c3a0..c5e45de010738 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index b74b8f94b53a9..a7dec4e5d4b92 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 9e85ce298e587..b324306f2fe68 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 41cdf516f4fd4..af9a07c45f49e 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 8c23ffb69af13..d226abe03ead6 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 3eb427b361b09..442f09454123d 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 22c462a6c2018..5f9d3022f659a 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index e65678bfbd35f..be2f06ef7536e 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 90e87e16d7d30..dfd3bf7729e7f 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index eb972cc57df2e..18d14d43e6849 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index e940dd0667d29..73de484ebebfc 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 0267f57d22b9f..3b190cec70608 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 86a81e2b71960..3f567d33cb80b 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index e6b40f8507189..e9bae2295ce6b 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 97ff80736e880..b1154f0077004 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index 42b5a7ce37cb3..b2cfba656d013 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 8651ad44b48cc..ffcbb478faf68 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index 0be2448f504e1..95a4d6a3b18d0 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 1964efd6114bc..1b3c94e60a094 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index da007d191fa08..67e894a919116 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index b86612fb8626b..249562b44e7a3 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 5231fbaadca4f..e9469d0ba49da 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 663a289a6e7f5..026662072f7f5 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index a87d828b924aa..3a93aefbd4a88 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 7f5aa7aaa0fe5..5cda9bb5d57aa 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 504ca839536f5..6950db835d0ef 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 19e49f4da7854..aec3bb9aaf17a 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 4ee035a7594f4..556db7cbd8804 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 11aa675d199ef..3f9ef95ec5f86 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 50b8c06dda953..ef0e1f0faafbb 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 523cde31fc56a..f30e34b0e835a 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 5fd341162deec..cb863f1a665fc 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0ff2ab9bf084a..461f120229577 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 26e63c9c17e3a..642bada91e9ec 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index f187c130a62b3..1656c7c8eaeab 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 45632ba18b9e6..cd0587aa40fc2 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 864b0bdf57857..ea233dbcb3e37 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 37a6bf7845045..5923fba60c62f 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index bfb9d035bb790..f730d74034ee6 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 40d9f9e6368fe..94d38b07e42b3 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 9ac899caf71a4..8cd4d4bf87d79 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 627c34aa6fb17..c6c96512d7c75 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 950e81978cfa1..07d38e561a7ca 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 1d1c6caa33995..707f790a3f190 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index e684e7a01f1a8..d159a2bd15d9a 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 49f1143b6a82b..af053a313dfc4 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 2cbdc9890009f..55f2ccc230a98 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 0c6ac2cf616d7..7e68a8aec7ab7 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 1f0faca4dd57a..45713f69c5a07 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 043bee2652309..4c37efa741850 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index cecbb55733665..827cf0e9b38b9 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 4a4b1f07bfb8c..e9a6de69bac2a 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 4310ffed62a01..4cd3a8f094ec3 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 21b71099e025f..eae43f1b90a3f 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 2ff0e55b7e3eb..6c47073a10efd 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 3535b1c50d843..765a1d5a0ea72 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 72b7114e4ef1b..55bc6963cc249 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index f3389336a82c7..e3398043f5adb 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 76f4c1415308a..214127c65ef7c 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 483dfadbd8d95..4dd98e68f79fb 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index e711f85c5787e..bb89310024cfc 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 28235ee0b99da..64a1d6c8d5896 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 90019f4174845..15f36b29c405e 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index c4ea467aa0abd..2b685c8e48da0 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 0ade916bd5131..cda4d5103274a 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 94bc521deeb93..009b3e80f4252 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 686f601c54af0..28f3fd2fac113 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index ccb44858f6833..991a65190d372 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 4f2891607d3ec..00c952d5762d3 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 26f455dcd4b32..5e3b5505412c6 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 45834d91eb5ca..d53a46624bb5a 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 4a62f202dbcd7..4c00defb0d556 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 6de88713e550d..31cd127240bab 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 9a389d1a54052..dd1b2c296e2ea 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index f47a9e58365f9..9ef7068d7508a 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 1807609122c7b..83c86c420743f 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 0f7ef6bc3e217..736d2f7c61673 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index aa34df5522543..c56929401b80d 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 59c1ad8d0e421..1d7f4e8963a52 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 1c2545ccaf4ad..490f057692837 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 967875f54e4f6..ea1a5d90addcb 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 6ad6e6f1339f5..6e2d93be61544 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 014aacf3cb650..efd1ad2207963 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index a74e17d699b05..7e765f58d5f8f 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 18d6ac89cddb2..6712cafe0adad 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 89960047bc769..6934a6ecfc054 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 8592794e84a80..06f2fb99d26b1 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 4a5f8a6ee68f2..4ee7528e6d0ec 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index a63ad17c6b934..a141d0ae309b4 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index 7269ea03eab1d..9683019a1823f 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -13677,6 +13677,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/privileges.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 289ad233ee67a..633bfd097faea 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 42f77ee79a73c..79cd1d94de9e9 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 006e2f7ff80cb..4cf341dd70cf2 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 8adfd198cb3cd..184cdb7c3a02b 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index f6254599c9b51..32832ae9270bc 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 187a4a8f01291..3c20f88b2dd11 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 8eae2dd6101a4..bfed5d8dd6444 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index f9b64a8ebc920..9353bf834efab 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 8029f50064266..98c1a3f59cb74 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 06d8a551056ee..2ce8c9dec7c5e 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 7f7e7c54b35ff..71a9981804c59 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 159366e24880a..97e3963df32d4 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index c3bbf04503213..df4462a68808c 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index d074cf9bd8ab5..6a28798c80aa8 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index 2eee201f8a935..1d8055895d75e 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 813c22b2d0f6b..b470874d1b247 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 0ab02fce28f97..b2fcde8a3fdaa 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index e4e8d277b28a0..8711122ae9a34 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index ac350f2d2da77..f684ce60399ae 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 8e0cf90b5bb79..6cece0a97c58d 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index b49e32449333d..0a6c50efc4b4c 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index d4c20e05d85b4..d51b093b1a4e7 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 7ccc1521887dc..57760e89a2d67 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 1c7128135a509..f8dbf0626def6 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index c00c179b0dec1..1eab49efc39b0 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 56354c13cd9cf..6a8021ba4d4c5 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index b76d95428b49f..ce456a9754dab 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 972fe030f8801..5184912a097d3 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index aaca0da559192..4439cc994907b 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index dad921a5a4f91..7ca390ff4afff 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 3aa7e3c4d6edc..b4443447e5e7e 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 590c64b31d2f1..39e3df3a51fc3 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index ee25fdb41e4e0..055e984b06c59 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 8632b2077520b..c658a2531e65d 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index cc0b53072a31f..c2ea1d001b960 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index c88dd187b402f..29c0bc19c043a 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 24654422cb36b..f46c53f9012dd 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index 8c3ac574c4983..d1a3ebcc5867a 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index c257dfdf2c3d7..46c2ac51dfde9 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index fc8273b259461..98214f94ba24c 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index d4bc54fa35e1d..2fbe838aa133d 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 5af3564d717ac..0526fac06a296 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 78022ff59ea90..f21023d7e35e2 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index a7a3ad38a2eae..dad2f09b2292c 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index c93e739c9c835..eea3a818205ce 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 378237fc12355..4ac3d8ee8de84 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 8cdd740695be2..3aa6ec5b119c3 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index edf41b5bf1d36..a6fb043736b36 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 532353dcd5d9c..7d83defe41a32 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index b497a27a4f659..30fb98fab7e1b 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index ab83d16639899..c51686553683f 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 5b5891b3871db..a62f49429cd11 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index bd45ae92a4372..785043f261b94 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 1d018d5189aaa..1873a2d1be89d 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index a148c06a70566..36abfdc2f9905 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 76c4f239a1711..8b0c6ed3f1b56 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 887fb99d53fb1..6566fab58e8ff 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 4114bc242151f..d526c4efad867 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index f85fc0a17bbce..fad9b797165a8 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index b26b175d9e7b4..fc778f45cf019 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index ec6d429102cc3..81aefd634ca88 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index ba0fc2625e733..0c152a236e68f 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 825dd41eb3e45..86e09402c0e22 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index b306fe34bad3a..c6e2dfe425bb3 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 736ae44b7cf5e..05cbe602e6eb9 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index a22cbc3996c19..08127cdf0d3ff 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 770e11254d5ad..79581cb6401ae 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index d08d25ab0af65..20918d15ce2bc 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 186bbc75bdfd7..3417204823ca4 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index fb90c0de54212..0ddf7fbba9714 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 89e8534c52608..3ad66a60adfbd 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 8c5c13b2e299c..38d8af7de5c97 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index 64c9cd0b69890..f10a69fbb62f5 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index ca19d2b4aae61..a1cb48b952c0a 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 7e4fda9109c66..e244c6916ff47 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index c9c5b8c691e50..f7a60ab489ce9 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 6d545e224a912..5c3615937762c 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index b6c5bc787ea2d..979b7a41b5d40 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 15b921c751934..980c15943ee60 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 59fe3e2baa211..bccccf1efc3ee 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 8e2da2c987d2a..3e2cf9eec123e 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 3b5988b9f038e..a7b60eb4c1ced 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index cc360a075dd0c..7ea6e0531ec3e 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 31f31f84f8182..f077a6d09b562 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 31ccc8b6dc9ce..8e26a337aa960 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 0d9fd4d75e2f3..2cc80fe28e28b 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 83634bea48d9b..4c5a748021846 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index aba65548ae33e..ce090187ce605 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_internal.mdx b/api_docs/kbn_core_user_settings_server_internal.mdx index 4fd14aef7ebc3..bdc715979d2b2 100644 --- a/api_docs/kbn_core_user_settings_server_internal.mdx +++ b/api_docs/kbn_core_user_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-internal title: "@kbn/core-user-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-internal plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-internal'] --- import kbnCoreUserSettingsServerInternalObj from './kbn_core_user_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index b098381d6e61b..9101074957060 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index ea735a65db460..7045156b8ef83 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 6478681e16f4f..497e154033cc4 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index 827cf426e0ac1..ca06a58a2b1bd 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 179ca7a031295..e68ea5623f8ca 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 5d384ceca36f8..d47abe2484419 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 21d45f5ea757f..f4e64334019eb 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 358a437ffe2c9..700b1c8a11c13 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index 3ba32bf99b1bf..568997040386c 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index f4d5df6045426..13d4046d8da2d 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index e18e7fc4c02b6..023ccb08c0e2b 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 5bac356eaac98..e47d50138d26e 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 4b545c5fed8d7..abedc2d1e19ec 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 784dd1ef28d8e..b6ce281b16fbe 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index dfe5cb5d17531..39608ed98eb36 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 1657b4bf2e811..56458b8f4c335 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index c2d1e334fab0a..c84a4851f4a1c 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 961b67847c595..e6d34af760e77 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 9e31040426108..9c0e1166ca0b1 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index c5a9900c27a9e..61f369ec0a0d1 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 9412574e49ec6..ba864857bc765 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 4c934cbad51d9..6237e74a35376 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 139f393095cc3..1805068ebc0a7 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 02288652f6d70..0ed984fb9f7f0 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 0149076fa9bb7..6f3c79c07d6b8 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index a44e98f40d55f..13f735b925da8 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 695da72403d05..5f6faef43baae 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index fe019478b9ee0..21a86b2225ee7 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 0af210660c732..bb3efc83e0b0b 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index c5192b5d7b660..2ba77976da1d2 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.devdocs.json b/api_docs/kbn_elastic_assistant.devdocs.json index e0d5da4f61278..8b855265a22ca 100644 --- a/api_docs/kbn_elastic_assistant.devdocs.json +++ b/api_docs/kbn_elastic_assistant.devdocs.json @@ -159,7 +159,7 @@ "label": "AssistantProvider", "description": [], "signature": [ - "({ actionTypeRegistry, assistantAvailability, assistantStreamingEnabled, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePath, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, modelEvaluatorEnabled, nameSpace, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, }: React.PropsWithChildren<", + "({ actionTypeRegistry, alertsIndexPattern, assistantAvailability, assistantStreamingEnabled, assistantTelemetry, augmentMessageCodeBlocks, baseAllow, baseAllowReplacement, defaultAllow, defaultAllowReplacement, docLinks, basePath, basePromptContexts, baseQuickPrompts, baseSystemPrompts, children, getComments, http, getInitialConversations, modelEvaluatorEnabled, nameSpace, ragOnAlerts, setConversations, setDefaultAllow, setDefaultAllowReplacement, title, toasts, }: React.PropsWithChildren<", "AssistantProviderProps", ">) => JSX.Element" ], @@ -172,7 +172,7 @@ "id": "def-public.AssistantProvider.$1", "type": "CompoundType", "tags": [], - "label": "{\n actionTypeRegistry,\n assistantAvailability,\n assistantStreamingEnabled = false,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePath,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n modelEvaluatorEnabled = false,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n}", + "label": "{\n actionTypeRegistry,\n alertsIndexPattern,\n assistantAvailability,\n assistantStreamingEnabled = false,\n assistantTelemetry,\n augmentMessageCodeBlocks,\n baseAllow,\n baseAllowReplacement,\n defaultAllow,\n defaultAllowReplacement,\n docLinks,\n basePath,\n basePromptContexts = [],\n baseQuickPrompts = [],\n baseSystemPrompts = BASE_SYSTEM_PROMPTS,\n children,\n getComments,\n http,\n getInitialConversations,\n modelEvaluatorEnabled = false,\n nameSpace = DEFAULT_ASSISTANT_NAMESPACE,\n ragOnAlerts = false,\n setConversations,\n setDefaultAllow,\n setDefaultAllowReplacement,\n title = DEFAULT_ASSISTANT_TITLE,\n toasts,\n}", "description": [], "signature": [ "React.PropsWithChildren<", @@ -970,6 +970,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/elastic-assistant", + "id": "def-public.Message.replacements", + "type": "Object", + "tags": [], + "label": "replacements", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/packages/kbn-elastic-assistant/impl/assistant_context/types.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/elastic-assistant", "id": "def-public.Message.content", diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index c5a9a4b849562..df94e38c01ee2 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/secur | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 97 | 0 | 77 | 6 | +| 98 | 0 | 78 | 6 | ## Client diff --git a/api_docs/kbn_elastic_assistant_common.devdocs.json b/api_docs/kbn_elastic_assistant_common.devdocs.json new file mode 100644 index 0000000000000..61136c90e37b6 --- /dev/null +++ b/api_docs/kbn_elastic_assistant_common.devdocs.json @@ -0,0 +1,459 @@ +{ + "id": "@kbn/elastic-assistant-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getAnonymizedValue", + "type": "Function", + "tags": [], + "label": "getAnonymizedValue", + "description": [], + "signature": [ + "({ currentReplacements, rawValue, }: { currentReplacements: Record | undefined; rawValue: string; }) => string" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/get_anonymized_value/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getAnonymizedValue.$1", + "type": "Object", + "tags": [], + "label": "{\n currentReplacements,\n rawValue,\n}", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/get_anonymized_value/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getAnonymizedValue.$1.currentReplacements", + "type": "Object", + "tags": [], + "label": "currentReplacements", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/get_anonymized_value/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getAnonymizedValue.$1.rawValue", + "type": "string", + "tags": [], + "label": "rawValue", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/get_anonymized_value/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getIsDataAnonymizable", + "type": "Function", + "tags": [], + "label": "getIsDataAnonymizable", + "description": [], + "signature": [ + "(rawData: string | Record) => boolean" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.getIsDataAnonymizable.$1", + "type": "CompoundType", + "tags": [], + "label": "rawData", + "description": [], + "signature": [ + "string | Record" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAllowed", + "type": "Function", + "tags": [], + "label": "isAllowed", + "description": [], + "signature": [ + "({ allowSet, field }: { allowSet: Set; field: string; }) => boolean" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAllowed.$1", + "type": "Object", + "tags": [], + "label": "{ allowSet, field }", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAllowed.$1.allowSet", + "type": "Object", + "tags": [], + "label": "allowSet", + "description": [], + "signature": [ + "Set" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAllowed.$1.field", + "type": "string", + "tags": [], + "label": "field", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAnonymized", + "type": "Function", + "tags": [], + "label": "isAnonymized", + "description": [], + "signature": [ + "({ allowReplacementSet, field, }: { allowReplacementSet: Set; field: string; }) => boolean" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAnonymized.$1", + "type": "Object", + "tags": [], + "label": "{\n allowReplacementSet,\n field,\n}", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAnonymized.$1.allowReplacementSet", + "type": "Object", + "tags": [], + "label": "allowReplacementSet", + "description": [], + "signature": [ + "Set" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isAnonymized.$1.field", + "type": "string", + "tags": [], + "label": "field", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isDenied", + "type": "Function", + "tags": [], + "label": "isDenied", + "description": [], + "signature": [ + "({ allowSet, field }: { allowSet: Set; field: string; }) => boolean" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isDenied.$1", + "type": "Object", + "tags": [], + "label": "{ allowSet, field }", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isDenied.$1.allowSet", + "type": "Object", + "tags": [], + "label": "allowSet", + "description": [], + "signature": [ + "Set" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.isDenied.$1.field", + "type": "string", + "tags": [], + "label": "field", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/helpers/index.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData", + "type": "Function", + "tags": [], + "label": "transformRawData", + "description": [], + "signature": [ + "({ allow, allowReplacement, currentReplacements, getAnonymizedValue, onNewReplacements, rawData, }: { allow: string[]; allowReplacement: string[]; currentReplacements: Record | undefined; getAnonymizedValue: ({ currentReplacements, rawValue, }: { currentReplacements: Record | undefined; rawValue: string; }) => string; onNewReplacements?: ((replacements: Record) => void) | undefined; rawData: string | Record; }) => string" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1", + "type": "Object", + "tags": [], + "label": "{\n allow,\n allowReplacement,\n currentReplacements,\n getAnonymizedValue,\n onNewReplacements,\n rawData,\n}", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.allow", + "type": "Array", + "tags": [], + "label": "allow", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.allowReplacement", + "type": "Array", + "tags": [], + "label": "allowReplacement", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.currentReplacements", + "type": "Object", + "tags": [], + "label": "currentReplacements", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.getAnonymizedValue", + "type": "Function", + "tags": [], + "label": "getAnonymizedValue", + "description": [], + "signature": [ + "({ currentReplacements, rawValue, }: { currentReplacements: Record | undefined; rawValue: string; }) => string" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.getAnonymizedValue.$1", + "type": "Object", + "tags": [], + "label": "{\n currentReplacements,\n rawValue,\n }", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.getAnonymizedValue.$1.currentReplacements", + "type": "Object", + "tags": [], + "label": "currentReplacements", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.getAnonymizedValue.$1.rawValue", + "type": "string", + "tags": [], + "label": "rawValue", + "description": [], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.onNewReplacements", + "type": "Function", + "tags": [], + "label": "onNewReplacements", + "description": [], + "signature": [ + "((replacements: Record) => void) | undefined" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.onNewReplacements.$1", + "type": "Object", + "tags": [], + "label": "replacements", + "description": [], + "signature": [ + "Record" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.transformRawData.$1.rawData", + "type": "CompoundType", + "tags": [], + "label": "rawData", + "description": [], + "signature": [ + "string | Record" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/data_anonymization/transform_raw_data/index.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx new file mode 100644 index 0000000000000..5d1982f8c7178 --- /dev/null +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnElasticAssistantCommonPluginApi +slug: /kibana-dev-docs/api/kbn-elastic-assistant-common +title: "@kbn/elastic-assistant-common" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/elastic-assistant-common plugin +date: 2023-12-07 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] +--- +import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; + + + +Contact [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 30 | 0 | 30 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index b3d931abdc13c..41278c9132687 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 1105b63d38238..736610abb33fc 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 60fbe00eba920..7819d34003939 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 7a16bba0fdc74..d9fc2c1753101 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 10848b0c5a95f..65ec23ee8ecd3 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 0ec2f9a16e53a..0f99a2863d0d3 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 607707da0611d..17bbf1a064628 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index a85d588fc531a..648c3a5b81f3c 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 77c61336b9c8b..2f71884625498 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index cfbe2477e7332..0183827284624 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 51bd26fcff794..24523c062236a 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 66f50048c137d..c446a680b20ec 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index d9a99b30c002a..e89e4566419c5 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b235635e152a3..907d5e78bfe61 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 9923a9648641a..eb3516efc11a2 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 10d98dc458223..1c7a114ef9810 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index d455ed35fcd8c..09737dee66a4a 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 58507c7ae78fd..e2bf407da0479 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 9a9e28c6be19e..22907693b064d 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 8a409375c7574..24c2b3b53f8b5 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 8c01bd91e00b2..e6ee2a1ff8a1b 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index c3032d3696953..d9e4daab4ecfa 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 0f084b08e4b12..4c4d59dd88a1e 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 563ca5456858c..517c78573e147 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 1f9429f181a5e..a9d5f1a84f854 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 7deecaf572e35..e475ac57b60f4 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 21a1140054461..bbbfe28701c2c 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 63926835c6a1d..6e4a029c47ff9 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index e54269fe5f369..b4527a00d808d 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index db6edfb40d24e..fbfe157e4b0b1 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 88314c7bdf245..0f5c370967c78 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 6527ab3fb2ff9..11f58e84f5955 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 417c0b4cc0d94..fb11b8173d3fb 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index b246a370cb081..ea7908030248a 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 569ecac3545a8..0c9133636ff48 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 0a6c2e1127eb0..f1a07f4e2b828 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index de702c06e673b..0e6d182fdc72e 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 1b1f634d51a4f..c814c8115555e 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index 629470fdf81e5..6501316481aca 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index dacbff8b9bffc..9796ad3b98b67 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 022808c37e0a8..333e19ffc2c54 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 6f8b36f2a2cb0..6951ecf0cd4e8 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 5f084177eb05f..79aa98838b9b9 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index 9056f8f0388e9..333a8a4a428b3 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 295602bc30032..362509f17cb86 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index f2d9579db11f8..0af6ffb073ad7 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index c196246928dd3..3db022d770179 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index b350aa5a253f3..2b1c83278f97b 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 5e3d524ca77c8..2e51ebd2f7b14 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 8df9159e606df..fb6a4d70ad0e3 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index 32dba348a6dc7..ad38c80338064 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 94d2d5f96b435..d7e8917e7cb71 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index c9989a723995e..4a5640b0d50e2 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index 599108b3a6a47..6ba4ac0b244e8 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index 3626455766411..22a25c0d770cd 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index 35615577a1b53..c734657c7a0c0 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index 0f553e6dc5890..c59b60246312c 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index f0271376a2c51..6333eb0e01947 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index e7f552f209df0..fcd3b8b420b01 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index f5699159196c1..a15f13d0fcb30 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 104d279c2973e..9654e920f5c56 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index 114cb70ecf0cf..5221b006b02c9 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index c6d7efc40755b..4079f0844b301 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index 3d1b321f8a744..c0ef5a71f351f 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 81784d60b2cc7..20d9d87296c7a 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 5964131ccd30c..a1a104d58207e 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 620237f3797eb..0ff1b755c6a42 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 00afc0f576c4c..fd7b16039727e 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index 5f8c886ebc307..e27930b569f15 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index 9ddb57988c8a5..28a827d468051 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index 6f44576089296..296e4ff55038b 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 82e18313c7c03..c5d5f0f521317 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index f5a253ff34d6d..8fa25142f3fc2 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 3ab9e935785c4..164431b638ff7 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 8274ea596bfa3..ae2b20683e1f5 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 1bacd69685bec..c57fbc1afe8c5 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 7c496eb0f1da5..0c2aa4ab235f2 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index a144e56d5d425..56e1a1f683ff1 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index a7d649ca97d61..9debb127f01b7 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 234916630b450..9c954ad046a18 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index f311c93319993..795d9acd2a219 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 19e9796495a2b..76b009ee74b9d 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index e305b2393987b..5fa0d5f5166a8 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 2af4c4eb061cf..e815cc9d6e6c4 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index fb344e1e64422..48f5f6982cd96 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 71658fa40b4c4..67c55f8ffee8d 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 43a166b020c3b..f3ae65d55d24a 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index fa880a54ec12b..130d080e8d31a 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 37932047ce1a6..a520958749463 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index a9a3c2b42a7e5..d3931cc20f6d7 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 23c1b2f8fe5dd..2efc15e8ada72 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 575e46d3876d1..988041a4438bb 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 0ee4bc75b7ca1..ae4ffea7f54fa 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index a940e2c6ae5b6..ac7d7c94d44cc 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 58ab11c8c1aaf..32cefa410d91c 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 5a4ff328e101e..1a476c29be31d 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 5f8c7b6013132..b1cd010ca242b 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index 6a18539c11112..b17667f4b84e8 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 4345e76e8afac..d140c646c2f3a 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 43ad35f4b1c6c..189b3f87ec3bc 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 5a83db86a7165..d81e0587a5f29 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 7da9101e0b4d5..98fbab1f767eb 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 064fe89454af4..6691d0fd6882f 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index e15e4333b7af4..c2b6dfa7d569a 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.devdocs.json b/api_docs/kbn_reporting_export_types_csv_common.devdocs.json index 4e6ff0c91e22c..b8e38bafbb458 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.devdocs.json +++ b/api_docs/kbn_reporting_export_types_csv_common.devdocs.json @@ -18,7 +18,94 @@ }, "common": { "classes": [], - "functions": [], + "functions": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.getQueryFromCsvJob", + "type": "Function", + "tags": [], + "label": "getQueryFromCsvJob", + "description": [ + "\nA utility to get the query from a CSV reporting job to inspect or analyze" + ], + "signature": [ + "(searchSource: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.ISearchSource", + "text": "ISearchSource" + }, + ", { scroll: config }: CsvConfigType, pitId?: string | undefined) => ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.QueryInspection", + "text": "QueryInspection" + } + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.getQueryFromCsvJob.$1", + "type": "Object", + "tags": [], + "label": "searchSource", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.ISearchSource", + "text": "ISearchSource" + } + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.getQueryFromCsvJob.$2", + "type": "Object", + "tags": [], + "label": "{ scroll: config }", + "description": [], + "signature": [ + "CsvConfigType" + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.getQueryFromCsvJob.$3", + "type": "string", + "tags": [], + "label": "pitId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], "interfaces": [ { "parentPluginId": "@kbn/reporting-export-types-csv-common", @@ -161,6 +248,36 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.QueryInspection", + "type": "Interface", + "tags": [], + "label": "QueryInspection", + "description": [ + "\nType to wrap the untyped object returned when\ngetting the query from SearchSource service" + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.QueryInspection.requestBody", + "type": "Object", + "tags": [], + "label": "requestBody", + "description": [], + "signature": [ + "SearchRequest" + ], + "path": "packages/kbn-reporting/export_types/csv_common/lib/get_query_from_job.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false } ], "enums": [], diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index 711a8a6ee756a..4637620bd653d 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 17 | 0 | 16 | 0 | +| 23 | 0 | 20 | 0 | ## Common +### Functions + + ### Interfaces diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 97c4aa3b59cc3..a50466424d4a0 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index ac70e46fa81bd..c0e988cf69964 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index cd3d83654cdd4..aee67186f6236 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index f600c6294d23b..7b7b4894b67aa 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index c75e4401b50c9..fada92cda6b6a 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.devdocs.json b/api_docs/kbn_reporting_public.devdocs.json index 5acb381f4e2a3..c41f423ba40c9 100644 --- a/api_docs/kbn_reporting_public.devdocs.json +++ b/api_docs/kbn_reporting_public.devdocs.json @@ -15,6 +15,20 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType.csv", + "type": "Object", + "tags": [], + "label": "csv", + "description": [], + "signature": [ + "{ scroll: { duration: string; size: number; }; }" + ], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/reporting-public", "id": "def-public.ClientConfigType.poll", diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index ded37cb4226c2..477132374a9bb 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 5 | 0 | 5 | 0 | +| 6 | 0 | 6 | 0 | ## Client diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index b78fd5dcacd8b..c3a777fbe744c 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 2dc3fb5964f35..2638346beb5bc 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index e1a7f6be5ea32..cab3574759034 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index e5b4e5f0d5f64..f402d0fc701bc 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index e299c8ffaf9fe..ecea2e8e31148 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 70c0939504f5b..35c311767e1b3 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index fd345773a7927..ef37a3d5b13b1 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index e6c9aa8222a5c..389f9f6ec52d0 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 449e828cc7a36..26df1846b7e78 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index b64bec1fe94ab..e753d346affd2 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 5cc0b256138b2..e98546e72e745 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 77936bae34bd7..e3403a01916ae 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index 0e8518910830a..c449f9e23a082 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 9acb2c9f27b96..f57ce87bd21f8 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index 714e77a74e0f9..c6d10064e662b 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index 111c64f6fee50..50e055d8b3f43 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index eb11bf6db7ad8..a031a42f3c36b 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 4671d3148d551..e859422cb9f08 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index c264ee94136aa..143e6c8fab95d 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 9e3fb696f7528..6a65a8c5524d0 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 826c61fedd9ee..961ec3dc18346 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 52146e6c49e52..dff51dc5933ef 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_grouping.mdx b/api_docs/kbn_securitysolution_grouping.mdx index deae59a654e2c..64f9f4bc9dae5 100644 --- a/api_docs/kbn_securitysolution_grouping.mdx +++ b/api_docs/kbn_securitysolution_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-grouping title: "@kbn/securitysolution-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-grouping plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-grouping'] --- import kbnSecuritysolutionGroupingObj from './kbn_securitysolution_grouping.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 8a1af33e073f5..0b0dbc429e2f3 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 2a49be0f4f2b3..a25dc2ee43cb7 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 9d3f2ef24d493..e37c4faec5ad3 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 73c112557e1fc..36a36de62fb5f 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index d7875f5769e72..9557e4e0952fe 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index b0a099ea60b80..c5e21afcc1aa4 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 86cb498c094f4..5e63ef926c52f 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 29e29c53fbe6d..fad4110c03fad 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 83afc19633ad9..fcb7359039d67 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index ac206a38e7b45..4359ca8c050a4 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 83648b6f409c8..15115a1b7c0a9 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 9583ecf805ba1..d9a25cf03a04f 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 9d55f551dda86..0c1d777afe8b8 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index f207367e9f1af..b797cad787604 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index ccf54e481e2ea..5a119483ea794 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 7a46e3996179d..014f498b2f55b 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 379c1a0264ef3..d747504339e5a 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 55d7c1c36fcea..1cc6e1339eb5e 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 4a016b01805af..2a59730bf71b7 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index b1a25f7f9f5ba..1d51c49628037 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 8de4e73655633..66712b110e8da 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 824718ab8870c..d7aa6330f7769 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index e2a8fdb5a0acd..e3cb89056113d 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 359360468a0b0..143dca4ace6b7 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 3d00a164bbebb..d4618344a3773 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 448fb42244833..3dd22cf7018ac 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index e2cb1623d9351..afe8181fe369e 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index da4f4dee73d4c..94f93747b9813 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 91b53a19414c6..2885c7340fd9b 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 57bcb6db7c00e..5d5fb20395c73 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index a89f9b6168646..5cf0ac04a741a 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 36a43fd080ee6..bd0f2e94a6d04 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 24eb90138942a..df9e06f66cee7 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index d29c1e094402a..ad3dbbe9b4266 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 97f4d57b2f4e7..b6779b3a30c9c 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 982b0ca363ad8..8f252359c70cd 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 44e0bc1442def..6f0f34cc3a2b0 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index d746d3ae04de9..ff831e7d31142 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 0ee8ca4d679ca..ef43807e0f9ac 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 5f5ca77450bcc..6820bd75637d2 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index eb8c7a80f3c06..916608c4c9af1 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 0410276deb996..86d756e7fb3e7 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 8e3e0a30d34bb..1a10c8f36bc10 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index bef1c329d7b0c..50c1b14112ee8 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index aab1a0956c2a3..0a99e84de5c73 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 010c91168162c..026c17029dd76 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 6a9623da18f56..52b6831c22e57 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 01884de12cf2d..3cf9aeba0cd30 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index b2f0d7208fbde..3601e6a2d7efb 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 7804db88c1abb..b4e0eacac0121 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 0bc4eab6f1117..21ba6fff1301c 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index b0d507f30cd0a..e1b1629aafe29 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index f019572bdb325..54591c9fa9307 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 25483a7abeb12..dcd7b37af65e1 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 0a181014f22ce..b02fee7cfa42a 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index c8f7aa079b643..19c45dde4496d 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 17d5b5ba43243..069afcb296fb9 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 769552a54bd0f..eb8c5b1c82bf7 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 5d75eb103f218..26f8781a777cd 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 98d3783bb094d..4405aa6bab96b 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 932b727927668..dcbb733286512 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e90a0a291a535..b59c0a1baa3b6 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 2b9748418bf39..41248c4cd29ab 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 346abc7b2d8d2..bcb034f362738 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 51e70b51a1c7c..0e1ed664e1476 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 987eace82b833..87c37f7ace8ef 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 5f83977035c19..e6daa8fbc17b6 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index f04ca978b127f..f668a0d99b697 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 237746026fda9..be028240e91db 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 71b538c3cdd46..ef83e6a362a6f 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 426019405e51a..a9e2095dafa7d 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index b5b2ddf20a839..53d640484e4d8 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index c1b7bc738666b..878ff56b860ad 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index db5905219cb2c..de6cae7ca1f13 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index e3b8b07062622..8eb30604a60eb 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index fd7909c3f8eb8..33d7627bb27b4 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 46dac5205b919..4723979b01447 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index d180bf0c7bdce..9e8988d009497 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 50606bd8b51b7..6131d8ae15296 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index bcc4ed005e261..90b25ec61068b 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index e07d7b4d0fce8..1b13f9e06f3fe 100644 --- a/api_docs/kbn_url_state.mdx +++ b/api_docs/kbn_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-url-state title: "@kbn/url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/url-state plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/url-state'] --- import kbnUrlStateObj from './kbn_url_state.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index d2e3c142f52ac..ffef023217133 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 0659c9a9738a4..c16fc955ab36b 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index e35245edccae8..49afacd1105d6 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index f47bdd5051461..ca493812d2697 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index d59758cb2eae8..41f066bdc603d 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index c7485b672eff4..8d089a0245708 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 9af72b4d86cac..1c94b4a0d73dc 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index ff97032b401a4..d14e3614d0a78 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 89390eefff8d8..269de1c9e876b 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index f185eb010689d..68fe71199d2b8 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.devdocs.json b/api_docs/kibana_react.devdocs.json index 06032a3c41846..71ecfa55073da 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -811,54 +811,6 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/index.tsx" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/range_slider/embeddable/range_slider_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/time_slider/embeddable/time_slider_embeddable.tsx" - }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx" @@ -2704,30 +2656,6 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/index.tsx" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_add_data_control_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/editor/open_edit_control_group_flyout.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/control_group/actions/edit_control_action.tsx" - }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/dashboard_container/embeddable/api/show_settings.tsx" diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 0c00c0c9c975a..5042fd79807d4 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 37a4b162798ff..ead3af45ffcce 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index d40f2b4b63069..f6f0148837549 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index ab352fb83b015..8e19ab8a174f2 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -5315,6 +5315,142 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState", + "type": "Interface", + "tags": [], + "label": "TagcloudState", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.layerId", + "type": "string", + "tags": [], + "label": "layerId", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.tagAccessor", + "type": "string", + "tags": [], + "label": "tagAccessor", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.valueAccessor", + "type": "string", + "tags": [], + "label": "valueAccessor", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.maxFontSize", + "type": "number", + "tags": [], + "label": "maxFontSize", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.minFontSize", + "type": "number", + "tags": [], + "label": "minFontSize", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.orientation", + "type": "CompoundType", + "tags": [], + "label": "orientation", + "description": [], + "signature": [ + "\"single\" | \"right angled\" | \"multiple\"" + ], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.palette", + "type": "Object", + "tags": [], + "label": "palette", + "description": [], + "signature": [ + { + "pluginId": "@kbn/coloring", + "scope": "common", + "docId": "kibKbnColoringPluginApi", + "section": "def-common.PaletteOutput", + "text": "PaletteOutput" + }, + "<{ [key: string]: unknown; }> | undefined" + ], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.showLabel", + "type": "boolean", + "tags": [], + "label": "showLabel", + "description": [], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.TagcloudState.colorMapping", + "type": "Object", + "tags": [], + "label": "colorMapping", + "description": [], + "signature": [ + "Config", + " | undefined" + ], + "path": "x-pack/plugins/lens/public/visualizations/tagcloud/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-public.TermsIndexPatternColumn", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 70c99299289ca..e262c6862b3c2 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 632 | 0 | 533 | 60 | +| 642 | 0 | 543 | 60 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index d899b0d492d4e..90e43aff2b00b 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 810524087e6fd..634dd906f8dbe 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index b0ccda2a318da..d45afd775dc6a 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 20d71605cc361..60b987f6e3128 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 383ee9b7698f8..8c0e5183b0b15 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/log_explorer.mdx b/api_docs/log_explorer.mdx index 783ebbe5f8230..307b78117b139 100644 --- a/api_docs/log_explorer.mdx +++ b/api_docs/log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logExplorer title: "logExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logExplorer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] --- import logExplorerObj from './log_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 138e859ea3562..51bfa81c07963 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index aab750ff0097c..61f51861bd7a3 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 9eebd149f52bb..817a8ae1decd0 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 4db816d33f3b3..f6d7e4e0f17cd 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index b72d87a2f1c48..9a0ee607c305c 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 92843b6328b8a..3903efbe1eea0 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index aeeabb3551660..b7b19e8d61c4d 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index d973f7b0f292f..153c9ea38664e 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index d943a77f50ed1..8b27d4bccfdb4 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index ee704e09120e0..d368c02cabc2a 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 8b0b68d06fde6..b601261f742dd 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index d01c14a6ad234..46582f568fbd2 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 16b4f60589a3a..10188af5b2898 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 89166e8475e7a..49879da9550bf 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index d7b36fc5cb861..f401452c64f0a 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_log_explorer.mdx b/api_docs/observability_log_explorer.mdx index 8f9a88079c037..a8ad32451c327 100644 --- a/api_docs/observability_log_explorer.mdx +++ b/api_docs/observability_log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogExplorer title: "observabilityLogExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogExplorer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogExplorer'] --- import observabilityLogExplorerObj from './observability_log_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index c397d006e5e54..56ae736a9302b 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index e2ab312ddb483..7abdc3f110406 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index a7a8bd53d09d4..e5f3c58f23eb1 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 8faf240d4a9ce..9cc56bba9856e 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 51fba6473c48c..c30d1bba746e6 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 731 | 621 | 40 | +| 732 | 622 | 40 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 77390 | 235 | 66122 | 1622 | +| 77438 | 235 | 66168 | 1622 | ## Plugin Directory @@ -120,7 +120,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 610 | 3 | 417 | 9 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 5 | 0 | 5 | 1 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 632 | 0 | 533 | 60 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 642 | 0 | 543 | 60 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 8 | 0 | 8 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -452,7 +452,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 35125 | 0 | 34718 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 13 | 0 | 5 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 35 | 0 | 34 | 0 | -| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 97 | 0 | 77 | 6 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 98 | 0 | 78 | 6 | +| | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 30 | 0 | 30 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 48 | 0 | 33 | 7 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 27 | 0 | 14 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 3 | 0 | @@ -557,13 +558,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 6 | 0 | 6 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 80 | 0 | 72 | 7 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 50 | 0 | 50 | 3 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 17 | 0 | 16 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 23 | 0 | 20 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 31 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 14 | 0 | 11 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 16 | 0 | 15 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 13 | 0 | 11 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 5 | 0 | 5 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 78 | 0 | 77 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | A component for creating resizable layouts containing a fixed width panel and a flexible panel, with support for horizontal and vertical layouts. | 18 | 0 | 5 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 13 | 2 | 8 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 1115ac3895761..13467ccca9fab 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index d962a4b894d6b..8f58cb4ae51a4 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index 40c879cbaf97d..308ecec574986 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 4f169d9a1554b..d81b1d80796a9 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 4ddd2c69e70b3..aae254e96693c 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 569904473e5c0..db307dac966a1 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index a70b113e3d83f..1b2290db9e771 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 463e9666574cb..1052af1668b8d 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index d2574e55c41cf..03f04320ecd24 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index cff800f6b0c0b..bb7512d531b67 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 9e54a0e8ac8a5..193d80c2d733c 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 42fd98534ddfb..98947dbec80e7 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 58baceba78aa8..951adf152e780 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index ee31f097c41af..165830a02bd1c 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 04a4e8ec1997e..94ca45b5d6776 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 9e18e06647752..d186b15e1dcfd 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 1cd99545b49f9..0933b324f69f7 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 72d6613ec0ffd..19db7381aec73 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -114,7 +114,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantRagOnAlerts: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -568,7 +568,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"alertSuppressionForThresholdRuleEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneManualHostActionsEnabled\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"assistantRagOnAlerts\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"alertSuppressionForThresholdRuleEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -648,7 +648,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"alertSuppressionForThresholdRuleEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneManualHostActionsEnabled\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"assistantRagOnAlerts\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"alertSuppressionForThresholdRuleEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -1913,7 +1913,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantRagOnAlerts: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/types.ts", "deprecated": false, @@ -3018,7 +3018,7 @@ "\nThe security solution generic experimental features" ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantRagOnAlerts: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/server/plugin_contract.ts", "deprecated": false, @@ -3194,7 +3194,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantRagOnAlerts: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3243,7 +3243,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly assistantRagOnAlerts: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly alertSuppressionForThresholdRuleEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index f99cfcd925a6e..eb7619a2d2398 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index fde4f3515ad24..c8e558298ac47 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 9239f5ba2909f..8556be20b6f71 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index ed9ce1c772a2f..b1d3b7596ed7e 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index f58248d1a6101..4360d4c7f3ce8 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index 14642016247c2..4a0e81608a300 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 72fca65dcd686..7c6aa02a220ea 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 7befc797bfa7b..7873dbf0bf30e 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index b1f449fc7c2f9..65478664db9d3 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index be25ce8e8c91a..3c8074fc775fc 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 54385ac0bdeac..e5288767d1adf 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 920dad1bba1cc..884878063349a 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 5ea85b22b9b25..2a8c88f13fe2f 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 9149a76e8e593..ab7d9acbfe66a 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 08a4096670996..34e0dda5ff4de 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 0b22b664d3f4b..a18711cb74a8b 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 6b92a4013a2ca..72281e4309d89 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 41394052543ad..d19f9c33fc5b7 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index f54033be09c04..aa01412fe059c 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index a05a72bf63f72..bbf3b3c37221a 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 55970aaafd7df..1aa6a2c292f6e 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index faad24c161a57..d7f977e4314bc 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index b95d756d2c1cc..e98005cf13fd6 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 890a90f593b33..29cb2aab5dbfd 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index d1fe9b2f53711..69ddfca827a10 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 1e39061586555..8ea4fbfde3159 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index ad26f33477a00..b9671a1549478 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index a2deaf6ef70ae..e802581c1b08f 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 206afd7728756..e901239edb89b 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 2fd2061cacafe..fdea899ee5fe4 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 3e53563cf9028..b7a5998728c04 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 1a08a4d89f21c..e07e3e85eba1a 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 6ee35f4a09012..1ba8689084e61 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 8c801bdf15fdd..c5e5dcd57182c 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index e8bfc54c56527..9f0685ae6277e 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 374c8e0181eab..69799057e2aec 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 5ac9b78ee2695..416ba35882949 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 251fc4d204892..4d666a49f8c4b 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 273a29683e905..d4e3da281627d 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 244745816d5f8..d1de0cf2883ec 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index e74e70bd54899..be97be2363795 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 231ba1f7c2e8c..dd88f173157b5 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 42a1e0c2f4726..523dc5637be23 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-12-06 +date: 2023-12-07 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/package.json b/package.json index f91f9061ec9e2..a0405e1fa3629 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dashboarding" ], "private": true, - "version": "8.12.0", + "version": "8.13.0", "branch": "main", "types": "./kibana.d.ts", "tsdocMetadata": "./build/tsdoc-metadata.json", @@ -168,6 +168,7 @@ "@kbn/assetManager-plugin": "link:x-pack/plugins/asset_manager", "@kbn/audit-log-plugin": "link:x-pack/test/security_api_integration/plugins/audit_log", "@kbn/banners-plugin": "link:x-pack/plugins/banners", + "@kbn/bfetch-error": "link:packages/kbn-bfetch-error", "@kbn/bfetch-explorer-plugin": "link:examples/bfetch_explorer", "@kbn/bfetch-plugin": "link:src/plugins/bfetch", "@kbn/calculate-auto": "link:packages/kbn-calculate-auto", @@ -653,6 +654,7 @@ "@kbn/screenshotting-plugin": "link:x-pack/plugins/screenshotting", "@kbn/search-api-panels": "link:packages/kbn-search-api-panels", "@kbn/search-connectors": "link:packages/kbn-search-connectors", + "@kbn/search-errors": "link:packages/kbn-search-errors", "@kbn/search-examples-plugin": "link:examples/search_examples", "@kbn/search-index-documents": "link:packages/kbn-search-index-documents", "@kbn/search-response-warnings": "link:packages/kbn-search-response-warnings", diff --git a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts index 60656e9dfd1cb..fc394702eadfa 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/analytics_service.ts @@ -184,6 +184,10 @@ export class AnalyticsService { type: 'keyword', _meta: { description: 'The Cluster version', optional: true }, }, + cluster_build_flavor: { + type: 'keyword', + _meta: { description: 'The Cluster build flavor', optional: true }, + }, }, }); } diff --git a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts index dd9d6bced5c98..01b46679c7452 100644 --- a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts +++ b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts @@ -16,6 +16,7 @@ export interface InjectedMetadataClusterInfo { cluster_uuid?: string; cluster_name?: string; cluster_version?: string; + cluster_build_flavor?: string; } /** @internal */ diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap index d513177d685bc..f709e0137730b 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -5,10 +5,6 @@ Object { "debug": Array [ Array [ "[.my-so-index] INIT RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] INIT -> LEGACY_REINDEX. took: 0ms.", @@ -233,10 +229,6 @@ Object { ], Array [ "[.my-so-index] LEGACY_REINDEX RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] LEGACY_REINDEX -> LEGACY_DELETE. took: 0ms.", @@ -465,10 +457,6 @@ Object { ], Array [ "[.my-so-index] LEGACY_DELETE RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] LEGACY_DELETE -> LEGACY_DELETE. took: 0ms.", @@ -701,10 +689,6 @@ Object { ], Array [ "[.my-so-index] LEGACY_DELETE RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] LEGACY_DELETE -> DONE. took: 0ms.", @@ -967,10 +951,6 @@ Object { "debug": Array [ Array [ "[.my-so-index] INIT RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] INIT -> LEGACY_DELETE. took: 0ms.", @@ -1206,10 +1186,6 @@ Object { ], Array [ "[.my-so-index] LEGACY_DELETE RESPONSE", - Object { - "_tag": "Right", - "right": "response", - }, ], Array [ "[.my-so-index] LEGACY_DELETE -> FATAL. took: 0ms.", diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts index 1cf531ef51cc4..04f6242632bd3 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/common/utils/logs.ts @@ -66,5 +66,5 @@ export const logActionResponse = ( state: LogAwareState, res: unknown ) => { - logger.debug(logMessagePrefix + `${state.controlState} RESPONSE`, res as LogMeta); + logger.debug(logMessagePrefix + `${state.controlState} RESPONSE`); }; diff --git a/packages/deeplinks/observability/index.ts b/packages/deeplinks/observability/index.ts index 39608b4b7f7a9..81dac13f6b6a0 100644 --- a/packages/deeplinks/observability/index.ts +++ b/packages/deeplinks/observability/index.ts @@ -6,7 +6,12 @@ * Side Public License, v 1. */ -export { OBSERVABILITY_ONBOARDING_APP_ID } from './constants'; +export { + OBSERVABILITY_ONBOARDING_APP_ID, + LOGS_APP_ID, + OBSERVABILITY_LOG_EXPLORER, + OBSERVABILITY_OVERVIEW_APP_ID, +} from './constants'; export type { AppId, DeepLinkId } from './deep_links'; diff --git a/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts b/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts index a051eda6519c1..1588963385834 100644 --- a/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts +++ b/packages/kbn-alerts-as-data-utils/src/schemas/generated/stack_schema.ts @@ -70,6 +70,7 @@ const StackAlertRequired = rt.type({ }); const StackAlertOptional = rt.partial({ 'kibana.alert.evaluation.conditions': schemaString, + 'kibana.alert.evaluation.threshold': schemaStringOrNumber, 'kibana.alert.evaluation.value': schemaString, 'kibana.alert.title': schemaString, }); diff --git a/packages/kbn-bfetch-error/BUILD.bazel b/packages/kbn-bfetch-error/BUILD.bazel new file mode 100644 index 0000000000000..88cb5bbe5b9e8 --- /dev/null +++ b/packages/kbn-bfetch-error/BUILD.bazel @@ -0,0 +1,35 @@ +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") + +SRCS = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/test_helpers.ts", + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +BUNDLER_DEPS = [ + "//packages/kbn-i18n", + "@npm//tslib", +] + +js_library( + name = "kbn-bfetch-error", + package_name = "@kbn/bfetch-error", + srcs = ["package.json"] + SRCS, + deps = BUNDLER_DEPS, + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-bfetch-error/README.md b/packages/kbn-bfetch-error/README.md new file mode 100644 index 0000000000000..c44118eef53a6 --- /dev/null +++ b/packages/kbn-bfetch-error/README.md @@ -0,0 +1,3 @@ +# @kbn/bfetch-error + +package isolating befetch error logic diff --git a/src/plugins/data/public/search/errors/index.ts b/packages/kbn-bfetch-error/index.ts similarity index 64% rename from src/plugins/data/public/search/errors/index.ts rename to packages/kbn-bfetch-error/index.ts index 27acf0baecdb4..9af059ac9d855 100644 --- a/src/plugins/data/public/search/errors/index.ts +++ b/packages/kbn-bfetch-error/index.ts @@ -6,9 +6,4 @@ * Side Public License, v 1. */ -export * from './es_error'; -export * from './painless_error'; -export * from './timeout_error'; -export * from './utils'; -export * from './types'; -export * from './search_session_incomplete_warning'; +export { BfetchRequestError } from './src/bfetch_error'; diff --git a/packages/kbn-bfetch-error/jest.config.js b/packages/kbn-bfetch-error/jest.config.js new file mode 100644 index 0000000000000..fb6554b8e0808 --- /dev/null +++ b/packages/kbn-bfetch-error/jest.config.js @@ -0,0 +1,13 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-bfetch-error'], +}; diff --git a/packages/kbn-bfetch-error/kibana.jsonc b/packages/kbn-bfetch-error/kibana.jsonc new file mode 100644 index 0000000000000..2cde90d13d99c --- /dev/null +++ b/packages/kbn-bfetch-error/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/bfetch-error", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/kbn-bfetch-error/package.json b/packages/kbn-bfetch-error/package.json new file mode 100644 index 0000000000000..539210ff96b26 --- /dev/null +++ b/packages/kbn-bfetch-error/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/bfetch-error", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/src/plugins/bfetch/common/bfetch_error.ts b/packages/kbn-bfetch-error/src/bfetch_error.ts similarity index 88% rename from src/plugins/bfetch/common/bfetch_error.ts rename to packages/kbn-bfetch-error/src/bfetch_error.ts index 582178f645b2b..be4f80e0dc7e2 100644 --- a/src/plugins/bfetch/common/bfetch_error.ts +++ b/packages/kbn-bfetch-error/src/bfetch_error.ts @@ -20,10 +20,10 @@ export class BfetchRequestError extends Error { constructor(code: number) { const message = code === 0 - ? i18n.translate('bfetch.networkError', { + ? i18n.translate('bfetchError.networkError', { defaultMessage: 'Check your network connection and try again.', }) - : i18n.translate('bfetch.networkErrorWithStatus', { + : i18n.translate('bfetchError.networkErrorWithStatus', { defaultMessage: 'Check your network connection and try again. Code {code}', values: { code }, }); diff --git a/packages/kbn-bfetch-error/tsconfig.json b/packages/kbn-bfetch-error/tsconfig.json new file mode 100644 index 0000000000000..c4703bc51cf6c --- /dev/null +++ b/packages/kbn-bfetch-error/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n", + ] +} diff --git a/packages/kbn-monaco/index.ts b/packages/kbn-monaco/index.ts index d7ff4d4abc94a..2ebb05bd0e393 100644 --- a/packages/kbn-monaco/index.ts +++ b/packages/kbn-monaco/index.ts @@ -12,7 +12,7 @@ export { monaco } from './src/monaco_imports'; export { XJsonLang } from './src/xjson'; export { SQLLang } from './src/sql'; export { ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang } from './src/esql'; -export type { ESQLCustomAutocompleteCallbacks } from './src/esql'; +export type { ESQLCallbacks } from './src/esql'; export * from './src/painless'; /* eslint-disable-next-line @kbn/eslint/module_migration */ diff --git a/packages/kbn-monaco/src/common/error_listener.ts b/packages/kbn-monaco/src/common/error_listener.ts index b072b132b26ac..efcacb88d2c2a 100644 --- a/packages/kbn-monaco/src/common/error_listener.ts +++ b/packages/kbn-monaco/src/common/error_listener.ts @@ -31,6 +31,7 @@ export class ANTLREErrorListener implements ANTLRErrorListener { startColumn: column, endColumn, message, + severity: 8, }); } diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 index 815cf7f237bfb..90a892d8d1dd6 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.g4 @@ -4,26 +4,27 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - + lexer grammar esql_lexer; +options { } DISSECT : D I S S E C T -> pushMode(EXPRESSION); -GROK : G R O K -> pushMode(EXPRESSION); +DROP : D R O P -> pushMode(SOURCE_IDENTIFIERS); +ENRICH : E N R I C H -> pushMode(SOURCE_IDENTIFIERS); EVAL : E V A L -> pushMode(EXPRESSION); -EXPLAIN : E X P L A I N -> pushMode(EXPLAIN_MODE); FROM : F R O M -> pushMode(SOURCE_IDENTIFIERS); +GROK : G R O K -> pushMode(EXPRESSION); +KEEP : K E E P -> pushMode(SOURCE_IDENTIFIERS); +LIMIT : L I M I T -> pushMode(EXPRESSION); +MV_EXPAND : M V UNDERSCORE E X P A N D -> pushMode(SOURCE_IDENTIFIERS); +PROJECT : P R O J E C T -> pushMode(SOURCE_IDENTIFIERS); +RENAME : R E N A M E -> pushMode(SOURCE_IDENTIFIERS); ROW : R O W -> pushMode(EXPRESSION); +SHOW : S H O W -> pushMode(EXPRESSION); +SORT : S O R T -> pushMode(EXPRESSION); STATS : S T A T S -> pushMode(EXPRESSION); WHERE : W H E R E -> pushMode(EXPRESSION); -SORT : S O R T -> pushMode(EXPRESSION); -MV_EXPAND : M V UNDERSCORE E X P A N D -> pushMode(EXPRESSION); -LIMIT : L I M I T -> pushMode(EXPRESSION); -PROJECT : P R O J E C T -> pushMode(EXPRESSION); -DROP : D R O P -> pushMode(EXPRESSION); -RENAME : R E N A M E -> pushMode(EXPRESSION); -SHOW : S H O W -> pushMode(EXPRESSION); -ENRICH : E N R I C H -> pushMode(ENRICH_IDENTIFIERS); -KEEP : K E E P -> pushMode(EXPRESSION); +UNKNOWN_CMD : ~[ \r\n\t[\]/]+ -> pushMode(EXPRESSION); LINE_COMMENT : '//' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) @@ -36,12 +37,7 @@ MULTILINE_COMMENT WS : [ \r\n\t]+ -> channel(HIDDEN) ; -mode EXPLAIN_MODE; -EXPLAIN_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(DEFAULT_MODE); -EXPLAIN_PIPE : '|' -> type(PIPE), popMode; -EXPLAIN_WS : WS -> channel(HIDDEN); -EXPLAIN_LINE_COMMENT : LINE_COMMENT -> channel(HIDDEN); -EXPLAIN_MULTILINE_COMMENT : MULTILINE_COMMENT -> channel(HIDDEN); + mode EXPRESSION; PIPE : '|' -> popMode; @@ -82,169 +78,60 @@ DECIMAL_LITERAL | DOT DIGIT+ EXPONENT ; -BY : 'by'; - -DATE_LITERAL - : 'year' - | 'month' - | 'day' - | 'second' - | 'minute' - | 'hour' - | 'week' - | 'millisecond' - | 'years' - | 'months' - | 'days' - | 'seconds' - | 'minutes' - | 'hours' - | 'weeks' - | 'milliseconds' - ; +BY : B Y; -AND : 'and'; +AND : A N D; +ASC : A S C; ASSIGN : '='; COMMA : ','; +DESC : D E S C; DOT : '.'; +FALSE : F A L S E; +FIRST : F I R S T; +LAST : L A S T; LP : '('; -OPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION); -CLOSING_BRACKET : ']' -> popMode, popMode; -NOT : N O T; -LIKE: L I K E; -RLIKE: R L I K E; IN: I N; IS: I S; -AS: A S; +LIKE: L I K E; +NOT : N O T; NULL : N U L L; -OR : 'or'; +NULLS : N U L L S; +OR : O R; +PARAM: '?'; +RLIKE: R L I K E; RP : ')'; +TRUE : T R U E; +INFO : I N F O; +FUNCTIONS : F U N C T I O N S; UNDERSCORE: '_'; -INFO : 'info'; -FUNCTIONS : 'functions'; - -BOOLEAN_VALUE - : 'true' - | 'false' - ; - -COMPARISON_OPERATOR - : '==' - |'!=' - | '<' - | '<=' - | '>' - | '>=' - ; + +EQ : '=='; +NEQ : '!='; +LT : '<'; +LTE : '<='; +GT : '>'; +GTE : '>='; PLUS : '+'; MINUS : '-'; ASTERISK : '*'; SLASH : '/'; PERCENT : '%'; -TEN: '10'; - -ORDERING - : 'asc' - | 'desc' - ; - -NULLS_ORDERING: 'nulls'; -NULLS_ORDERING_DIRECTION - : 'first' - | 'last' - ; -MATH_FUNCTION - : R O U N D - | A B S - | P O W - | L O G TEN - | P I - | T A U - | E - | S U B S T R I N G - | T R I M - | C O N C A T - | C O A L E S C E - | G R E A T E S T - | L E F T - | N O W - | R I G H T - | S T A R T S UNDERSCORE W I T H - | D A T E UNDERSCORE F O R M A T - | D A T E UNDERSCORE T R U N C - | D A T E UNDERSCORE P A R S E - | A U T O UNDERSCORE B U C K E T - | D A T E UNDERSCORE E X T R A C T - | I S UNDERSCORE F I N I T E - | I S UNDERSCORE I N F I N I T E - | C A S E - | L E N G T H - | M V UNDERSCORE M A X - | M V UNDERSCORE M I N - | M V UNDERSCORE A V G - | M V UNDERSCORE S U M - | M V UNDERSCORE C O U N T - | M V UNDERSCORE C O N C A T - | M V UNDERSCORE J O I N - | M V UNDERSCORE M E D I A N - | M V UNDERSCORE D E D U P E - | M E T A D A T A - | S P L I T - | T O UNDERSCORE S T R I N G - | T O UNDERSCORE S T R - | T O UNDERSCORE B O O L - | T O UNDERSCORE B O O L E A N - | T O UNDERSCORE D A T E T I M E - | T O UNDERSCORE D T - | T O UNDERSCORE D B L - | T O UNDERSCORE D O U B L E - | T O UNDERSCORE D E G R E E S - | T O UNDERSCORE I N T - | T O UNDERSCORE I N T E G E R - | T O UNDERSCORE I P - | T O UNDERSCORE L O N G - | T O UNDERSCORE R A D I A N S - | T O UNDERSCORE V E R S I O N - | T O UNDERSCORE U N S I G N E D UNDERSCORE L O N G - ; - -UNARY_FUNCTION - : A V G - | M I N - | M A X - | S U M - | C O U N T - | C O U N T UNDERSCORE D I S T I N C T - | P E R C E N T I L E - | M E D I A N - | M E D I A N UNDERSCORE A B S O L U T E UNDERSCORE D E V I A T I O N - | A C O S - | A S I N - | A T A N - | A T A N '2' - | C E I L - | C O S - | C O S H - | F L O O R - | L T R I M - | S I N - | S I N H - | S Q R T - | T A N - | T A N H - ; +// Brackets are funny. We can happen upon a CLOSING_BRACKET in two ways - one +// way is to start in an explain command which then shifts us to expression +// mode. Thus, the two popModes on CLOSING_BRACKET. The other way could as +// the start of a multivalued field constant. To line up with the double pop +// the explain mode needs, we double push when we see that. +OPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION); +CLOSING_BRACKET : ']' -> popMode, popMode; -WHERE_FUNCTIONS - : C I D R UNDERSCORE M A T C H - ; UNQUOTED_IDENTIFIER - : LETTER (LETTER | DIGIT | '_' | ASTERISK)* + : LETTER (LETTER | DIGIT | '_')* // only allow @ at beginning of identifier to keep the option to allow @ as infix operator in the future // also, single `_` and `@` characters are not valid identifiers - | ('_' | '@') (LETTER | DIGIT | '_' | ASTERISK)+ + | ('_' | '@') (LETTER | DIGIT | '_')+ ; QUOTED_IDENTIFIER @@ -264,6 +151,7 @@ EXPR_WS ; + mode SOURCE_IDENTIFIERS; SRC_PIPE : '|' -> type(PIPE), popMode; @@ -271,7 +159,10 @@ SRC_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(SOURCE_IDENTIFIERS) SRC_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); SRC_COMMA : ',' -> type(COMMA); SRC_ASSIGN : '=' -> type(ASSIGN); +AS : A S; METADATA: M E T A D A T A; +ON : O N; +WITH : W I T H; SRC_UNQUOTED_IDENTIFIER : SRC_UNQUOTED_IDENTIFIER_PART+ @@ -298,41 +189,6 @@ SRC_WS : WS -> channel(HIDDEN) ; -mode ENRICH_IDENTIFIERS; - -ON : O N; -WITH : W I T H; - -ENR_PIPE : '|' -> type(PIPE), popMode; -ENR_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET); -ENR_COMMA : ',' -> type(COMMA); -ENR_ASSIGN : '=' -> type(ASSIGN); - -ENR_UNQUOTED_IDENTIFIER - : ENR_UNQUOTED_IDENTIFIER_PART+ - ; - -fragment ENR_UNQUOTED_IDENTIFIER_PART - : ~[=`|,[\]/ \t\r\n]+ - | '/' ~[*/] // allow single / but not followed by another / or * which would start a comment - ; - -ENR_QUOTED_IDENTIFIER - : QUOTED_IDENTIFIER - ; - -ENR_LINE_COMMENT - : LINE_COMMENT -> channel(HIDDEN) - ; - -ENR_MULTILINE_COMMENT - : MULTILINE_COMMENT -> channel(HIDDEN) - ; - -ENR_WS - : WS -> channel(HIDDEN) - ; - fragment A : [aA]; // match either an 'a' or 'A' fragment B : [bB]; fragment C : [cC]; diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp index 80f8a20f9d322..0ff1f62c47445 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.interp @@ -27,46 +27,41 @@ null null null null -'by' null -'and' null null '.' +null +null +null '(' null -']' null null null null null null +'?' null -'or' ')' -'_' -'info' -'functions' null null +null +'_' +'==' +'!=' +'<' +'<=' +'>' +'>=' '+' '-' '*' '/' '%' -'10' -null -'nulls' -null -null -null -null -null -null -null -null null +']' null null null @@ -85,113 +80,103 @@ null token symbolic names: null DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_UNQUOTED_IDENTIFIER -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS -EXPLAIN_PIPE rule names: DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_OPENING_BRACKET -EXPLAIN_PIPE -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE DIGIT LETTER @@ -202,40 +187,43 @@ STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT @@ -246,25 +234,16 @@ SRC_OPENING_BRACKET SRC_CLOSING_BRACKET SRC_COMMA SRC_ASSIGN +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_UNQUOTED_IDENTIFIER_PART SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_PIPE -ENR_CLOSING_BRACKET -ENR_COMMA -ENR_ASSIGN -ENR_UNQUOTED_IDENTIFIER -ENR_UNQUOTED_IDENTIFIER_PART -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS A B C @@ -298,10 +277,8 @@ HIDDEN mode names: DEFAULT_MODE -EXPLAIN_MODE EXPRESSION SOURCE_IDENTIFIERS -ENRICH_IDENTIFIERS atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 83, 1600, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 4, 121, 9, 121, 4, 122, 9, 122, 4, 123, 9, 123, 4, 124, 9, 124, 4, 125, 9, 125, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 399, 10, 19, 12, 19, 14, 19, 402, 11, 19, 3, 19, 5, 19, 405, 10, 19, 3, 19, 5, 19, 408, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 417, 10, 20, 12, 20, 14, 20, 420, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 428, 10, 21, 13, 21, 14, 21, 429, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 5, 32, 471, 10, 32, 3, 32, 6, 32, 474, 10, 32, 13, 32, 14, 32, 475, 3, 33, 3, 33, 3, 33, 7, 33, 481, 10, 33, 12, 33, 14, 33, 484, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 492, 10, 33, 12, 33, 14, 33, 495, 11, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 502, 10, 33, 3, 33, 5, 33, 505, 10, 33, 5, 33, 507, 10, 33, 3, 34, 6, 34, 510, 10, 34, 13, 34, 14, 34, 511, 3, 35, 6, 35, 515, 10, 35, 13, 35, 14, 35, 516, 3, 35, 3, 35, 7, 35, 521, 10, 35, 12, 35, 14, 35, 524, 11, 35, 3, 35, 3, 35, 6, 35, 528, 10, 35, 13, 35, 14, 35, 529, 3, 35, 6, 35, 533, 10, 35, 13, 35, 14, 35, 534, 3, 35, 3, 35, 7, 35, 539, 10, 35, 12, 35, 14, 35, 542, 11, 35, 5, 35, 544, 10, 35, 3, 35, 3, 35, 3, 35, 3, 35, 6, 35, 550, 10, 35, 13, 35, 14, 35, 551, 3, 35, 3, 35, 5, 35, 556, 10, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 5, 37, 655, 10, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 5, 57, 739, 10, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 5, 58, 751, 10, 58, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 5, 65, 773, 10, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 5, 67, 790, 10, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 5, 68, 1222, 10, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 5, 69, 1375, 10, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 7, 71, 1393, 10, 71, 12, 71, 14, 71, 1396, 11, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 6, 71, 1403, 10, 71, 13, 71, 14, 71, 1404, 5, 71, 1407, 10, 71, 3, 72, 3, 72, 3, 72, 3, 72, 7, 72, 1413, 10, 72, 12, 72, 14, 72, 1416, 11, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 6, 82, 1467, 10, 82, 13, 82, 14, 82, 1468, 3, 83, 6, 83, 1472, 10, 83, 13, 83, 14, 83, 1473, 3, 83, 3, 83, 5, 83, 1478, 10, 83, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 89, 3, 89, 3, 89, 3, 90, 3, 90, 3, 90, 3, 90, 3, 90, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 91, 3, 92, 3, 92, 3, 92, 3, 92, 3, 93, 3, 93, 3, 93, 3, 93, 3, 94, 6, 94, 1522, 10, 94, 13, 94, 14, 94, 1523, 3, 95, 6, 95, 1527, 10, 95, 13, 95, 14, 95, 1528, 3, 95, 3, 95, 5, 95, 1533, 10, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 3, 97, 3, 98, 3, 98, 3, 98, 3, 98, 3, 99, 3, 99, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 3, 115, 3, 115, 3, 116, 3, 116, 3, 117, 3, 117, 3, 118, 3, 118, 3, 119, 3, 119, 3, 120, 3, 120, 3, 121, 3, 121, 3, 122, 3, 122, 3, 123, 3, 123, 3, 124, 3, 124, 3, 125, 3, 125, 4, 418, 493, 2, 2, 126, 7, 2, 3, 9, 2, 4, 11, 2, 5, 13, 2, 6, 15, 2, 7, 17, 2, 8, 19, 2, 9, 21, 2, 10, 23, 2, 11, 25, 2, 12, 27, 2, 13, 29, 2, 14, 31, 2, 15, 33, 2, 16, 35, 2, 17, 37, 2, 18, 39, 2, 19, 41, 2, 20, 43, 2, 21, 45, 2, 22, 47, 2, 2, 49, 2, 83, 51, 2, 23, 53, 2, 24, 55, 2, 25, 57, 2, 26, 59, 2, 2, 61, 2, 2, 63, 2, 2, 65, 2, 2, 67, 2, 2, 69, 2, 27, 71, 2, 28, 73, 2, 29, 75, 2, 30, 77, 2, 31, 79, 2, 32, 81, 2, 33, 83, 2, 34, 85, 2, 35, 87, 2, 36, 89, 2, 37, 91, 2, 38, 93, 2, 39, 95, 2, 40, 97, 2, 41, 99, 2, 42, 101, 2, 43, 103, 2, 44, 105, 2, 45, 107, 2, 46, 109, 2, 47, 111, 2, 48, 113, 2, 49, 115, 2, 50, 117, 2, 51, 119, 2, 52, 121, 2, 53, 123, 2, 54, 125, 2, 55, 127, 2, 56, 129, 2, 57, 131, 2, 58, 133, 2, 59, 135, 2, 60, 137, 2, 61, 139, 2, 62, 141, 2, 63, 143, 2, 64, 145, 2, 65, 147, 2, 66, 149, 2, 67, 151, 2, 68, 153, 2, 69, 155, 2, 2, 157, 2, 2, 159, 2, 2, 161, 2, 2, 163, 2, 2, 165, 2, 70, 167, 2, 71, 169, 2, 2, 171, 2, 72, 173, 2, 73, 175, 2, 74, 177, 2, 75, 179, 2, 76, 181, 2, 77, 183, 2, 2, 185, 2, 2, 187, 2, 2, 189, 2, 2, 191, 2, 78, 193, 2, 2, 195, 2, 79, 197, 2, 80, 199, 2, 81, 201, 2, 82, 203, 2, 2, 205, 2, 2, 207, 2, 2, 209, 2, 2, 211, 2, 2, 213, 2, 2, 215, 2, 2, 217, 2, 2, 219, 2, 2, 221, 2, 2, 223, 2, 2, 225, 2, 2, 227, 2, 2, 229, 2, 2, 231, 2, 2, 233, 2, 2, 235, 2, 2, 237, 2, 2, 239, 2, 2, 241, 2, 2, 243, 2, 2, 245, 2, 2, 247, 2, 2, 249, 2, 2, 251, 2, 2, 253, 2, 2, 7, 2, 3, 4, 5, 6, 39, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 4, 2, 66, 66, 97, 97, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 1700, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 3, 47, 3, 2, 2, 2, 3, 49, 3, 2, 2, 2, 3, 51, 3, 2, 2, 2, 3, 53, 3, 2, 2, 2, 3, 55, 3, 2, 2, 2, 4, 57, 3, 2, 2, 2, 4, 69, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 4, 73, 3, 2, 2, 2, 4, 75, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 4, 79, 3, 2, 2, 2, 4, 81, 3, 2, 2, 2, 4, 83, 3, 2, 2, 2, 4, 85, 3, 2, 2, 2, 4, 87, 3, 2, 2, 2, 4, 89, 3, 2, 2, 2, 4, 91, 3, 2, 2, 2, 4, 93, 3, 2, 2, 2, 4, 95, 3, 2, 2, 2, 4, 97, 3, 2, 2, 2, 4, 99, 3, 2, 2, 2, 4, 101, 3, 2, 2, 2, 4, 103, 3, 2, 2, 2, 4, 105, 3, 2, 2, 2, 4, 107, 3, 2, 2, 2, 4, 109, 3, 2, 2, 2, 4, 111, 3, 2, 2, 2, 4, 113, 3, 2, 2, 2, 4, 115, 3, 2, 2, 2, 4, 117, 3, 2, 2, 2, 4, 119, 3, 2, 2, 2, 4, 121, 3, 2, 2, 2, 4, 123, 3, 2, 2, 2, 4, 125, 3, 2, 2, 2, 4, 127, 3, 2, 2, 2, 4, 129, 3, 2, 2, 2, 4, 131, 3, 2, 2, 2, 4, 133, 3, 2, 2, 2, 4, 135, 3, 2, 2, 2, 4, 137, 3, 2, 2, 2, 4, 139, 3, 2, 2, 2, 4, 141, 3, 2, 2, 2, 4, 143, 3, 2, 2, 2, 4, 145, 3, 2, 2, 2, 4, 147, 3, 2, 2, 2, 4, 149, 3, 2, 2, 2, 4, 151, 3, 2, 2, 2, 4, 153, 3, 2, 2, 2, 5, 155, 3, 2, 2, 2, 5, 157, 3, 2, 2, 2, 5, 159, 3, 2, 2, 2, 5, 161, 3, 2, 2, 2, 5, 163, 3, 2, 2, 2, 5, 165, 3, 2, 2, 2, 5, 167, 3, 2, 2, 2, 5, 171, 3, 2, 2, 2, 5, 173, 3, 2, 2, 2, 5, 175, 3, 2, 2, 2, 5, 177, 3, 2, 2, 2, 6, 179, 3, 2, 2, 2, 6, 181, 3, 2, 2, 2, 6, 183, 3, 2, 2, 2, 6, 185, 3, 2, 2, 2, 6, 187, 3, 2, 2, 2, 6, 189, 3, 2, 2, 2, 6, 191, 3, 2, 2, 2, 6, 195, 3, 2, 2, 2, 6, 197, 3, 2, 2, 2, 6, 199, 3, 2, 2, 2, 6, 201, 3, 2, 2, 2, 7, 255, 3, 2, 2, 2, 9, 265, 3, 2, 2, 2, 11, 272, 3, 2, 2, 2, 13, 279, 3, 2, 2, 2, 15, 289, 3, 2, 2, 2, 17, 296, 3, 2, 2, 2, 19, 302, 3, 2, 2, 2, 21, 310, 3, 2, 2, 2, 23, 318, 3, 2, 2, 2, 25, 325, 3, 2, 2, 2, 27, 337, 3, 2, 2, 2, 29, 345, 3, 2, 2, 2, 31, 355, 3, 2, 2, 2, 33, 362, 3, 2, 2, 2, 35, 371, 3, 2, 2, 2, 37, 378, 3, 2, 2, 2, 39, 387, 3, 2, 2, 2, 41, 394, 3, 2, 2, 2, 43, 411, 3, 2, 2, 2, 45, 427, 3, 2, 2, 2, 47, 433, 3, 2, 2, 2, 49, 438, 3, 2, 2, 2, 51, 443, 3, 2, 2, 2, 53, 447, 3, 2, 2, 2, 55, 451, 3, 2, 2, 2, 57, 455, 3, 2, 2, 2, 59, 459, 3, 2, 2, 2, 61, 461, 3, 2, 2, 2, 63, 463, 3, 2, 2, 2, 65, 466, 3, 2, 2, 2, 67, 468, 3, 2, 2, 2, 69, 506, 3, 2, 2, 2, 71, 509, 3, 2, 2, 2, 73, 555, 3, 2, 2, 2, 75, 557, 3, 2, 2, 2, 77, 654, 3, 2, 2, 2, 79, 656, 3, 2, 2, 2, 81, 660, 3, 2, 2, 2, 83, 662, 3, 2, 2, 2, 85, 664, 3, 2, 2, 2, 87, 666, 3, 2, 2, 2, 89, 668, 3, 2, 2, 2, 91, 673, 3, 2, 2, 2, 93, 678, 3, 2, 2, 2, 95, 682, 3, 2, 2, 2, 97, 687, 3, 2, 2, 2, 99, 693, 3, 2, 2, 2, 101, 696, 3, 2, 2, 2, 103, 699, 3, 2, 2, 2, 105, 702, 3, 2, 2, 2, 107, 707, 3, 2, 2, 2, 109, 710, 3, 2, 2, 2, 111, 712, 3, 2, 2, 2, 113, 714, 3, 2, 2, 2, 115, 719, 3, 2, 2, 2, 117, 738, 3, 2, 2, 2, 119, 750, 3, 2, 2, 2, 121, 752, 3, 2, 2, 2, 123, 754, 3, 2, 2, 2, 125, 756, 3, 2, 2, 2, 127, 758, 3, 2, 2, 2, 129, 760, 3, 2, 2, 2, 131, 762, 3, 2, 2, 2, 133, 772, 3, 2, 2, 2, 135, 774, 3, 2, 2, 2, 137, 789, 3, 2, 2, 2, 139, 1221, 3, 2, 2, 2, 141, 1374, 3, 2, 2, 2, 143, 1376, 3, 2, 2, 2, 145, 1406, 3, 2, 2, 2, 147, 1408, 3, 2, 2, 2, 149, 1419, 3, 2, 2, 2, 151, 1423, 3, 2, 2, 2, 153, 1427, 3, 2, 2, 2, 155, 1431, 3, 2, 2, 2, 157, 1436, 3, 2, 2, 2, 159, 1442, 3, 2, 2, 2, 161, 1448, 3, 2, 2, 2, 163, 1452, 3, 2, 2, 2, 165, 1456, 3, 2, 2, 2, 167, 1466, 3, 2, 2, 2, 169, 1477, 3, 2, 2, 2, 171, 1479, 3, 2, 2, 2, 173, 1481, 3, 2, 2, 2, 175, 1485, 3, 2, 2, 2, 177, 1489, 3, 2, 2, 2, 179, 1493, 3, 2, 2, 2, 181, 1496, 3, 2, 2, 2, 183, 1501, 3, 2, 2, 2, 185, 1506, 3, 2, 2, 2, 187, 1512, 3, 2, 2, 2, 189, 1516, 3, 2, 2, 2, 191, 1521, 3, 2, 2, 2, 193, 1532, 3, 2, 2, 2, 195, 1534, 3, 2, 2, 2, 197, 1536, 3, 2, 2, 2, 199, 1540, 3, 2, 2, 2, 201, 1544, 3, 2, 2, 2, 203, 1548, 3, 2, 2, 2, 205, 1550, 3, 2, 2, 2, 207, 1552, 3, 2, 2, 2, 209, 1554, 3, 2, 2, 2, 211, 1556, 3, 2, 2, 2, 213, 1558, 3, 2, 2, 2, 215, 1560, 3, 2, 2, 2, 217, 1562, 3, 2, 2, 2, 219, 1564, 3, 2, 2, 2, 221, 1566, 3, 2, 2, 2, 223, 1568, 3, 2, 2, 2, 225, 1570, 3, 2, 2, 2, 227, 1572, 3, 2, 2, 2, 229, 1574, 3, 2, 2, 2, 231, 1576, 3, 2, 2, 2, 233, 1578, 3, 2, 2, 2, 235, 1580, 3, 2, 2, 2, 237, 1582, 3, 2, 2, 2, 239, 1584, 3, 2, 2, 2, 241, 1586, 3, 2, 2, 2, 243, 1588, 3, 2, 2, 2, 245, 1590, 3, 2, 2, 2, 247, 1592, 3, 2, 2, 2, 249, 1594, 3, 2, 2, 2, 251, 1596, 3, 2, 2, 2, 253, 1598, 3, 2, 2, 2, 255, 256, 5, 209, 103, 2, 256, 257, 5, 219, 108, 2, 257, 258, 5, 239, 118, 2, 258, 259, 5, 239, 118, 2, 259, 260, 5, 211, 104, 2, 260, 261, 5, 207, 102, 2, 261, 262, 5, 241, 119, 2, 262, 263, 3, 2, 2, 2, 263, 264, 8, 2, 2, 2, 264, 8, 3, 2, 2, 2, 265, 266, 5, 215, 106, 2, 266, 267, 5, 237, 117, 2, 267, 268, 5, 231, 114, 2, 268, 269, 5, 223, 110, 2, 269, 270, 3, 2, 2, 2, 270, 271, 8, 3, 2, 2, 271, 10, 3, 2, 2, 2, 272, 273, 5, 211, 104, 2, 273, 274, 5, 245, 121, 2, 274, 275, 5, 203, 100, 2, 275, 276, 5, 225, 111, 2, 276, 277, 3, 2, 2, 2, 277, 278, 8, 4, 2, 2, 278, 12, 3, 2, 2, 2, 279, 280, 5, 211, 104, 2, 280, 281, 5, 249, 123, 2, 281, 282, 5, 233, 115, 2, 282, 283, 5, 225, 111, 2, 283, 284, 5, 203, 100, 2, 284, 285, 5, 219, 108, 2, 285, 286, 5, 229, 113, 2, 286, 287, 3, 2, 2, 2, 287, 288, 8, 5, 3, 2, 288, 14, 3, 2, 2, 2, 289, 290, 5, 213, 105, 2, 290, 291, 5, 237, 117, 2, 291, 292, 5, 231, 114, 2, 292, 293, 5, 227, 112, 2, 293, 294, 3, 2, 2, 2, 294, 295, 8, 6, 4, 2, 295, 16, 3, 2, 2, 2, 296, 297, 5, 237, 117, 2, 297, 298, 5, 231, 114, 2, 298, 299, 5, 247, 122, 2, 299, 300, 3, 2, 2, 2, 300, 301, 8, 7, 2, 2, 301, 18, 3, 2, 2, 2, 302, 303, 5, 239, 118, 2, 303, 304, 5, 241, 119, 2, 304, 305, 5, 203, 100, 2, 305, 306, 5, 241, 119, 2, 306, 307, 5, 239, 118, 2, 307, 308, 3, 2, 2, 2, 308, 309, 8, 8, 2, 2, 309, 20, 3, 2, 2, 2, 310, 311, 5, 247, 122, 2, 311, 312, 5, 217, 107, 2, 312, 313, 5, 211, 104, 2, 313, 314, 5, 237, 117, 2, 314, 315, 5, 211, 104, 2, 315, 316, 3, 2, 2, 2, 316, 317, 8, 9, 2, 2, 317, 22, 3, 2, 2, 2, 318, 319, 5, 239, 118, 2, 319, 320, 5, 231, 114, 2, 320, 321, 5, 237, 117, 2, 321, 322, 5, 241, 119, 2, 322, 323, 3, 2, 2, 2, 323, 324, 8, 10, 2, 2, 324, 24, 3, 2, 2, 2, 325, 326, 5, 227, 112, 2, 326, 327, 5, 245, 121, 2, 327, 328, 5, 111, 54, 2, 328, 329, 5, 211, 104, 2, 329, 330, 5, 249, 123, 2, 330, 331, 5, 233, 115, 2, 331, 332, 5, 203, 100, 2, 332, 333, 5, 229, 113, 2, 333, 334, 5, 209, 103, 2, 334, 335, 3, 2, 2, 2, 335, 336, 8, 11, 2, 2, 336, 26, 3, 2, 2, 2, 337, 338, 5, 225, 111, 2, 338, 339, 5, 219, 108, 2, 339, 340, 5, 227, 112, 2, 340, 341, 5, 219, 108, 2, 341, 342, 5, 241, 119, 2, 342, 343, 3, 2, 2, 2, 343, 344, 8, 12, 2, 2, 344, 28, 3, 2, 2, 2, 345, 346, 5, 233, 115, 2, 346, 347, 5, 237, 117, 2, 347, 348, 5, 231, 114, 2, 348, 349, 5, 221, 109, 2, 349, 350, 5, 211, 104, 2, 350, 351, 5, 207, 102, 2, 351, 352, 5, 241, 119, 2, 352, 353, 3, 2, 2, 2, 353, 354, 8, 13, 2, 2, 354, 30, 3, 2, 2, 2, 355, 356, 5, 209, 103, 2, 356, 357, 5, 237, 117, 2, 357, 358, 5, 231, 114, 2, 358, 359, 5, 233, 115, 2, 359, 360, 3, 2, 2, 2, 360, 361, 8, 14, 2, 2, 361, 32, 3, 2, 2, 2, 362, 363, 5, 237, 117, 2, 363, 364, 5, 211, 104, 2, 364, 365, 5, 229, 113, 2, 365, 366, 5, 203, 100, 2, 366, 367, 5, 227, 112, 2, 367, 368, 5, 211, 104, 2, 368, 369, 3, 2, 2, 2, 369, 370, 8, 15, 2, 2, 370, 34, 3, 2, 2, 2, 371, 372, 5, 239, 118, 2, 372, 373, 5, 217, 107, 2, 373, 374, 5, 231, 114, 2, 374, 375, 5, 247, 122, 2, 375, 376, 3, 2, 2, 2, 376, 377, 8, 16, 2, 2, 377, 36, 3, 2, 2, 2, 378, 379, 5, 211, 104, 2, 379, 380, 5, 229, 113, 2, 380, 381, 5, 237, 117, 2, 381, 382, 5, 219, 108, 2, 382, 383, 5, 207, 102, 2, 383, 384, 5, 217, 107, 2, 384, 385, 3, 2, 2, 2, 385, 386, 8, 17, 5, 2, 386, 38, 3, 2, 2, 2, 387, 388, 5, 223, 110, 2, 388, 389, 5, 211, 104, 2, 389, 390, 5, 211, 104, 2, 390, 391, 5, 233, 115, 2, 391, 392, 3, 2, 2, 2, 392, 393, 8, 18, 2, 2, 393, 40, 3, 2, 2, 2, 394, 395, 7, 49, 2, 2, 395, 396, 7, 49, 2, 2, 396, 400, 3, 2, 2, 2, 397, 399, 10, 2, 2, 2, 398, 397, 3, 2, 2, 2, 399, 402, 3, 2, 2, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 404, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 403, 405, 7, 15, 2, 2, 404, 403, 3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 407, 3, 2, 2, 2, 406, 408, 7, 12, 2, 2, 407, 406, 3, 2, 2, 2, 407, 408, 3, 2, 2, 2, 408, 409, 3, 2, 2, 2, 409, 410, 8, 19, 6, 2, 410, 42, 3, 2, 2, 2, 411, 412, 7, 49, 2, 2, 412, 413, 7, 44, 2, 2, 413, 418, 3, 2, 2, 2, 414, 417, 5, 43, 20, 2, 415, 417, 11, 2, 2, 2, 416, 414, 3, 2, 2, 2, 416, 415, 3, 2, 2, 2, 417, 420, 3, 2, 2, 2, 418, 419, 3, 2, 2, 2, 418, 416, 3, 2, 2, 2, 419, 421, 3, 2, 2, 2, 420, 418, 3, 2, 2, 2, 421, 422, 7, 44, 2, 2, 422, 423, 7, 49, 2, 2, 423, 424, 3, 2, 2, 2, 424, 425, 8, 20, 6, 2, 425, 44, 3, 2, 2, 2, 426, 428, 9, 3, 2, 2, 427, 426, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 427, 3, 2, 2, 2, 429, 430, 3, 2, 2, 2, 430, 431, 3, 2, 2, 2, 431, 432, 8, 21, 6, 2, 432, 46, 3, 2, 2, 2, 433, 434, 7, 93, 2, 2, 434, 435, 3, 2, 2, 2, 435, 436, 8, 22, 7, 2, 436, 437, 8, 22, 8, 2, 437, 48, 3, 2, 2, 2, 438, 439, 7, 126, 2, 2, 439, 440, 3, 2, 2, 2, 440, 441, 8, 23, 9, 2, 441, 442, 8, 23, 10, 2, 442, 50, 3, 2, 2, 2, 443, 444, 5, 45, 21, 2, 444, 445, 3, 2, 2, 2, 445, 446, 8, 24, 6, 2, 446, 52, 3, 2, 2, 2, 447, 448, 5, 41, 19, 2, 448, 449, 3, 2, 2, 2, 449, 450, 8, 25, 6, 2, 450, 54, 3, 2, 2, 2, 451, 452, 5, 43, 20, 2, 452, 453, 3, 2, 2, 2, 453, 454, 8, 26, 6, 2, 454, 56, 3, 2, 2, 2, 455, 456, 7, 126, 2, 2, 456, 457, 3, 2, 2, 2, 457, 458, 8, 27, 10, 2, 458, 58, 3, 2, 2, 2, 459, 460, 9, 4, 2, 2, 460, 60, 3, 2, 2, 2, 461, 462, 9, 5, 2, 2, 462, 62, 3, 2, 2, 2, 463, 464, 7, 94, 2, 2, 464, 465, 9, 6, 2, 2, 465, 64, 3, 2, 2, 2, 466, 467, 10, 7, 2, 2, 467, 66, 3, 2, 2, 2, 468, 470, 9, 8, 2, 2, 469, 471, 9, 9, 2, 2, 470, 469, 3, 2, 2, 2, 470, 471, 3, 2, 2, 2, 471, 473, 3, 2, 2, 2, 472, 474, 5, 59, 28, 2, 473, 472, 3, 2, 2, 2, 474, 475, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 475, 476, 3, 2, 2, 2, 476, 68, 3, 2, 2, 2, 477, 482, 7, 36, 2, 2, 478, 481, 5, 63, 30, 2, 479, 481, 5, 65, 31, 2, 480, 478, 3, 2, 2, 2, 480, 479, 3, 2, 2, 2, 481, 484, 3, 2, 2, 2, 482, 480, 3, 2, 2, 2, 482, 483, 3, 2, 2, 2, 483, 485, 3, 2, 2, 2, 484, 482, 3, 2, 2, 2, 485, 507, 7, 36, 2, 2, 486, 487, 7, 36, 2, 2, 487, 488, 7, 36, 2, 2, 488, 489, 7, 36, 2, 2, 489, 493, 3, 2, 2, 2, 490, 492, 10, 2, 2, 2, 491, 490, 3, 2, 2, 2, 492, 495, 3, 2, 2, 2, 493, 494, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 494, 496, 3, 2, 2, 2, 495, 493, 3, 2, 2, 2, 496, 497, 7, 36, 2, 2, 497, 498, 7, 36, 2, 2, 498, 499, 7, 36, 2, 2, 499, 501, 3, 2, 2, 2, 500, 502, 7, 36, 2, 2, 501, 500, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 504, 3, 2, 2, 2, 503, 505, 7, 36, 2, 2, 504, 503, 3, 2, 2, 2, 504, 505, 3, 2, 2, 2, 505, 507, 3, 2, 2, 2, 506, 477, 3, 2, 2, 2, 506, 486, 3, 2, 2, 2, 507, 70, 3, 2, 2, 2, 508, 510, 5, 59, 28, 2, 509, 508, 3, 2, 2, 2, 510, 511, 3, 2, 2, 2, 511, 509, 3, 2, 2, 2, 511, 512, 3, 2, 2, 2, 512, 72, 3, 2, 2, 2, 513, 515, 5, 59, 28, 2, 514, 513, 3, 2, 2, 2, 515, 516, 3, 2, 2, 2, 516, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 518, 3, 2, 2, 2, 518, 522, 5, 85, 41, 2, 519, 521, 5, 59, 28, 2, 520, 519, 3, 2, 2, 2, 521, 524, 3, 2, 2, 2, 522, 520, 3, 2, 2, 2, 522, 523, 3, 2, 2, 2, 523, 556, 3, 2, 2, 2, 524, 522, 3, 2, 2, 2, 525, 527, 5, 85, 41, 2, 526, 528, 5, 59, 28, 2, 527, 526, 3, 2, 2, 2, 528, 529, 3, 2, 2, 2, 529, 527, 3, 2, 2, 2, 529, 530, 3, 2, 2, 2, 530, 556, 3, 2, 2, 2, 531, 533, 5, 59, 28, 2, 532, 531, 3, 2, 2, 2, 533, 534, 3, 2, 2, 2, 534, 532, 3, 2, 2, 2, 534, 535, 3, 2, 2, 2, 535, 543, 3, 2, 2, 2, 536, 540, 5, 85, 41, 2, 537, 539, 5, 59, 28, 2, 538, 537, 3, 2, 2, 2, 539, 542, 3, 2, 2, 2, 540, 538, 3, 2, 2, 2, 540, 541, 3, 2, 2, 2, 541, 544, 3, 2, 2, 2, 542, 540, 3, 2, 2, 2, 543, 536, 3, 2, 2, 2, 543, 544, 3, 2, 2, 2, 544, 545, 3, 2, 2, 2, 545, 546, 5, 67, 32, 2, 546, 556, 3, 2, 2, 2, 547, 549, 5, 85, 41, 2, 548, 550, 5, 59, 28, 2, 549, 548, 3, 2, 2, 2, 550, 551, 3, 2, 2, 2, 551, 549, 3, 2, 2, 2, 551, 552, 3, 2, 2, 2, 552, 553, 3, 2, 2, 2, 553, 554, 5, 67, 32, 2, 554, 556, 3, 2, 2, 2, 555, 514, 3, 2, 2, 2, 555, 525, 3, 2, 2, 2, 555, 532, 3, 2, 2, 2, 555, 547, 3, 2, 2, 2, 556, 74, 3, 2, 2, 2, 557, 558, 7, 100, 2, 2, 558, 559, 7, 123, 2, 2, 559, 76, 3, 2, 2, 2, 560, 561, 7, 123, 2, 2, 561, 562, 7, 103, 2, 2, 562, 563, 7, 99, 2, 2, 563, 655, 7, 116, 2, 2, 564, 565, 7, 111, 2, 2, 565, 566, 7, 113, 2, 2, 566, 567, 7, 112, 2, 2, 567, 568, 7, 118, 2, 2, 568, 655, 7, 106, 2, 2, 569, 570, 7, 102, 2, 2, 570, 571, 7, 99, 2, 2, 571, 655, 7, 123, 2, 2, 572, 573, 7, 117, 2, 2, 573, 574, 7, 103, 2, 2, 574, 575, 7, 101, 2, 2, 575, 576, 7, 113, 2, 2, 576, 577, 7, 112, 2, 2, 577, 655, 7, 102, 2, 2, 578, 579, 7, 111, 2, 2, 579, 580, 7, 107, 2, 2, 580, 581, 7, 112, 2, 2, 581, 582, 7, 119, 2, 2, 582, 583, 7, 118, 2, 2, 583, 655, 7, 103, 2, 2, 584, 585, 7, 106, 2, 2, 585, 586, 7, 113, 2, 2, 586, 587, 7, 119, 2, 2, 587, 655, 7, 116, 2, 2, 588, 589, 7, 121, 2, 2, 589, 590, 7, 103, 2, 2, 590, 591, 7, 103, 2, 2, 591, 655, 7, 109, 2, 2, 592, 593, 7, 111, 2, 2, 593, 594, 7, 107, 2, 2, 594, 595, 7, 110, 2, 2, 595, 596, 7, 110, 2, 2, 596, 597, 7, 107, 2, 2, 597, 598, 7, 117, 2, 2, 598, 599, 7, 103, 2, 2, 599, 600, 7, 101, 2, 2, 600, 601, 7, 113, 2, 2, 601, 602, 7, 112, 2, 2, 602, 655, 7, 102, 2, 2, 603, 604, 7, 123, 2, 2, 604, 605, 7, 103, 2, 2, 605, 606, 7, 99, 2, 2, 606, 607, 7, 116, 2, 2, 607, 655, 7, 117, 2, 2, 608, 609, 7, 111, 2, 2, 609, 610, 7, 113, 2, 2, 610, 611, 7, 112, 2, 2, 611, 612, 7, 118, 2, 2, 612, 613, 7, 106, 2, 2, 613, 655, 7, 117, 2, 2, 614, 615, 7, 102, 2, 2, 615, 616, 7, 99, 2, 2, 616, 617, 7, 123, 2, 2, 617, 655, 7, 117, 2, 2, 618, 619, 7, 117, 2, 2, 619, 620, 7, 103, 2, 2, 620, 621, 7, 101, 2, 2, 621, 622, 7, 113, 2, 2, 622, 623, 7, 112, 2, 2, 623, 624, 7, 102, 2, 2, 624, 655, 7, 117, 2, 2, 625, 626, 7, 111, 2, 2, 626, 627, 7, 107, 2, 2, 627, 628, 7, 112, 2, 2, 628, 629, 7, 119, 2, 2, 629, 630, 7, 118, 2, 2, 630, 631, 7, 103, 2, 2, 631, 655, 7, 117, 2, 2, 632, 633, 7, 106, 2, 2, 633, 634, 7, 113, 2, 2, 634, 635, 7, 119, 2, 2, 635, 636, 7, 116, 2, 2, 636, 655, 7, 117, 2, 2, 637, 638, 7, 121, 2, 2, 638, 639, 7, 103, 2, 2, 639, 640, 7, 103, 2, 2, 640, 641, 7, 109, 2, 2, 641, 655, 7, 117, 2, 2, 642, 643, 7, 111, 2, 2, 643, 644, 7, 107, 2, 2, 644, 645, 7, 110, 2, 2, 645, 646, 7, 110, 2, 2, 646, 647, 7, 107, 2, 2, 647, 648, 7, 117, 2, 2, 648, 649, 7, 103, 2, 2, 649, 650, 7, 101, 2, 2, 650, 651, 7, 113, 2, 2, 651, 652, 7, 112, 2, 2, 652, 653, 7, 102, 2, 2, 653, 655, 7, 117, 2, 2, 654, 560, 3, 2, 2, 2, 654, 564, 3, 2, 2, 2, 654, 569, 3, 2, 2, 2, 654, 572, 3, 2, 2, 2, 654, 578, 3, 2, 2, 2, 654, 584, 3, 2, 2, 2, 654, 588, 3, 2, 2, 2, 654, 592, 3, 2, 2, 2, 654, 603, 3, 2, 2, 2, 654, 608, 3, 2, 2, 2, 654, 614, 3, 2, 2, 2, 654, 618, 3, 2, 2, 2, 654, 625, 3, 2, 2, 2, 654, 632, 3, 2, 2, 2, 654, 637, 3, 2, 2, 2, 654, 642, 3, 2, 2, 2, 655, 78, 3, 2, 2, 2, 656, 657, 7, 99, 2, 2, 657, 658, 7, 112, 2, 2, 658, 659, 7, 102, 2, 2, 659, 80, 3, 2, 2, 2, 660, 661, 7, 63, 2, 2, 661, 82, 3, 2, 2, 2, 662, 663, 7, 46, 2, 2, 663, 84, 3, 2, 2, 2, 664, 665, 7, 48, 2, 2, 665, 86, 3, 2, 2, 2, 666, 667, 7, 42, 2, 2, 667, 88, 3, 2, 2, 2, 668, 669, 7, 93, 2, 2, 669, 670, 3, 2, 2, 2, 670, 671, 8, 43, 2, 2, 671, 672, 8, 43, 2, 2, 672, 90, 3, 2, 2, 2, 673, 674, 7, 95, 2, 2, 674, 675, 3, 2, 2, 2, 675, 676, 8, 44, 10, 2, 676, 677, 8, 44, 10, 2, 677, 92, 3, 2, 2, 2, 678, 679, 5, 229, 113, 2, 679, 680, 5, 231, 114, 2, 680, 681, 5, 241, 119, 2, 681, 94, 3, 2, 2, 2, 682, 683, 5, 225, 111, 2, 683, 684, 5, 219, 108, 2, 684, 685, 5, 223, 110, 2, 685, 686, 5, 211, 104, 2, 686, 96, 3, 2, 2, 2, 687, 688, 5, 237, 117, 2, 688, 689, 5, 225, 111, 2, 689, 690, 5, 219, 108, 2, 690, 691, 5, 223, 110, 2, 691, 692, 5, 211, 104, 2, 692, 98, 3, 2, 2, 2, 693, 694, 5, 219, 108, 2, 694, 695, 5, 229, 113, 2, 695, 100, 3, 2, 2, 2, 696, 697, 5, 219, 108, 2, 697, 698, 5, 239, 118, 2, 698, 102, 3, 2, 2, 2, 699, 700, 5, 203, 100, 2, 700, 701, 5, 239, 118, 2, 701, 104, 3, 2, 2, 2, 702, 703, 5, 229, 113, 2, 703, 704, 5, 243, 120, 2, 704, 705, 5, 225, 111, 2, 705, 706, 5, 225, 111, 2, 706, 106, 3, 2, 2, 2, 707, 708, 7, 113, 2, 2, 708, 709, 7, 116, 2, 2, 709, 108, 3, 2, 2, 2, 710, 711, 7, 43, 2, 2, 711, 110, 3, 2, 2, 2, 712, 713, 7, 97, 2, 2, 713, 112, 3, 2, 2, 2, 714, 715, 7, 107, 2, 2, 715, 716, 7, 112, 2, 2, 716, 717, 7, 104, 2, 2, 717, 718, 7, 113, 2, 2, 718, 114, 3, 2, 2, 2, 719, 720, 7, 104, 2, 2, 720, 721, 7, 119, 2, 2, 721, 722, 7, 112, 2, 2, 722, 723, 7, 101, 2, 2, 723, 724, 7, 118, 2, 2, 724, 725, 7, 107, 2, 2, 725, 726, 7, 113, 2, 2, 726, 727, 7, 112, 2, 2, 727, 728, 7, 117, 2, 2, 728, 116, 3, 2, 2, 2, 729, 730, 7, 118, 2, 2, 730, 731, 7, 116, 2, 2, 731, 732, 7, 119, 2, 2, 732, 739, 7, 103, 2, 2, 733, 734, 7, 104, 2, 2, 734, 735, 7, 99, 2, 2, 735, 736, 7, 110, 2, 2, 736, 737, 7, 117, 2, 2, 737, 739, 7, 103, 2, 2, 738, 729, 3, 2, 2, 2, 738, 733, 3, 2, 2, 2, 739, 118, 3, 2, 2, 2, 740, 741, 7, 63, 2, 2, 741, 751, 7, 63, 2, 2, 742, 743, 7, 35, 2, 2, 743, 751, 7, 63, 2, 2, 744, 751, 7, 62, 2, 2, 745, 746, 7, 62, 2, 2, 746, 751, 7, 63, 2, 2, 747, 751, 7, 64, 2, 2, 748, 749, 7, 64, 2, 2, 749, 751, 7, 63, 2, 2, 750, 740, 3, 2, 2, 2, 750, 742, 3, 2, 2, 2, 750, 744, 3, 2, 2, 2, 750, 745, 3, 2, 2, 2, 750, 747, 3, 2, 2, 2, 750, 748, 3, 2, 2, 2, 751, 120, 3, 2, 2, 2, 752, 753, 7, 45, 2, 2, 753, 122, 3, 2, 2, 2, 754, 755, 7, 47, 2, 2, 755, 124, 3, 2, 2, 2, 756, 757, 7, 44, 2, 2, 757, 126, 3, 2, 2, 2, 758, 759, 7, 49, 2, 2, 759, 128, 3, 2, 2, 2, 760, 761, 7, 39, 2, 2, 761, 130, 3, 2, 2, 2, 762, 763, 7, 51, 2, 2, 763, 764, 7, 50, 2, 2, 764, 132, 3, 2, 2, 2, 765, 766, 7, 99, 2, 2, 766, 767, 7, 117, 2, 2, 767, 773, 7, 101, 2, 2, 768, 769, 7, 102, 2, 2, 769, 770, 7, 103, 2, 2, 770, 771, 7, 117, 2, 2, 771, 773, 7, 101, 2, 2, 772, 765, 3, 2, 2, 2, 772, 768, 3, 2, 2, 2, 773, 134, 3, 2, 2, 2, 774, 775, 7, 112, 2, 2, 775, 776, 7, 119, 2, 2, 776, 777, 7, 110, 2, 2, 777, 778, 7, 110, 2, 2, 778, 779, 7, 117, 2, 2, 779, 136, 3, 2, 2, 2, 780, 781, 7, 104, 2, 2, 781, 782, 7, 107, 2, 2, 782, 783, 7, 116, 2, 2, 783, 784, 7, 117, 2, 2, 784, 790, 7, 118, 2, 2, 785, 786, 7, 110, 2, 2, 786, 787, 7, 99, 2, 2, 787, 788, 7, 117, 2, 2, 788, 790, 7, 118, 2, 2, 789, 780, 3, 2, 2, 2, 789, 785, 3, 2, 2, 2, 790, 138, 3, 2, 2, 2, 791, 792, 5, 237, 117, 2, 792, 793, 5, 231, 114, 2, 793, 794, 5, 243, 120, 2, 794, 795, 5, 229, 113, 2, 795, 796, 5, 209, 103, 2, 796, 1222, 3, 2, 2, 2, 797, 798, 5, 203, 100, 2, 798, 799, 5, 205, 101, 2, 799, 800, 5, 239, 118, 2, 800, 1222, 3, 2, 2, 2, 801, 802, 5, 233, 115, 2, 802, 803, 5, 231, 114, 2, 803, 804, 5, 247, 122, 2, 804, 1222, 3, 2, 2, 2, 805, 806, 5, 225, 111, 2, 806, 807, 5, 231, 114, 2, 807, 808, 5, 215, 106, 2, 808, 809, 5, 131, 64, 2, 809, 1222, 3, 2, 2, 2, 810, 811, 5, 233, 115, 2, 811, 812, 5, 219, 108, 2, 812, 1222, 3, 2, 2, 2, 813, 814, 5, 241, 119, 2, 814, 815, 5, 203, 100, 2, 815, 816, 5, 243, 120, 2, 816, 1222, 3, 2, 2, 2, 817, 1222, 5, 211, 104, 2, 818, 819, 5, 239, 118, 2, 819, 820, 5, 243, 120, 2, 820, 821, 5, 205, 101, 2, 821, 822, 5, 239, 118, 2, 822, 823, 5, 241, 119, 2, 823, 824, 5, 237, 117, 2, 824, 825, 5, 219, 108, 2, 825, 826, 5, 229, 113, 2, 826, 827, 5, 215, 106, 2, 827, 1222, 3, 2, 2, 2, 828, 829, 5, 241, 119, 2, 829, 830, 5, 237, 117, 2, 830, 831, 5, 219, 108, 2, 831, 832, 5, 227, 112, 2, 832, 1222, 3, 2, 2, 2, 833, 834, 5, 207, 102, 2, 834, 835, 5, 231, 114, 2, 835, 836, 5, 229, 113, 2, 836, 837, 5, 207, 102, 2, 837, 838, 5, 203, 100, 2, 838, 839, 5, 241, 119, 2, 839, 1222, 3, 2, 2, 2, 840, 841, 5, 207, 102, 2, 841, 842, 5, 231, 114, 2, 842, 843, 5, 203, 100, 2, 843, 844, 5, 225, 111, 2, 844, 845, 5, 211, 104, 2, 845, 846, 5, 239, 118, 2, 846, 847, 5, 207, 102, 2, 847, 848, 5, 211, 104, 2, 848, 1222, 3, 2, 2, 2, 849, 850, 5, 215, 106, 2, 850, 851, 5, 237, 117, 2, 851, 852, 5, 211, 104, 2, 852, 853, 5, 203, 100, 2, 853, 854, 5, 241, 119, 2, 854, 855, 5, 211, 104, 2, 855, 856, 5, 239, 118, 2, 856, 857, 5, 241, 119, 2, 857, 1222, 3, 2, 2, 2, 858, 859, 5, 225, 111, 2, 859, 860, 5, 211, 104, 2, 860, 861, 5, 213, 105, 2, 861, 862, 5, 241, 119, 2, 862, 1222, 3, 2, 2, 2, 863, 864, 5, 229, 113, 2, 864, 865, 5, 231, 114, 2, 865, 866, 5, 247, 122, 2, 866, 1222, 3, 2, 2, 2, 867, 868, 5, 237, 117, 2, 868, 869, 5, 219, 108, 2, 869, 870, 5, 215, 106, 2, 870, 871, 5, 217, 107, 2, 871, 872, 5, 241, 119, 2, 872, 1222, 3, 2, 2, 2, 873, 874, 5, 239, 118, 2, 874, 875, 5, 241, 119, 2, 875, 876, 5, 203, 100, 2, 876, 877, 5, 237, 117, 2, 877, 878, 5, 241, 119, 2, 878, 879, 5, 239, 118, 2, 879, 880, 5, 111, 54, 2, 880, 881, 5, 247, 122, 2, 881, 882, 5, 219, 108, 2, 882, 883, 5, 241, 119, 2, 883, 884, 5, 217, 107, 2, 884, 1222, 3, 2, 2, 2, 885, 886, 5, 209, 103, 2, 886, 887, 5, 203, 100, 2, 887, 888, 5, 241, 119, 2, 888, 889, 5, 211, 104, 2, 889, 890, 5, 111, 54, 2, 890, 891, 5, 213, 105, 2, 891, 892, 5, 231, 114, 2, 892, 893, 5, 237, 117, 2, 893, 894, 5, 227, 112, 2, 894, 895, 5, 203, 100, 2, 895, 896, 5, 241, 119, 2, 896, 1222, 3, 2, 2, 2, 897, 898, 5, 209, 103, 2, 898, 899, 5, 203, 100, 2, 899, 900, 5, 241, 119, 2, 900, 901, 5, 211, 104, 2, 901, 902, 5, 111, 54, 2, 902, 903, 5, 241, 119, 2, 903, 904, 5, 237, 117, 2, 904, 905, 5, 243, 120, 2, 905, 906, 5, 229, 113, 2, 906, 907, 5, 207, 102, 2, 907, 1222, 3, 2, 2, 2, 908, 909, 5, 209, 103, 2, 909, 910, 5, 203, 100, 2, 910, 911, 5, 241, 119, 2, 911, 912, 5, 211, 104, 2, 912, 913, 5, 111, 54, 2, 913, 914, 5, 233, 115, 2, 914, 915, 5, 203, 100, 2, 915, 916, 5, 237, 117, 2, 916, 917, 5, 239, 118, 2, 917, 918, 5, 211, 104, 2, 918, 1222, 3, 2, 2, 2, 919, 920, 5, 203, 100, 2, 920, 921, 5, 243, 120, 2, 921, 922, 5, 241, 119, 2, 922, 923, 5, 231, 114, 2, 923, 924, 5, 111, 54, 2, 924, 925, 5, 205, 101, 2, 925, 926, 5, 243, 120, 2, 926, 927, 5, 207, 102, 2, 927, 928, 5, 223, 110, 2, 928, 929, 5, 211, 104, 2, 929, 930, 5, 241, 119, 2, 930, 1222, 3, 2, 2, 2, 931, 932, 5, 209, 103, 2, 932, 933, 5, 203, 100, 2, 933, 934, 5, 241, 119, 2, 934, 935, 5, 211, 104, 2, 935, 936, 5, 111, 54, 2, 936, 937, 5, 211, 104, 2, 937, 938, 5, 249, 123, 2, 938, 939, 5, 241, 119, 2, 939, 940, 5, 237, 117, 2, 940, 941, 5, 203, 100, 2, 941, 942, 5, 207, 102, 2, 942, 943, 5, 241, 119, 2, 943, 1222, 3, 2, 2, 2, 944, 945, 5, 219, 108, 2, 945, 946, 5, 239, 118, 2, 946, 947, 5, 111, 54, 2, 947, 948, 5, 213, 105, 2, 948, 949, 5, 219, 108, 2, 949, 950, 5, 229, 113, 2, 950, 951, 5, 219, 108, 2, 951, 952, 5, 241, 119, 2, 952, 953, 5, 211, 104, 2, 953, 1222, 3, 2, 2, 2, 954, 955, 5, 219, 108, 2, 955, 956, 5, 239, 118, 2, 956, 957, 5, 111, 54, 2, 957, 958, 5, 219, 108, 2, 958, 959, 5, 229, 113, 2, 959, 960, 5, 213, 105, 2, 960, 961, 5, 219, 108, 2, 961, 962, 5, 229, 113, 2, 962, 963, 5, 219, 108, 2, 963, 964, 5, 241, 119, 2, 964, 965, 5, 211, 104, 2, 965, 1222, 3, 2, 2, 2, 966, 967, 5, 207, 102, 2, 967, 968, 5, 203, 100, 2, 968, 969, 5, 239, 118, 2, 969, 970, 5, 211, 104, 2, 970, 1222, 3, 2, 2, 2, 971, 972, 5, 225, 111, 2, 972, 973, 5, 211, 104, 2, 973, 974, 5, 229, 113, 2, 974, 975, 5, 215, 106, 2, 975, 976, 5, 241, 119, 2, 976, 977, 5, 217, 107, 2, 977, 1222, 3, 2, 2, 2, 978, 979, 5, 227, 112, 2, 979, 980, 5, 245, 121, 2, 980, 981, 5, 111, 54, 2, 981, 982, 5, 227, 112, 2, 982, 983, 5, 203, 100, 2, 983, 984, 5, 249, 123, 2, 984, 1222, 3, 2, 2, 2, 985, 986, 5, 227, 112, 2, 986, 987, 5, 245, 121, 2, 987, 988, 5, 111, 54, 2, 988, 989, 5, 227, 112, 2, 989, 990, 5, 219, 108, 2, 990, 991, 5, 229, 113, 2, 991, 1222, 3, 2, 2, 2, 992, 993, 5, 227, 112, 2, 993, 994, 5, 245, 121, 2, 994, 995, 5, 111, 54, 2, 995, 996, 5, 203, 100, 2, 996, 997, 5, 245, 121, 2, 997, 998, 5, 215, 106, 2, 998, 1222, 3, 2, 2, 2, 999, 1000, 5, 227, 112, 2, 1000, 1001, 5, 245, 121, 2, 1001, 1002, 5, 111, 54, 2, 1002, 1003, 5, 239, 118, 2, 1003, 1004, 5, 243, 120, 2, 1004, 1005, 5, 227, 112, 2, 1005, 1222, 3, 2, 2, 2, 1006, 1007, 5, 227, 112, 2, 1007, 1008, 5, 245, 121, 2, 1008, 1009, 5, 111, 54, 2, 1009, 1010, 5, 207, 102, 2, 1010, 1011, 5, 231, 114, 2, 1011, 1012, 5, 243, 120, 2, 1012, 1013, 5, 229, 113, 2, 1013, 1014, 5, 241, 119, 2, 1014, 1222, 3, 2, 2, 2, 1015, 1016, 5, 227, 112, 2, 1016, 1017, 5, 245, 121, 2, 1017, 1018, 5, 111, 54, 2, 1018, 1019, 5, 207, 102, 2, 1019, 1020, 5, 231, 114, 2, 1020, 1021, 5, 229, 113, 2, 1021, 1022, 5, 207, 102, 2, 1022, 1023, 5, 203, 100, 2, 1023, 1024, 5, 241, 119, 2, 1024, 1222, 3, 2, 2, 2, 1025, 1026, 5, 227, 112, 2, 1026, 1027, 5, 245, 121, 2, 1027, 1028, 5, 111, 54, 2, 1028, 1029, 5, 221, 109, 2, 1029, 1030, 5, 231, 114, 2, 1030, 1031, 5, 219, 108, 2, 1031, 1032, 5, 229, 113, 2, 1032, 1222, 3, 2, 2, 2, 1033, 1034, 5, 227, 112, 2, 1034, 1035, 5, 245, 121, 2, 1035, 1036, 5, 111, 54, 2, 1036, 1037, 5, 227, 112, 2, 1037, 1038, 5, 211, 104, 2, 1038, 1039, 5, 209, 103, 2, 1039, 1040, 5, 219, 108, 2, 1040, 1041, 5, 203, 100, 2, 1041, 1042, 5, 229, 113, 2, 1042, 1222, 3, 2, 2, 2, 1043, 1044, 5, 227, 112, 2, 1044, 1045, 5, 245, 121, 2, 1045, 1046, 5, 111, 54, 2, 1046, 1047, 5, 209, 103, 2, 1047, 1048, 5, 211, 104, 2, 1048, 1049, 5, 209, 103, 2, 1049, 1050, 5, 243, 120, 2, 1050, 1051, 5, 233, 115, 2, 1051, 1052, 5, 211, 104, 2, 1052, 1222, 3, 2, 2, 2, 1053, 1054, 5, 227, 112, 2, 1054, 1055, 5, 211, 104, 2, 1055, 1056, 5, 241, 119, 2, 1056, 1057, 5, 203, 100, 2, 1057, 1058, 5, 209, 103, 2, 1058, 1059, 5, 203, 100, 2, 1059, 1060, 5, 241, 119, 2, 1060, 1061, 5, 203, 100, 2, 1061, 1222, 3, 2, 2, 2, 1062, 1063, 5, 239, 118, 2, 1063, 1064, 5, 233, 115, 2, 1064, 1065, 5, 225, 111, 2, 1065, 1066, 5, 219, 108, 2, 1066, 1067, 5, 241, 119, 2, 1067, 1222, 3, 2, 2, 2, 1068, 1069, 5, 241, 119, 2, 1069, 1070, 5, 231, 114, 2, 1070, 1071, 5, 111, 54, 2, 1071, 1072, 5, 239, 118, 2, 1072, 1073, 5, 241, 119, 2, 1073, 1074, 5, 237, 117, 2, 1074, 1075, 5, 219, 108, 2, 1075, 1076, 5, 229, 113, 2, 1076, 1077, 5, 215, 106, 2, 1077, 1222, 3, 2, 2, 2, 1078, 1079, 5, 241, 119, 2, 1079, 1080, 5, 231, 114, 2, 1080, 1081, 5, 111, 54, 2, 1081, 1082, 5, 239, 118, 2, 1082, 1083, 5, 241, 119, 2, 1083, 1084, 5, 237, 117, 2, 1084, 1222, 3, 2, 2, 2, 1085, 1086, 5, 241, 119, 2, 1086, 1087, 5, 231, 114, 2, 1087, 1088, 5, 111, 54, 2, 1088, 1089, 5, 205, 101, 2, 1089, 1090, 5, 231, 114, 2, 1090, 1091, 5, 231, 114, 2, 1091, 1092, 5, 225, 111, 2, 1092, 1222, 3, 2, 2, 2, 1093, 1094, 5, 241, 119, 2, 1094, 1095, 5, 231, 114, 2, 1095, 1096, 5, 111, 54, 2, 1096, 1097, 5, 205, 101, 2, 1097, 1098, 5, 231, 114, 2, 1098, 1099, 5, 231, 114, 2, 1099, 1100, 5, 225, 111, 2, 1100, 1101, 5, 211, 104, 2, 1101, 1102, 5, 203, 100, 2, 1102, 1103, 5, 229, 113, 2, 1103, 1222, 3, 2, 2, 2, 1104, 1105, 5, 241, 119, 2, 1105, 1106, 5, 231, 114, 2, 1106, 1107, 5, 111, 54, 2, 1107, 1108, 5, 209, 103, 2, 1108, 1109, 5, 203, 100, 2, 1109, 1110, 5, 241, 119, 2, 1110, 1111, 5, 211, 104, 2, 1111, 1112, 5, 241, 119, 2, 1112, 1113, 5, 219, 108, 2, 1113, 1114, 5, 227, 112, 2, 1114, 1115, 5, 211, 104, 2, 1115, 1222, 3, 2, 2, 2, 1116, 1117, 5, 241, 119, 2, 1117, 1118, 5, 231, 114, 2, 1118, 1119, 5, 111, 54, 2, 1119, 1120, 5, 209, 103, 2, 1120, 1121, 5, 241, 119, 2, 1121, 1222, 3, 2, 2, 2, 1122, 1123, 5, 241, 119, 2, 1123, 1124, 5, 231, 114, 2, 1124, 1125, 5, 111, 54, 2, 1125, 1126, 5, 209, 103, 2, 1126, 1127, 5, 205, 101, 2, 1127, 1128, 5, 225, 111, 2, 1128, 1222, 3, 2, 2, 2, 1129, 1130, 5, 241, 119, 2, 1130, 1131, 5, 231, 114, 2, 1131, 1132, 5, 111, 54, 2, 1132, 1133, 5, 209, 103, 2, 1133, 1134, 5, 231, 114, 2, 1134, 1135, 5, 243, 120, 2, 1135, 1136, 5, 205, 101, 2, 1136, 1137, 5, 225, 111, 2, 1137, 1138, 5, 211, 104, 2, 1138, 1222, 3, 2, 2, 2, 1139, 1140, 5, 241, 119, 2, 1140, 1141, 5, 231, 114, 2, 1141, 1142, 5, 111, 54, 2, 1142, 1143, 5, 209, 103, 2, 1143, 1144, 5, 211, 104, 2, 1144, 1145, 5, 215, 106, 2, 1145, 1146, 5, 237, 117, 2, 1146, 1147, 5, 211, 104, 2, 1147, 1148, 5, 211, 104, 2, 1148, 1149, 5, 239, 118, 2, 1149, 1222, 3, 2, 2, 2, 1150, 1151, 5, 241, 119, 2, 1151, 1152, 5, 231, 114, 2, 1152, 1153, 5, 111, 54, 2, 1153, 1154, 5, 219, 108, 2, 1154, 1155, 5, 229, 113, 2, 1155, 1156, 5, 241, 119, 2, 1156, 1222, 3, 2, 2, 2, 1157, 1158, 5, 241, 119, 2, 1158, 1159, 5, 231, 114, 2, 1159, 1160, 5, 111, 54, 2, 1160, 1161, 5, 219, 108, 2, 1161, 1162, 5, 229, 113, 2, 1162, 1163, 5, 241, 119, 2, 1163, 1164, 5, 211, 104, 2, 1164, 1165, 5, 215, 106, 2, 1165, 1166, 5, 211, 104, 2, 1166, 1167, 5, 237, 117, 2, 1167, 1222, 3, 2, 2, 2, 1168, 1169, 5, 241, 119, 2, 1169, 1170, 5, 231, 114, 2, 1170, 1171, 5, 111, 54, 2, 1171, 1172, 5, 219, 108, 2, 1172, 1173, 5, 233, 115, 2, 1173, 1222, 3, 2, 2, 2, 1174, 1175, 5, 241, 119, 2, 1175, 1176, 5, 231, 114, 2, 1176, 1177, 5, 111, 54, 2, 1177, 1178, 5, 225, 111, 2, 1178, 1179, 5, 231, 114, 2, 1179, 1180, 5, 229, 113, 2, 1180, 1181, 5, 215, 106, 2, 1181, 1222, 3, 2, 2, 2, 1182, 1183, 5, 241, 119, 2, 1183, 1184, 5, 231, 114, 2, 1184, 1185, 5, 111, 54, 2, 1185, 1186, 5, 237, 117, 2, 1186, 1187, 5, 203, 100, 2, 1187, 1188, 5, 209, 103, 2, 1188, 1189, 5, 219, 108, 2, 1189, 1190, 5, 203, 100, 2, 1190, 1191, 5, 229, 113, 2, 1191, 1192, 5, 239, 118, 2, 1192, 1222, 3, 2, 2, 2, 1193, 1194, 5, 241, 119, 2, 1194, 1195, 5, 231, 114, 2, 1195, 1196, 5, 111, 54, 2, 1196, 1197, 5, 245, 121, 2, 1197, 1198, 5, 211, 104, 2, 1198, 1199, 5, 237, 117, 2, 1199, 1200, 5, 239, 118, 2, 1200, 1201, 5, 219, 108, 2, 1201, 1202, 5, 231, 114, 2, 1202, 1203, 5, 229, 113, 2, 1203, 1222, 3, 2, 2, 2, 1204, 1205, 5, 241, 119, 2, 1205, 1206, 5, 231, 114, 2, 1206, 1207, 5, 111, 54, 2, 1207, 1208, 5, 243, 120, 2, 1208, 1209, 5, 229, 113, 2, 1209, 1210, 5, 239, 118, 2, 1210, 1211, 5, 219, 108, 2, 1211, 1212, 5, 215, 106, 2, 1212, 1213, 5, 229, 113, 2, 1213, 1214, 5, 211, 104, 2, 1214, 1215, 5, 209, 103, 2, 1215, 1216, 5, 111, 54, 2, 1216, 1217, 5, 225, 111, 2, 1217, 1218, 5, 231, 114, 2, 1218, 1219, 5, 229, 113, 2, 1219, 1220, 5, 215, 106, 2, 1220, 1222, 3, 2, 2, 2, 1221, 791, 3, 2, 2, 2, 1221, 797, 3, 2, 2, 2, 1221, 801, 3, 2, 2, 2, 1221, 805, 3, 2, 2, 2, 1221, 810, 3, 2, 2, 2, 1221, 813, 3, 2, 2, 2, 1221, 817, 3, 2, 2, 2, 1221, 818, 3, 2, 2, 2, 1221, 828, 3, 2, 2, 2, 1221, 833, 3, 2, 2, 2, 1221, 840, 3, 2, 2, 2, 1221, 849, 3, 2, 2, 2, 1221, 858, 3, 2, 2, 2, 1221, 863, 3, 2, 2, 2, 1221, 867, 3, 2, 2, 2, 1221, 873, 3, 2, 2, 2, 1221, 885, 3, 2, 2, 2, 1221, 897, 3, 2, 2, 2, 1221, 908, 3, 2, 2, 2, 1221, 919, 3, 2, 2, 2, 1221, 931, 3, 2, 2, 2, 1221, 944, 3, 2, 2, 2, 1221, 954, 3, 2, 2, 2, 1221, 966, 3, 2, 2, 2, 1221, 971, 3, 2, 2, 2, 1221, 978, 3, 2, 2, 2, 1221, 985, 3, 2, 2, 2, 1221, 992, 3, 2, 2, 2, 1221, 999, 3, 2, 2, 2, 1221, 1006, 3, 2, 2, 2, 1221, 1015, 3, 2, 2, 2, 1221, 1025, 3, 2, 2, 2, 1221, 1033, 3, 2, 2, 2, 1221, 1043, 3, 2, 2, 2, 1221, 1053, 3, 2, 2, 2, 1221, 1062, 3, 2, 2, 2, 1221, 1068, 3, 2, 2, 2, 1221, 1078, 3, 2, 2, 2, 1221, 1085, 3, 2, 2, 2, 1221, 1093, 3, 2, 2, 2, 1221, 1104, 3, 2, 2, 2, 1221, 1116, 3, 2, 2, 2, 1221, 1122, 3, 2, 2, 2, 1221, 1129, 3, 2, 2, 2, 1221, 1139, 3, 2, 2, 2, 1221, 1150, 3, 2, 2, 2, 1221, 1157, 3, 2, 2, 2, 1221, 1168, 3, 2, 2, 2, 1221, 1174, 3, 2, 2, 2, 1221, 1182, 3, 2, 2, 2, 1221, 1193, 3, 2, 2, 2, 1221, 1204, 3, 2, 2, 2, 1222, 140, 3, 2, 2, 2, 1223, 1224, 5, 203, 100, 2, 1224, 1225, 5, 245, 121, 2, 1225, 1226, 5, 215, 106, 2, 1226, 1375, 3, 2, 2, 2, 1227, 1228, 5, 227, 112, 2, 1228, 1229, 5, 219, 108, 2, 1229, 1230, 5, 229, 113, 2, 1230, 1375, 3, 2, 2, 2, 1231, 1232, 5, 227, 112, 2, 1232, 1233, 5, 203, 100, 2, 1233, 1234, 5, 249, 123, 2, 1234, 1375, 3, 2, 2, 2, 1235, 1236, 5, 239, 118, 2, 1236, 1237, 5, 243, 120, 2, 1237, 1238, 5, 227, 112, 2, 1238, 1375, 3, 2, 2, 2, 1239, 1240, 5, 207, 102, 2, 1240, 1241, 5, 231, 114, 2, 1241, 1242, 5, 243, 120, 2, 1242, 1243, 5, 229, 113, 2, 1243, 1244, 5, 241, 119, 2, 1244, 1375, 3, 2, 2, 2, 1245, 1246, 5, 207, 102, 2, 1246, 1247, 5, 231, 114, 2, 1247, 1248, 5, 243, 120, 2, 1248, 1249, 5, 229, 113, 2, 1249, 1250, 5, 241, 119, 2, 1250, 1251, 5, 111, 54, 2, 1251, 1252, 5, 209, 103, 2, 1252, 1253, 5, 219, 108, 2, 1253, 1254, 5, 239, 118, 2, 1254, 1255, 5, 241, 119, 2, 1255, 1256, 5, 219, 108, 2, 1256, 1257, 5, 229, 113, 2, 1257, 1258, 5, 207, 102, 2, 1258, 1259, 5, 241, 119, 2, 1259, 1375, 3, 2, 2, 2, 1260, 1261, 5, 233, 115, 2, 1261, 1262, 5, 211, 104, 2, 1262, 1263, 5, 237, 117, 2, 1263, 1264, 5, 207, 102, 2, 1264, 1265, 5, 211, 104, 2, 1265, 1266, 5, 229, 113, 2, 1266, 1267, 5, 241, 119, 2, 1267, 1268, 5, 219, 108, 2, 1268, 1269, 5, 225, 111, 2, 1269, 1270, 5, 211, 104, 2, 1270, 1375, 3, 2, 2, 2, 1271, 1272, 5, 227, 112, 2, 1272, 1273, 5, 211, 104, 2, 1273, 1274, 5, 209, 103, 2, 1274, 1275, 5, 219, 108, 2, 1275, 1276, 5, 203, 100, 2, 1276, 1277, 5, 229, 113, 2, 1277, 1375, 3, 2, 2, 2, 1278, 1279, 5, 227, 112, 2, 1279, 1280, 5, 211, 104, 2, 1280, 1281, 5, 209, 103, 2, 1281, 1282, 5, 219, 108, 2, 1282, 1283, 5, 203, 100, 2, 1283, 1284, 5, 229, 113, 2, 1284, 1285, 5, 111, 54, 2, 1285, 1286, 5, 203, 100, 2, 1286, 1287, 5, 205, 101, 2, 1287, 1288, 5, 239, 118, 2, 1288, 1289, 5, 231, 114, 2, 1289, 1290, 5, 225, 111, 2, 1290, 1291, 5, 243, 120, 2, 1291, 1292, 5, 241, 119, 2, 1292, 1293, 5, 211, 104, 2, 1293, 1294, 5, 111, 54, 2, 1294, 1295, 5, 209, 103, 2, 1295, 1296, 5, 211, 104, 2, 1296, 1297, 5, 245, 121, 2, 1297, 1298, 5, 219, 108, 2, 1298, 1299, 5, 203, 100, 2, 1299, 1300, 5, 241, 119, 2, 1300, 1301, 5, 219, 108, 2, 1301, 1302, 5, 231, 114, 2, 1302, 1303, 5, 229, 113, 2, 1303, 1375, 3, 2, 2, 2, 1304, 1305, 5, 203, 100, 2, 1305, 1306, 5, 207, 102, 2, 1306, 1307, 5, 231, 114, 2, 1307, 1308, 5, 239, 118, 2, 1308, 1375, 3, 2, 2, 2, 1309, 1310, 5, 203, 100, 2, 1310, 1311, 5, 239, 118, 2, 1311, 1312, 5, 219, 108, 2, 1312, 1313, 5, 229, 113, 2, 1313, 1375, 3, 2, 2, 2, 1314, 1315, 5, 203, 100, 2, 1315, 1316, 5, 241, 119, 2, 1316, 1317, 5, 203, 100, 2, 1317, 1318, 5, 229, 113, 2, 1318, 1375, 3, 2, 2, 2, 1319, 1320, 5, 203, 100, 2, 1320, 1321, 5, 241, 119, 2, 1321, 1322, 5, 203, 100, 2, 1322, 1323, 5, 229, 113, 2, 1323, 1324, 7, 52, 2, 2, 1324, 1375, 3, 2, 2, 2, 1325, 1326, 5, 207, 102, 2, 1326, 1327, 5, 211, 104, 2, 1327, 1328, 5, 219, 108, 2, 1328, 1329, 5, 225, 111, 2, 1329, 1375, 3, 2, 2, 2, 1330, 1331, 5, 207, 102, 2, 1331, 1332, 5, 231, 114, 2, 1332, 1333, 5, 239, 118, 2, 1333, 1375, 3, 2, 2, 2, 1334, 1335, 5, 207, 102, 2, 1335, 1336, 5, 231, 114, 2, 1336, 1337, 5, 239, 118, 2, 1337, 1338, 5, 217, 107, 2, 1338, 1375, 3, 2, 2, 2, 1339, 1340, 5, 213, 105, 2, 1340, 1341, 5, 225, 111, 2, 1341, 1342, 5, 231, 114, 2, 1342, 1343, 5, 231, 114, 2, 1343, 1344, 5, 237, 117, 2, 1344, 1375, 3, 2, 2, 2, 1345, 1346, 5, 225, 111, 2, 1346, 1347, 5, 241, 119, 2, 1347, 1348, 5, 237, 117, 2, 1348, 1349, 5, 219, 108, 2, 1349, 1350, 5, 227, 112, 2, 1350, 1375, 3, 2, 2, 2, 1351, 1352, 5, 239, 118, 2, 1352, 1353, 5, 219, 108, 2, 1353, 1354, 5, 229, 113, 2, 1354, 1375, 3, 2, 2, 2, 1355, 1356, 5, 239, 118, 2, 1356, 1357, 5, 219, 108, 2, 1357, 1358, 5, 229, 113, 2, 1358, 1359, 5, 217, 107, 2, 1359, 1375, 3, 2, 2, 2, 1360, 1361, 5, 239, 118, 2, 1361, 1362, 5, 235, 116, 2, 1362, 1363, 5, 237, 117, 2, 1363, 1364, 5, 241, 119, 2, 1364, 1375, 3, 2, 2, 2, 1365, 1366, 5, 241, 119, 2, 1366, 1367, 5, 203, 100, 2, 1367, 1368, 5, 229, 113, 2, 1368, 1375, 3, 2, 2, 2, 1369, 1370, 5, 241, 119, 2, 1370, 1371, 5, 203, 100, 2, 1371, 1372, 5, 229, 113, 2, 1372, 1373, 5, 217, 107, 2, 1373, 1375, 3, 2, 2, 2, 1374, 1223, 3, 2, 2, 2, 1374, 1227, 3, 2, 2, 2, 1374, 1231, 3, 2, 2, 2, 1374, 1235, 3, 2, 2, 2, 1374, 1239, 3, 2, 2, 2, 1374, 1245, 3, 2, 2, 2, 1374, 1260, 3, 2, 2, 2, 1374, 1271, 3, 2, 2, 2, 1374, 1278, 3, 2, 2, 2, 1374, 1304, 3, 2, 2, 2, 1374, 1309, 3, 2, 2, 2, 1374, 1314, 3, 2, 2, 2, 1374, 1319, 3, 2, 2, 2, 1374, 1325, 3, 2, 2, 2, 1374, 1330, 3, 2, 2, 2, 1374, 1334, 3, 2, 2, 2, 1374, 1339, 3, 2, 2, 2, 1374, 1345, 3, 2, 2, 2, 1374, 1351, 3, 2, 2, 2, 1374, 1355, 3, 2, 2, 2, 1374, 1360, 3, 2, 2, 2, 1374, 1365, 3, 2, 2, 2, 1374, 1369, 3, 2, 2, 2, 1375, 142, 3, 2, 2, 2, 1376, 1377, 5, 207, 102, 2, 1377, 1378, 5, 219, 108, 2, 1378, 1379, 5, 209, 103, 2, 1379, 1380, 5, 237, 117, 2, 1380, 1381, 5, 111, 54, 2, 1381, 1382, 5, 227, 112, 2, 1382, 1383, 5, 203, 100, 2, 1383, 1384, 5, 241, 119, 2, 1384, 1385, 5, 207, 102, 2, 1385, 1386, 5, 217, 107, 2, 1386, 144, 3, 2, 2, 2, 1387, 1394, 5, 61, 29, 2, 1388, 1393, 5, 61, 29, 2, 1389, 1393, 5, 59, 28, 2, 1390, 1393, 7, 97, 2, 2, 1391, 1393, 5, 125, 61, 2, 1392, 1388, 3, 2, 2, 2, 1392, 1389, 3, 2, 2, 2, 1392, 1390, 3, 2, 2, 2, 1392, 1391, 3, 2, 2, 2, 1393, 1396, 3, 2, 2, 2, 1394, 1392, 3, 2, 2, 2, 1394, 1395, 3, 2, 2, 2, 1395, 1407, 3, 2, 2, 2, 1396, 1394, 3, 2, 2, 2, 1397, 1402, 9, 10, 2, 2, 1398, 1403, 5, 61, 29, 2, 1399, 1403, 5, 59, 28, 2, 1400, 1403, 7, 97, 2, 2, 1401, 1403, 5, 125, 61, 2, 1402, 1398, 3, 2, 2, 2, 1402, 1399, 3, 2, 2, 2, 1402, 1400, 3, 2, 2, 2, 1402, 1401, 3, 2, 2, 2, 1403, 1404, 3, 2, 2, 2, 1404, 1402, 3, 2, 2, 2, 1404, 1405, 3, 2, 2, 2, 1405, 1407, 3, 2, 2, 2, 1406, 1387, 3, 2, 2, 2, 1406, 1397, 3, 2, 2, 2, 1407, 146, 3, 2, 2, 2, 1408, 1414, 7, 98, 2, 2, 1409, 1413, 10, 11, 2, 2, 1410, 1411, 7, 98, 2, 2, 1411, 1413, 7, 98, 2, 2, 1412, 1409, 3, 2, 2, 2, 1412, 1410, 3, 2, 2, 2, 1413, 1416, 3, 2, 2, 2, 1414, 1412, 3, 2, 2, 2, 1414, 1415, 3, 2, 2, 2, 1415, 1417, 3, 2, 2, 2, 1416, 1414, 3, 2, 2, 2, 1417, 1418, 7, 98, 2, 2, 1418, 148, 3, 2, 2, 2, 1419, 1420, 5, 41, 19, 2, 1420, 1421, 3, 2, 2, 2, 1421, 1422, 8, 73, 6, 2, 1422, 150, 3, 2, 2, 2, 1423, 1424, 5, 43, 20, 2, 1424, 1425, 3, 2, 2, 2, 1425, 1426, 8, 74, 6, 2, 1426, 152, 3, 2, 2, 2, 1427, 1428, 5, 45, 21, 2, 1428, 1429, 3, 2, 2, 2, 1429, 1430, 8, 75, 6, 2, 1430, 154, 3, 2, 2, 2, 1431, 1432, 7, 126, 2, 2, 1432, 1433, 3, 2, 2, 2, 1433, 1434, 8, 76, 9, 2, 1434, 1435, 8, 76, 10, 2, 1435, 156, 3, 2, 2, 2, 1436, 1437, 7, 93, 2, 2, 1437, 1438, 3, 2, 2, 2, 1438, 1439, 8, 77, 7, 2, 1439, 1440, 8, 77, 4, 2, 1440, 1441, 8, 77, 4, 2, 1441, 158, 3, 2, 2, 2, 1442, 1443, 7, 95, 2, 2, 1443, 1444, 3, 2, 2, 2, 1444, 1445, 8, 78, 10, 2, 1445, 1446, 8, 78, 10, 2, 1446, 1447, 8, 78, 11, 2, 1447, 160, 3, 2, 2, 2, 1448, 1449, 7, 46, 2, 2, 1449, 1450, 3, 2, 2, 2, 1450, 1451, 8, 79, 12, 2, 1451, 162, 3, 2, 2, 2, 1452, 1453, 7, 63, 2, 2, 1453, 1454, 3, 2, 2, 2, 1454, 1455, 8, 80, 13, 2, 1455, 164, 3, 2, 2, 2, 1456, 1457, 5, 227, 112, 2, 1457, 1458, 5, 211, 104, 2, 1458, 1459, 5, 241, 119, 2, 1459, 1460, 5, 203, 100, 2, 1460, 1461, 5, 209, 103, 2, 1461, 1462, 5, 203, 100, 2, 1462, 1463, 5, 241, 119, 2, 1463, 1464, 5, 203, 100, 2, 1464, 166, 3, 2, 2, 2, 1465, 1467, 5, 169, 83, 2, 1466, 1465, 3, 2, 2, 2, 1467, 1468, 3, 2, 2, 2, 1468, 1466, 3, 2, 2, 2, 1468, 1469, 3, 2, 2, 2, 1469, 168, 3, 2, 2, 2, 1470, 1472, 10, 12, 2, 2, 1471, 1470, 3, 2, 2, 2, 1472, 1473, 3, 2, 2, 2, 1473, 1471, 3, 2, 2, 2, 1473, 1474, 3, 2, 2, 2, 1474, 1478, 3, 2, 2, 2, 1475, 1476, 7, 49, 2, 2, 1476, 1478, 10, 13, 2, 2, 1477, 1471, 3, 2, 2, 2, 1477, 1475, 3, 2, 2, 2, 1478, 170, 3, 2, 2, 2, 1479, 1480, 5, 147, 72, 2, 1480, 172, 3, 2, 2, 2, 1481, 1482, 5, 41, 19, 2, 1482, 1483, 3, 2, 2, 2, 1483, 1484, 8, 85, 6, 2, 1484, 174, 3, 2, 2, 2, 1485, 1486, 5, 43, 20, 2, 1486, 1487, 3, 2, 2, 2, 1487, 1488, 8, 86, 6, 2, 1488, 176, 3, 2, 2, 2, 1489, 1490, 5, 45, 21, 2, 1490, 1491, 3, 2, 2, 2, 1491, 1492, 8, 87, 6, 2, 1492, 178, 3, 2, 2, 2, 1493, 1494, 5, 231, 114, 2, 1494, 1495, 5, 229, 113, 2, 1495, 180, 3, 2, 2, 2, 1496, 1497, 5, 247, 122, 2, 1497, 1498, 5, 219, 108, 2, 1498, 1499, 5, 241, 119, 2, 1499, 1500, 5, 217, 107, 2, 1500, 182, 3, 2, 2, 2, 1501, 1502, 7, 126, 2, 2, 1502, 1503, 3, 2, 2, 2, 1503, 1504, 8, 90, 9, 2, 1504, 1505, 8, 90, 10, 2, 1505, 184, 3, 2, 2, 2, 1506, 1507, 7, 95, 2, 2, 1507, 1508, 3, 2, 2, 2, 1508, 1509, 8, 91, 10, 2, 1509, 1510, 8, 91, 10, 2, 1510, 1511, 8, 91, 11, 2, 1511, 186, 3, 2, 2, 2, 1512, 1513, 7, 46, 2, 2, 1513, 1514, 3, 2, 2, 2, 1514, 1515, 8, 92, 12, 2, 1515, 188, 3, 2, 2, 2, 1516, 1517, 7, 63, 2, 2, 1517, 1518, 3, 2, 2, 2, 1518, 1519, 8, 93, 13, 2, 1519, 190, 3, 2, 2, 2, 1520, 1522, 5, 193, 95, 2, 1521, 1520, 3, 2, 2, 2, 1522, 1523, 3, 2, 2, 2, 1523, 1521, 3, 2, 2, 2, 1523, 1524, 3, 2, 2, 2, 1524, 192, 3, 2, 2, 2, 1525, 1527, 10, 12, 2, 2, 1526, 1525, 3, 2, 2, 2, 1527, 1528, 3, 2, 2, 2, 1528, 1526, 3, 2, 2, 2, 1528, 1529, 3, 2, 2, 2, 1529, 1533, 3, 2, 2, 2, 1530, 1531, 7, 49, 2, 2, 1531, 1533, 10, 13, 2, 2, 1532, 1526, 3, 2, 2, 2, 1532, 1530, 3, 2, 2, 2, 1533, 194, 3, 2, 2, 2, 1534, 1535, 5, 147, 72, 2, 1535, 196, 3, 2, 2, 2, 1536, 1537, 5, 41, 19, 2, 1537, 1538, 3, 2, 2, 2, 1538, 1539, 8, 97, 6, 2, 1539, 198, 3, 2, 2, 2, 1540, 1541, 5, 43, 20, 2, 1541, 1542, 3, 2, 2, 2, 1542, 1543, 8, 98, 6, 2, 1543, 200, 3, 2, 2, 2, 1544, 1545, 5, 45, 21, 2, 1545, 1546, 3, 2, 2, 2, 1546, 1547, 8, 99, 6, 2, 1547, 202, 3, 2, 2, 2, 1548, 1549, 9, 14, 2, 2, 1549, 204, 3, 2, 2, 2, 1550, 1551, 9, 15, 2, 2, 1551, 206, 3, 2, 2, 2, 1552, 1553, 9, 16, 2, 2, 1553, 208, 3, 2, 2, 2, 1554, 1555, 9, 17, 2, 2, 1555, 210, 3, 2, 2, 2, 1556, 1557, 9, 8, 2, 2, 1557, 212, 3, 2, 2, 2, 1558, 1559, 9, 18, 2, 2, 1559, 214, 3, 2, 2, 2, 1560, 1561, 9, 19, 2, 2, 1561, 216, 3, 2, 2, 2, 1562, 1563, 9, 20, 2, 2, 1563, 218, 3, 2, 2, 2, 1564, 1565, 9, 21, 2, 2, 1565, 220, 3, 2, 2, 2, 1566, 1567, 9, 22, 2, 2, 1567, 222, 3, 2, 2, 2, 1568, 1569, 9, 23, 2, 2, 1569, 224, 3, 2, 2, 2, 1570, 1571, 9, 24, 2, 2, 1571, 226, 3, 2, 2, 2, 1572, 1573, 9, 25, 2, 2, 1573, 228, 3, 2, 2, 2, 1574, 1575, 9, 26, 2, 2, 1575, 230, 3, 2, 2, 2, 1576, 1577, 9, 27, 2, 2, 1577, 232, 3, 2, 2, 2, 1578, 1579, 9, 28, 2, 2, 1579, 234, 3, 2, 2, 2, 1580, 1581, 9, 29, 2, 2, 1581, 236, 3, 2, 2, 2, 1582, 1583, 9, 30, 2, 2, 1583, 238, 3, 2, 2, 2, 1584, 1585, 9, 31, 2, 2, 1585, 240, 3, 2, 2, 2, 1586, 1587, 9, 32, 2, 2, 1587, 242, 3, 2, 2, 2, 1588, 1589, 9, 33, 2, 2, 1589, 244, 3, 2, 2, 2, 1590, 1591, 9, 34, 2, 2, 1591, 246, 3, 2, 2, 2, 1592, 1593, 9, 35, 2, 2, 1593, 248, 3, 2, 2, 2, 1594, 1595, 9, 36, 2, 2, 1595, 250, 3, 2, 2, 2, 1596, 1597, 9, 37, 2, 2, 1597, 252, 3, 2, 2, 2, 1598, 1599, 9, 38, 2, 2, 1599, 254, 3, 2, 2, 2, 50, 2, 3, 4, 5, 6, 400, 404, 407, 416, 418, 429, 470, 475, 480, 482, 493, 501, 504, 506, 511, 516, 522, 529, 534, 540, 543, 551, 555, 654, 738, 750, 772, 789, 1221, 1374, 1392, 1394, 1402, 1404, 1406, 1412, 1414, 1468, 1473, 1477, 1523, 1528, 1532, 14, 7, 4, 2, 7, 3, 2, 7, 5, 2, 7, 6, 2, 2, 3, 2, 9, 37, 2, 7, 2, 2, 9, 26, 2, 6, 2, 2, 9, 38, 2, 9, 34, 2, 9, 33, 2] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 78, 813, 8, 1, 8, 1, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 6, 18, 362, 10, 18, 13, 18, 14, 18, 363, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 372, 10, 19, 12, 19, 14, 19, 375, 11, 19, 3, 19, 5, 19, 378, 10, 19, 3, 19, 5, 19, 381, 10, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 390, 10, 20, 12, 20, 14, 20, 393, 11, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 6, 21, 401, 10, 21, 13, 21, 14, 21, 402, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 5, 27, 422, 10, 27, 3, 27, 6, 27, 425, 10, 27, 13, 27, 14, 27, 426, 3, 28, 3, 28, 3, 28, 7, 28, 432, 10, 28, 12, 28, 14, 28, 435, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 443, 10, 28, 12, 28, 14, 28, 446, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 453, 10, 28, 3, 28, 5, 28, 456, 10, 28, 5, 28, 458, 10, 28, 3, 29, 6, 29, 461, 10, 29, 13, 29, 14, 29, 462, 3, 30, 6, 30, 466, 10, 30, 13, 30, 14, 30, 467, 3, 30, 3, 30, 7, 30, 472, 10, 30, 12, 30, 14, 30, 475, 11, 30, 3, 30, 3, 30, 6, 30, 479, 10, 30, 13, 30, 14, 30, 480, 3, 30, 6, 30, 484, 10, 30, 13, 30, 14, 30, 485, 3, 30, 3, 30, 7, 30, 490, 10, 30, 12, 30, 14, 30, 493, 11, 30, 5, 30, 495, 10, 30, 3, 30, 3, 30, 3, 30, 3, 30, 6, 30, 501, 10, 30, 13, 30, 14, 30, 502, 3, 30, 3, 30, 5, 30, 507, 10, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 3, 63, 3, 64, 3, 64, 3, 65, 3, 65, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 69, 7, 69, 651, 10, 69, 12, 69, 14, 69, 654, 11, 69, 3, 69, 3, 69, 3, 69, 3, 69, 6, 69, 660, 10, 69, 13, 69, 14, 69, 661, 5, 69, 664, 10, 69, 3, 70, 3, 70, 3, 70, 3, 70, 7, 70, 670, 10, 70, 12, 70, 14, 70, 673, 11, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 82, 3, 82, 3, 83, 6, 83, 735, 10, 83, 13, 83, 14, 83, 736, 3, 84, 6, 84, 740, 10, 84, 13, 84, 14, 84, 741, 3, 84, 3, 84, 5, 84, 746, 10, 84, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 96, 3, 96, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 4, 391, 444, 2, 2, 115, 5, 2, 3, 7, 2, 4, 9, 2, 5, 11, 2, 6, 13, 2, 7, 15, 2, 8, 17, 2, 9, 19, 2, 10, 21, 2, 11, 23, 2, 12, 25, 2, 13, 27, 2, 14, 29, 2, 15, 31, 2, 16, 33, 2, 17, 35, 2, 18, 37, 2, 19, 39, 2, 20, 41, 2, 21, 43, 2, 22, 45, 2, 23, 47, 2, 2, 49, 2, 2, 51, 2, 2, 53, 2, 2, 55, 2, 2, 57, 2, 24, 59, 2, 25, 61, 2, 26, 63, 2, 27, 65, 2, 28, 67, 2, 29, 69, 2, 30, 71, 2, 31, 73, 2, 32, 75, 2, 33, 77, 2, 34, 79, 2, 35, 81, 2, 36, 83, 2, 37, 85, 2, 38, 87, 2, 39, 89, 2, 40, 91, 2, 41, 93, 2, 42, 95, 2, 43, 97, 2, 44, 99, 2, 45, 101, 2, 46, 103, 2, 47, 105, 2, 48, 107, 2, 49, 109, 2, 50, 111, 2, 51, 113, 2, 52, 115, 2, 53, 117, 2, 54, 119, 2, 55, 121, 2, 56, 123, 2, 57, 125, 2, 58, 127, 2, 59, 129, 2, 60, 131, 2, 61, 133, 2, 62, 135, 2, 63, 137, 2, 64, 139, 2, 65, 141, 2, 66, 143, 2, 67, 145, 2, 68, 147, 2, 69, 149, 2, 2, 151, 2, 2, 153, 2, 2, 155, 2, 2, 157, 2, 2, 159, 2, 70, 161, 2, 71, 163, 2, 72, 165, 2, 73, 167, 2, 74, 169, 2, 2, 171, 2, 75, 173, 2, 76, 175, 2, 77, 177, 2, 78, 179, 2, 2, 181, 2, 2, 183, 2, 2, 185, 2, 2, 187, 2, 2, 189, 2, 2, 191, 2, 2, 193, 2, 2, 195, 2, 2, 197, 2, 2, 199, 2, 2, 201, 2, 2, 203, 2, 2, 205, 2, 2, 207, 2, 2, 209, 2, 2, 211, 2, 2, 213, 2, 2, 215, 2, 2, 217, 2, 2, 219, 2, 2, 221, 2, 2, 223, 2, 2, 225, 2, 2, 227, 2, 2, 229, 2, 2, 5, 2, 3, 4, 40, 8, 2, 11, 12, 15, 15, 34, 34, 49, 49, 93, 93, 95, 95, 4, 2, 12, 12, 15, 15, 5, 2, 11, 12, 15, 15, 34, 34, 3, 2, 50, 59, 4, 2, 67, 92, 99, 124, 7, 2, 36, 36, 94, 94, 112, 112, 116, 116, 118, 118, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45, 47, 47, 4, 2, 66, 66, 97, 97, 3, 2, 98, 98, 12, 2, 11, 12, 15, 15, 34, 34, 46, 46, 49, 49, 63, 63, 93, 93, 95, 95, 98, 98, 126, 126, 4, 2, 44, 44, 49, 49, 4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4, 2, 70, 70, 102, 102, 4, 2, 72, 72, 104, 104, 4, 2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4, 2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4, 2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4, 2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4, 2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4, 2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4, 2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 2, 816, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 3, 45, 3, 2, 2, 2, 3, 57, 3, 2, 2, 2, 3, 59, 3, 2, 2, 2, 3, 61, 3, 2, 2, 2, 3, 63, 3, 2, 2, 2, 3, 65, 3, 2, 2, 2, 3, 67, 3, 2, 2, 2, 3, 69, 3, 2, 2, 2, 3, 71, 3, 2, 2, 2, 3, 73, 3, 2, 2, 2, 3, 75, 3, 2, 2, 2, 3, 77, 3, 2, 2, 2, 3, 79, 3, 2, 2, 2, 3, 81, 3, 2, 2, 2, 3, 83, 3, 2, 2, 2, 3, 85, 3, 2, 2, 2, 3, 87, 3, 2, 2, 2, 3, 89, 3, 2, 2, 2, 3, 91, 3, 2, 2, 2, 3, 93, 3, 2, 2, 2, 3, 95, 3, 2, 2, 2, 3, 97, 3, 2, 2, 2, 3, 99, 3, 2, 2, 2, 3, 101, 3, 2, 2, 2, 3, 103, 3, 2, 2, 2, 3, 105, 3, 2, 2, 2, 3, 107, 3, 2, 2, 2, 3, 109, 3, 2, 2, 2, 3, 111, 3, 2, 2, 2, 3, 113, 3, 2, 2, 2, 3, 115, 3, 2, 2, 2, 3, 117, 3, 2, 2, 2, 3, 119, 3, 2, 2, 2, 3, 121, 3, 2, 2, 2, 3, 123, 3, 2, 2, 2, 3, 125, 3, 2, 2, 2, 3, 127, 3, 2, 2, 2, 3, 129, 3, 2, 2, 2, 3, 131, 3, 2, 2, 2, 3, 133, 3, 2, 2, 2, 3, 135, 3, 2, 2, 2, 3, 137, 3, 2, 2, 2, 3, 139, 3, 2, 2, 2, 3, 141, 3, 2, 2, 2, 3, 143, 3, 2, 2, 2, 3, 145, 3, 2, 2, 2, 3, 147, 3, 2, 2, 2, 4, 149, 3, 2, 2, 2, 4, 151, 3, 2, 2, 2, 4, 153, 3, 2, 2, 2, 4, 155, 3, 2, 2, 2, 4, 157, 3, 2, 2, 2, 4, 159, 3, 2, 2, 2, 4, 161, 3, 2, 2, 2, 4, 163, 3, 2, 2, 2, 4, 165, 3, 2, 2, 2, 4, 167, 3, 2, 2, 2, 4, 171, 3, 2, 2, 2, 4, 173, 3, 2, 2, 2, 4, 175, 3, 2, 2, 2, 4, 177, 3, 2, 2, 2, 5, 231, 3, 2, 2, 2, 7, 241, 3, 2, 2, 2, 9, 248, 3, 2, 2, 2, 11, 257, 3, 2, 2, 2, 13, 264, 3, 2, 2, 2, 15, 271, 3, 2, 2, 2, 17, 278, 3, 2, 2, 2, 19, 285, 3, 2, 2, 2, 21, 293, 3, 2, 2, 2, 23, 305, 3, 2, 2, 2, 25, 315, 3, 2, 2, 2, 27, 324, 3, 2, 2, 2, 29, 330, 3, 2, 2, 2, 31, 337, 3, 2, 2, 2, 33, 344, 3, 2, 2, 2, 35, 352, 3, 2, 2, 2, 37, 361, 3, 2, 2, 2, 39, 367, 3, 2, 2, 2, 41, 384, 3, 2, 2, 2, 43, 400, 3, 2, 2, 2, 45, 406, 3, 2, 2, 2, 47, 410, 3, 2, 2, 2, 49, 412, 3, 2, 2, 2, 51, 414, 3, 2, 2, 2, 53, 417, 3, 2, 2, 2, 55, 419, 3, 2, 2, 2, 57, 457, 3, 2, 2, 2, 59, 460, 3, 2, 2, 2, 61, 506, 3, 2, 2, 2, 63, 508, 3, 2, 2, 2, 65, 511, 3, 2, 2, 2, 67, 515, 3, 2, 2, 2, 69, 519, 3, 2, 2, 2, 71, 521, 3, 2, 2, 2, 73, 523, 3, 2, 2, 2, 75, 528, 3, 2, 2, 2, 77, 530, 3, 2, 2, 2, 79, 536, 3, 2, 2, 2, 81, 542, 3, 2, 2, 2, 83, 547, 3, 2, 2, 2, 85, 549, 3, 2, 2, 2, 87, 552, 3, 2, 2, 2, 89, 555, 3, 2, 2, 2, 91, 560, 3, 2, 2, 2, 93, 564, 3, 2, 2, 2, 95, 569, 3, 2, 2, 2, 97, 575, 3, 2, 2, 2, 99, 578, 3, 2, 2, 2, 101, 580, 3, 2, 2, 2, 103, 586, 3, 2, 2, 2, 105, 588, 3, 2, 2, 2, 107, 593, 3, 2, 2, 2, 109, 598, 3, 2, 2, 2, 111, 608, 3, 2, 2, 2, 113, 610, 3, 2, 2, 2, 115, 613, 3, 2, 2, 2, 117, 616, 3, 2, 2, 2, 119, 618, 3, 2, 2, 2, 121, 621, 3, 2, 2, 2, 123, 623, 3, 2, 2, 2, 125, 626, 3, 2, 2, 2, 127, 628, 3, 2, 2, 2, 129, 630, 3, 2, 2, 2, 131, 632, 3, 2, 2, 2, 133, 634, 3, 2, 2, 2, 135, 636, 3, 2, 2, 2, 137, 641, 3, 2, 2, 2, 139, 663, 3, 2, 2, 2, 141, 665, 3, 2, 2, 2, 143, 676, 3, 2, 2, 2, 145, 680, 3, 2, 2, 2, 147, 684, 3, 2, 2, 2, 149, 688, 3, 2, 2, 2, 151, 693, 3, 2, 2, 2, 153, 699, 3, 2, 2, 2, 155, 705, 3, 2, 2, 2, 157, 709, 3, 2, 2, 2, 159, 713, 3, 2, 2, 2, 161, 716, 3, 2, 2, 2, 163, 725, 3, 2, 2, 2, 165, 728, 3, 2, 2, 2, 167, 734, 3, 2, 2, 2, 169, 745, 3, 2, 2, 2, 171, 747, 3, 2, 2, 2, 173, 749, 3, 2, 2, 2, 175, 753, 3, 2, 2, 2, 177, 757, 3, 2, 2, 2, 179, 761, 3, 2, 2, 2, 181, 763, 3, 2, 2, 2, 183, 765, 3, 2, 2, 2, 185, 767, 3, 2, 2, 2, 187, 769, 3, 2, 2, 2, 189, 771, 3, 2, 2, 2, 191, 773, 3, 2, 2, 2, 193, 775, 3, 2, 2, 2, 195, 777, 3, 2, 2, 2, 197, 779, 3, 2, 2, 2, 199, 781, 3, 2, 2, 2, 201, 783, 3, 2, 2, 2, 203, 785, 3, 2, 2, 2, 205, 787, 3, 2, 2, 2, 207, 789, 3, 2, 2, 2, 209, 791, 3, 2, 2, 2, 211, 793, 3, 2, 2, 2, 213, 795, 3, 2, 2, 2, 215, 797, 3, 2, 2, 2, 217, 799, 3, 2, 2, 2, 219, 801, 3, 2, 2, 2, 221, 803, 3, 2, 2, 2, 223, 805, 3, 2, 2, 2, 225, 807, 3, 2, 2, 2, 227, 809, 3, 2, 2, 2, 229, 811, 3, 2, 2, 2, 231, 232, 5, 185, 92, 2, 232, 233, 5, 195, 97, 2, 233, 234, 5, 215, 107, 2, 234, 235, 5, 215, 107, 2, 235, 236, 5, 187, 93, 2, 236, 237, 5, 183, 91, 2, 237, 238, 5, 217, 108, 2, 238, 239, 3, 2, 2, 2, 239, 240, 8, 2, 2, 2, 240, 6, 3, 2, 2, 2, 241, 242, 5, 185, 92, 2, 242, 243, 5, 213, 106, 2, 243, 244, 5, 207, 103, 2, 244, 245, 5, 209, 104, 2, 245, 246, 3, 2, 2, 2, 246, 247, 8, 3, 3, 2, 247, 8, 3, 2, 2, 2, 248, 249, 5, 187, 93, 2, 249, 250, 5, 205, 102, 2, 250, 251, 5, 213, 106, 2, 251, 252, 5, 195, 97, 2, 252, 253, 5, 183, 91, 2, 253, 254, 5, 193, 96, 2, 254, 255, 3, 2, 2, 2, 255, 256, 8, 4, 3, 2, 256, 10, 3, 2, 2, 2, 257, 258, 5, 187, 93, 2, 258, 259, 5, 221, 110, 2, 259, 260, 5, 179, 89, 2, 260, 261, 5, 201, 100, 2, 261, 262, 3, 2, 2, 2, 262, 263, 8, 5, 2, 2, 263, 12, 3, 2, 2, 2, 264, 265, 5, 189, 94, 2, 265, 266, 5, 213, 106, 2, 266, 267, 5, 207, 103, 2, 267, 268, 5, 203, 101, 2, 268, 269, 3, 2, 2, 2, 269, 270, 8, 6, 3, 2, 270, 14, 3, 2, 2, 2, 271, 272, 5, 191, 95, 2, 272, 273, 5, 213, 106, 2, 273, 274, 5, 207, 103, 2, 274, 275, 5, 199, 99, 2, 275, 276, 3, 2, 2, 2, 276, 277, 8, 7, 2, 2, 277, 16, 3, 2, 2, 2, 278, 279, 5, 199, 99, 2, 279, 280, 5, 187, 93, 2, 280, 281, 5, 187, 93, 2, 281, 282, 5, 209, 104, 2, 282, 283, 3, 2, 2, 2, 283, 284, 8, 8, 3, 2, 284, 18, 3, 2, 2, 2, 285, 286, 5, 201, 100, 2, 286, 287, 5, 195, 97, 2, 287, 288, 5, 203, 101, 2, 288, 289, 5, 195, 97, 2, 289, 290, 5, 217, 108, 2, 290, 291, 3, 2, 2, 2, 291, 292, 8, 9, 2, 2, 292, 20, 3, 2, 2, 2, 293, 294, 5, 203, 101, 2, 294, 295, 5, 221, 110, 2, 295, 296, 5, 111, 55, 2, 296, 297, 5, 187, 93, 2, 297, 298, 5, 225, 112, 2, 298, 299, 5, 209, 104, 2, 299, 300, 5, 179, 89, 2, 300, 301, 5, 205, 102, 2, 301, 302, 5, 185, 92, 2, 302, 303, 3, 2, 2, 2, 303, 304, 8, 10, 3, 2, 304, 22, 3, 2, 2, 2, 305, 306, 5, 209, 104, 2, 306, 307, 5, 213, 106, 2, 307, 308, 5, 207, 103, 2, 308, 309, 5, 197, 98, 2, 309, 310, 5, 187, 93, 2, 310, 311, 5, 183, 91, 2, 311, 312, 5, 217, 108, 2, 312, 313, 3, 2, 2, 2, 313, 314, 8, 11, 3, 2, 314, 24, 3, 2, 2, 2, 315, 316, 5, 213, 106, 2, 316, 317, 5, 187, 93, 2, 317, 318, 5, 205, 102, 2, 318, 319, 5, 179, 89, 2, 319, 320, 5, 203, 101, 2, 320, 321, 5, 187, 93, 2, 321, 322, 3, 2, 2, 2, 322, 323, 8, 12, 3, 2, 323, 26, 3, 2, 2, 2, 324, 325, 5, 213, 106, 2, 325, 326, 5, 207, 103, 2, 326, 327, 5, 223, 111, 2, 327, 328, 3, 2, 2, 2, 328, 329, 8, 13, 2, 2, 329, 28, 3, 2, 2, 2, 330, 331, 5, 215, 107, 2, 331, 332, 5, 193, 96, 2, 332, 333, 5, 207, 103, 2, 333, 334, 5, 223, 111, 2, 334, 335, 3, 2, 2, 2, 335, 336, 8, 14, 2, 2, 336, 30, 3, 2, 2, 2, 337, 338, 5, 215, 107, 2, 338, 339, 5, 207, 103, 2, 339, 340, 5, 213, 106, 2, 340, 341, 5, 217, 108, 2, 341, 342, 3, 2, 2, 2, 342, 343, 8, 15, 2, 2, 343, 32, 3, 2, 2, 2, 344, 345, 5, 215, 107, 2, 345, 346, 5, 217, 108, 2, 346, 347, 5, 179, 89, 2, 347, 348, 5, 217, 108, 2, 348, 349, 5, 215, 107, 2, 349, 350, 3, 2, 2, 2, 350, 351, 8, 16, 2, 2, 351, 34, 3, 2, 2, 2, 352, 353, 5, 223, 111, 2, 353, 354, 5, 193, 96, 2, 354, 355, 5, 187, 93, 2, 355, 356, 5, 213, 106, 2, 356, 357, 5, 187, 93, 2, 357, 358, 3, 2, 2, 2, 358, 359, 8, 17, 2, 2, 359, 36, 3, 2, 2, 2, 360, 362, 10, 2, 2, 2, 361, 360, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 361, 3, 2, 2, 2, 363, 364, 3, 2, 2, 2, 364, 365, 3, 2, 2, 2, 365, 366, 8, 18, 2, 2, 366, 38, 3, 2, 2, 2, 367, 368, 7, 49, 2, 2, 368, 369, 7, 49, 2, 2, 369, 373, 3, 2, 2, 2, 370, 372, 10, 3, 2, 2, 371, 370, 3, 2, 2, 2, 372, 375, 3, 2, 2, 2, 373, 371, 3, 2, 2, 2, 373, 374, 3, 2, 2, 2, 374, 377, 3, 2, 2, 2, 375, 373, 3, 2, 2, 2, 376, 378, 7, 15, 2, 2, 377, 376, 3, 2, 2, 2, 377, 378, 3, 2, 2, 2, 378, 380, 3, 2, 2, 2, 379, 381, 7, 12, 2, 2, 380, 379, 3, 2, 2, 2, 380, 381, 3, 2, 2, 2, 381, 382, 3, 2, 2, 2, 382, 383, 8, 19, 4, 2, 383, 40, 3, 2, 2, 2, 384, 385, 7, 49, 2, 2, 385, 386, 7, 44, 2, 2, 386, 391, 3, 2, 2, 2, 387, 390, 5, 41, 20, 2, 388, 390, 11, 2, 2, 2, 389, 387, 3, 2, 2, 2, 389, 388, 3, 2, 2, 2, 390, 393, 3, 2, 2, 2, 391, 392, 3, 2, 2, 2, 391, 389, 3, 2, 2, 2, 392, 394, 3, 2, 2, 2, 393, 391, 3, 2, 2, 2, 394, 395, 7, 44, 2, 2, 395, 396, 7, 49, 2, 2, 396, 397, 3, 2, 2, 2, 397, 398, 8, 20, 4, 2, 398, 42, 3, 2, 2, 2, 399, 401, 9, 4, 2, 2, 400, 399, 3, 2, 2, 2, 401, 402, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 402, 403, 3, 2, 2, 2, 403, 404, 3, 2, 2, 2, 404, 405, 8, 21, 4, 2, 405, 44, 3, 2, 2, 2, 406, 407, 7, 126, 2, 2, 407, 408, 3, 2, 2, 2, 408, 409, 8, 22, 5, 2, 409, 46, 3, 2, 2, 2, 410, 411, 9, 5, 2, 2, 411, 48, 3, 2, 2, 2, 412, 413, 9, 6, 2, 2, 413, 50, 3, 2, 2, 2, 414, 415, 7, 94, 2, 2, 415, 416, 9, 7, 2, 2, 416, 52, 3, 2, 2, 2, 417, 418, 10, 8, 2, 2, 418, 54, 3, 2, 2, 2, 419, 421, 9, 9, 2, 2, 420, 422, 9, 10, 2, 2, 421, 420, 3, 2, 2, 2, 421, 422, 3, 2, 2, 2, 422, 424, 3, 2, 2, 2, 423, 425, 5, 47, 23, 2, 424, 423, 3, 2, 2, 2, 425, 426, 3, 2, 2, 2, 426, 424, 3, 2, 2, 2, 426, 427, 3, 2, 2, 2, 427, 56, 3, 2, 2, 2, 428, 433, 7, 36, 2, 2, 429, 432, 5, 51, 25, 2, 430, 432, 5, 53, 26, 2, 431, 429, 3, 2, 2, 2, 431, 430, 3, 2, 2, 2, 432, 435, 3, 2, 2, 2, 433, 431, 3, 2, 2, 2, 433, 434, 3, 2, 2, 2, 434, 436, 3, 2, 2, 2, 435, 433, 3, 2, 2, 2, 436, 458, 7, 36, 2, 2, 437, 438, 7, 36, 2, 2, 438, 439, 7, 36, 2, 2, 439, 440, 7, 36, 2, 2, 440, 444, 3, 2, 2, 2, 441, 443, 10, 3, 2, 2, 442, 441, 3, 2, 2, 2, 443, 446, 3, 2, 2, 2, 444, 445, 3, 2, 2, 2, 444, 442, 3, 2, 2, 2, 445, 447, 3, 2, 2, 2, 446, 444, 3, 2, 2, 2, 447, 448, 7, 36, 2, 2, 448, 449, 7, 36, 2, 2, 449, 450, 7, 36, 2, 2, 450, 452, 3, 2, 2, 2, 451, 453, 7, 36, 2, 2, 452, 451, 3, 2, 2, 2, 452, 453, 3, 2, 2, 2, 453, 455, 3, 2, 2, 2, 454, 456, 7, 36, 2, 2, 455, 454, 3, 2, 2, 2, 455, 456, 3, 2, 2, 2, 456, 458, 3, 2, 2, 2, 457, 428, 3, 2, 2, 2, 457, 437, 3, 2, 2, 2, 458, 58, 3, 2, 2, 2, 459, 461, 5, 47, 23, 2, 460, 459, 3, 2, 2, 2, 461, 462, 3, 2, 2, 2, 462, 460, 3, 2, 2, 2, 462, 463, 3, 2, 2, 2, 463, 60, 3, 2, 2, 2, 464, 466, 5, 47, 23, 2, 465, 464, 3, 2, 2, 2, 466, 467, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 467, 468, 3, 2, 2, 2, 468, 469, 3, 2, 2, 2, 469, 473, 5, 75, 37, 2, 470, 472, 5, 47, 23, 2, 471, 470, 3, 2, 2, 2, 472, 475, 3, 2, 2, 2, 473, 471, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 507, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 476, 478, 5, 75, 37, 2, 477, 479, 5, 47, 23, 2, 478, 477, 3, 2, 2, 2, 479, 480, 3, 2, 2, 2, 480, 478, 3, 2, 2, 2, 480, 481, 3, 2, 2, 2, 481, 507, 3, 2, 2, 2, 482, 484, 5, 47, 23, 2, 483, 482, 3, 2, 2, 2, 484, 485, 3, 2, 2, 2, 485, 483, 3, 2, 2, 2, 485, 486, 3, 2, 2, 2, 486, 494, 3, 2, 2, 2, 487, 491, 5, 75, 37, 2, 488, 490, 5, 47, 23, 2, 489, 488, 3, 2, 2, 2, 490, 493, 3, 2, 2, 2, 491, 489, 3, 2, 2, 2, 491, 492, 3, 2, 2, 2, 492, 495, 3, 2, 2, 2, 493, 491, 3, 2, 2, 2, 494, 487, 3, 2, 2, 2, 494, 495, 3, 2, 2, 2, 495, 496, 3, 2, 2, 2, 496, 497, 5, 55, 27, 2, 497, 507, 3, 2, 2, 2, 498, 500, 5, 75, 37, 2, 499, 501, 5, 47, 23, 2, 500, 499, 3, 2, 2, 2, 501, 502, 3, 2, 2, 2, 502, 500, 3, 2, 2, 2, 502, 503, 3, 2, 2, 2, 503, 504, 3, 2, 2, 2, 504, 505, 5, 55, 27, 2, 505, 507, 3, 2, 2, 2, 506, 465, 3, 2, 2, 2, 506, 476, 3, 2, 2, 2, 506, 483, 3, 2, 2, 2, 506, 498, 3, 2, 2, 2, 507, 62, 3, 2, 2, 2, 508, 509, 5, 181, 90, 2, 509, 510, 5, 227, 113, 2, 510, 64, 3, 2, 2, 2, 511, 512, 5, 179, 89, 2, 512, 513, 5, 205, 102, 2, 513, 514, 5, 185, 92, 2, 514, 66, 3, 2, 2, 2, 515, 516, 5, 179, 89, 2, 516, 517, 5, 215, 107, 2, 517, 518, 5, 183, 91, 2, 518, 68, 3, 2, 2, 2, 519, 520, 7, 63, 2, 2, 520, 70, 3, 2, 2, 2, 521, 522, 7, 46, 2, 2, 522, 72, 3, 2, 2, 2, 523, 524, 5, 185, 92, 2, 524, 525, 5, 187, 93, 2, 525, 526, 5, 215, 107, 2, 526, 527, 5, 183, 91, 2, 527, 74, 3, 2, 2, 2, 528, 529, 7, 48, 2, 2, 529, 76, 3, 2, 2, 2, 530, 531, 5, 189, 94, 2, 531, 532, 5, 179, 89, 2, 532, 533, 5, 201, 100, 2, 533, 534, 5, 215, 107, 2, 534, 535, 5, 187, 93, 2, 535, 78, 3, 2, 2, 2, 536, 537, 5, 189, 94, 2, 537, 538, 5, 195, 97, 2, 538, 539, 5, 213, 106, 2, 539, 540, 5, 215, 107, 2, 540, 541, 5, 217, 108, 2, 541, 80, 3, 2, 2, 2, 542, 543, 5, 201, 100, 2, 543, 544, 5, 179, 89, 2, 544, 545, 5, 215, 107, 2, 545, 546, 5, 217, 108, 2, 546, 82, 3, 2, 2, 2, 547, 548, 7, 42, 2, 2, 548, 84, 3, 2, 2, 2, 549, 550, 5, 195, 97, 2, 550, 551, 5, 205, 102, 2, 551, 86, 3, 2, 2, 2, 552, 553, 5, 195, 97, 2, 553, 554, 5, 215, 107, 2, 554, 88, 3, 2, 2, 2, 555, 556, 5, 201, 100, 2, 556, 557, 5, 195, 97, 2, 557, 558, 5, 199, 99, 2, 558, 559, 5, 187, 93, 2, 559, 90, 3, 2, 2, 2, 560, 561, 5, 205, 102, 2, 561, 562, 5, 207, 103, 2, 562, 563, 5, 217, 108, 2, 563, 92, 3, 2, 2, 2, 564, 565, 5, 205, 102, 2, 565, 566, 5, 219, 109, 2, 566, 567, 5, 201, 100, 2, 567, 568, 5, 201, 100, 2, 568, 94, 3, 2, 2, 2, 569, 570, 5, 205, 102, 2, 570, 571, 5, 219, 109, 2, 571, 572, 5, 201, 100, 2, 572, 573, 5, 201, 100, 2, 573, 574, 5, 215, 107, 2, 574, 96, 3, 2, 2, 2, 575, 576, 5, 207, 103, 2, 576, 577, 5, 213, 106, 2, 577, 98, 3, 2, 2, 2, 578, 579, 7, 65, 2, 2, 579, 100, 3, 2, 2, 2, 580, 581, 5, 213, 106, 2, 581, 582, 5, 201, 100, 2, 582, 583, 5, 195, 97, 2, 583, 584, 5, 199, 99, 2, 584, 585, 5, 187, 93, 2, 585, 102, 3, 2, 2, 2, 586, 587, 7, 43, 2, 2, 587, 104, 3, 2, 2, 2, 588, 589, 5, 217, 108, 2, 589, 590, 5, 213, 106, 2, 590, 591, 5, 219, 109, 2, 591, 592, 5, 187, 93, 2, 592, 106, 3, 2, 2, 2, 593, 594, 5, 195, 97, 2, 594, 595, 5, 205, 102, 2, 595, 596, 5, 189, 94, 2, 596, 597, 5, 207, 103, 2, 597, 108, 3, 2, 2, 2, 598, 599, 5, 189, 94, 2, 599, 600, 5, 219, 109, 2, 600, 601, 5, 205, 102, 2, 601, 602, 5, 183, 91, 2, 602, 603, 5, 217, 108, 2, 603, 604, 5, 195, 97, 2, 604, 605, 5, 207, 103, 2, 605, 606, 5, 205, 102, 2, 606, 607, 5, 215, 107, 2, 607, 110, 3, 2, 2, 2, 608, 609, 7, 97, 2, 2, 609, 112, 3, 2, 2, 2, 610, 611, 7, 63, 2, 2, 611, 612, 7, 63, 2, 2, 612, 114, 3, 2, 2, 2, 613, 614, 7, 35, 2, 2, 614, 615, 7, 63, 2, 2, 615, 116, 3, 2, 2, 2, 616, 617, 7, 62, 2, 2, 617, 118, 3, 2, 2, 2, 618, 619, 7, 62, 2, 2, 619, 620, 7, 63, 2, 2, 620, 120, 3, 2, 2, 2, 621, 622, 7, 64, 2, 2, 622, 122, 3, 2, 2, 2, 623, 624, 7, 64, 2, 2, 624, 625, 7, 63, 2, 2, 625, 124, 3, 2, 2, 2, 626, 627, 7, 45, 2, 2, 627, 126, 3, 2, 2, 2, 628, 629, 7, 47, 2, 2, 629, 128, 3, 2, 2, 2, 630, 631, 7, 44, 2, 2, 631, 130, 3, 2, 2, 2, 632, 633, 7, 49, 2, 2, 633, 132, 3, 2, 2, 2, 634, 635, 7, 39, 2, 2, 635, 134, 3, 2, 2, 2, 636, 637, 7, 93, 2, 2, 637, 638, 3, 2, 2, 2, 638, 639, 8, 67, 2, 2, 639, 640, 8, 67, 2, 2, 640, 136, 3, 2, 2, 2, 641, 642, 7, 95, 2, 2, 642, 643, 3, 2, 2, 2, 643, 644, 8, 68, 5, 2, 644, 645, 8, 68, 5, 2, 645, 138, 3, 2, 2, 2, 646, 652, 5, 49, 24, 2, 647, 651, 5, 49, 24, 2, 648, 651, 5, 47, 23, 2, 649, 651, 7, 97, 2, 2, 650, 647, 3, 2, 2, 2, 650, 648, 3, 2, 2, 2, 650, 649, 3, 2, 2, 2, 651, 654, 3, 2, 2, 2, 652, 650, 3, 2, 2, 2, 652, 653, 3, 2, 2, 2, 653, 664, 3, 2, 2, 2, 654, 652, 3, 2, 2, 2, 655, 659, 9, 11, 2, 2, 656, 660, 5, 49, 24, 2, 657, 660, 5, 47, 23, 2, 658, 660, 7, 97, 2, 2, 659, 656, 3, 2, 2, 2, 659, 657, 3, 2, 2, 2, 659, 658, 3, 2, 2, 2, 660, 661, 3, 2, 2, 2, 661, 659, 3, 2, 2, 2, 661, 662, 3, 2, 2, 2, 662, 664, 3, 2, 2, 2, 663, 646, 3, 2, 2, 2, 663, 655, 3, 2, 2, 2, 664, 140, 3, 2, 2, 2, 665, 671, 7, 98, 2, 2, 666, 670, 10, 12, 2, 2, 667, 668, 7, 98, 2, 2, 668, 670, 7, 98, 2, 2, 669, 666, 3, 2, 2, 2, 669, 667, 3, 2, 2, 2, 670, 673, 3, 2, 2, 2, 671, 669, 3, 2, 2, 2, 671, 672, 3, 2, 2, 2, 672, 674, 3, 2, 2, 2, 673, 671, 3, 2, 2, 2, 674, 675, 7, 98, 2, 2, 675, 142, 3, 2, 2, 2, 676, 677, 5, 39, 19, 2, 677, 678, 3, 2, 2, 2, 678, 679, 8, 71, 4, 2, 679, 144, 3, 2, 2, 2, 680, 681, 5, 41, 20, 2, 681, 682, 3, 2, 2, 2, 682, 683, 8, 72, 4, 2, 683, 146, 3, 2, 2, 2, 684, 685, 5, 43, 21, 2, 685, 686, 3, 2, 2, 2, 686, 687, 8, 73, 4, 2, 687, 148, 3, 2, 2, 2, 688, 689, 7, 126, 2, 2, 689, 690, 3, 2, 2, 2, 690, 691, 8, 74, 6, 2, 691, 692, 8, 74, 5, 2, 692, 150, 3, 2, 2, 2, 693, 694, 7, 93, 2, 2, 694, 695, 3, 2, 2, 2, 695, 696, 8, 75, 7, 2, 696, 697, 8, 75, 3, 2, 697, 698, 8, 75, 3, 2, 698, 152, 3, 2, 2, 2, 699, 700, 7, 95, 2, 2, 700, 701, 3, 2, 2, 2, 701, 702, 8, 76, 5, 2, 702, 703, 8, 76, 5, 2, 703, 704, 8, 76, 8, 2, 704, 154, 3, 2, 2, 2, 705, 706, 7, 46, 2, 2, 706, 707, 3, 2, 2, 2, 707, 708, 8, 77, 9, 2, 708, 156, 3, 2, 2, 2, 709, 710, 7, 63, 2, 2, 710, 711, 3, 2, 2, 2, 711, 712, 8, 78, 10, 2, 712, 158, 3, 2, 2, 2, 713, 714, 5, 179, 89, 2, 714, 715, 5, 215, 107, 2, 715, 160, 3, 2, 2, 2, 716, 717, 5, 203, 101, 2, 717, 718, 5, 187, 93, 2, 718, 719, 5, 217, 108, 2, 719, 720, 5, 179, 89, 2, 720, 721, 5, 185, 92, 2, 721, 722, 5, 179, 89, 2, 722, 723, 5, 217, 108, 2, 723, 724, 5, 179, 89, 2, 724, 162, 3, 2, 2, 2, 725, 726, 5, 207, 103, 2, 726, 727, 5, 205, 102, 2, 727, 164, 3, 2, 2, 2, 728, 729, 5, 223, 111, 2, 729, 730, 5, 195, 97, 2, 730, 731, 5, 217, 108, 2, 731, 732, 5, 193, 96, 2, 732, 166, 3, 2, 2, 2, 733, 735, 5, 169, 84, 2, 734, 733, 3, 2, 2, 2, 735, 736, 3, 2, 2, 2, 736, 734, 3, 2, 2, 2, 736, 737, 3, 2, 2, 2, 737, 168, 3, 2, 2, 2, 738, 740, 10, 13, 2, 2, 739, 738, 3, 2, 2, 2, 740, 741, 3, 2, 2, 2, 741, 739, 3, 2, 2, 2, 741, 742, 3, 2, 2, 2, 742, 746, 3, 2, 2, 2, 743, 744, 7, 49, 2, 2, 744, 746, 10, 14, 2, 2, 745, 739, 3, 2, 2, 2, 745, 743, 3, 2, 2, 2, 746, 170, 3, 2, 2, 2, 747, 748, 5, 141, 70, 2, 748, 172, 3, 2, 2, 2, 749, 750, 5, 39, 19, 2, 750, 751, 3, 2, 2, 2, 751, 752, 8, 86, 4, 2, 752, 174, 3, 2, 2, 2, 753, 754, 5, 41, 20, 2, 754, 755, 3, 2, 2, 2, 755, 756, 8, 87, 4, 2, 756, 176, 3, 2, 2, 2, 757, 758, 5, 43, 21, 2, 758, 759, 3, 2, 2, 2, 759, 760, 8, 88, 4, 2, 760, 178, 3, 2, 2, 2, 761, 762, 9, 15, 2, 2, 762, 180, 3, 2, 2, 2, 763, 764, 9, 16, 2, 2, 764, 182, 3, 2, 2, 2, 765, 766, 9, 17, 2, 2, 766, 184, 3, 2, 2, 2, 767, 768, 9, 18, 2, 2, 768, 186, 3, 2, 2, 2, 769, 770, 9, 9, 2, 2, 770, 188, 3, 2, 2, 2, 771, 772, 9, 19, 2, 2, 772, 190, 3, 2, 2, 2, 773, 774, 9, 20, 2, 2, 774, 192, 3, 2, 2, 2, 775, 776, 9, 21, 2, 2, 776, 194, 3, 2, 2, 2, 777, 778, 9, 22, 2, 2, 778, 196, 3, 2, 2, 2, 779, 780, 9, 23, 2, 2, 780, 198, 3, 2, 2, 2, 781, 782, 9, 24, 2, 2, 782, 200, 3, 2, 2, 2, 783, 784, 9, 25, 2, 2, 784, 202, 3, 2, 2, 2, 785, 786, 9, 26, 2, 2, 786, 204, 3, 2, 2, 2, 787, 788, 9, 27, 2, 2, 788, 206, 3, 2, 2, 2, 789, 790, 9, 28, 2, 2, 790, 208, 3, 2, 2, 2, 791, 792, 9, 29, 2, 2, 792, 210, 3, 2, 2, 2, 793, 794, 9, 30, 2, 2, 794, 212, 3, 2, 2, 2, 795, 796, 9, 31, 2, 2, 796, 214, 3, 2, 2, 2, 797, 798, 9, 32, 2, 2, 798, 216, 3, 2, 2, 2, 799, 800, 9, 33, 2, 2, 800, 218, 3, 2, 2, 2, 801, 802, 9, 34, 2, 2, 802, 220, 3, 2, 2, 2, 803, 804, 9, 35, 2, 2, 804, 222, 3, 2, 2, 2, 805, 806, 9, 36, 2, 2, 806, 224, 3, 2, 2, 2, 807, 808, 9, 37, 2, 2, 808, 226, 3, 2, 2, 2, 809, 810, 9, 38, 2, 2, 810, 228, 3, 2, 2, 2, 811, 812, 9, 39, 2, 2, 812, 230, 3, 2, 2, 2, 39, 2, 3, 4, 363, 373, 377, 380, 389, 391, 402, 421, 426, 431, 433, 444, 452, 455, 457, 462, 467, 473, 480, 485, 491, 494, 502, 506, 650, 652, 659, 661, 663, 669, 671, 736, 741, 745, 11, 7, 3, 2, 7, 4, 2, 2, 3, 2, 6, 2, 2, 9, 23, 2, 9, 63, 2, 9, 64, 2, 9, 31, 2, 9, 30, 2] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens index b72e97b9a2961..c3160ce1f6472 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.tokens @@ -1,98 +1,93 @@ DISSECT=1 -GROK=2 -EVAL=3 -EXPLAIN=4 +DROP=2 +ENRICH=3 +EVAL=4 FROM=5 -ROW=6 -STATS=7 -WHERE=8 -SORT=9 -MV_EXPAND=10 -LIMIT=11 -PROJECT=12 -DROP=13 -RENAME=14 -SHOW=15 -ENRICH=16 -KEEP=17 +GROK=6 +KEEP=7 +LIMIT=8 +MV_EXPAND=9 +PROJECT=10 +RENAME=11 +ROW=12 +SHOW=13 +SORT=14 +STATS=15 +WHERE=16 +UNKNOWN_CMD=17 LINE_COMMENT=18 MULTILINE_COMMENT=19 WS=20 -EXPLAIN_WS=21 -EXPLAIN_LINE_COMMENT=22 -EXPLAIN_MULTILINE_COMMENT=23 -PIPE=24 -STRING=25 -INTEGER_LITERAL=26 -DECIMAL_LITERAL=27 -BY=28 -DATE_LITERAL=29 -AND=30 -ASSIGN=31 -COMMA=32 -DOT=33 -LP=34 -OPENING_BRACKET=35 -CLOSING_BRACKET=36 -NOT=37 +PIPE=21 +STRING=22 +INTEGER_LITERAL=23 +DECIMAL_LITERAL=24 +BY=25 +AND=26 +ASC=27 +ASSIGN=28 +COMMA=29 +DESC=30 +DOT=31 +FALSE=32 +FIRST=33 +LAST=34 +LP=35 +IN=36 +IS=37 LIKE=38 -RLIKE=39 -IN=40 -IS=41 -AS=42 -NULL=43 -OR=44 +NOT=39 +NULL=40 +NULLS=41 +OR=42 +PARAM=43 +RLIKE=44 RP=45 -UNDERSCORE=46 +TRUE=46 INFO=47 FUNCTIONS=48 -BOOLEAN_VALUE=49 -COMPARISON_OPERATOR=50 -PLUS=51 -MINUS=52 -ASTERISK=53 -SLASH=54 -PERCENT=55 -TEN=56 -ORDERING=57 -NULLS_ORDERING=58 -NULLS_ORDERING_DIRECTION=59 -MATH_FUNCTION=60 -UNARY_FUNCTION=61 -WHERE_FUNCTIONS=62 +UNDERSCORE=49 +EQ=50 +NEQ=51 +LT=52 +LTE=53 +GT=54 +GTE=55 +PLUS=56 +MINUS=57 +ASTERISK=58 +SLASH=59 +PERCENT=60 +OPENING_BRACKET=61 +CLOSING_BRACKET=62 UNQUOTED_IDENTIFIER=63 QUOTED_IDENTIFIER=64 EXPR_LINE_COMMENT=65 EXPR_MULTILINE_COMMENT=66 EXPR_WS=67 -METADATA=68 -SRC_UNQUOTED_IDENTIFIER=69 -SRC_QUOTED_IDENTIFIER=70 -SRC_LINE_COMMENT=71 -SRC_MULTILINE_COMMENT=72 -SRC_WS=73 -ON=74 -WITH=75 -ENR_UNQUOTED_IDENTIFIER=76 -ENR_QUOTED_IDENTIFIER=77 -ENR_LINE_COMMENT=78 -ENR_MULTILINE_COMMENT=79 -ENR_WS=80 -EXPLAIN_PIPE=81 -'by'=28 -'and'=30 -'.'=33 -'('=34 -']'=36 -'or'=44 +AS=68 +METADATA=69 +ON=70 +WITH=71 +SRC_UNQUOTED_IDENTIFIER=72 +SRC_QUOTED_IDENTIFIER=73 +SRC_LINE_COMMENT=74 +SRC_MULTILINE_COMMENT=75 +SRC_WS=76 +'.'=31 +'('=35 +'?'=43 ')'=45 -'_'=46 -'info'=47 -'functions'=48 -'+'=51 -'-'=52 -'*'=53 -'/'=54 -'%'=55 -'10'=56 -'nulls'=58 +'_'=49 +'=='=50 +'!='=51 +'<'=52 +'<='=53 +'>'=54 +'>='=55 +'+'=56 +'-'=57 +'*'=58 +'/'=59 +'%'=60 +']'=62 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts index 1c5fc5a918aa4..4bbb3eb4968c3 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_lexer.ts @@ -18,90 +18,83 @@ import * as Utils from "antlr4ts/misc/Utils"; export class esql_lexer extends Lexer { public static readonly DISSECT = 1; - public static readonly GROK = 2; - public static readonly EVAL = 3; - public static readonly EXPLAIN = 4; + public static readonly DROP = 2; + public static readonly ENRICH = 3; + public static readonly EVAL = 4; public static readonly FROM = 5; - public static readonly ROW = 6; - public static readonly STATS = 7; - public static readonly WHERE = 8; - public static readonly SORT = 9; - public static readonly MV_EXPAND = 10; - public static readonly LIMIT = 11; - public static readonly PROJECT = 12; - public static readonly DROP = 13; - public static readonly RENAME = 14; - public static readonly SHOW = 15; - public static readonly ENRICH = 16; - public static readonly KEEP = 17; + public static readonly GROK = 6; + public static readonly KEEP = 7; + public static readonly LIMIT = 8; + public static readonly MV_EXPAND = 9; + public static readonly PROJECT = 10; + public static readonly RENAME = 11; + public static readonly ROW = 12; + public static readonly SHOW = 13; + public static readonly SORT = 14; + public static readonly STATS = 15; + public static readonly WHERE = 16; + public static readonly UNKNOWN_CMD = 17; public static readonly LINE_COMMENT = 18; public static readonly MULTILINE_COMMENT = 19; public static readonly WS = 20; - public static readonly EXPLAIN_WS = 21; - public static readonly EXPLAIN_LINE_COMMENT = 22; - public static readonly EXPLAIN_MULTILINE_COMMENT = 23; - public static readonly PIPE = 24; - public static readonly STRING = 25; - public static readonly INTEGER_LITERAL = 26; - public static readonly DECIMAL_LITERAL = 27; - public static readonly BY = 28; - public static readonly DATE_LITERAL = 29; - public static readonly AND = 30; - public static readonly ASSIGN = 31; - public static readonly COMMA = 32; - public static readonly DOT = 33; - public static readonly LP = 34; - public static readonly OPENING_BRACKET = 35; - public static readonly CLOSING_BRACKET = 36; - public static readonly NOT = 37; + public static readonly PIPE = 21; + public static readonly STRING = 22; + public static readonly INTEGER_LITERAL = 23; + public static readonly DECIMAL_LITERAL = 24; + public static readonly BY = 25; + public static readonly AND = 26; + public static readonly ASC = 27; + public static readonly ASSIGN = 28; + public static readonly COMMA = 29; + public static readonly DESC = 30; + public static readonly DOT = 31; + public static readonly FALSE = 32; + public static readonly FIRST = 33; + public static readonly LAST = 34; + public static readonly LP = 35; + public static readonly IN = 36; + public static readonly IS = 37; public static readonly LIKE = 38; - public static readonly RLIKE = 39; - public static readonly IN = 40; - public static readonly IS = 41; - public static readonly AS = 42; - public static readonly NULL = 43; - public static readonly OR = 44; + public static readonly NOT = 39; + public static readonly NULL = 40; + public static readonly NULLS = 41; + public static readonly OR = 42; + public static readonly PARAM = 43; + public static readonly RLIKE = 44; public static readonly RP = 45; - public static readonly UNDERSCORE = 46; + public static readonly TRUE = 46; public static readonly INFO = 47; public static readonly FUNCTIONS = 48; - public static readonly BOOLEAN_VALUE = 49; - public static readonly COMPARISON_OPERATOR = 50; - public static readonly PLUS = 51; - public static readonly MINUS = 52; - public static readonly ASTERISK = 53; - public static readonly SLASH = 54; - public static readonly PERCENT = 55; - public static readonly TEN = 56; - public static readonly ORDERING = 57; - public static readonly NULLS_ORDERING = 58; - public static readonly NULLS_ORDERING_DIRECTION = 59; - public static readonly MATH_FUNCTION = 60; - public static readonly UNARY_FUNCTION = 61; - public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNDERSCORE = 49; + public static readonly EQ = 50; + public static readonly NEQ = 51; + public static readonly LT = 52; + public static readonly LTE = 53; + public static readonly GT = 54; + public static readonly GTE = 55; + public static readonly PLUS = 56; + public static readonly MINUS = 57; + public static readonly ASTERISK = 58; + public static readonly SLASH = 59; + public static readonly PERCENT = 60; + public static readonly OPENING_BRACKET = 61; + public static readonly CLOSING_BRACKET = 62; public static readonly UNQUOTED_IDENTIFIER = 63; public static readonly QUOTED_IDENTIFIER = 64; public static readonly EXPR_LINE_COMMENT = 65; public static readonly EXPR_MULTILINE_COMMENT = 66; public static readonly EXPR_WS = 67; - public static readonly METADATA = 68; - public static readonly SRC_UNQUOTED_IDENTIFIER = 69; - public static readonly SRC_QUOTED_IDENTIFIER = 70; - public static readonly SRC_LINE_COMMENT = 71; - public static readonly SRC_MULTILINE_COMMENT = 72; - public static readonly SRC_WS = 73; - public static readonly ON = 74; - public static readonly WITH = 75; - public static readonly ENR_UNQUOTED_IDENTIFIER = 76; - public static readonly ENR_QUOTED_IDENTIFIER = 77; - public static readonly ENR_LINE_COMMENT = 78; - public static readonly ENR_MULTILINE_COMMENT = 79; - public static readonly ENR_WS = 80; - public static readonly EXPLAIN_PIPE = 81; - public static readonly EXPLAIN_MODE = 1; - public static readonly EXPRESSION = 2; - public static readonly SOURCE_IDENTIFIERS = 3; - public static readonly ENRICH_IDENTIFIERS = 4; + public static readonly AS = 68; + public static readonly METADATA = 69; + public static readonly ON = 70; + public static readonly WITH = 71; + public static readonly SRC_UNQUOTED_IDENTIFIER = 72; + public static readonly SRC_QUOTED_IDENTIFIER = 73; + public static readonly SRC_LINE_COMMENT = 74; + public static readonly SRC_MULTILINE_COMMENT = 75; + public static readonly SRC_WS = 76; + public static readonly EXPRESSION = 1; + public static readonly SOURCE_IDENTIFIERS = 2; // tslint:disable:no-trailing-whitespace public static readonly channelNames: string[] = [ @@ -110,30 +103,26 @@ export class esql_lexer extends Lexer { // tslint:disable:no-trailing-whitespace public static readonly modeNames: string[] = [ - "DEFAULT_MODE", "EXPLAIN_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", "ENRICH_IDENTIFIERS", + "DEFAULT_MODE", "EXPRESSION", "SOURCE_IDENTIFIERS", ]; public static readonly ruleNames: string[] = [ - "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", "WHERE", - "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", "ENRICH", - "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_OPENING_BRACKET", - "EXPLAIN_PIPE", "EXPLAIN_WS", "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", - "PIPE", "DIGIT", "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", - "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", - "AND", "ASSIGN", "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", - "NOT", "LIKE", "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", - "INFO", "FUNCTIONS", "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", - "ASTERISK", "SLASH", "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", "SRC_COMMA", - "SRC_ASSIGN", "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_UNQUOTED_IDENTIFIER_PART", - "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", - "SRC_WS", "ON", "WITH", "ENR_PIPE", "ENR_CLOSING_BRACKET", "ENR_COMMA", - "ENR_ASSIGN", "ENR_UNQUOTED_IDENTIFIER", "ENR_UNQUOTED_IDENTIFIER_PART", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", - "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", "LIMIT", + "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", "WHERE", + "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", "DIGIT", + "LETTER", "ESCAPE_SEQUENCE", "UNESCAPED_CHARS", "EXPONENT", "STRING", + "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", "COMMA", + "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", "NOT", + "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", "FUNCTIONS", + "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", "MINUS", + "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "SRC_PIPE", "SRC_OPENING_BRACKET", "SRC_CLOSING_BRACKET", "SRC_COMMA", + "SRC_ASSIGN", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_UNQUOTED_IDENTIFIER_PART", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", + "SRC_MULTILINE_COMMENT", "SRC_WS", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -141,27 +130,25 @@ export class esql_lexer extends Lexer { undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, - "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, - "']'", undefined, undefined, undefined, undefined, undefined, undefined, - undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, - "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", + undefined, undefined, undefined, "'.'", undefined, undefined, undefined, + "'('", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'?'", undefined, "')'", undefined, undefined, undefined, "'_'", + "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", + "'%'", undefined, "']'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", - "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", - "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", - "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", - "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", - "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", - "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", - "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "EXPLAIN_PIPE", + undefined, "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", + "LIMIT", "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", + "WHERE", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", + "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", + "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", + "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", + "FUNCTIONS", "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", + "SRC_WS", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_lexer._LITERAL_NAMES, esql_lexer._SYMBOLIC_NAMES, []); @@ -193,780 +180,400 @@ export class esql_lexer extends Lexer { // @Override public get modeNames(): string[] { return esql_lexer.modeNames; } - private static readonly _serializedATNSegments: number = 3; + private static readonly _serializedATNSegments: number = 2; private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02S\u0640\b\x01" + - "\b\x01\b\x01\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04" + - "\x05\t\x05\x04\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04" + - "\v\t\v\x04\f\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04" + - "\x11\t\x11\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04" + - "\x16\t\x16\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04" + - "\x1B\t\x1B\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04" + - " \t \x04!\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(" + - "\t(\x04)\t)\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x04" + - "1\t1\x042\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04" + - ":\t:\x04;\t;\x04<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04" + - "C\tC\x04D\tD\x04E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04" + - "L\tL\x04M\tM\x04N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04" + - "U\tU\x04V\tV\x04W\tW\x04X\tX\x04Y\tY\x04Z\tZ\x04[\t[\x04\\\t\\\x04]\t" + - "]\x04^\t^\x04_\t_\x04`\t`\x04a\ta\x04b\tb\x04c\tc\x04d\td\x04e\te\x04" + - "f\tf\x04g\tg\x04h\th\x04i\ti\x04j\tj\x04k\tk\x04l\tl\x04m\tm\x04n\tn\x04" + - "o\to\x04p\tp\x04q\tq\x04r\tr\x04s\ts\x04t\tt\x04u\tu\x04v\tv\x04w\tw\x04" + - "x\tx\x04y\ty\x04z\tz\x04{\t{\x04|\t|\x04}\t}\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + - "\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03" + - "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + - "\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03" + - "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03" + - "\f\x03\f\x03\f\x03\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03" + - "\r\x03\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03" + - "\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03" + - "\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03" + - "\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x12\x03" + - "\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03" + - "\x13\x07\x13\u018F\n\x13\f\x13\x0E\x13\u0192\v\x13\x03\x13\x05\x13\u0195" + - "\n\x13\x03\x13\x05\x13\u0198\n\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03" + - "\x14\x03\x14\x03\x14\x07\x14\u01A1\n\x14\f\x14\x0E\x14\u01A4\v\x14\x03" + - "\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x15\x06\x15\u01AC\n\x15\r\x15" + - "\x0E\x15\u01AD\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16" + - "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18" + - "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E" + - "\x03\x1E\x03\x1F\x03\x1F\x03 \x03 \x05 \u01D7\n \x03 \x06 \u01DA\n \r" + - " \x0E \u01DB\x03!\x03!\x03!\x07!\u01E1\n!\f!\x0E!\u01E4\v!\x03!\x03!\x03" + - "!\x03!\x03!\x03!\x07!\u01EC\n!\f!\x0E!\u01EF\v!\x03!\x03!\x03!\x03!\x03" + - "!\x05!\u01F6\n!\x03!\x05!\u01F9\n!\x05!\u01FB\n!\x03\"\x06\"\u01FE\n\"" + - "\r\"\x0E\"\u01FF\x03#\x06#\u0203\n#\r#\x0E#\u0204\x03#\x03#\x07#\u0209" + - "\n#\f#\x0E#\u020C\v#\x03#\x03#\x06#\u0210\n#\r#\x0E#\u0211\x03#\x06#\u0215" + - "\n#\r#\x0E#\u0216\x03#\x03#\x07#\u021B\n#\f#\x0E#\u021E\v#\x05#\u0220" + - "\n#\x03#\x03#\x03#\x03#\x06#\u0226\n#\r#\x0E#\u0227\x03#\x03#\x05#\u022C" + - "\n#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03" + - "%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x03%\x05" + - "%\u028F\n%\x03&\x03&\x03&\x03&\x03\'\x03\'\x03(\x03(\x03)\x03)\x03*\x03" + - "*\x03+\x03+\x03+\x03+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x03-\x03" + - "-\x03.\x03.\x03.\x03.\x03.\x03/\x03/\x03/\x03/\x03/\x03/\x030\x030\x03" + - "0\x031\x031\x031\x032\x032\x032\x033\x033\x033\x033\x033\x034\x034\x03" + - "4\x035\x035\x036\x036\x037\x037\x037\x037\x037\x038\x038\x038\x038\x03" + - "8\x038\x038\x038\x038\x038\x039\x039\x039\x039\x039\x039\x039\x039\x03" + - "9\x059\u02E3\n9\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x03:\x05" + - ":\u02EF\n:\x03;\x03;\x03<\x03<\x03=\x03=\x03>\x03>\x03?\x03?\x03@\x03" + - "@\x03@\x03A\x03A\x03A\x03A\x03A\x03A\x03A\x05A\u0305\nA\x03B\x03B\x03" + - "B\x03B\x03B\x03B\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x03C\x05C\u0316" + - "\nC\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03" + - "D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x03D\x05D\u04C6\nD\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03" + - "E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x03E\x05E\u055F\nE\x03" + - "F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03F\x03G\x03G\x03G\x03" + - "G\x03G\x07G\u0571\nG\fG\x0EG\u0574\vG\x03G\x03G\x03G\x03G\x03G\x06G\u057B" + - "\nG\rG\x0EG\u057C\x05G\u057F\nG\x03H\x03H\x03H\x03H\x07H\u0585\nH\fH\x0E" + - "H\u0588\vH\x03H\x03H\x03I\x03I\x03I\x03I\x03J\x03J\x03J\x03J\x03K\x03" + - "K\x03K\x03K\x03L\x03L\x03L\x03L\x03L\x03M\x03M\x03M\x03M\x03M\x03M\x03" + - "N\x03N\x03N\x03N\x03N\x03N\x03O\x03O\x03O\x03O\x03P\x03P\x03P\x03P\x03" + - "Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03Q\x03R\x06R\u05BB\nR\rR\x0ER\u05BC" + - "\x03S\x06S\u05C0\nS\rS\x0ES\u05C1\x03S\x03S\x05S\u05C6\nS\x03T\x03T\x03" + - "U\x03U\x03U\x03U\x03V\x03V\x03V\x03V\x03W\x03W\x03W\x03W\x03X\x03X\x03" + - "X\x03Y\x03Y\x03Y\x03Y\x03Y\x03Z\x03Z\x03Z\x03Z\x03Z\x03[\x03[\x03[\x03" + - "[\x03[\x03[\x03\\\x03\\\x03\\\x03\\\x03]\x03]\x03]\x03]\x03^\x06^\u05F2" + - "\n^\r^\x0E^\u05F3\x03_\x06_\u05F7\n_\r_\x0E_\u05F8\x03_\x03_\x05_\u05FD" + - "\n_\x03`\x03`\x03a\x03a\x03a\x03a\x03b\x03b\x03b\x03b\x03c\x03c\x03c\x03" + - "c\x03d\x03d\x03e\x03e\x03f\x03f\x03g\x03g\x03h\x03h\x03i\x03i\x03j\x03" + - "j\x03k\x03k\x03l\x03l\x03m\x03m\x03n\x03n\x03o\x03o\x03p\x03p\x03q\x03" + - "q\x03r\x03r\x03s\x03s\x03t\x03t\x03u\x03u\x03v\x03v\x03w\x03w\x03x\x03" + - "x\x03y\x03y\x03z\x03z\x03{\x03{\x03|\x03|\x03}\x03}\x04\u01A2\u01ED\x02" + - "\x02~\x07\x02\x03\t\x02\x04\v\x02\x05\r\x02\x06\x0F\x02\x07\x11\x02\b" + - "\x13\x02\t\x15\x02\n\x17\x02\v\x19\x02\f\x1B\x02\r\x1D\x02\x0E\x1F\x02" + - "\x0F!\x02\x10#\x02\x11%\x02\x12\'\x02\x13)\x02\x14+\x02\x15-\x02\x16/" + - "\x02\x021\x02S3\x02\x175\x02\x187\x02\x199\x02\x1A;\x02\x02=\x02\x02?" + - "\x02\x02A\x02\x02C\x02\x02E\x02\x1BG\x02\x1CI\x02\x1DK\x02\x1EM\x02\x1F" + - "O\x02 Q\x02!S\x02\"U\x02#W\x02$Y\x02%[\x02&]\x02\'_\x02(a\x02)c\x02*e" + - "\x02+g\x02,i\x02-k\x02.m\x02/o\x020q\x021s\x022u\x023w\x024y\x025{\x02" + - "6}\x027\x7F\x028\x81\x029\x83\x02:\x85\x02;\x87\x02<\x89\x02=\x8B\x02" + - ">\x8D\x02?\x8F\x02@\x91\x02A\x93\x02B\x95\x02C\x97\x02D\x99\x02E\x9B\x02" + - "\x02\x9D\x02\x02\x9F\x02\x02\xA1\x02\x02\xA3\x02\x02\xA5\x02F\xA7\x02" + - "G\xA9\x02\x02\xAB\x02H\xAD\x02I\xAF\x02J\xB1\x02K\xB3\x02L\xB5\x02M\xB7" + - "\x02\x02\xB9\x02\x02\xBB\x02\x02\xBD\x02\x02\xBF\x02N\xC1\x02\x02\xC3" + - "\x02O\xC5\x02P\xC7\x02Q\xC9\x02R\xCB\x02\x02\xCD\x02\x02\xCF\x02\x02\xD1" + - "\x02\x02\xD3\x02\x02\xD5\x02\x02\xD7\x02\x02\xD9\x02\x02\xDB\x02\x02\xDD" + - "\x02\x02\xDF\x02\x02\xE1\x02\x02\xE3\x02\x02\xE5\x02\x02\xE7\x02\x02\xE9" + - "\x02\x02\xEB\x02\x02\xED\x02\x02\xEF\x02\x02\xF1\x02\x02\xF3\x02\x02\xF5" + - "\x02\x02\xF7\x02\x02\xF9\x02\x02\xFB\x02\x02\xFD\x02\x02\x07\x02\x03\x04" + - "\x05\x06\'\x04\x02\f\f\x0F\x0F\x05\x02\v\f\x0F\x0F\"\"\x03\x022;\x04\x02" + - "C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f\x0F\x0F$$^^\x04\x02GGgg\x04\x02--" + - "//\x04\x02BBaa\x03\x02bb\f\x02\v\f\x0F\x0F\"\"..11??]]__bb~~\x04\x02," + - ",11\x04\x02CCcc\x04\x02DDdd\x04\x02EEee\x04\x02FFff\x04\x02HHhh\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02N\u032D\b\x01" + + "\b\x01\b\x01\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04" + + "\x06\t\x06\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f" + + "\t\f\x04\r\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11" + + "\x04\x12\t\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16" + + "\x04\x17\t\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B" + + "\x04\x1C\t\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!" + + "\t!\x04\"\t\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t" + + ")\x04*\t*\x04+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x04" + + "2\t2\x043\t3\x044\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04" + + ";\t;\x04<\t<\x04=\t=\x04>\t>\x04?\t?\x04@\t@\x04A\tA\x04B\tB\x04C\tC\x04" + + "D\tD\x04E\tE\x04F\tF\x04G\tG\x04H\tH\x04I\tI\x04J\tJ\x04K\tK\x04L\tL\x04" + + "M\tM\x04N\tN\x04O\tO\x04P\tP\x04Q\tQ\x04R\tR\x04S\tS\x04T\tT\x04U\tU\x04" + + "V\tV\x04W\tW\x04X\tX\x04Y\tY\x04Z\tZ\x04[\t[\x04\\\t\\\x04]\t]\x04^\t" + + "^\x04_\t_\x04`\t`\x04a\ta\x04b\tb\x04c\tc\x04d\td\x04e\te\x04f\tf\x04" + + "g\tg\x04h\th\x04i\ti\x04j\tj\x04k\tk\x04l\tl\x04m\tm\x04n\tn\x04o\to\x04" + + "p\tp\x04q\tq\x04r\tr\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x07\x03\x07\x03" + + "\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03" + + "\b\x03\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03" + + "\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03" + + "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x03" + + "\f\x03\f\x03\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03\x0E" + + "\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F" + + "\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10" + + "\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11" + + "\x03\x11\x03\x11\x03\x12\x06\x12\u016A\n\x12\r\x12\x0E\x12\u016B\x03\x12" + + "\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x07\x13\u0174\n\x13\f\x13\x0E" + + "\x13\u0177\v\x13\x03\x13\x05\x13\u017A\n\x13\x03\x13\x05\x13\u017D\n\x13" + + "\x03\x13\x03\x13\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14\x07\x14\u0186" + + "\n\x14\f\x14\x0E\x14\u0189\v\x14\x03\x14\x03\x14\x03\x14\x03\x14\x03\x14" + + "\x03\x15\x06\x15\u0191\n\x15\r\x15\x0E\x15\u0192\x03\x15\x03\x15\x03\x16" + + "\x03\x16\x03\x16\x03\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03\x19\x03\x19" + + "\x03\x19\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x05\x1B\u01A6\n\x1B\x03\x1B\x06" + + "\x1B\u01A9\n\x1B\r\x1B\x0E\x1B\u01AA\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u01B0" + + "\n\x1C\f\x1C\x0E\x1C\u01B3\v\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C" + + "\x03\x1C\x07\x1C\u01BB\n\x1C\f\x1C\x0E\x1C\u01BE\v\x1C\x03\x1C\x03\x1C" + + "\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u01C5\n\x1C\x03\x1C\x05\x1C\u01C8\n\x1C" + + "\x05\x1C\u01CA\n\x1C\x03\x1D\x06\x1D\u01CD\n\x1D\r\x1D\x0E\x1D\u01CE\x03" + + "\x1E\x06\x1E\u01D2\n\x1E\r\x1E\x0E\x1E\u01D3\x03\x1E\x03\x1E\x07\x1E\u01D8" + + "\n\x1E\f\x1E\x0E\x1E\u01DB\v\x1E\x03\x1E\x03\x1E\x06\x1E\u01DF\n\x1E\r" + + "\x1E\x0E\x1E\u01E0\x03\x1E\x06\x1E\u01E4\n\x1E\r\x1E\x0E\x1E\u01E5\x03" + + "\x1E\x03\x1E\x07\x1E\u01EA\n\x1E\f\x1E\x0E\x1E\u01ED\v\x1E\x05\x1E\u01EF" + + "\n\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x06\x1E\u01F5\n\x1E\r\x1E\x0E\x1E" + + "\u01F6\x03\x1E\x03\x1E\x05\x1E\u01FB\n\x1E\x03\x1F\x03\x1F\x03\x1F\x03" + + " \x03 \x03 \x03 \x03!\x03!\x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03" + + "$\x03$\x03$\x03%\x03%\x03&\x03&\x03&\x03&\x03&\x03&\x03\'\x03\'\x03\'" + + "\x03\'\x03\'\x03\'\x03(\x03(\x03(\x03(\x03(\x03)\x03)\x03*\x03*\x03*\x03" + + "+\x03+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x03-\x03-\x03.\x03.\x03" + + ".\x03.\x03.\x03/\x03/\x03/\x03/\x03/\x03/\x030\x030\x030\x031\x031\x03" + + "2\x032\x032\x032\x032\x032\x033\x033\x034\x034\x034\x034\x034\x035\x03" + + "5\x035\x035\x035\x036\x036\x036\x036\x036\x036\x036\x036\x036\x036\x03" + + "7\x037\x038\x038\x038\x039\x039\x039\x03:\x03:\x03;\x03;\x03;\x03<\x03" + + "<\x03=\x03=\x03=\x03>\x03>\x03?\x03?\x03@\x03@\x03A\x03A\x03B\x03B\x03" + + "C\x03C\x03C\x03C\x03C\x03D\x03D\x03D\x03D\x03D\x03E\x03E\x03E\x03E\x07" + + "E\u028B\nE\fE\x0EE\u028E\vE\x03E\x03E\x03E\x03E\x06E\u0294\nE\rE\x0EE" + + "\u0295\x05E\u0298\nE\x03F\x03F\x03F\x03F\x07F\u029E\nF\fF\x0EF\u02A1\v" + + "F\x03F\x03F\x03G\x03G\x03G\x03G\x03H\x03H\x03H\x03H\x03I\x03I\x03I\x03" + + "I\x03J\x03J\x03J\x03J\x03J\x03K\x03K\x03K\x03K\x03K\x03K\x03L\x03L\x03" + + "L\x03L\x03L\x03L\x03M\x03M\x03M\x03M\x03N\x03N\x03N\x03N\x03O\x03O\x03" + + "O\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03P\x03Q\x03Q\x03Q\x03R\x03" + + "R\x03R\x03R\x03R\x03S\x06S\u02DF\nS\rS\x0ES\u02E0\x03T\x06T\u02E4\nT\r" + + "T\x0ET\u02E5\x03T\x03T\x05T\u02EA\nT\x03U\x03U\x03V\x03V\x03V\x03V\x03" + + "W\x03W\x03W\x03W\x03X\x03X\x03X\x03X\x03Y\x03Y\x03Z\x03Z\x03[\x03[\x03" + + "\\\x03\\\x03]\x03]\x03^\x03^\x03_\x03_\x03`\x03`\x03a\x03a\x03b\x03b\x03" + + "c\x03c\x03d\x03d\x03e\x03e\x03f\x03f\x03g\x03g\x03h\x03h\x03i\x03i\x03" + + "j\x03j\x03k\x03k\x03l\x03l\x03m\x03m\x03n\x03n\x03o\x03o\x03p\x03p\x03" + + "q\x03q\x03r\x03r\x04\u0187\u01BC\x02\x02s\x05\x02\x03\x07\x02\x04\t\x02" + + "\x05\v\x02\x06\r\x02\x07\x0F\x02\b\x11\x02\t\x13\x02\n\x15\x02\v\x17\x02" + + "\f\x19\x02\r\x1B\x02\x0E\x1D\x02\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02" + + "\x13\'\x02\x14)\x02\x15+\x02\x16-\x02\x17/\x02\x021\x02\x023\x02\x025" + + "\x02\x027\x02\x029\x02\x18;\x02\x19=\x02\x1A?\x02\x1BA\x02\x1CC\x02\x1D" + + "E\x02\x1EG\x02\x1FI\x02 K\x02!M\x02\"O\x02#Q\x02$S\x02%U\x02&W\x02\'Y" + + "\x02([\x02)]\x02*_\x02+a\x02,c\x02-e\x02.g\x02/i\x020k\x021m\x022o\x02" + + "3q\x024s\x025u\x026w\x027y\x028{\x029}\x02:\x7F\x02;\x81\x02<\x83\x02" + + "=\x85\x02>\x87\x02?\x89\x02@\x8B\x02A\x8D\x02B\x8F\x02C\x91\x02D\x93\x02" + + "E\x95\x02\x02\x97\x02\x02\x99\x02\x02\x9B\x02\x02\x9D\x02\x02\x9F\x02" + + "F\xA1\x02G\xA3\x02H\xA5\x02I\xA7\x02J\xA9\x02\x02\xAB\x02K\xAD\x02L\xAF" + + "\x02M\xB1\x02N\xB3\x02\x02\xB5\x02\x02\xB7\x02\x02\xB9\x02\x02\xBB\x02" + + "\x02\xBD\x02\x02\xBF\x02\x02\xC1\x02\x02\xC3\x02\x02\xC5\x02\x02\xC7\x02" + + "\x02\xC9\x02\x02\xCB\x02\x02\xCD\x02\x02\xCF\x02\x02\xD1\x02\x02\xD3\x02" + + "\x02\xD5\x02\x02\xD7\x02\x02\xD9\x02\x02\xDB\x02\x02\xDD\x02\x02\xDF\x02" + + "\x02\xE1\x02\x02\xE3\x02\x02\xE5\x02\x02\x05\x02\x03\x04(\b\x02\v\f\x0F" + + "\x0F\"\"11]]__\x04\x02\f\f\x0F\x0F\x05\x02\v\f\x0F\x0F\"\"\x03\x022;\x04" + + "\x02C\\c|\x07\x02$$^^ppttvv\x06\x02\f\f\x0F\x0F$$^^\x04\x02GGgg\x04\x02" + + "--//\x04\x02BBaa\x03\x02bb\f\x02\v\f\x0F\x0F\"\"..11??]]__bb~~\x04\x02" + + ",,11\x04\x02CCcc\x04\x02DDdd\x04\x02EEee\x04\x02FFff\x04\x02HHhh\x04\x02" + "IIii\x04\x02JJjj\x04\x02KKkk\x04\x02LLll\x04\x02MMmm\x04\x02NNnn\x04\x02" + "OOoo\x04\x02PPpp\x04\x02QQqq\x04\x02RRrr\x04\x02SSss\x04\x02TTtt\x04\x02" + "UUuu\x04\x02VVvv\x04\x02WWww\x04\x02XXxx\x04\x02YYyy\x04\x02ZZzz\x04\x02" + - "[[{{\x04\x02\\\\||\x02\u06A4\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02" + - "\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02" + - "\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02" + - "\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02" + - "\x02\x1D\x03\x02\x02\x02\x02\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02" + - "\x02#\x03\x02\x02\x02\x02%\x03\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)" + - "\x03\x02\x02\x02\x02+\x03\x02\x02\x02\x02-\x03\x02\x02\x02\x03/\x03\x02" + - "\x02\x02\x031\x03\x02\x02\x02\x033\x03\x02\x02\x02\x035\x03\x02\x02\x02" + - "\x037\x03\x02\x02\x02\x049\x03\x02\x02\x02\x04E\x03\x02\x02\x02\x04G\x03" + - "\x02\x02\x02\x04I\x03\x02\x02\x02\x04K\x03\x02\x02\x02\x04M\x03\x02\x02" + - "\x02\x04O\x03\x02\x02\x02\x04Q\x03\x02\x02\x02\x04S\x03\x02\x02\x02\x04" + - "U\x03\x02\x02\x02\x04W\x03\x02\x02\x02\x04Y\x03\x02\x02\x02\x04[\x03\x02" + - "\x02\x02\x04]\x03\x02\x02\x02\x04_\x03\x02\x02\x02\x04a\x03\x02\x02\x02" + - "\x04c\x03\x02\x02\x02\x04e\x03\x02\x02\x02\x04g\x03\x02\x02\x02\x04i\x03" + - "\x02\x02\x02\x04k\x03\x02\x02\x02\x04m\x03\x02\x02\x02\x04o\x03\x02\x02" + - "\x02\x04q\x03\x02\x02\x02\x04s\x03\x02\x02\x02\x04u\x03\x02\x02\x02\x04" + - "w\x03\x02\x02\x02\x04y\x03\x02\x02\x02\x04{\x03\x02\x02\x02\x04}\x03\x02" + - "\x02\x02\x04\x7F\x03\x02\x02\x02\x04\x81\x03\x02\x02\x02\x04\x83\x03\x02" + - "\x02\x02\x04\x85\x03\x02\x02\x02\x04\x87\x03\x02\x02\x02\x04\x89\x03\x02" + - "\x02\x02\x04\x8B\x03\x02\x02\x02\x04\x8D\x03\x02\x02\x02\x04\x8F\x03\x02" + - "\x02\x02\x04\x91\x03\x02\x02\x02\x04\x93\x03\x02\x02\x02\x04\x95\x03\x02" + - "\x02\x02\x04\x97\x03\x02\x02\x02\x04\x99\x03\x02\x02\x02\x05\x9B\x03\x02" + - "\x02\x02\x05\x9D\x03\x02\x02\x02\x05\x9F\x03\x02\x02\x02\x05\xA1\x03\x02" + - "\x02\x02\x05\xA3\x03\x02\x02\x02\x05\xA5\x03\x02\x02\x02\x05\xA7\x03\x02" + - "\x02\x02\x05\xAB\x03\x02\x02\x02\x05\xAD\x03\x02\x02\x02\x05\xAF\x03\x02" + - "\x02\x02\x05\xB1\x03\x02\x02\x02\x06\xB3\x03\x02\x02\x02\x06\xB5\x03\x02" + - "\x02\x02\x06\xB7\x03\x02\x02\x02\x06\xB9\x03\x02\x02\x02\x06\xBB\x03\x02" + - "\x02\x02\x06\xBD\x03\x02\x02\x02\x06\xBF\x03\x02\x02\x02\x06\xC3\x03\x02" + - "\x02\x02\x06\xC5\x03\x02\x02\x02\x06\xC7\x03\x02\x02\x02\x06\xC9\x03\x02" + - "\x02\x02\x07\xFF\x03\x02\x02\x02\t\u0109\x03\x02\x02\x02\v\u0110\x03\x02" + - "\x02\x02\r\u0117\x03\x02\x02\x02\x0F\u0121\x03\x02\x02\x02\x11\u0128\x03" + - "\x02\x02\x02\x13\u012E\x03\x02\x02\x02\x15\u0136\x03\x02\x02\x02\x17\u013E" + - "\x03\x02\x02\x02\x19\u0145\x03\x02\x02\x02\x1B\u0151\x03\x02\x02\x02\x1D" + - "\u0159\x03\x02\x02\x02\x1F\u0163\x03\x02\x02\x02!\u016A\x03\x02\x02\x02" + - "#\u0173\x03\x02\x02\x02%\u017A\x03\x02\x02\x02\'\u0183\x03\x02\x02\x02" + - ")\u018A\x03\x02\x02\x02+\u019B\x03\x02\x02\x02-\u01AB\x03\x02\x02\x02" + - "/\u01B1\x03\x02\x02\x021\u01B6\x03\x02\x02\x023\u01BB\x03\x02\x02\x02" + - "5\u01BF\x03\x02\x02\x027\u01C3\x03\x02\x02\x029\u01C7\x03\x02\x02\x02" + - ";\u01CB\x03\x02\x02\x02=\u01CD\x03\x02\x02\x02?\u01CF\x03\x02\x02\x02" + - "A\u01D2\x03\x02\x02\x02C\u01D4\x03\x02\x02\x02E\u01FA\x03\x02\x02\x02" + - "G\u01FD\x03\x02\x02\x02I\u022B\x03\x02\x02\x02K\u022D\x03\x02\x02\x02" + - "M\u028E\x03\x02\x02\x02O\u0290\x03\x02\x02\x02Q\u0294\x03\x02\x02\x02" + - "S\u0296\x03\x02\x02\x02U\u0298\x03\x02\x02\x02W\u029A\x03\x02\x02\x02" + - "Y\u029C\x03\x02\x02\x02[\u02A1\x03\x02\x02\x02]\u02A6\x03\x02\x02\x02" + - "_\u02AA\x03\x02\x02\x02a\u02AF\x03\x02\x02\x02c\u02B5\x03\x02\x02\x02" + - "e\u02B8\x03\x02\x02\x02g\u02BB\x03\x02\x02\x02i\u02BE\x03\x02\x02\x02" + - "k\u02C3\x03\x02\x02\x02m\u02C6\x03\x02\x02\x02o\u02C8\x03\x02\x02\x02" + - "q\u02CA\x03\x02\x02\x02s\u02CF\x03\x02\x02\x02u\u02E2\x03\x02\x02\x02" + - "w\u02EE\x03\x02\x02\x02y\u02F0\x03\x02\x02\x02{\u02F2\x03\x02\x02\x02" + - "}\u02F4\x03\x02\x02\x02\x7F\u02F6\x03\x02\x02\x02\x81\u02F8\x03\x02\x02" + - "\x02\x83\u02FA\x03\x02\x02\x02\x85\u0304\x03\x02\x02\x02\x87\u0306\x03" + - "\x02\x02\x02\x89\u0315\x03\x02\x02\x02\x8B\u04C5\x03\x02\x02\x02\x8D\u055E" + - "\x03\x02\x02\x02\x8F\u0560\x03\x02\x02\x02\x91\u057E\x03\x02\x02\x02\x93" + - "\u0580\x03\x02\x02\x02\x95\u058B\x03\x02\x02\x02\x97\u058F\x03\x02\x02" + - "\x02\x99\u0593\x03\x02\x02\x02\x9B\u0597\x03\x02\x02\x02\x9D\u059C\x03" + - "\x02\x02\x02\x9F\u05A2\x03\x02\x02\x02\xA1\u05A8\x03\x02\x02\x02\xA3\u05AC" + - "\x03\x02\x02\x02\xA5\u05B0\x03\x02\x02\x02\xA7\u05BA\x03\x02\x02\x02\xA9" + - "\u05C5\x03\x02\x02\x02\xAB\u05C7\x03\x02\x02\x02\xAD\u05C9\x03\x02\x02" + - "\x02\xAF\u05CD\x03\x02\x02\x02\xB1\u05D1\x03\x02\x02\x02\xB3\u05D5\x03" + - "\x02\x02\x02\xB5\u05D8\x03\x02\x02\x02\xB7\u05DD\x03\x02\x02\x02\xB9\u05E2" + - "\x03\x02\x02\x02\xBB\u05E8\x03\x02\x02\x02\xBD\u05EC\x03\x02\x02\x02\xBF" + - "\u05F1\x03"; + "[[{{\x04\x02\\\\||\x02\u0330\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02" + + "\x02\x02\t\x03\x02\x02\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02" + + "\x02\x0F\x03\x02\x02\x02\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02" + + "\x02\x15\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02" + + "\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02\x1F\x03\x02\x02\x02" + + "\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03\x02\x02\x02\x02\'" + + "\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02\x02\x03-\x03\x02" + + "\x02\x02\x039\x03\x02\x02\x02\x03;\x03\x02\x02\x02\x03=\x03\x02\x02\x02" + + "\x03?\x03\x02\x02\x02\x03A\x03\x02\x02\x02\x03C\x03\x02\x02\x02\x03E\x03" + + "\x02\x02\x02\x03G\x03\x02\x02\x02\x03I\x03\x02\x02\x02\x03K\x03\x02\x02" + + "\x02\x03M\x03\x02\x02\x02\x03O\x03\x02\x02\x02\x03Q\x03\x02\x02\x02\x03" + + "S\x03\x02\x02\x02\x03U\x03\x02\x02\x02\x03W\x03\x02\x02\x02\x03Y\x03\x02" + + "\x02\x02\x03[\x03\x02\x02\x02\x03]\x03\x02\x02\x02\x03_\x03\x02\x02\x02" + + "\x03a\x03\x02\x02\x02\x03c\x03\x02\x02\x02\x03e\x03\x02\x02\x02\x03g\x03" + + "\x02\x02\x02\x03i\x03\x02\x02\x02\x03k\x03\x02\x02\x02\x03m\x03\x02\x02" + + "\x02\x03o\x03\x02\x02\x02\x03q\x03\x02\x02\x02\x03s\x03\x02\x02\x02\x03" + + "u\x03\x02\x02\x02\x03w\x03\x02\x02\x02\x03y\x03\x02\x02\x02\x03{\x03\x02" + + "\x02\x02\x03}\x03\x02\x02\x02\x03\x7F\x03\x02\x02\x02\x03\x81\x03\x02" + + "\x02\x02\x03\x83\x03\x02\x02\x02\x03\x85\x03\x02\x02\x02\x03\x87\x03\x02" + + "\x02\x02\x03\x89\x03\x02\x02\x02\x03\x8B\x03\x02\x02\x02\x03\x8D\x03\x02" + + "\x02\x02\x03\x8F\x03\x02\x02\x02\x03\x91\x03\x02\x02\x02\x03\x93\x03\x02" + + "\x02\x02\x04\x95\x03\x02\x02\x02\x04\x97\x03\x02\x02\x02\x04\x99\x03\x02" + + "\x02\x02\x04\x9B\x03\x02\x02\x02\x04\x9D\x03\x02\x02\x02\x04\x9F\x03\x02" + + "\x02\x02\x04\xA1\x03\x02\x02\x02\x04\xA3\x03\x02\x02\x02\x04\xA5\x03\x02" + + "\x02\x02\x04\xA7\x03\x02\x02\x02\x04\xAB\x03\x02\x02\x02\x04\xAD\x03\x02" + + "\x02\x02\x04\xAF\x03\x02\x02\x02\x04\xB1\x03\x02\x02\x02\x05\xE7\x03\x02" + + "\x02\x02\x07\xF1\x03\x02\x02\x02\t\xF8\x03\x02\x02\x02\v\u0101\x03\x02" + + "\x02\x02\r\u0108\x03\x02\x02\x02\x0F\u010F\x03\x02\x02\x02\x11\u0116\x03" + + "\x02\x02\x02\x13\u011D\x03\x02\x02\x02\x15\u0125\x03\x02\x02\x02\x17\u0131" + + "\x03\x02\x02\x02\x19\u013B\x03\x02\x02\x02\x1B\u0144\x03\x02\x02\x02\x1D" + + "\u014A\x03\x02\x02\x02\x1F\u0151\x03\x02\x02\x02!\u0158\x03\x02\x02\x02" + + "#\u0160\x03\x02\x02\x02%\u0169\x03\x02\x02\x02\'\u016F\x03\x02\x02\x02" + + ")\u0180\x03\x02\x02\x02+\u0190\x03\x02\x02\x02-\u0196\x03\x02\x02\x02" + + "/\u019A\x03\x02\x02\x021\u019C\x03\x02\x02\x023\u019E\x03\x02\x02\x02" + + "5\u01A1\x03\x02\x02\x027\u01A3\x03\x02\x02\x029\u01C9\x03\x02\x02\x02" + + ";\u01CC\x03\x02\x02\x02=\u01FA\x03\x02\x02\x02?\u01FC\x03\x02\x02\x02" + + "A\u01FF\x03\x02\x02\x02C\u0203\x03\x02\x02\x02E\u0207\x03\x02\x02\x02" + + "G\u0209\x03\x02\x02\x02I\u020B\x03\x02\x02\x02K\u0210\x03\x02\x02\x02" + + "M\u0212\x03\x02\x02\x02O\u0218\x03\x02\x02\x02Q\u021E\x03\x02\x02\x02" + + "S\u0223\x03\x02\x02\x02U\u0225\x03\x02\x02\x02W\u0228\x03\x02\x02\x02" + + "Y\u022B\x03\x02\x02\x02[\u0230\x03\x02\x02\x02]\u0234\x03\x02\x02\x02" + + "_\u0239\x03\x02\x02\x02a\u023F\x03\x02\x02\x02c\u0242\x03\x02\x02\x02" + + "e\u0244\x03\x02\x02\x02g\u024A\x03\x02\x02\x02i\u024C\x03\x02\x02\x02" + + "k\u0251\x03\x02\x02\x02m\u0256\x03\x02\x02\x02o\u0260\x03\x02\x02\x02" + + "q\u0262\x03\x02\x02\x02s\u0265\x03\x02\x02\x02u\u0268\x03\x02\x02\x02" + + "w\u026A\x03\x02\x02\x02y\u026D\x03\x02\x02\x02{\u026F\x03\x02\x02\x02" + + "}\u0272\x03\x02\x02\x02\x7F\u0274\x03\x02\x02\x02\x81\u0276\x03\x02\x02" + + "\x02\x83\u0278\x03\x02\x02\x02\x85\u027A\x03\x02\x02\x02\x87\u027C\x03" + + "\x02\x02\x02\x89\u0281\x03\x02\x02\x02\x8B\u0297\x03\x02\x02\x02\x8D\u0299" + + "\x03\x02\x02\x02\x8F\u02A4\x03\x02\x02\x02\x91\u02A8\x03\x02\x02\x02\x93" + + "\u02AC\x03\x02\x02\x02\x95\u02B0\x03\x02\x02\x02\x97\u02B5\x03\x02\x02" + + "\x02\x99\u02BB\x03\x02\x02\x02\x9B\u02C1\x03\x02\x02\x02\x9D\u02C5\x03" + + "\x02\x02\x02\x9F\u02C9\x03\x02\x02\x02\xA1\u02CC\x03\x02\x02\x02\xA3\u02D5" + + "\x03\x02\x02\x02\xA5\u02D8\x03\x02\x02\x02\xA7\u02DE\x03\x02\x02\x02\xA9" + + "\u02E9\x03\x02\x02\x02\xAB\u02EB\x03\x02\x02\x02\xAD\u02ED\x03\x02\x02" + + "\x02\xAF\u02F1\x03\x02\x02\x02\xB1\u02F5\x03\x02\x02\x02\xB3\u02F9\x03" + + "\x02\x02\x02\xB5\u02FB\x03\x02\x02\x02\xB7\u02FD\x03\x02\x02\x02\xB9\u02FF" + + "\x03\x02\x02\x02\xBB\u0301\x03\x02\x02\x02\xBD\u0303\x03\x02\x02\x02\xBF" + + "\u0305\x03\x02\x02\x02\xC1\u0307\x03\x02\x02\x02\xC3\u0309\x03\x02\x02" + + "\x02\xC5\u030B\x03\x02\x02\x02\xC7\u030D\x03\x02\x02\x02\xC9\u030F\x03" + + "\x02\x02\x02\xCB\u0311\x03\x02\x02\x02\xCD\u0313\x03\x02\x02\x02\xCF\u0315" + + "\x03\x02\x02\x02\xD1\u0317\x03\x02\x02\x02\xD3\u0319\x03\x02\x02\x02\xD5" + + "\u031B\x03\x02\x02\x02\xD7\u031D\x03\x02\x02\x02\xD9\u031F\x03\x02\x02" + + "\x02\xDB\u0321\x03\x02\x02\x02\xDD\u0323\x03\x02\x02\x02\xDF\u0325\x03" + + "\x02\x02\x02\xE1\u0327\x03\x02\x02\x02\xE3\u0329\x03\x02\x02\x02\xE5\u032B" + + "\x03\x02\x02\x02\xE7\xE8\x05\xB9\\\x02\xE8\xE9\x05\xC3a\x02\xE9\xEA\x05" + + "\xD7k\x02\xEA\xEB\x05\xD7k\x02\xEB\xEC\x05\xBB]\x02\xEC\xED\x05\xB7[\x02" + + "\xED\xEE\x05\xD9l\x02\xEE\xEF\x03\x02\x02\x02\xEF\xF0\b\x02\x02\x02\xF0" + + "\x06\x03\x02\x02\x02\xF1\xF2\x05\xB9\\\x02\xF2\xF3\x05\xD5j\x02\xF3\xF4" + + "\x05\xCFg\x02\xF4\xF5\x05\xD1h\x02\xF5\xF6\x03\x02\x02\x02\xF6\xF7\b\x03" + + "\x03\x02\xF7\b\x03\x02\x02\x02\xF8\xF9\x05\xBB]\x02\xF9\xFA\x05\xCDf\x02" + + "\xFA\xFB\x05\xD5j\x02\xFB\xFC\x05\xC3a\x02\xFC\xFD\x05\xB7[\x02\xFD\xFE" + + "\x05\xC1`\x02\xFE\xFF\x03\x02\x02\x02\xFF\u0100\b\x04\x03\x02\u0100\n" + + "\x03\x02\x02\x02\u0101\u0102\x05\xBB]\x02\u0102\u0103\x05\xDDn\x02\u0103" + + "\u0104\x05\xB3Y\x02\u0104\u0105\x05\xC9d\x02\u0105\u0106\x03\x02\x02\x02" + + "\u0106\u0107\b\x05\x02\x02\u0107\f\x03\x02\x02\x02\u0108\u0109\x05\xBD" + + "^\x02\u0109\u010A\x05\xD5j\x02\u010A\u010B\x05\xCFg\x02\u010B\u010C\x05" + + "\xCBe\x02\u010C\u010D\x03\x02\x02\x02\u010D\u010E\b\x06\x03\x02\u010E" + + "\x0E\x03\x02\x02\x02\u010F\u0110\x05\xBF_\x02\u0110\u0111\x05\xD5j\x02" + + "\u0111\u0112\x05\xCFg\x02\u0112\u0113\x05\xC7c\x02\u0113\u0114\x03\x02" + + "\x02\x02\u0114\u0115\b\x07\x02\x02\u0115\x10\x03\x02\x02\x02\u0116\u0117" + + "\x05\xC7c\x02\u0117\u0118\x05\xBB]\x02\u0118\u0119\x05\xBB]\x02\u0119" + + "\u011A\x05\xD1h\x02\u011A\u011B\x03\x02\x02\x02\u011B\u011C\b\b\x03\x02" + + "\u011C\x12\x03\x02\x02\x02\u011D\u011E\x05\xC9d\x02\u011E\u011F\x05\xC3" + + "a\x02\u011F\u0120\x05\xCBe\x02\u0120\u0121\x05\xC3a\x02\u0121\u0122\x05" + + "\xD9l\x02\u0122\u0123\x03\x02\x02\x02\u0123\u0124\b\t\x02\x02\u0124\x14" + + "\x03\x02\x02\x02\u0125\u0126\x05\xCBe\x02\u0126\u0127\x05\xDDn\x02\u0127" + + "\u0128\x05o7\x02\u0128\u0129\x05\xBB]\x02\u0129\u012A\x05\xE1p\x02\u012A" + + "\u012B\x05\xD1h\x02\u012B\u012C\x05\xB3Y\x02\u012C\u012D\x05\xCDf\x02" + + "\u012D\u012E\x05\xB9\\\x02\u012E\u012F\x03\x02\x02\x02\u012F\u0130\b\n" + + "\x03\x02\u0130\x16\x03\x02\x02\x02\u0131\u0132\x05\xD1h\x02\u0132\u0133" + + "\x05\xD5j\x02\u0133\u0134\x05\xCFg\x02\u0134\u0135\x05\xC5b\x02\u0135" + + "\u0136\x05\xBB]\x02\u0136\u0137\x05\xB7[\x02\u0137\u0138\x05\xD9l\x02" + + "\u0138\u0139\x03\x02\x02\x02\u0139\u013A\b\v\x03\x02\u013A\x18\x03\x02" + + "\x02\x02\u013B\u013C\x05\xD5j\x02\u013C\u013D\x05\xBB]\x02\u013D\u013E" + + "\x05\xCDf\x02\u013E\u013F\x05\xB3Y\x02\u013F\u0140\x05\xCBe\x02\u0140" + + "\u0141\x05\xBB]\x02\u0141\u0142\x03\x02\x02\x02\u0142\u0143\b\f\x03\x02" + + "\u0143\x1A\x03\x02\x02\x02\u0144\u0145\x05\xD5j\x02\u0145\u0146\x05\xCF" + + "g\x02\u0146\u0147\x05\xDFo\x02\u0147\u0148\x03\x02\x02\x02\u0148\u0149" + + "\b\r\x02\x02\u0149\x1C\x03\x02\x02\x02\u014A\u014B\x05\xD7k\x02\u014B" + + "\u014C\x05\xC1`\x02\u014C\u014D\x05\xCFg\x02\u014D\u014E\x05\xDFo\x02" + + "\u014E\u014F\x03\x02\x02\x02\u014F\u0150\b\x0E\x02\x02\u0150\x1E\x03\x02" + + "\x02\x02\u0151\u0152\x05\xD7k\x02\u0152\u0153\x05\xCFg\x02\u0153\u0154" + + "\x05\xD5j\x02\u0154\u0155\x05\xD9l\x02\u0155\u0156\x03\x02\x02\x02\u0156" + + "\u0157\b\x0F\x02\x02\u0157 \x03\x02\x02\x02\u0158\u0159\x05\xD7k\x02\u0159" + + "\u015A\x05\xD9l\x02\u015A\u015B\x05\xB3Y\x02\u015B\u015C\x05\xD9l\x02" + + "\u015C\u015D\x05\xD7k\x02\u015D\u015E\x03\x02\x02\x02\u015E\u015F\b\x10" + + "\x02\x02\u015F\"\x03\x02\x02\x02\u0160\u0161\x05\xDFo\x02\u0161\u0162" + + "\x05\xC1`\x02\u0162\u0163\x05\xBB]\x02\u0163\u0164\x05\xD5j\x02\u0164" + + "\u0165\x05\xBB]\x02\u0165\u0166\x03\x02\x02\x02\u0166\u0167\b\x11\x02" + + "\x02\u0167$\x03\x02\x02\x02\u0168\u016A\n\x02\x02\x02\u0169\u0168\x03" + + "\x02\x02\x02\u016A\u016B\x03\x02\x02\x02\u016B\u0169\x03\x02\x02\x02\u016B" + + "\u016C\x03\x02\x02\x02\u016C\u016D\x03\x02\x02\x02\u016D\u016E\b\x12\x02" + + "\x02\u016E&\x03\x02\x02\x02\u016F\u0170\x071\x02\x02\u0170\u0171\x071" + + "\x02\x02\u0171\u0175\x03\x02\x02\x02\u0172\u0174\n\x03\x02\x02\u0173\u0172" + + "\x03\x02\x02\x02\u0174\u0177\x03\x02\x02\x02\u0175\u0173\x03\x02\x02\x02" + + "\u0175\u0176\x03\x02\x02\x02\u0176\u0179\x03\x02\x02\x02\u0177\u0175\x03" + + "\x02\x02\x02\u0178\u017A\x07\x0F\x02\x02\u0179\u0178\x03\x02\x02\x02\u0179" + + "\u017A\x03\x02\x02\x02\u017A\u017C\x03\x02\x02\x02\u017B\u017D\x07\f\x02" + + "\x02\u017C\u017B\x03\x02\x02\x02\u017C\u017D\x03\x02\x02\x02\u017D\u017E" + + "\x03\x02\x02\x02\u017E\u017F\b\x13\x04\x02\u017F(\x03\x02\x02\x02\u0180" + + "\u0181\x071\x02\x02\u0181\u0182\x07,\x02\x02\u0182\u0187\x03\x02\x02\x02" + + "\u0183\u0186\x05)\x14\x02\u0184\u0186\v\x02\x02\x02\u0185\u0183\x03\x02" + + "\x02\x02\u0185\u0184\x03\x02\x02\x02\u0186\u0189\x03\x02\x02\x02\u0187" + + "\u0188\x03\x02\x02\x02\u0187\u0185\x03\x02\x02\x02\u0188\u018A\x03\x02" + + "\x02\x02\u0189\u0187\x03\x02\x02\x02\u018A\u018B\x07,\x02\x02\u018B\u018C" + + "\x071\x02\x02\u018C\u018D\x03\x02\x02\x02\u018D\u018E\b\x14\x04\x02\u018E" + + "*\x03\x02\x02\x02\u018F\u0191\t\x04\x02\x02\u0190\u018F\x03\x02\x02\x02" + + "\u0191\u0192\x03\x02\x02\x02\u0192\u0190\x03\x02\x02\x02\u0192\u0193\x03" + + "\x02\x02\x02\u0193\u0194\x03\x02\x02\x02\u0194\u0195\b\x15\x04\x02\u0195" + + ",\x03\x02\x02\x02\u0196\u0197\x07~\x02\x02\u0197\u0198\x03\x02\x02\x02" + + "\u0198\u0199\b\x16\x05\x02\u0199.\x03\x02\x02\x02\u019A\u019B\t\x05\x02" + + "\x02\u019B0\x03\x02\x02\x02\u019C\u019D\t\x06\x02\x02\u019D2\x03\x02\x02" + + "\x02\u019E\u019F\x07^\x02\x02\u019F\u01A0\t\x07\x02\x02\u01A04\x03\x02" + + "\x02\x02\u01A1\u01A2\n\b\x02\x02\u01A26\x03\x02\x02\x02\u01A3\u01A5\t" + + "\t\x02\x02\u01A4\u01A6\t\n\x02\x02\u01A5\u01A4\x03\x02\x02\x02\u01A5\u01A6" + + "\x03\x02\x02\x02\u01A6\u01A8\x03\x02\x02\x02\u01A7\u01A9\x05/\x17\x02" + + "\u01A8\u01A7\x03\x02\x02\x02\u01A9\u01AA\x03\x02\x02\x02\u01AA\u01A8\x03" + + "\x02\x02\x02\u01AA\u01AB\x03\x02\x02\x02\u01AB8\x03\x02\x02\x02\u01AC" + + "\u01B1\x07$\x02\x02\u01AD\u01B0\x053\x19\x02\u01AE\u01B0\x055\x1A\x02" + + "\u01AF\u01AD\x03\x02\x02\x02\u01AF\u01AE\x03\x02\x02\x02\u01B0\u01B3\x03" + + "\x02\x02\x02\u01B1\u01AF\x03\x02\x02\x02\u01B1\u01B2\x03\x02\x02\x02\u01B2" + + "\u01B4\x03\x02\x02\x02\u01B3\u01B1\x03\x02\x02\x02\u01B4\u01CA\x07$\x02" + + "\x02\u01B5\u01B6\x07$\x02\x02\u01B6\u01B7\x07$\x02\x02\u01B7\u01B8\x07" + + "$\x02\x02\u01B8\u01BC\x03\x02\x02\x02\u01B9\u01BB\n\x03\x02\x02\u01BA" + + "\u01B9\x03\x02\x02\x02\u01BB\u01BE\x03\x02\x02\x02\u01BC\u01BD\x03\x02" + + "\x02\x02\u01BC\u01BA\x03\x02\x02\x02\u01BD\u01BF\x03\x02\x02\x02\u01BE" + + "\u01BC\x03\x02\x02\x02\u01BF\u01C0\x07$\x02\x02\u01C0\u01C1\x07$\x02\x02" + + "\u01C1\u01C2\x07$\x02\x02\u01C2\u01C4\x03\x02\x02\x02\u01C3\u01C5\x07" + + "$\x02\x02\u01C4\u01C3\x03\x02\x02\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5" + + "\u01C7\x03\x02\x02\x02\u01C6\u01C8\x07$\x02\x02\u01C7\u01C6\x03\x02\x02" + + "\x02\u01C7\u01C8\x03\x02\x02\x02\u01C8\u01CA\x03\x02\x02\x02\u01C9\u01AC" + + "\x03\x02\x02\x02\u01C9\u01B5\x03\x02\x02\x02\u01CA:\x03\x02\x02\x02\u01CB" + + "\u01CD\x05/\x17\x02\u01CC\u01CB\x03\x02\x02\x02\u01CD\u01CE\x03\x02\x02" + + "\x02\u01CE\u01CC\x03\x02\x02\x02\u01CE\u01CF\x03\x02\x02\x02\u01CF<\x03" + + "\x02\x02\x02\u01D0\u01D2\x05/\x17\x02\u01D1\u01D0\x03\x02\x02\x02\u01D2" + + "\u01D3\x03\x02\x02\x02\u01D3\u01D1\x03\x02\x02\x02\u01D3\u01D4\x03\x02" + + "\x02\x02\u01D4\u01D5\x03\x02\x02\x02\u01D5\u01D9\x05K%\x02\u01D6\u01D8" + + "\x05/\x17\x02"; private static readonly _serializedATNSegment1: string = - "\x02\x02\x02\xC1\u05FC\x03\x02\x02\x02\xC3\u05FE\x03\x02\x02\x02\xC5\u0600" + - "\x03\x02\x02\x02\xC7\u0604\x03\x02\x02\x02\xC9\u0608\x03\x02\x02\x02\xCB" + - "\u060C\x03\x02\x02\x02\xCD\u060E\x03\x02\x02\x02\xCF\u0610\x03\x02\x02" + - "\x02\xD1\u0612\x03\x02\x02\x02\xD3\u0614\x03\x02\x02\x02\xD5\u0616\x03" + - "\x02\x02\x02\xD7\u0618\x03\x02\x02\x02\xD9\u061A\x03\x02\x02\x02\xDB\u061C" + - "\x03\x02\x02\x02\xDD\u061E\x03\x02\x02\x02\xDF\u0620\x03\x02\x02\x02\xE1" + - "\u0622\x03\x02\x02\x02\xE3\u0624\x03\x02\x02\x02\xE5\u0626\x03\x02\x02" + - "\x02\xE7\u0628\x03\x02\x02\x02\xE9\u062A\x03\x02\x02\x02\xEB\u062C\x03" + - "\x02\x02\x02\xED\u062E\x03\x02\x02\x02\xEF\u0630\x03\x02\x02\x02\xF1\u0632" + - "\x03\x02\x02\x02\xF3\u0634\x03\x02\x02\x02\xF5\u0636\x03\x02\x02\x02\xF7" + - "\u0638\x03\x02\x02\x02\xF9\u063A\x03\x02\x02\x02\xFB\u063C\x03\x02\x02" + - "\x02\xFD\u063E\x03\x02\x02\x02\xFF\u0100\x05\xD1g\x02\u0100\u0101\x05" + - "\xDBl\x02\u0101\u0102\x05\xEFv\x02\u0102\u0103\x05\xEFv\x02\u0103\u0104" + - "\x05\xD3h\x02\u0104\u0105\x05\xCFf\x02\u0105\u0106\x05\xF1w\x02\u0106" + - "\u0107\x03\x02\x02\x02\u0107\u0108\b\x02\x02\x02\u0108\b\x03\x02\x02\x02" + - "\u0109\u010A\x05\xD7j\x02\u010A\u010B\x05\xEDu\x02\u010B\u010C\x05\xE7" + - "r\x02\u010C\u010D\x05\xDFn\x02\u010D\u010E\x03\x02\x02\x02\u010E\u010F" + - "\b\x03\x02\x02\u010F\n\x03\x02\x02\x02\u0110\u0111\x05\xD3h\x02\u0111" + - "\u0112\x05\xF5y\x02\u0112\u0113\x05\xCBd\x02\u0113\u0114\x05\xE1o\x02" + - "\u0114\u0115\x03\x02\x02\x02\u0115\u0116\b\x04\x02\x02\u0116\f\x03\x02" + - "\x02\x02\u0117\u0118\x05\xD3h\x02\u0118\u0119\x05\xF9{\x02\u0119\u011A" + - "\x05\xE9s\x02\u011A\u011B\x05\xE1o\x02\u011B\u011C\x05\xCBd\x02\u011C" + - "\u011D\x05\xDBl\x02\u011D\u011E\x05\xE5q\x02\u011E\u011F\x03\x02\x02\x02" + - "\u011F\u0120\b\x05\x03\x02\u0120\x0E\x03\x02\x02\x02\u0121\u0122\x05\xD5" + - "i\x02\u0122\u0123\x05\xEDu\x02\u0123\u0124\x05\xE7r\x02\u0124\u0125\x05" + - "\xE3p\x02\u0125\u0126\x03\x02\x02\x02\u0126\u0127\b\x06\x04\x02\u0127" + - "\x10\x03\x02\x02\x02\u0128\u0129\x05\xEDu\x02\u0129\u012A\x05\xE7r\x02" + - "\u012A\u012B\x05\xF7z\x02\u012B\u012C\x03\x02\x02\x02\u012C\u012D\b\x07" + - "\x02\x02\u012D\x12\x03\x02\x02\x02\u012E\u012F\x05\xEFv\x02\u012F\u0130" + - "\x05\xF1w\x02\u0130\u0131\x05\xCBd\x02\u0131\u0132\x05\xF1w\x02\u0132" + - "\u0133\x05\xEFv\x02\u0133\u0134\x03\x02\x02\x02\u0134\u0135\b\b\x02\x02" + - "\u0135\x14\x03\x02\x02\x02\u0136\u0137\x05\xF7z\x02\u0137\u0138\x05\xD9" + - "k\x02\u0138\u0139\x05\xD3h\x02\u0139\u013A\x05\xEDu\x02\u013A\u013B\x05" + - "\xD3h\x02\u013B\u013C\x03\x02\x02\x02\u013C\u013D\b\t\x02\x02\u013D\x16" + - "\x03\x02\x02\x02\u013E\u013F\x05\xEFv\x02\u013F\u0140\x05\xE7r\x02\u0140" + - "\u0141\x05\xEDu\x02\u0141\u0142\x05\xF1w\x02\u0142\u0143\x03\x02\x02\x02" + - "\u0143\u0144\b\n\x02\x02\u0144\x18\x03\x02\x02\x02\u0145\u0146\x05\xE3" + - "p\x02\u0146\u0147\x05\xF5y\x02\u0147\u0148\x05o6\x02\u0148\u0149\x05\xD3" + - "h\x02\u0149\u014A\x05\xF9{\x02\u014A\u014B\x05\xE9s\x02\u014B\u014C\x05" + - "\xCBd\x02\u014C\u014D\x05\xE5q\x02\u014D\u014E\x05\xD1g\x02\u014E\u014F" + - "\x03\x02\x02\x02\u014F\u0150\b\v\x02\x02\u0150\x1A\x03\x02\x02\x02\u0151" + - "\u0152\x05\xE1o\x02\u0152\u0153\x05\xDBl\x02\u0153\u0154\x05\xE3p\x02" + - "\u0154\u0155\x05\xDBl\x02\u0155\u0156\x05\xF1w\x02\u0156\u0157\x03\x02" + - "\x02\x02\u0157\u0158\b\f\x02\x02\u0158\x1C\x03\x02\x02\x02\u0159\u015A" + - "\x05\xE9s\x02\u015A\u015B\x05\xEDu\x02\u015B\u015C\x05\xE7r\x02\u015C" + - "\u015D\x05\xDDm\x02\u015D\u015E\x05\xD3h\x02\u015E\u015F\x05\xCFf\x02" + - "\u015F\u0160\x05\xF1w\x02\u0160\u0161\x03\x02\x02\x02\u0161\u0162\b\r" + - "\x02\x02\u0162\x1E\x03\x02\x02\x02\u0163\u0164\x05\xD1g\x02\u0164\u0165" + - "\x05\xEDu\x02\u0165\u0166\x05\xE7r\x02\u0166\u0167\x05\xE9s\x02\u0167" + - "\u0168\x03\x02\x02\x02\u0168\u0169\b\x0E\x02\x02\u0169 \x03\x02\x02\x02" + - "\u016A\u016B\x05\xEDu\x02\u016B\u016C\x05\xD3h\x02\u016C\u016D\x05\xE5" + - "q\x02\u016D\u016E\x05\xCBd\x02\u016E\u016F\x05\xE3p\x02\u016F\u0170\x05" + - "\xD3h\x02\u0170\u0171\x03\x02\x02\x02\u0171\u0172\b\x0F\x02\x02\u0172" + - "\"\x03\x02\x02\x02\u0173\u0174\x05\xEFv\x02\u0174\u0175\x05\xD9k\x02\u0175" + - "\u0176\x05\xE7r\x02\u0176\u0177\x05\xF7z\x02\u0177\u0178\x03\x02\x02\x02" + - "\u0178\u0179\b\x10\x02\x02\u0179$\x03\x02\x02\x02\u017A\u017B\x05\xD3" + - "h\x02\u017B\u017C\x05\xE5q\x02\u017C\u017D\x05\xEDu\x02\u017D\u017E\x05" + - "\xDBl\x02\u017E\u017F\x05\xCFf\x02\u017F\u0180\x05\xD9k\x02\u0180\u0181" + - "\x03\x02\x02\x02\u0181\u0182\b\x11\x05\x02\u0182&\x03\x02\x02\x02\u0183" + - "\u0184\x05\xDFn\x02\u0184\u0185\x05\xD3h\x02\u0185\u0186\x05\xD3h\x02" + - "\u0186\u0187\x05\xE9s\x02\u0187\u0188\x03\x02\x02\x02\u0188\u0189\b\x12" + - "\x02\x02\u0189(\x03\x02\x02\x02\u018A\u018B\x071\x02\x02\u018B\u018C\x07" + - "1\x02\x02\u018C\u0190\x03\x02\x02\x02\u018D\u018F\n\x02\x02\x02\u018E" + - "\u018D\x03\x02\x02\x02\u018F\u0192\x03\x02\x02\x02\u0190\u018E\x03\x02" + - "\x02\x02\u0190\u0191\x03\x02\x02\x02\u0191\u0194\x03\x02\x02\x02\u0192" + - "\u0190\x03\x02\x02\x02\u0193\u0195\x07\x0F\x02\x02\u0194\u0193\x03\x02" + - "\x02\x02\u0194\u0195\x03\x02\x02\x02\u0195\u0197\x03\x02\x02\x02\u0196" + - "\u0198\x07\f\x02\x02\u0197\u0196\x03\x02\x02\x02\u0197\u0198\x03\x02\x02" + - "\x02\u0198\u0199\x03\x02\x02\x02\u0199\u019A\b\x13\x06\x02\u019A*\x03" + - "\x02\x02\x02\u019B\u019C\x071\x02\x02\u019C\u019D\x07,\x02\x02\u019D\u01A2" + - "\x03\x02\x02\x02\u019E\u01A1\x05+\x14\x02\u019F\u01A1\v\x02\x02\x02\u01A0" + - "\u019E\x03\x02\x02\x02\u01A0\u019F\x03\x02\x02\x02\u01A1\u01A4\x03\x02" + - "\x02\x02\u01A2\u01A3\x03\x02\x02\x02\u01A2\u01A0\x03\x02\x02\x02\u01A3" + - "\u01A5\x03\x02\x02\x02\u01A4\u01A2\x03\x02\x02\x02\u01A5\u01A6\x07,\x02" + - "\x02\u01A6\u01A7\x071\x02\x02\u01A7\u01A8\x03\x02\x02\x02\u01A8\u01A9" + - "\b\x14\x06\x02\u01A9,\x03\x02\x02\x02\u01AA\u01AC\t\x03\x02\x02\u01AB" + - "\u01AA\x03\x02\x02\x02\u01AC\u01AD\x03\x02\x02\x02\u01AD\u01AB\x03\x02" + - "\x02\x02\u01AD\u01AE\x03\x02\x02\x02\u01AE\u01AF\x03\x02\x02\x02\u01AF" + - "\u01B0\b\x15\x06\x02\u01B0.\x03\x02\x02\x02\u01B1\u01B2\x07]\x02\x02\u01B2" + - "\u01B3\x03\x02\x02\x02\u01B3\u01B4\b\x16\x07\x02\u01B4\u01B5\b\x16\b\x02" + - "\u01B50\x03\x02\x02\x02\u01B6\u01B7\x07~\x02\x02\u01B7\u01B8\x03\x02\x02" + - "\x02\u01B8\u01B9\b\x17\t\x02\u01B9\u01BA\b\x17\n\x02\u01BA2\x03\x02\x02" + - "\x02\u01BB\u01BC\x05-\x15\x02\u01BC\u01BD\x03\x02\x02\x02\u01BD\u01BE" + - "\b\x18\x06\x02\u01BE4\x03\x02\x02\x02\u01BF\u01C0\x05)\x13\x02\u01C0\u01C1" + - "\x03\x02\x02\x02\u01C1\u01C2\b\x19\x06\x02\u01C26\x03\x02\x02\x02\u01C3" + - "\u01C4\x05+\x14\x02\u01C4\u01C5\x03\x02\x02\x02\u01C5\u01C6\b\x1A\x06" + - "\x02\u01C68\x03\x02\x02\x02\u01C7\u01C8\x07~\x02\x02\u01C8\u01C9\x03\x02" + - "\x02\x02\u01C9\u01CA\b\x1B\n\x02\u01CA:\x03\x02\x02\x02\u01CB\u01CC\t" + - "\x04\x02\x02\u01CC<\x03\x02\x02\x02\u01CD\u01CE\t\x05\x02\x02\u01CE>\x03" + - "\x02\x02\x02\u01CF\u01D0\x07^\x02\x02\u01D0\u01D1\t\x06\x02\x02\u01D1" + - "@\x03\x02\x02\x02\u01D2\u01D3\n\x07\x02\x02\u01D3B\x03\x02\x02\x02\u01D4" + - "\u01D6\t\b\x02\x02\u01D5\u01D7\t\t\x02\x02\u01D6\u01D5\x03\x02\x02\x02" + - "\u01D6\u01D7\x03\x02\x02\x02\u01D7\u01D9\x03\x02\x02\x02\u01D8\u01DA\x05" + - ";\x1C\x02\u01D9\u01D8\x03\x02\x02\x02\u01DA\u01DB\x03\x02\x02\x02\u01DB" + - "\u01D9\x03\x02\x02\x02\u01DB\u01DC\x03\x02\x02\x02\u01DCD\x03\x02\x02" + - "\x02\u01DD\u01E2\x07$\x02\x02\u01DE\u01E1\x05?\x1E\x02\u01DF\u01E1\x05" + - "A\x1F\x02\u01E0\u01DE\x03\x02\x02\x02\u01E0\u01DF\x03\x02\x02\x02\u01E1" + - "\u01E4\x03\x02\x02\x02\u01E2\u01E0\x03\x02\x02\x02\u01E2\u01E3\x03\x02" + - "\x02\x02\u01E3\u01E5\x03\x02\x02\x02\u01E4\u01E2\x03\x02\x02\x02\u01E5" + - "\u01FB\x07$\x02\x02\u01E6\u01E7\x07$\x02\x02\u01E7\u01E8\x07$\x02\x02" + - "\u01E8\u01E9\x07$\x02\x02\u01E9\u01ED\x03\x02\x02\x02\u01EA\u01EC\n\x02" + - "\x02\x02\u01EB\u01EA\x03\x02\x02\x02\u01EC\u01EF\x03\x02\x02\x02\u01ED" + - "\u01EE\x03\x02\x02\x02\u01ED\u01EB\x03\x02\x02\x02\u01EE\u01F0\x03\x02" + - "\x02\x02\u01EF\u01ED\x03\x02\x02\x02\u01F0\u01F1\x07$\x02\x02\u01F1\u01F2" + - "\x07$\x02\x02\u01F2\u01F3\x07$\x02\x02\u01F3\u01F5\x03\x02\x02\x02\u01F4" + - "\u01F6\x07$\x02\x02\u01F5\u01F4\x03\x02\x02\x02\u01F5\u01F6\x03\x02\x02" + - "\x02\u01F6\u01F8\x03\x02\x02\x02\u01F7\u01F9\x07$\x02\x02\u01F8\u01F7" + - "\x03\x02\x02\x02\u01F8\u01F9\x03\x02\x02\x02\u01F9\u01FB\x03\x02\x02\x02" + - "\u01FA\u01DD\x03\x02\x02\x02\u01FA\u01E6\x03\x02\x02\x02\u01FBF\x03\x02" + - "\x02\x02\u01FC\u01FE\x05;\x1C\x02\u01FD\u01FC\x03\x02\x02\x02\u01FE\u01FF" + - "\x03\x02\x02\x02\u01FF\u01FD\x03\x02\x02\x02\u01FF\u0200\x03\x02\x02\x02" + - "\u0200H\x03\x02\x02\x02\u0201\u0203\x05;\x1C\x02\u0202\u0201\x03\x02\x02" + - "\x02\u0203\u0204\x03\x02\x02\x02\u0204\u0202\x03\x02\x02\x02\u0204\u0205" + - "\x03\x02\x02\x02\u0205\u0206\x03\x02\x02\x02\u0206\u020A\x05U)\x02\u0207" + - "\u0209\x05;\x1C\x02\u0208\u0207\x03\x02\x02\x02\u0209\u020C\x03\x02\x02" + - "\x02\u020A\u0208\x03\x02\x02\x02\u020A\u020B\x03\x02\x02\x02\u020B\u022C" + - "\x03\x02\x02\x02\u020C\u020A\x03\x02\x02\x02\u020D\u020F\x05U)\x02\u020E" + - "\u0210\x05;\x1C\x02\u020F\u020E\x03\x02\x02\x02\u0210\u0211\x03\x02\x02" + - "\x02\u0211\u020F\x03\x02\x02\x02\u0211\u0212\x03\x02\x02\x02\u0212\u022C" + - "\x03\x02\x02\x02\u0213\u0215\x05;\x1C\x02\u0214\u0213\x03\x02\x02\x02" + - "\u0215\u0216\x03\x02\x02\x02\u0216\u0214\x03\x02\x02\x02\u0216\u0217\x03" + - "\x02\x02\x02\u0217\u021F\x03\x02\x02\x02\u0218\u021C\x05U)\x02\u0219\u021B" + - "\x05;\x1C\x02\u021A\u0219\x03\x02\x02\x02\u021B\u021E\x03\x02\x02\x02" + - "\u021C\u021A\x03\x02\x02\x02\u021C\u021D\x03\x02\x02\x02\u021D\u0220\x03" + - "\x02\x02\x02\u021E\u021C\x03\x02\x02\x02\u021F\u0218\x03\x02\x02\x02\u021F" + - "\u0220\x03\x02\x02\x02\u0220\u0221\x03\x02\x02\x02\u0221\u0222\x05C \x02" + - "\u0222\u022C\x03\x02\x02\x02\u0223\u0225\x05U)\x02\u0224\u0226\x05;\x1C" + - "\x02\u0225\u0224\x03\x02\x02\x02\u0226\u0227\x03\x02\x02\x02\u0227\u0225" + - "\x03\x02\x02\x02\u0227\u0228\x03\x02\x02\x02\u0228\u0229\x03\x02\x02\x02" + - "\u0229\u022A\x05C \x02\u022A\u022C\x03\x02\x02\x02\u022B\u0202\x03\x02" + - "\x02\x02\u022B\u020D\x03\x02\x02\x02\u022B\u0214\x03\x02\x02\x02\u022B" + - "\u0223\x03\x02\x02\x02\u022CJ\x03\x02\x02\x02\u022D\u022E\x07d\x02\x02" + - "\u022E\u022F\x07{\x02\x02\u022FL\x03\x02\x02\x02\u0230\u0231\x07{\x02" + - "\x02\u0231\u0232\x07g\x02\x02\u0232\u0233\x07c\x02\x02\u0233\u028F\x07" + - "t\x02\x02\u0234\u0235\x07o\x02\x02\u0235\u0236\x07q\x02\x02\u0236\u0237" + - "\x07p\x02\x02\u0237\u0238\x07v\x02\x02\u0238\u028F\x07j\x02\x02\u0239" + - "\u023A\x07f\x02\x02\u023A\u023B\x07c\x02\x02\u023B\u028F\x07{\x02\x02" + - "\u023C\u023D\x07u\x02\x02\u023D\u023E\x07g\x02\x02\u023E\u023F\x07e\x02" + - "\x02\u023F\u0240\x07q\x02\x02\u0240\u0241\x07p\x02\x02\u0241\u028F\x07" + - "f\x02\x02\u0242\u0243\x07o\x02\x02\u0243\u0244\x07k\x02\x02\u0244\u0245" + - "\x07p\x02\x02\u0245\u0246\x07w\x02\x02\u0246\u0247\x07v\x02\x02\u0247" + - "\u028F\x07g\x02\x02\u0248\u0249\x07j\x02\x02\u0249\u024A\x07q\x02\x02" + - "\u024A\u024B\x07w\x02\x02\u024B\u028F\x07t\x02\x02\u024C\u024D\x07y\x02" + - "\x02\u024D\u024E\x07g\x02\x02\u024E\u024F\x07g\x02\x02\u024F\u028F\x07" + - "m\x02\x02\u0250\u0251\x07o\x02\x02\u0251\u0252\x07k\x02\x02\u0252\u0253" + - "\x07n\x02\x02\u0253\u0254\x07n\x02\x02\u0254\u0255\x07k\x02\x02\u0255" + - "\u0256\x07u\x02\x02\u0256\u0257\x07g\x02\x02\u0257\u0258\x07e\x02\x02" + - "\u0258\u0259\x07q\x02\x02\u0259\u025A\x07p\x02\x02\u025A\u028F\x07f\x02" + - "\x02\u025B\u025C\x07{\x02\x02\u025C\u025D\x07g\x02\x02\u025D\u025E\x07" + - "c\x02\x02\u025E\u025F\x07t\x02\x02\u025F\u028F\x07u\x02\x02\u0260\u0261" + - "\x07o\x02\x02\u0261\u0262\x07q\x02\x02\u0262\u0263\x07p\x02\x02\u0263" + - "\u0264\x07v\x02\x02\u0264\u0265\x07j\x02\x02\u0265\u028F\x07u\x02\x02" + - "\u0266\u0267\x07f\x02\x02\u0267\u0268\x07c\x02\x02\u0268\u0269\x07{\x02" + - "\x02\u0269\u028F\x07u\x02\x02\u026A\u026B\x07u\x02\x02\u026B\u026C\x07" + - "g\x02\x02\u026C\u026D\x07e\x02\x02\u026D\u026E\x07q\x02\x02\u026E\u026F" + - "\x07p\x02\x02\u026F\u0270\x07f\x02\x02\u0270\u028F\x07u\x02\x02\u0271" + - "\u0272\x07o\x02\x02\u0272\u0273\x07k\x02\x02\u0273\u0274\x07p\x02\x02" + - "\u0274\u0275\x07w\x02\x02\u0275\u0276\x07v\x02\x02\u0276\u0277\x07g\x02" + - "\x02\u0277\u028F\x07u\x02\x02\u0278\u0279\x07j\x02\x02\u0279\u027A\x07" + - "q\x02\x02\u027A\u027B\x07w\x02\x02\u027B\u027C\x07t\x02\x02\u027C\u028F" + - "\x07u\x02\x02\u027D\u027E\x07y\x02\x02\u027E\u027F\x07g\x02\x02\u027F" + - "\u0280\x07g\x02\x02\u0280\u0281\x07m\x02\x02\u0281\u028F\x07u\x02\x02" + - "\u0282\u0283\x07o\x02\x02\u0283\u0284\x07k\x02\x02\u0284\u0285\x07n\x02" + - "\x02\u0285\u0286\x07n\x02\x02\u0286\u0287\x07k\x02\x02\u0287\u0288\x07" + - "u\x02\x02\u0288\u0289\x07g\x02\x02\u0289\u028A\x07e\x02\x02\u028A\u028B" + - "\x07q\x02\x02\u028B\u028C\x07p\x02\x02\u028C\u028D\x07f\x02\x02\u028D" + - "\u028F\x07u\x02\x02\u028E\u0230\x03\x02\x02\x02\u028E\u0234\x03\x02\x02" + - "\x02\u028E\u0239\x03\x02\x02\x02\u028E\u023C\x03\x02\x02\x02\u028E\u0242" + - "\x03\x02\x02\x02\u028E\u0248\x03\x02\x02\x02\u028E\u024C\x03\x02\x02\x02" + - "\u028E\u0250\x03\x02\x02\x02\u028E\u025B\x03\x02\x02\x02\u028E\u0260\x03" + - "\x02\x02\x02\u028E\u0266\x03\x02\x02\x02\u028E\u026A\x03\x02\x02\x02\u028E" + - "\u0271\x03\x02\x02\x02\u028E\u0278\x03\x02\x02\x02\u028E\u027D\x03\x02" + - "\x02\x02\u028E\u0282\x03\x02\x02\x02\u028FN\x03\x02\x02\x02\u0290\u0291" + - "\x07c\x02\x02\u0291\u0292\x07p\x02\x02\u0292\u0293\x07f\x02\x02\u0293" + - "P\x03\x02\x02\x02\u0294\u0295\x07?\x02\x02\u0295R\x03\x02\x02\x02\u0296" + - "\u0297\x07.\x02\x02\u0297T\x03\x02\x02\x02\u0298\u0299\x070\x02\x02\u0299" + - "V\x03\x02\x02\x02\u029A\u029B\x07*\x02\x02\u029BX\x03\x02\x02\x02\u029C" + - "\u029D\x07]\x02\x02\u029D\u029E\x03\x02\x02\x02\u029E\u029F\b+\x02\x02" + - "\u029F\u02A0\b+\x02\x02\u02A0Z\x03\x02\x02\x02\u02A1\u02A2\x07_\x02\x02" + - "\u02A2\u02A3\x03\x02\x02\x02\u02A3\u02A4\b,\n\x02\u02A4\u02A5\b,\n\x02" + - "\u02A5\\\x03\x02\x02\x02\u02A6\u02A7\x05\xE5q\x02\u02A7\u02A8\x05\xE7" + - "r\x02\u02A8\u02A9\x05\xF1w\x02\u02A9^\x03\x02\x02\x02\u02AA\u02AB\x05" + - "\xE1o\x02\u02AB\u02AC\x05\xDBl\x02\u02AC\u02AD\x05\xDFn\x02\u02AD\u02AE" + - "\x05\xD3h\x02\u02AE`\x03\x02\x02\x02\u02AF\u02B0\x05\xEDu\x02\u02B0\u02B1" + - "\x05\xE1o\x02\u02B1\u02B2\x05\xDBl\x02\u02B2\u02B3\x05\xDFn\x02\u02B3" + - "\u02B4\x05\xD3h\x02\u02B4b\x03\x02\x02\x02\u02B5\u02B6\x05\xDBl\x02\u02B6" + - "\u02B7\x05\xE5q\x02\u02B7d\x03\x02\x02\x02\u02B8\u02B9\x05\xDBl\x02\u02B9" + - "\u02BA\x05\xEFv\x02\u02BAf\x03\x02\x02\x02\u02BB\u02BC\x05\xCBd\x02\u02BC" + - "\u02BD\x05\xEFv\x02\u02BDh\x03\x02\x02\x02\u02BE\u02BF\x05\xE5q\x02\u02BF" + - "\u02C0\x05\xF3x\x02\u02C0\u02C1\x05\xE1o\x02\u02C1\u02C2\x05\xE1o\x02" + - "\u02C2j\x03\x02\x02\x02\u02C3\u02C4\x07q\x02\x02\u02C4\u02C5\x07t\x02" + - "\x02\u02C5l\x03\x02\x02\x02\u02C6\u02C7\x07+\x02\x02\u02C7n\x03\x02\x02" + - "\x02\u02C8\u02C9\x07a\x02\x02\u02C9p\x03\x02\x02\x02\u02CA\u02CB\x07k" + - "\x02\x02\u02CB\u02CC\x07p\x02\x02\u02CC\u02CD\x07h\x02\x02\u02CD\u02CE" + - "\x07q\x02\x02\u02CEr\x03\x02\x02\x02\u02CF\u02D0\x07h\x02\x02\u02D0\u02D1" + - "\x07w\x02\x02\u02D1\u02D2\x07p\x02\x02\u02D2\u02D3\x07e\x02\x02\u02D3" + - "\u02D4\x07v\x02\x02\u02D4\u02D5\x07k\x02\x02\u02D5\u02D6\x07q\x02\x02" + - "\u02D6\u02D7\x07p\x02\x02\u02D7\u02D8\x07u\x02\x02\u02D8t\x03\x02\x02" + - "\x02\u02D9\u02DA\x07v\x02\x02\u02DA\u02DB\x07t\x02\x02\u02DB\u02DC\x07" + - "w\x02\x02\u02DC\u02E3\x07g\x02\x02\u02DD\u02DE\x07h\x02\x02\u02DE\u02DF" + - "\x07c\x02\x02\u02DF\u02E0\x07n\x02\x02\u02E0\u02E1\x07u\x02\x02\u02E1" + - "\u02E3\x07g\x02\x02\u02E2\u02D9\x03\x02\x02\x02\u02E2\u02DD\x03\x02\x02" + - "\x02\u02E3v\x03\x02\x02\x02\u02E4\u02E5\x07?\x02\x02\u02E5\u02EF\x07?" + - "\x02\x02\u02E6\u02E7\x07#\x02\x02\u02E7\u02EF\x07?\x02\x02\u02E8\u02EF" + - "\x07>\x02\x02\u02E9\u02EA\x07>\x02\x02\u02EA\u02EF\x07?\x02\x02\u02EB" + - "\u02EF\x07@\x02\x02\u02EC\u02ED\x07@\x02\x02\u02ED\u02EF\x07?\x02\x02" + - "\u02EE\u02E4\x03\x02\x02\x02\u02EE\u02E6\x03\x02\x02\x02\u02EE\u02E8\x03" + - "\x02\x02\x02\u02EE\u02E9\x03\x02\x02\x02\u02EE\u02EB\x03\x02\x02\x02\u02EE" + - "\u02EC\x03\x02\x02\x02\u02EFx\x03\x02\x02\x02\u02F0\u02F1\x07-\x02\x02" + - "\u02F1z\x03\x02\x02\x02\u02F2\u02F3\x07/\x02\x02\u02F3|\x03\x02\x02\x02" + - "\u02F4\u02F5\x07,\x02\x02\u02F5~\x03\x02\x02\x02\u02F6\u02F7\x071\x02" + - "\x02\u02F7\x80\x03\x02\x02\x02\u02F8\u02F9\x07\'\x02\x02\u02F9\x82\x03" + - "\x02\x02\x02\u02FA\u02FB\x073\x02\x02\u02FB\u02FC\x072\x02\x02\u02FC\x84" + - "\x03\x02\x02\x02\u02FD\u02FE\x07c\x02\x02\u02FE\u02FF\x07u\x02\x02\u02FF" + - "\u0305\x07e\x02\x02\u0300\u0301\x07f\x02\x02\u0301\u0302\x07g\x02\x02" + - "\u0302\u0303\x07u\x02\x02\u0303\u0305\x07e\x02\x02\u0304\u02FD\x03\x02" + - "\x02\x02\u0304\u0300\x03\x02\x02\x02\u0305\x86\x03\x02\x02\x02\u0306\u0307" + - "\x07p\x02\x02\u0307\u0308\x07w\x02\x02\u0308\u0309\x07n\x02\x02\u0309" + - "\u030A\x07n\x02\x02\u030A\u030B\x07u\x02\x02\u030B\x88\x03\x02\x02\x02" + - "\u030C\u030D\x07h\x02\x02\u030D\u030E\x07k\x02\x02\u030E\u030F\x07t\x02" + - "\x02\u030F\u0310\x07u\x02\x02\u0310\u0316\x07v\x02\x02\u0311\u0312\x07" + - "n\x02\x02\u0312\u0313\x07c\x02\x02\u0313\u0314\x07u\x02\x02\u0314\u0316" + - "\x07v\x02\x02\u0315\u030C\x03\x02\x02\x02\u0315\u0311\x03\x02\x02\x02" + - "\u0316\x8A\x03\x02\x02\x02\u0317\u0318\x05\xEDu\x02\u0318\u0319\x05\xE7" + - "r\x02\u0319\u031A\x05\xF3x\x02\u031A\u031B\x05\xE5q\x02\u031B\u031C\x05" + - "\xD1g\x02\u031C\u04C6\x03\x02\x02\x02\u031D\u031E\x05\xCBd\x02\u031E\u031F" + - "\x05\xCDe\x02\u031F\u0320\x05\xEFv\x02\u0320\u04C6\x03\x02\x02\x02\u0321" + - "\u0322\x05\xE9s\x02\u0322\u0323\x05\xE7r\x02\u0323\u0324\x05\xF7z\x02" + - "\u0324\u04C6\x03\x02\x02\x02\u0325\u0326\x05\xE1o\x02\u0326\u0327\x05" + - "\xE7r\x02\u0327\u0328\x05\xD7j\x02\u0328\u0329\x05\x83@\x02\u0329\u04C6" + - "\x03\x02\x02\x02\u032A\u032B\x05\xE9s\x02\u032B\u032C\x05\xDBl\x02\u032C" + - "\u04C6\x03\x02\x02\x02\u032D\u032E\x05\xF1w\x02\u032E\u032F\x05\xCBd\x02" + - "\u032F\u0330\x05\xF3x\x02\u0330\u04C6\x03\x02\x02\x02\u0331\u04C6\x05" + - "\xD3h\x02\u0332\u0333\x05\xEFv\x02\u0333\u0334\x05\xF3x\x02\u0334\u0335" + - "\x05\xCDe\x02\u0335\u0336\x05\xEFv\x02\u0336\u0337\x05\xF1w\x02\u0337" + - "\u0338\x05\xEDu\x02\u0338\u0339\x05\xDBl\x02\u0339\u033A\x05\xE5q\x02" + - "\u033A\u033B\x05\xD7j\x02\u033B\u04C6\x03\x02\x02\x02\u033C\u033D\x05" + - "\xF1w\x02\u033D\u033E\x05\xEDu\x02\u033E\u033F\x05\xDBl\x02\u033F\u0340" + - "\x05\xE3p\x02\u0340\u04C6\x03\x02\x02\x02\u0341\u0342\x05\xCFf\x02\u0342" + - "\u0343\x05\xE7r\x02\u0343\u0344\x05\xE5q\x02\u0344\u0345\x05\xCFf\x02" + - "\u0345\u0346\x05\xCBd\x02\u0346\u0347\x05\xF1w\x02\u0347\u04C6\x03\x02" + - "\x02\x02\u0348\u0349\x05\xCFf\x02\u0349\u034A\x05\xE7r\x02\u034A\u034B" + - "\x05\xCBd\x02\u034B\u034C\x05\xE1o\x02\u034C\u034D\x05\xD3h\x02\u034D" + - "\u034E\x05\xEFv\x02\u034E\u034F\x05\xCFf\x02\u034F\u0350\x05\xD3h\x02" + - "\u0350\u04C6\x03\x02\x02\x02\u0351\u0352\x05\xD7j\x02\u0352\u0353\x05" + - "\xEDu\x02\u0353\u0354\x05\xD3h\x02\u0354\u0355\x05\xCBd\x02\u0355\u0356" + - "\x05\xF1w\x02\u0356\u0357\x05\xD3h\x02\u0357\u0358\x05\xEFv\x02\u0358" + - "\u0359\x05\xF1w\x02\u0359\u04C6\x03\x02\x02\x02\u035A\u035B\x05\xE1o\x02" + - "\u035B\u035C\x05\xD3h\x02\u035C\u035D\x05\xD5i\x02\u035D\u035E\x05\xF1" + - "w\x02\u035E\u04C6\x03\x02\x02\x02\u035F\u0360\x05\xE5q\x02\u0360\u0361" + - "\x05\xE7r\x02\u0361\u0362\x05\xF7z\x02\u0362\u04C6\x03\x02\x02\x02\u0363" + - "\u0364\x05\xEDu\x02\u0364\u0365\x05\xDBl\x02\u0365\u0366\x05\xD7j\x02" + - "\u0366\u0367\x05\xD9k\x02\u0367\u0368\x05\xF1w\x02\u0368\u04C6\x03\x02" + - "\x02\x02\u0369\u036A\x05\xEFv\x02\u036A\u036B\x05\xF1w\x02\u036B\u036C" + - "\x05\xCBd\x02\u036C\u036D\x05\xEDu\x02\u036D\u036E\x05\xF1w\x02\u036E" + - "\u036F\x05\xEFv\x02\u036F\u0370\x05o6\x02\u0370\u0371\x05\xF7z\x02\u0371" + - "\u0372\x05\xDBl\x02\u0372\u0373\x05\xF1w\x02\u0373\u0374\x05\xD9k\x02" + - "\u0374\u04C6\x03\x02\x02\x02\u0375\u0376\x05\xD1g\x02\u0376\u0377\x05" + - "\xCBd\x02\u0377\u0378\x05\xF1w\x02\u0378\u0379\x05\xD3h\x02\u0379\u037A" + - "\x05o6\x02\u037A\u037B\x05\xD5i\x02\u037B\u037C\x05\xE7r\x02\u037C\u037D" + - "\x05\xEDu\x02\u037D\u037E\x05\xE3p\x02\u037E\u037F\x05\xCBd\x02\u037F" + - "\u0380\x05\xF1w\x02\u0380\u04C6\x03\x02\x02\x02\u0381\u0382\x05\xD1g\x02" + - "\u0382\u0383\x05\xCBd\x02\u0383\u0384\x05\xF1w\x02\u0384\u0385\x05\xD3" + - "h\x02\u0385\u0386\x05o6\x02\u0386\u0387\x05\xF1w\x02\u0387\u0388\x05\xED" + - "u\x02\u0388\u0389\x05\xF3x\x02\u0389\u038A\x05\xE5q\x02\u038A\u038B\x05" + - "\xCFf\x02\u038B\u04C6\x03\x02\x02\x02\u038C\u038D\x05\xD1g\x02\u038D\u038E" + - "\x05\xCBd\x02\u038E\u038F\x05\xF1w\x02\u038F\u0390\x05\xD3h\x02\u0390" + - "\u0391\x05o6\x02\u0391\u0392\x05\xE9s\x02\u0392\u0393\x05\xCBd\x02\u0393" + - "\u0394\x05\xEDu\x02\u0394\u0395\x05\xEFv\x02\u0395\u0396\x05\xD3h\x02" + - "\u0396\u04C6\x03\x02\x02\x02\u0397\u0398\x05\xCBd\x02\u0398\u0399\x05" + - "\xF3x\x02\u0399\u039A\x05\xF1w\x02\u039A\u039B\x05\xE7r\x02\u039B\u039C" + - "\x05o6\x02\u039C\u039D\x05\xCDe\x02\u039D\u039E\x05\xF3x\x02\u039E\u039F" + - "\x05\xCFf\x02\u039F\u03A0\x05\xDFn\x02\u03A0\u03A1\x05\xD3h\x02\u03A1" + - "\u03A2\x05\xF1w\x02\u03A2\u04C6\x03\x02\x02\x02\u03A3\u03A4\x05\xD1g\x02" + - "\u03A4\u03A5\x05\xCBd\x02\u03A5\u03A6\x05\xF1w\x02\u03A6\u03A7\x05\xD3" + - "h\x02\u03A7\u03A8\x05o6\x02\u03A8\u03A9\x05\xD3h\x02\u03A9\u03AA\x05\xF9" + - "{\x02\u03AA\u03AB\x05\xF1w\x02\u03AB\u03AC\x05\xEDu\x02\u03AC\u03AD\x05" + - "\xCBd\x02\u03AD\u03AE\x05\xCFf\x02\u03AE\u03AF\x05\xF1w\x02\u03AF\u04C6" + - "\x03\x02\x02\x02\u03B0\u03B1\x05\xDBl\x02\u03B1\u03B2\x05\xEFv\x02\u03B2" + - "\u03B3\x05o6\x02\u03B3\u03B4\x05\xD5i\x02\u03B4\u03B5\x05\xDBl\x02\u03B5" + - "\u03B6\x05\xE5q\x02\u03B6\u03B7\x05\xDBl\x02\u03B7\u03B8\x05\xF1w\x02" + - "\u03B8\u03B9\x05\xD3h\x02\u03B9\u04C6\x03\x02\x02\x02\u03BA\u03BB\x05" + - "\xDBl\x02\u03BB\u03BC\x05\xEFv\x02\u03BC\u03BD\x05o6\x02\u03BD\u03BE\x05" + - "\xDBl\x02\u03BE\u03BF\x05\xE5q\x02\u03BF\u03C0\x05\xD5i\x02\u03C0\u03C1" + - "\x05\xDBl\x02\u03C1\u03C2\x05\xE5q\x02\u03C2\u03C3\x05\xDBl\x02\u03C3" + - "\u03C4\x05\xF1w\x02\u03C4\u03C5\x05\xD3h\x02\u03C5\u04C6\x03\x02\x02\x02" + - "\u03C6\u03C7\x05\xCFf\x02\u03C7\u03C8\x05\xCBd\x02\u03C8\u03C9\x05\xEF" + - "v\x02\u03C9\u03CA\x05\xD3h\x02\u03CA\u04C6\x03\x02\x02\x02\u03CB\u03CC" + - "\x05\xE1o\x02\u03CC\u03CD\x05\xD3h\x02\u03CD\u03CE\x05\xE5q\x02\u03CE" + - "\u03CF\x05\xD7j\x02\u03CF\u03D0\x05\xF1w\x02\u03D0\u03D1\x05\xD9k\x02" + - "\u03D1\u04C6\x03\x02\x02\x02\u03D2\u03D3\x05\xE3p\x02\u03D3\u03D4\x05" + - "\xF5y\x02\u03D4\u03D5\x05o6\x02\u03D5\u03D6\x05\xE3p\x02\u03D6\u03D7\x05" + - "\xCBd\x02\u03D7\u03D8\x05\xF9{\x02\u03D8\u04C6\x03\x02\x02\x02\u03D9\u03DA" + - "\x05\xE3p\x02\u03DA\u03DB\x05\xF5y\x02\u03DB\u03DC\x05o6\x02\u03DC\u03DD" + - "\x05\xE3p\x02\u03DD\u03DE\x05\xDBl\x02\u03DE\u03DF\x05\xE5q\x02\u03DF" + - "\u04C6\x03\x02\x02\x02\u03E0\u03E1\x05\xE3p\x02\u03E1\u03E2\x05\xF5y\x02" + - "\u03E2\u03E3\x05o6\x02\u03E3\u03E4\x05\xCBd\x02\u03E4\u03E5\x05\xF5y\x02" + - "\u03E5\u03E6\x05\xD7j\x02\u03E6\u04C6\x03\x02\x02\x02\u03E7\u03E8\x05" + - "\xE3p\x02\u03E8\u03E9\x05\xF5y\x02\u03E9\u03EA\x05o6\x02\u03EA\u03EB\x05" + - "\xEFv\x02\u03EB\u03EC\x05\xF3x\x02\u03EC\u03ED\x05\xE3p\x02\u03ED\u04C6" + - "\x03\x02\x02\x02\u03EE\u03EF\x05\xE3p\x02\u03EF\u03F0\x05\xF5y\x02\u03F0" + - "\u03F1\x05o6"; - private static readonly _serializedATNSegment2: string = - "\x02\u03F1\u03F2\x05\xCFf\x02\u03F2\u03F3\x05\xE7r\x02\u03F3\u03F4\x05" + - "\xF3x\x02\u03F4\u03F5\x05\xE5q\x02\u03F5\u03F6\x05\xF1w\x02\u03F6\u04C6" + - "\x03\x02\x02\x02\u03F7\u03F8\x05\xE3p\x02\u03F8\u03F9\x05\xF5y\x02\u03F9" + - "\u03FA\x05o6\x02\u03FA\u03FB\x05\xCFf\x02\u03FB\u03FC\x05\xE7r\x02\u03FC" + - "\u03FD\x05\xE5q\x02\u03FD\u03FE\x05\xCFf\x02\u03FE\u03FF\x05\xCBd\x02" + - "\u03FF\u0400\x05\xF1w\x02\u0400\u04C6\x03\x02\x02\x02\u0401\u0402\x05" + - "\xE3p\x02\u0402\u0403\x05\xF5y\x02\u0403\u0404\x05o6\x02\u0404\u0405\x05" + - "\xDDm\x02\u0405\u0406\x05\xE7r\x02\u0406\u0407\x05\xDBl\x02\u0407\u0408" + - "\x05\xE5q\x02\u0408\u04C6\x03\x02\x02\x02\u0409\u040A\x05\xE3p\x02\u040A" + - "\u040B\x05\xF5y\x02\u040B\u040C\x05o6\x02\u040C\u040D\x05\xE3p\x02\u040D" + - "\u040E\x05\xD3h\x02\u040E\u040F\x05\xD1g\x02\u040F\u0410\x05\xDBl\x02" + - "\u0410\u0411\x05\xCBd\x02\u0411\u0412\x05\xE5q\x02\u0412\u04C6\x03\x02" + - "\x02\x02\u0413\u0414\x05\xE3p\x02\u0414\u0415\x05\xF5y\x02\u0415\u0416" + - "\x05o6\x02\u0416\u0417\x05\xD1g\x02\u0417\u0418\x05\xD3h\x02\u0418\u0419" + - "\x05\xD1g\x02\u0419\u041A\x05\xF3x\x02\u041A\u041B\x05\xE9s\x02\u041B" + - "\u041C\x05\xD3h\x02\u041C\u04C6\x03\x02\x02\x02\u041D\u041E\x05\xE3p\x02" + - "\u041E\u041F\x05\xD3h\x02\u041F\u0420\x05\xF1w\x02\u0420\u0421\x05\xCB" + - "d\x02\u0421\u0422\x05\xD1g\x02\u0422\u0423\x05\xCBd\x02\u0423\u0424\x05" + - "\xF1w\x02\u0424\u0425\x05\xCBd\x02\u0425\u04C6\x03\x02\x02\x02\u0426\u0427" + - "\x05\xEFv\x02\u0427\u0428\x05\xE9s\x02\u0428\u0429\x05\xE1o\x02\u0429" + - "\u042A\x05\xDBl\x02\u042A\u042B\x05\xF1w\x02\u042B\u04C6\x03\x02\x02\x02" + - "\u042C\u042D\x05\xF1w\x02\u042D\u042E\x05\xE7r\x02\u042E\u042F\x05o6\x02" + - "\u042F\u0430\x05\xEFv\x02\u0430\u0431\x05\xF1w\x02\u0431\u0432\x05\xED" + - "u\x02\u0432\u0433\x05\xDBl\x02\u0433\u0434\x05\xE5q\x02\u0434\u0435\x05" + - "\xD7j\x02\u0435\u04C6\x03\x02\x02\x02\u0436\u0437\x05\xF1w\x02\u0437\u0438" + - "\x05\xE7r\x02\u0438\u0439\x05o6\x02\u0439\u043A\x05\xEFv\x02\u043A\u043B" + - "\x05\xF1w\x02\u043B\u043C\x05\xEDu\x02\u043C\u04C6\x03\x02\x02\x02\u043D" + - "\u043E\x05\xF1w\x02\u043E\u043F\x05\xE7r\x02\u043F\u0440\x05o6\x02\u0440" + - "\u0441\x05\xCDe\x02\u0441\u0442\x05\xE7r\x02\u0442\u0443\x05\xE7r\x02" + - "\u0443\u0444\x05\xE1o\x02\u0444\u04C6\x03\x02\x02\x02\u0445\u0446\x05" + - "\xF1w\x02\u0446\u0447\x05\xE7r\x02\u0447\u0448\x05o6\x02\u0448\u0449\x05" + - "\xCDe\x02\u0449\u044A\x05\xE7r\x02\u044A\u044B\x05\xE7r\x02\u044B\u044C" + - "\x05\xE1o\x02\u044C\u044D\x05\xD3h\x02\u044D\u044E\x05\xCBd\x02\u044E" + - "\u044F\x05\xE5q\x02\u044F\u04C6\x03\x02\x02\x02\u0450\u0451\x05\xF1w\x02" + - "\u0451\u0452\x05\xE7r\x02\u0452\u0453\x05o6\x02\u0453\u0454\x05\xD1g\x02" + - "\u0454\u0455\x05\xCBd\x02\u0455\u0456\x05\xF1w\x02\u0456\u0457\x05\xD3" + - "h\x02\u0457\u0458\x05\xF1w\x02\u0458\u0459\x05\xDBl\x02\u0459\u045A\x05" + - "\xE3p\x02\u045A\u045B\x05\xD3h\x02\u045B\u04C6\x03\x02\x02\x02\u045C\u045D" + - "\x05\xF1w\x02\u045D\u045E\x05\xE7r\x02\u045E\u045F\x05o6\x02\u045F\u0460" + - "\x05\xD1g\x02\u0460\u0461\x05\xF1w\x02\u0461\u04C6\x03\x02\x02\x02\u0462" + - "\u0463\x05\xF1w\x02\u0463\u0464\x05\xE7r\x02\u0464\u0465\x05o6\x02\u0465" + - "\u0466\x05\xD1g\x02\u0466\u0467\x05\xCDe\x02\u0467\u0468\x05\xE1o\x02" + - "\u0468\u04C6\x03\x02\x02\x02\u0469\u046A\x05\xF1w\x02\u046A\u046B\x05" + - "\xE7r\x02\u046B\u046C\x05o6\x02\u046C\u046D\x05\xD1g\x02\u046D\u046E\x05" + - "\xE7r\x02\u046E\u046F\x05\xF3x\x02\u046F\u0470\x05\xCDe\x02\u0470\u0471" + - "\x05\xE1o\x02\u0471\u0472\x05\xD3h\x02\u0472\u04C6\x03\x02\x02\x02\u0473" + - "\u0474\x05\xF1w\x02\u0474\u0475\x05\xE7r\x02\u0475\u0476\x05o6\x02\u0476" + - "\u0477\x05\xD1g\x02\u0477\u0478\x05\xD3h\x02\u0478\u0479\x05\xD7j\x02" + - "\u0479\u047A\x05\xEDu\x02\u047A\u047B\x05\xD3h\x02\u047B\u047C\x05\xD3" + - "h\x02\u047C\u047D\x05\xEFv\x02\u047D\u04C6\x03\x02\x02\x02\u047E\u047F" + - "\x05\xF1w\x02\u047F\u0480\x05\xE7r\x02\u0480\u0481\x05o6\x02\u0481\u0482" + - "\x05\xDBl\x02\u0482\u0483\x05\xE5q\x02\u0483\u0484\x05\xF1w\x02\u0484" + - "\u04C6\x03\x02\x02\x02\u0485\u0486\x05\xF1w\x02\u0486\u0487\x05\xE7r\x02" + - "\u0487\u0488\x05o6\x02\u0488\u0489\x05\xDBl\x02\u0489\u048A\x05\xE5q\x02" + - "\u048A\u048B\x05\xF1w\x02\u048B\u048C\x05\xD3h\x02\u048C\u048D\x05\xD7" + - "j\x02\u048D\u048E\x05\xD3h\x02\u048E\u048F\x05\xEDu\x02\u048F\u04C6\x03" + - "\x02\x02\x02\u0490\u0491\x05\xF1w\x02\u0491\u0492\x05\xE7r\x02\u0492\u0493" + - "\x05o6\x02\u0493\u0494\x05\xDBl\x02\u0494\u0495\x05\xE9s\x02\u0495\u04C6" + - "\x03\x02\x02\x02\u0496\u0497\x05\xF1w\x02\u0497\u0498\x05\xE7r\x02\u0498" + - "\u0499\x05o6\x02\u0499\u049A\x05\xE1o\x02\u049A\u049B\x05\xE7r\x02\u049B" + - "\u049C\x05\xE5q\x02\u049C\u049D\x05\xD7j\x02\u049D\u04C6\x03\x02\x02\x02" + - "\u049E\u049F\x05\xF1w\x02\u049F\u04A0\x05\xE7r\x02\u04A0\u04A1\x05o6\x02" + - "\u04A1\u04A2\x05\xEDu\x02\u04A2\u04A3\x05\xCBd\x02\u04A3\u04A4\x05\xD1" + - "g\x02\u04A4\u04A5\x05\xDBl\x02\u04A5\u04A6\x05\xCBd\x02\u04A6\u04A7\x05" + - "\xE5q\x02\u04A7\u04A8\x05\xEFv\x02\u04A8\u04C6\x03\x02\x02\x02\u04A9\u04AA" + - "\x05\xF1w\x02\u04AA\u04AB\x05\xE7r\x02\u04AB\u04AC\x05o6\x02\u04AC\u04AD" + - "\x05\xF5y\x02\u04AD\u04AE\x05\xD3h\x02\u04AE\u04AF\x05\xEDu\x02\u04AF" + - "\u04B0\x05\xEFv\x02\u04B0\u04B1\x05\xDBl\x02\u04B1\u04B2\x05\xE7r\x02" + - "\u04B2\u04B3\x05\xE5q\x02\u04B3\u04C6\x03\x02\x02\x02\u04B4\u04B5\x05" + - "\xF1w\x02\u04B5\u04B6\x05\xE7r\x02\u04B6\u04B7\x05o6\x02\u04B7\u04B8\x05" + - "\xF3x\x02\u04B8\u04B9\x05\xE5q\x02\u04B9\u04BA\x05\xEFv\x02\u04BA\u04BB" + - "\x05\xDBl\x02\u04BB\u04BC\x05\xD7j\x02\u04BC\u04BD\x05\xE5q\x02\u04BD" + - "\u04BE\x05\xD3h\x02\u04BE\u04BF\x05\xD1g\x02\u04BF\u04C0\x05o6\x02\u04C0" + - "\u04C1\x05\xE1o\x02\u04C1\u04C2\x05\xE7r\x02\u04C2\u04C3\x05\xE5q\x02" + - "\u04C3\u04C4\x05\xD7j\x02\u04C4\u04C6\x03\x02\x02\x02\u04C5\u0317\x03" + - "\x02\x02\x02\u04C5\u031D\x03\x02\x02\x02\u04C5\u0321\x03\x02\x02\x02\u04C5" + - "\u0325\x03\x02\x02\x02\u04C5\u032A\x03\x02\x02\x02\u04C5\u032D\x03\x02" + - "\x02\x02\u04C5\u0331\x03\x02\x02\x02\u04C5\u0332\x03\x02\x02\x02\u04C5" + - "\u033C\x03\x02\x02\x02\u04C5\u0341\x03\x02\x02\x02\u04C5\u0348\x03\x02" + - "\x02\x02\u04C5\u0351\x03\x02\x02\x02\u04C5\u035A\x03\x02\x02\x02\u04C5" + - "\u035F\x03\x02\x02\x02\u04C5\u0363\x03\x02\x02\x02\u04C5\u0369\x03\x02" + - "\x02\x02\u04C5\u0375\x03\x02\x02\x02\u04C5\u0381\x03\x02\x02\x02\u04C5" + - "\u038C\x03\x02\x02\x02\u04C5\u0397\x03\x02\x02\x02\u04C5\u03A3\x03\x02" + - "\x02\x02\u04C5\u03B0\x03\x02\x02\x02\u04C5\u03BA\x03\x02\x02\x02\u04C5" + - "\u03C6\x03\x02\x02\x02\u04C5\u03CB\x03\x02\x02\x02\u04C5\u03D2\x03\x02" + - "\x02\x02\u04C5\u03D9\x03\x02\x02\x02\u04C5\u03E0\x03\x02\x02\x02\u04C5" + - "\u03E7\x03\x02\x02\x02\u04C5\u03EE\x03\x02\x02\x02\u04C5\u03F7\x03\x02" + - "\x02\x02\u04C5\u0401\x03\x02\x02\x02\u04C5\u0409\x03\x02\x02\x02\u04C5" + - "\u0413\x03\x02\x02\x02\u04C5\u041D\x03\x02\x02\x02\u04C5\u0426\x03\x02" + - "\x02\x02\u04C5\u042C\x03\x02\x02\x02\u04C5\u0436\x03\x02\x02\x02\u04C5" + - "\u043D\x03\x02\x02\x02\u04C5\u0445\x03\x02\x02\x02\u04C5\u0450\x03\x02" + - "\x02\x02\u04C5\u045C\x03\x02\x02\x02\u04C5\u0462\x03\x02\x02\x02\u04C5" + - "\u0469\x03\x02\x02\x02\u04C5\u0473\x03\x02\x02\x02\u04C5\u047E\x03\x02" + - "\x02\x02\u04C5\u0485\x03\x02\x02\x02\u04C5\u0490\x03\x02\x02\x02\u04C5" + - "\u0496\x03\x02\x02\x02\u04C5\u049E\x03\x02\x02\x02\u04C5\u04A9\x03\x02" + - "\x02\x02\u04C5\u04B4\x03\x02\x02\x02\u04C6\x8C\x03\x02\x02\x02\u04C7\u04C8" + - "\x05\xCBd\x02\u04C8\u04C9\x05\xF5y\x02\u04C9\u04CA\x05\xD7j\x02\u04CA" + - "\u055F\x03\x02\x02\x02\u04CB\u04CC\x05\xE3p\x02\u04CC\u04CD\x05\xDBl\x02" + - "\u04CD\u04CE\x05\xE5q\x02\u04CE\u055F\x03\x02\x02\x02\u04CF\u04D0\x05" + - "\xE3p\x02\u04D0\u04D1\x05\xCBd\x02\u04D1\u04D2\x05\xF9{\x02\u04D2\u055F" + - "\x03\x02\x02\x02\u04D3\u04D4\x05\xEFv\x02\u04D4\u04D5\x05\xF3x\x02\u04D5" + - "\u04D6\x05\xE3p\x02\u04D6\u055F\x03\x02\x02\x02\u04D7\u04D8\x05\xCFf\x02" + - "\u04D8\u04D9\x05\xE7r\x02\u04D9\u04DA\x05\xF3x\x02\u04DA\u04DB\x05\xE5" + - "q\x02\u04DB\u04DC\x05\xF1w\x02\u04DC\u055F\x03\x02\x02\x02\u04DD\u04DE" + - "\x05\xCFf\x02\u04DE\u04DF\x05\xE7r\x02\u04DF\u04E0\x05\xF3x\x02\u04E0" + - "\u04E1\x05\xE5q\x02\u04E1\u04E2\x05\xF1w\x02\u04E2\u04E3\x05o6\x02\u04E3" + - "\u04E4\x05\xD1g\x02\u04E4\u04E5\x05\xDBl\x02\u04E5\u04E6\x05\xEFv\x02" + - "\u04E6\u04E7\x05\xF1w\x02\u04E7\u04E8\x05\xDBl\x02\u04E8\u04E9\x05\xE5" + - "q\x02\u04E9\u04EA\x05\xCFf\x02\u04EA\u04EB\x05\xF1w\x02\u04EB\u055F\x03" + - "\x02\x02\x02\u04EC\u04ED\x05\xE9s\x02\u04ED\u04EE\x05\xD3h\x02\u04EE\u04EF" + - "\x05\xEDu\x02\u04EF\u04F0\x05\xCFf\x02\u04F0\u04F1\x05\xD3h\x02\u04F1" + - "\u04F2\x05\xE5q\x02\u04F2\u04F3\x05\xF1w\x02\u04F3\u04F4\x05\xDBl\x02" + - "\u04F4\u04F5\x05\xE1o\x02\u04F5\u04F6\x05\xD3h\x02\u04F6\u055F\x03\x02" + - "\x02\x02\u04F7\u04F8\x05\xE3p\x02\u04F8\u04F9\x05\xD3h\x02\u04F9\u04FA" + - "\x05\xD1g\x02\u04FA\u04FB\x05\xDBl\x02\u04FB\u04FC\x05\xCBd\x02\u04FC" + - "\u04FD\x05\xE5q\x02\u04FD\u055F\x03\x02\x02\x02\u04FE\u04FF\x05\xE3p\x02" + - "\u04FF\u0500\x05\xD3h\x02\u0500\u0501\x05\xD1g\x02\u0501\u0502\x05\xDB" + - "l\x02\u0502\u0503\x05\xCBd\x02\u0503\u0504\x05\xE5q\x02\u0504\u0505\x05" + - "o6\x02\u0505\u0506\x05\xCBd\x02\u0506\u0507\x05\xCDe\x02\u0507\u0508\x05" + - "\xEFv\x02\u0508\u0509\x05\xE7r\x02\u0509\u050A\x05\xE1o\x02\u050A\u050B" + - "\x05\xF3x\x02\u050B\u050C\x05\xF1w\x02\u050C\u050D\x05\xD3h\x02\u050D" + - "\u050E\x05o6\x02\u050E\u050F\x05\xD1g\x02\u050F\u0510\x05\xD3h\x02\u0510" + - "\u0511\x05\xF5y\x02\u0511\u0512\x05\xDBl\x02\u0512\u0513\x05\xCBd\x02" + - "\u0513\u0514\x05\xF1w\x02\u0514\u0515\x05\xDBl\x02\u0515\u0516\x05\xE7" + - "r\x02\u0516\u0517\x05\xE5q\x02\u0517\u055F\x03\x02\x02\x02\u0518\u0519" + - "\x05\xCBd\x02\u0519\u051A\x05\xCFf\x02\u051A\u051B\x05\xE7r\x02\u051B" + - "\u051C\x05\xEFv\x02\u051C\u055F\x03\x02\x02\x02\u051D\u051E\x05\xCBd\x02" + - "\u051E\u051F\x05\xEFv\x02\u051F\u0520\x05\xDBl\x02\u0520\u0521\x05\xE5" + - "q\x02\u0521\u055F\x03\x02\x02\x02\u0522\u0523\x05\xCBd\x02\u0523\u0524" + - "\x05\xF1w\x02\u0524\u0525\x05\xCBd\x02\u0525\u0526\x05\xE5q\x02\u0526" + - "\u055F\x03\x02\x02\x02\u0527\u0528\x05\xCBd\x02\u0528\u0529\x05\xF1w\x02" + - "\u0529\u052A\x05\xCBd\x02\u052A\u052B\x05\xE5q\x02\u052B\u052C\x074\x02" + - "\x02\u052C\u055F\x03\x02\x02\x02\u052D\u052E\x05\xCFf\x02\u052E\u052F" + - "\x05\xD3h\x02\u052F\u0530\x05\xDBl\x02\u0530\u0531\x05\xE1o\x02\u0531" + - "\u055F\x03\x02\x02\x02\u0532\u0533\x05\xCFf\x02\u0533\u0534\x05\xE7r\x02" + - "\u0534\u0535\x05\xEFv\x02\u0535\u055F\x03\x02\x02\x02\u0536\u0537\x05" + - "\xCFf\x02\u0537\u0538\x05\xE7r\x02\u0538\u0539\x05\xEFv\x02\u0539\u053A" + - "\x05\xD9k\x02\u053A\u055F\x03\x02\x02\x02\u053B\u053C\x05\xD5i\x02\u053C" + - "\u053D\x05\xE1o\x02\u053D\u053E\x05\xE7r\x02\u053E\u053F\x05\xE7r\x02" + - "\u053F\u0540\x05\xEDu\x02\u0540\u055F\x03\x02\x02\x02\u0541\u0542\x05" + - "\xE1o\x02\u0542\u0543\x05\xF1w\x02\u0543\u0544\x05\xEDu\x02\u0544\u0545" + - "\x05\xDBl\x02\u0545\u0546\x05\xE3p\x02\u0546\u055F\x03\x02\x02\x02\u0547" + - "\u0548\x05\xEFv\x02\u0548\u0549\x05\xDBl\x02\u0549\u054A\x05\xE5q\x02" + - "\u054A\u055F\x03\x02\x02\x02\u054B\u054C\x05\xEFv\x02\u054C\u054D\x05" + - "\xDBl\x02\u054D\u054E\x05\xE5q\x02\u054E\u054F\x05\xD9k\x02\u054F\u055F" + - "\x03\x02\x02\x02\u0550\u0551\x05\xEFv\x02\u0551\u0552\x05\xEBt\x02\u0552" + - "\u0553\x05\xEDu\x02\u0553\u0554\x05\xF1w\x02\u0554\u055F\x03\x02\x02\x02" + - "\u0555\u0556\x05\xF1w\x02\u0556\u0557\x05\xCBd\x02\u0557\u0558\x05\xE5" + - "q\x02\u0558\u055F\x03\x02\x02\x02\u0559\u055A\x05\xF1w\x02\u055A\u055B" + - "\x05\xCBd\x02\u055B\u055C\x05\xE5q\x02\u055C\u055D\x05\xD9k\x02\u055D" + - "\u055F\x03\x02\x02\x02\u055E\u04C7\x03\x02\x02\x02\u055E\u04CB\x03\x02" + - "\x02\x02\u055E\u04CF\x03\x02\x02\x02\u055E\u04D3\x03\x02\x02\x02\u055E" + - "\u04D7\x03\x02\x02\x02\u055E\u04DD\x03\x02\x02\x02\u055E\u04EC\x03\x02" + - "\x02\x02\u055E\u04F7\x03\x02\x02\x02\u055E\u04FE\x03\x02\x02\x02\u055E" + - "\u0518\x03\x02\x02\x02\u055E\u051D\x03\x02\x02\x02\u055E\u0522\x03\x02" + - "\x02\x02\u055E\u0527\x03\x02\x02\x02\u055E\u052D\x03\x02\x02\x02\u055E" + - "\u0532\x03\x02\x02\x02\u055E\u0536\x03\x02\x02\x02\u055E\u053B\x03\x02" + - "\x02\x02\u055E\u0541\x03\x02\x02\x02\u055E\u0547\x03\x02\x02\x02\u055E" + - "\u054B\x03\x02\x02\x02\u055E\u0550\x03\x02\x02\x02\u055E\u0555\x03\x02" + - "\x02\x02\u055E\u0559\x03\x02\x02\x02\u055F\x8E\x03\x02\x02\x02\u0560\u0561" + - "\x05\xCFf\x02\u0561\u0562\x05\xDBl\x02\u0562\u0563\x05\xD1g\x02\u0563" + - "\u0564\x05\xEDu\x02\u0564\u0565\x05o6\x02\u0565\u0566\x05\xE3p\x02\u0566" + - "\u0567\x05\xCBd\x02\u0567\u0568\x05\xF1w\x02\u0568\u0569\x05\xCFf\x02" + - "\u0569\u056A\x05\xD9k\x02\u056A\x90\x03\x02\x02\x02\u056B\u0572\x05=\x1D" + - "\x02\u056C\u0571\x05=\x1D\x02\u056D\u0571\x05;\x1C\x02\u056E\u0571\x07" + - "a\x02\x02\u056F\u0571\x05}=\x02\u0570\u056C\x03\x02\x02\x02\u0570\u056D" + - "\x03\x02\x02\x02\u0570\u056E\x03\x02\x02\x02\u0570\u056F\x03\x02\x02\x02" + - "\u0571\u0574\x03\x02\x02\x02\u0572\u0570\x03\x02\x02\x02\u0572\u0573\x03" + - "\x02\x02\x02\u0573\u057F\x03\x02\x02\x02\u0574\u0572\x03\x02\x02\x02\u0575" + - "\u057A\t\n\x02\x02\u0576\u057B\x05=\x1D\x02\u0577\u057B\x05;\x1C\x02\u0578" + - "\u057B\x07a\x02\x02\u0579\u057B\x05}=\x02\u057A\u0576\x03\x02\x02\x02" + - "\u057A\u0577\x03\x02\x02\x02\u057A\u0578\x03\x02\x02\x02\u057A\u0579\x03" + - "\x02\x02\x02\u057B\u057C\x03\x02\x02\x02\u057C\u057A\x03\x02\x02\x02\u057C" + - "\u057D\x03\x02\x02\x02\u057D\u057F\x03\x02\x02\x02\u057E\u056B\x03\x02" + - "\x02\x02\u057E\u0575\x03\x02\x02\x02\u057F\x92\x03\x02\x02\x02\u0580\u0586" + - "\x07b\x02\x02\u0581\u0585\n\v\x02\x02\u0582\u0583\x07b\x02\x02\u0583\u0585" + - "\x07b\x02\x02\u0584\u0581\x03\x02\x02\x02\u0584\u0582\x03\x02\x02\x02" + - "\u0585\u0588\x03\x02\x02\x02\u0586\u0584\x03\x02\x02\x02\u0586\u0587\x03" + - "\x02\x02\x02\u0587\u0589\x03\x02\x02\x02\u0588\u0586\x03\x02\x02\x02\u0589" + - "\u058A\x07b\x02\x02\u058A\x94\x03\x02\x02\x02\u058B\u058C\x05)\x13\x02" + - "\u058C\u058D\x03\x02\x02\x02\u058D\u058E\bI\x06\x02\u058E\x96\x03\x02" + - "\x02\x02\u058F\u0590\x05+\x14\x02\u0590\u0591\x03\x02\x02\x02\u0591\u0592" + - "\bJ\x06\x02\u0592\x98\x03\x02\x02\x02\u0593\u0594\x05-\x15\x02\u0594\u0595" + - "\x03\x02\x02\x02\u0595\u0596\bK\x06\x02\u0596\x9A\x03\x02\x02\x02\u0597" + - "\u0598\x07~\x02\x02\u0598\u0599\x03\x02\x02\x02\u0599\u059A\bL\t\x02\u059A" + - "\u059B\bL\n\x02\u059B\x9C\x03\x02\x02\x02\u059C\u059D\x07]\x02\x02\u059D" + - "\u059E\x03\x02\x02\x02\u059E\u059F\bM\x07\x02\u059F\u05A0\bM\x04\x02\u05A0" + - "\u05A1\bM\x04\x02\u05A1\x9E\x03\x02\x02\x02\u05A2\u05A3\x07_\x02\x02\u05A3" + - "\u05A4\x03\x02\x02\x02\u05A4\u05A5\bN\n\x02\u05A5\u05A6\bN\n\x02\u05A6" + - "\u05A7\bN\v\x02\u05A7\xA0\x03\x02\x02\x02\u05A8\u05A9\x07.\x02\x02\u05A9" + - "\u05AA\x03\x02\x02\x02\u05AA\u05AB\bO\f\x02\u05AB\xA2\x03\x02\x02\x02" + - "\u05AC\u05AD\x07?\x02\x02\u05AD\u05AE\x03\x02\x02\x02\u05AE\u05AF\bP\r" + - "\x02\u05AF\xA4\x03\x02\x02\x02\u05B0\u05B1\x05\xE3p\x02\u05B1\u05B2\x05" + - "\xD3h\x02\u05B2\u05B3\x05\xF1w\x02\u05B3\u05B4\x05\xCBd\x02\u05B4\u05B5" + - "\x05\xD1g\x02\u05B5\u05B6\x05\xCBd\x02\u05B6\u05B7\x05\xF1w\x02\u05B7" + - "\u05B8\x05\xCBd\x02\u05B8\xA6\x03\x02\x02\x02\u05B9\u05BB\x05\xA9S\x02" + - "\u05BA\u05B9\x03\x02\x02\x02\u05BB\u05BC\x03\x02\x02\x02\u05BC\u05BA\x03" + - "\x02\x02\x02\u05BC\u05BD\x03\x02\x02\x02\u05BD\xA8\x03\x02\x02\x02\u05BE" + - "\u05C0\n\f\x02\x02\u05BF\u05BE\x03\x02\x02\x02\u05C0\u05C1\x03\x02\x02" + - "\x02\u05C1\u05BF\x03\x02\x02\x02\u05C1\u05C2\x03\x02\x02\x02\u05C2\u05C6" + - "\x03\x02\x02\x02\u05C3\u05C4\x071\x02\x02\u05C4\u05C6\n\r\x02\x02\u05C5" + - "\u05BF\x03\x02\x02\x02\u05C5\u05C3\x03\x02\x02\x02\u05C6\xAA\x03\x02\x02" + - "\x02\u05C7\u05C8\x05\x93H\x02\u05C8\xAC\x03\x02\x02\x02\u05C9\u05CA\x05" + - ")\x13\x02\u05CA\u05CB\x03\x02\x02\x02\u05CB\u05CC\bU\x06\x02\u05CC\xAE" + - "\x03\x02\x02\x02\u05CD\u05CE\x05+\x14\x02\u05CE\u05CF\x03\x02\x02\x02" + - "\u05CF\u05D0\bV\x06\x02\u05D0\xB0\x03\x02\x02\x02\u05D1\u05D2\x05-\x15" + - "\x02\u05D2\u05D3\x03\x02\x02\x02\u05D3\u05D4\bW\x06\x02\u05D4\xB2\x03" + - "\x02\x02\x02\u05D5\u05D6\x05\xE7r\x02\u05D6\u05D7\x05\xE5q\x02\u05D7\xB4" + - "\x03\x02\x02\x02\u05D8\u05D9\x05\xF7z\x02\u05D9\u05DA\x05\xDBl\x02\u05DA" + - "\u05DB\x05\xF1w\x02\u05DB\u05DC\x05\xD9k\x02\u05DC\xB6\x03\x02\x02\x02" + - "\u05DD\u05DE\x07~\x02\x02\u05DE\u05DF\x03\x02\x02\x02\u05DF\u05E0\bZ\t" + - "\x02\u05E0\u05E1\bZ\n\x02\u05E1\xB8\x03\x02\x02\x02\u05E2\u05E3\x07_\x02" + - "\x02\u05E3\u05E4\x03\x02\x02\x02\u05E4\u05E5\b[\n\x02\u05E5\u05E6\b[\n" + - "\x02\u05E6\u05E7\b[\v\x02\u05E7\xBA\x03\x02\x02\x02\u05E8\u05E9\x07.\x02" + - "\x02\u05E9\u05EA\x03\x02\x02\x02\u05EA\u05EB\b\\\f\x02\u05EB\xBC\x03\x02" + - "\x02\x02\u05EC\u05ED\x07?\x02\x02\u05ED\u05EE\x03\x02\x02\x02\u05EE\u05EF" + - "\b]\r\x02\u05EF\xBE\x03\x02\x02\x02\u05F0\u05F2\x05\xC1_\x02\u05F1\u05F0" + - "\x03\x02\x02\x02\u05F2\u05F3\x03\x02\x02\x02\u05F3\u05F1\x03\x02\x02\x02" + - "\u05F3\u05F4\x03\x02\x02\x02\u05F4\xC0\x03\x02\x02\x02\u05F5\u05F7\n\f" + - "\x02\x02\u05F6\u05F5\x03\x02\x02\x02\u05F7\u05F8\x03\x02\x02\x02\u05F8" + - "\u05F6\x03\x02\x02\x02\u05F8\u05F9\x03\x02\x02\x02\u05F9\u05FD\x03\x02" + - "\x02\x02\u05FA\u05FB\x071\x02\x02\u05FB\u05FD\n\r\x02\x02\u05FC\u05F6" + - "\x03\x02\x02\x02\u05FC\u05FA\x03\x02\x02\x02\u05FD\xC2\x03\x02\x02\x02" + - "\u05FE\u05FF\x05\x93H\x02\u05FF\xC4\x03\x02\x02\x02\u0600\u0601\x05)\x13" + - "\x02\u0601\u0602\x03\x02\x02\x02\u0602\u0603\ba\x06\x02\u0603\xC6\x03" + - "\x02\x02\x02\u0604\u0605\x05+\x14\x02\u0605\u0606\x03\x02\x02\x02\u0606" + - "\u0607\bb\x06\x02\u0607\xC8\x03\x02\x02\x02\u0608\u0609\x05-\x15\x02\u0609" + - "\u060A\x03\x02\x02\x02\u060A\u060B\bc\x06\x02\u060B\xCA\x03\x02\x02\x02" + - "\u060C\u060D\t\x0E\x02\x02\u060D\xCC\x03\x02\x02\x02\u060E\u060F\t\x0F" + - "\x02\x02\u060F\xCE\x03\x02\x02\x02\u0610\u0611\t\x10\x02\x02\u0611\xD0" + - "\x03\x02\x02\x02\u0612\u0613\t\x11\x02\x02\u0613\xD2\x03\x02\x02\x02\u0614" + - "\u0615\t\b\x02\x02\u0615\xD4\x03\x02\x02\x02\u0616\u0617\t\x12\x02\x02" + - "\u0617\xD6\x03\x02\x02\x02\u0618\u0619\t\x13\x02\x02\u0619\xD8\x03\x02" + - "\x02\x02\u061A\u061B\t\x14\x02\x02\u061B\xDA\x03\x02\x02\x02\u061C\u061D" + - "\t\x15\x02\x02\u061D\xDC\x03\x02\x02\x02\u061E\u061F\t\x16\x02\x02\u061F" + - "\xDE\x03\x02\x02\x02\u0620\u0621\t\x17\x02\x02\u0621\xE0\x03\x02\x02\x02" + - "\u0622\u0623\t\x18\x02\x02\u0623\xE2\x03\x02\x02\x02\u0624\u0625\t\x19" + - "\x02\x02\u0625\xE4\x03\x02\x02\x02\u0626\u0627\t\x1A\x02\x02\u0627\xE6" + - "\x03\x02\x02\x02\u0628\u0629\t\x1B\x02\x02\u0629\xE8\x03\x02\x02\x02\u062A" + - "\u062B\t\x1C\x02\x02\u062B\xEA\x03\x02\x02\x02\u062C\u062D\t\x1D\x02\x02" + - "\u062D\xEC\x03\x02\x02\x02\u062E\u062F\t\x1E\x02\x02\u062F\xEE\x03\x02" + - "\x02\x02\u0630\u0631\t\x1F\x02\x02\u0631\xF0\x03\x02\x02\x02\u0632\u0633" + - "\t \x02\x02\u0633\xF2\x03\x02\x02\x02\u0634\u0635\t!\x02\x02\u0635\xF4" + - "\x03\x02\x02\x02\u0636\u0637\t\"\x02\x02\u0637\xF6\x03\x02\x02\x02\u0638" + - "\u0639\t#\x02\x02\u0639\xF8\x03\x02\x02\x02\u063A\u063B\t$\x02\x02\u063B" + - "\xFA\x03\x02\x02\x02\u063C\u063D\t%\x02\x02\u063D\xFC\x03\x02\x02\x02" + - "\u063E\u063F\t&\x02\x02\u063F\xFE\x03\x02\x02\x022\x02\x03\x04\x05\x06" + - "\u0190\u0194\u0197\u01A0\u01A2\u01AD\u01D6\u01DB\u01E0\u01E2\u01ED\u01F5" + - "\u01F8\u01FA\u01FF\u0204\u020A\u0211\u0216\u021C\u021F\u0227\u022B\u028E" + - "\u02E2\u02EE\u0304\u0315\u04C5\u055E\u0570\u0572\u057A\u057C\u057E\u0584" + - "\u0586\u05BC\u05C1\u05C5\u05F3\u05F8\u05FC\x0E\x07\x04\x02\x07\x03\x02" + - "\x07\x05\x02\x07\x06\x02\x02\x03\x02\t%\x02\x07\x02\x02\t\x1A\x02\x06" + - "\x02\x02\t&\x02\t\"\x02\t!\x02"; + "\u01D7\u01D6\x03\x02\x02\x02\u01D8\u01DB\x03\x02\x02\x02\u01D9\u01D7\x03" + + "\x02\x02\x02\u01D9\u01DA\x03\x02\x02\x02\u01DA\u01FB\x03\x02\x02\x02\u01DB" + + "\u01D9\x03\x02\x02\x02\u01DC\u01DE\x05K%\x02\u01DD\u01DF\x05/\x17\x02" + + "\u01DE\u01DD\x03\x02\x02\x02\u01DF\u01E0\x03\x02\x02\x02\u01E0\u01DE\x03" + + "\x02\x02\x02\u01E0\u01E1\x03\x02\x02\x02\u01E1\u01FB\x03\x02\x02\x02\u01E2" + + "\u01E4\x05/\x17\x02\u01E3\u01E2\x03\x02\x02\x02\u01E4\u01E5\x03\x02\x02" + + "\x02\u01E5\u01E3\x03\x02\x02\x02\u01E5\u01E6\x03\x02\x02\x02\u01E6\u01EE" + + "\x03\x02\x02\x02\u01E7\u01EB\x05K%\x02\u01E8\u01EA\x05/\x17\x02\u01E9" + + "\u01E8\x03\x02\x02\x02\u01EA\u01ED\x03\x02\x02\x02\u01EB\u01E9\x03\x02" + + "\x02\x02\u01EB\u01EC\x03\x02\x02\x02\u01EC\u01EF\x03\x02\x02\x02\u01ED" + + "\u01EB\x03\x02\x02\x02\u01EE\u01E7\x03\x02\x02\x02\u01EE\u01EF\x03\x02" + + "\x02\x02\u01EF\u01F0\x03\x02\x02\x02\u01F0\u01F1\x057\x1B\x02\u01F1\u01FB" + + "\x03\x02\x02\x02\u01F2\u01F4\x05K%\x02\u01F3\u01F5\x05/\x17\x02\u01F4" + + "\u01F3\x03\x02\x02\x02\u01F5\u01F6\x03\x02\x02\x02\u01F6\u01F4\x03\x02" + + "\x02\x02\u01F6\u01F7\x03\x02\x02\x02\u01F7\u01F8\x03\x02\x02\x02\u01F8" + + "\u01F9\x057\x1B\x02\u01F9\u01FB\x03\x02\x02\x02\u01FA\u01D1\x03\x02\x02" + + "\x02\u01FA\u01DC\x03\x02\x02\x02\u01FA\u01E3\x03\x02\x02\x02\u01FA\u01F2" + + "\x03\x02\x02\x02\u01FB>\x03\x02\x02\x02\u01FC\u01FD\x05\xB5Z\x02\u01FD" + + "\u01FE\x05\xE3q\x02\u01FE@\x03\x02\x02\x02\u01FF\u0200\x05\xB3Y\x02\u0200" + + "\u0201\x05\xCDf\x02\u0201\u0202\x05\xB9\\\x02\u0202B\x03\x02\x02\x02\u0203" + + "\u0204\x05\xB3Y\x02\u0204\u0205\x05\xD7k\x02\u0205\u0206\x05\xB7[\x02" + + "\u0206D\x03\x02\x02\x02\u0207\u0208\x07?\x02\x02\u0208F\x03\x02\x02\x02" + + "\u0209\u020A\x07.\x02\x02\u020AH\x03\x02\x02\x02\u020B\u020C\x05\xB9\\" + + "\x02\u020C\u020D\x05\xBB]\x02\u020D\u020E\x05\xD7k\x02\u020E\u020F\x05" + + "\xB7[\x02\u020FJ\x03\x02\x02\x02\u0210\u0211\x070\x02\x02\u0211L\x03\x02" + + "\x02\x02\u0212\u0213\x05\xBD^\x02\u0213\u0214\x05\xB3Y\x02\u0214\u0215" + + "\x05\xC9d\x02\u0215\u0216\x05\xD7k\x02\u0216\u0217\x05\xBB]\x02\u0217" + + "N\x03\x02\x02\x02\u0218\u0219\x05\xBD^\x02\u0219\u021A\x05\xC3a\x02\u021A" + + "\u021B\x05\xD5j\x02\u021B\u021C\x05\xD7k\x02\u021C\u021D\x05\xD9l\x02" + + "\u021DP\x03\x02\x02\x02\u021E\u021F\x05\xC9d\x02\u021F\u0220\x05\xB3Y" + + "\x02\u0220\u0221\x05\xD7k\x02\u0221\u0222\x05\xD9l\x02\u0222R\x03\x02" + + "\x02\x02\u0223\u0224\x07*\x02\x02\u0224T\x03\x02\x02\x02\u0225\u0226\x05" + + "\xC3a\x02\u0226\u0227\x05\xCDf\x02\u0227V\x03\x02\x02\x02\u0228\u0229" + + "\x05\xC3a\x02\u0229\u022A\x05\xD7k\x02\u022AX\x03\x02\x02\x02\u022B\u022C" + + "\x05\xC9d\x02\u022C\u022D\x05\xC3a\x02\u022D\u022E\x05\xC7c\x02\u022E" + + "\u022F\x05\xBB]\x02\u022FZ\x03\x02\x02\x02\u0230\u0231\x05\xCDf\x02\u0231" + + "\u0232\x05\xCFg\x02\u0232\u0233\x05\xD9l\x02\u0233\\\x03\x02\x02\x02\u0234" + + "\u0235\x05\xCDf\x02\u0235\u0236\x05\xDBm\x02\u0236\u0237\x05\xC9d\x02" + + "\u0237\u0238\x05\xC9d\x02\u0238^\x03\x02\x02\x02\u0239\u023A\x05\xCDf" + + "\x02\u023A\u023B\x05\xDBm\x02\u023B\u023C\x05\xC9d\x02\u023C\u023D\x05" + + "\xC9d\x02\u023D\u023E\x05\xD7k\x02\u023E`\x03\x02\x02\x02\u023F\u0240" + + "\x05\xCFg\x02\u0240\u0241\x05\xD5j\x02\u0241b\x03\x02\x02\x02\u0242\u0243" + + "\x07A\x02\x02\u0243d\x03\x02\x02\x02\u0244\u0245\x05\xD5j\x02\u0245\u0246" + + "\x05\xC9d\x02\u0246\u0247\x05\xC3a\x02\u0247\u0248\x05\xC7c\x02\u0248" + + "\u0249\x05\xBB]\x02\u0249f\x03\x02\x02\x02\u024A\u024B\x07+\x02\x02\u024B" + + "h\x03\x02\x02\x02\u024C\u024D\x05\xD9l\x02\u024D\u024E\x05\xD5j\x02\u024E" + + "\u024F\x05\xDBm\x02\u024F\u0250\x05\xBB]\x02\u0250j\x03\x02\x02\x02\u0251" + + "\u0252\x05\xC3a\x02\u0252\u0253\x05\xCDf\x02\u0253\u0254\x05\xBD^\x02" + + "\u0254\u0255\x05\xCFg\x02\u0255l\x03\x02\x02\x02\u0256\u0257\x05\xBD^" + + "\x02\u0257\u0258\x05\xDBm\x02\u0258\u0259\x05\xCDf\x02\u0259\u025A\x05" + + "\xB7[\x02\u025A\u025B\x05\xD9l\x02\u025B\u025C\x05\xC3a\x02\u025C\u025D" + + "\x05\xCFg\x02\u025D\u025E\x05\xCDf\x02\u025E\u025F\x05\xD7k\x02\u025F" + + "n\x03\x02\x02\x02\u0260\u0261\x07a\x02\x02\u0261p\x03\x02\x02\x02\u0262" + + "\u0263\x07?\x02\x02\u0263\u0264\x07?\x02\x02\u0264r\x03\x02\x02\x02\u0265" + + "\u0266\x07#\x02\x02\u0266\u0267\x07?\x02\x02\u0267t\x03\x02\x02\x02\u0268" + + "\u0269\x07>\x02\x02\u0269v\x03\x02\x02\x02\u026A\u026B\x07>\x02\x02\u026B" + + "\u026C\x07?\x02\x02\u026Cx\x03\x02\x02\x02\u026D\u026E\x07@\x02\x02\u026E" + + "z\x03\x02\x02\x02\u026F\u0270\x07@\x02\x02\u0270\u0271\x07?\x02\x02\u0271" + + "|\x03\x02\x02\x02\u0272\u0273\x07-\x02\x02\u0273~\x03\x02\x02\x02\u0274" + + "\u0275\x07/\x02\x02\u0275\x80\x03\x02\x02\x02\u0276\u0277\x07,\x02\x02" + + "\u0277\x82\x03\x02\x02\x02\u0278\u0279\x071\x02\x02\u0279\x84\x03\x02" + + "\x02\x02\u027A\u027B\x07\'\x02\x02\u027B\x86\x03\x02\x02\x02\u027C\u027D" + + "\x07]\x02\x02\u027D\u027E\x03\x02\x02\x02\u027E\u027F\bC\x02\x02\u027F" + + "\u0280\bC\x02\x02\u0280\x88\x03\x02\x02\x02\u0281\u0282\x07_\x02\x02\u0282" + + "\u0283\x03\x02\x02\x02\u0283\u0284\bD\x05\x02\u0284\u0285\bD\x05\x02\u0285" + + "\x8A\x03\x02\x02\x02\u0286\u028C\x051\x18\x02\u0287\u028B\x051\x18\x02" + + "\u0288\u028B\x05/\x17\x02\u0289\u028B\x07a\x02\x02\u028A\u0287\x03\x02" + + "\x02\x02\u028A\u0288\x03\x02\x02\x02\u028A\u0289\x03\x02\x02\x02\u028B" + + "\u028E\x03\x02\x02\x02\u028C\u028A\x03\x02\x02\x02\u028C\u028D\x03\x02" + + "\x02\x02\u028D\u0298\x03\x02\x02\x02\u028E\u028C\x03\x02\x02\x02\u028F" + + "\u0293\t\v\x02\x02\u0290\u0294\x051\x18\x02\u0291\u0294\x05/\x17\x02\u0292" + + "\u0294\x07a\x02\x02\u0293\u0290\x03\x02\x02\x02\u0293\u0291\x03\x02\x02" + + "\x02\u0293\u0292\x03\x02\x02\x02\u0294\u0295\x03\x02\x02\x02\u0295\u0293" + + "\x03\x02\x02\x02\u0295\u0296\x03\x02\x02\x02\u0296\u0298\x03\x02\x02\x02" + + "\u0297\u0286\x03\x02\x02\x02\u0297\u028F\x03\x02\x02\x02\u0298\x8C\x03" + + "\x02\x02\x02\u0299\u029F\x07b\x02\x02\u029A\u029E\n\f\x02\x02\u029B\u029C" + + "\x07b\x02\x02\u029C\u029E\x07b\x02\x02\u029D\u029A\x03\x02\x02\x02\u029D" + + "\u029B\x03\x02\x02\x02\u029E\u02A1\x03\x02\x02\x02\u029F\u029D\x03\x02" + + "\x02\x02\u029F\u02A0\x03\x02\x02\x02\u02A0\u02A2\x03\x02\x02\x02\u02A1" + + "\u029F\x03\x02\x02\x02\u02A2\u02A3\x07b\x02\x02\u02A3\x8E\x03\x02\x02" + + "\x02\u02A4\u02A5\x05\'\x13\x02\u02A5\u02A6\x03\x02\x02\x02\u02A6\u02A7" + + "\bG\x04\x02\u02A7\x90\x03\x02\x02\x02\u02A8\u02A9\x05)\x14\x02\u02A9\u02AA" + + "\x03\x02\x02\x02\u02AA\u02AB\bH\x04\x02\u02AB\x92\x03\x02\x02\x02\u02AC" + + "\u02AD\x05+\x15\x02\u02AD\u02AE\x03\x02\x02\x02\u02AE\u02AF\bI\x04\x02" + + "\u02AF\x94\x03\x02\x02\x02\u02B0\u02B1\x07~\x02\x02\u02B1\u02B2\x03\x02" + + "\x02\x02\u02B2\u02B3\bJ\x06\x02\u02B3\u02B4\bJ\x05\x02\u02B4\x96\x03\x02" + + "\x02\x02\u02B5\u02B6\x07]\x02\x02\u02B6\u02B7\x03\x02\x02\x02\u02B7\u02B8" + + "\bK\x07\x02\u02B8\u02B9\bK\x03\x02\u02B9\u02BA\bK\x03\x02\u02BA\x98\x03" + + "\x02\x02\x02\u02BB\u02BC\x07_\x02\x02\u02BC\u02BD\x03\x02\x02\x02\u02BD" + + "\u02BE\bL\x05\x02\u02BE\u02BF\bL\x05\x02\u02BF\u02C0\bL\b\x02\u02C0\x9A" + + "\x03\x02\x02\x02\u02C1\u02C2\x07.\x02\x02\u02C2\u02C3\x03\x02\x02\x02" + + "\u02C3\u02C4\bM\t\x02\u02C4\x9C\x03\x02\x02\x02\u02C5\u02C6\x07?\x02\x02" + + "\u02C6\u02C7\x03\x02\x02\x02\u02C7\u02C8\bN\n\x02\u02C8\x9E\x03\x02\x02" + + "\x02\u02C9\u02CA\x05\xB3Y\x02\u02CA\u02CB\x05\xD7k\x02\u02CB\xA0\x03\x02" + + "\x02\x02\u02CC\u02CD\x05\xCBe\x02\u02CD\u02CE\x05\xBB]\x02\u02CE\u02CF" + + "\x05\xD9l\x02\u02CF\u02D0\x05\xB3Y\x02\u02D0\u02D1\x05\xB9\\\x02\u02D1" + + "\u02D2\x05\xB3Y\x02\u02D2\u02D3\x05\xD9l\x02\u02D3\u02D4\x05\xB3Y\x02" + + "\u02D4\xA2\x03\x02\x02\x02\u02D5\u02D6\x05\xCFg\x02\u02D6\u02D7\x05\xCD" + + "f\x02\u02D7\xA4\x03\x02\x02\x02\u02D8\u02D9\x05\xDFo\x02\u02D9\u02DA\x05" + + "\xC3a\x02\u02DA\u02DB\x05\xD9l\x02\u02DB\u02DC\x05\xC1`\x02\u02DC\xA6" + + "\x03\x02\x02\x02\u02DD\u02DF\x05\xA9T\x02\u02DE\u02DD\x03\x02\x02\x02" + + "\u02DF\u02E0\x03\x02\x02\x02\u02E0\u02DE\x03\x02\x02\x02\u02E0\u02E1\x03" + + "\x02\x02\x02\u02E1\xA8\x03\x02\x02\x02\u02E2\u02E4\n\r\x02\x02\u02E3\u02E2" + + "\x03\x02\x02\x02\u02E4\u02E5\x03\x02\x02\x02\u02E5\u02E3\x03\x02\x02\x02" + + "\u02E5\u02E6\x03\x02\x02\x02\u02E6\u02EA\x03\x02\x02\x02\u02E7\u02E8\x07" + + "1\x02\x02\u02E8\u02EA\n\x0E\x02\x02\u02E9\u02E3\x03\x02\x02\x02\u02E9" + + "\u02E7\x03\x02\x02\x02\u02EA\xAA\x03\x02\x02\x02\u02EB\u02EC\x05\x8DF" + + "\x02\u02EC\xAC\x03\x02\x02\x02\u02ED\u02EE\x05\'\x13\x02\u02EE\u02EF\x03" + + "\x02\x02\x02\u02EF\u02F0\bV\x04\x02\u02F0\xAE\x03\x02\x02\x02\u02F1\u02F2" + + "\x05)\x14\x02\u02F2\u02F3\x03\x02\x02\x02\u02F3\u02F4\bW\x04\x02\u02F4" + + "\xB0\x03\x02\x02\x02\u02F5\u02F6\x05+\x15\x02\u02F6\u02F7\x03\x02\x02" + + "\x02\u02F7\u02F8\bX\x04\x02\u02F8\xB2\x03\x02\x02\x02\u02F9\u02FA\t\x0F" + + "\x02\x02\u02FA\xB4\x03\x02\x02\x02\u02FB\u02FC\t\x10\x02\x02\u02FC\xB6" + + "\x03\x02\x02\x02\u02FD\u02FE\t\x11\x02\x02\u02FE\xB8\x03\x02\x02\x02\u02FF" + + "\u0300\t\x12\x02\x02\u0300\xBA\x03\x02\x02\x02\u0301\u0302\t\t\x02\x02" + + "\u0302\xBC\x03\x02\x02\x02\u0303\u0304\t\x13\x02\x02\u0304\xBE\x03\x02" + + "\x02\x02\u0305\u0306\t\x14\x02\x02\u0306\xC0\x03\x02\x02\x02\u0307\u0308" + + "\t\x15\x02\x02\u0308\xC2\x03\x02\x02\x02\u0309\u030A\t\x16\x02\x02\u030A" + + "\xC4\x03\x02\x02\x02\u030B\u030C\t\x17\x02\x02\u030C\xC6\x03\x02\x02\x02" + + "\u030D\u030E\t\x18\x02\x02\u030E\xC8\x03\x02\x02\x02\u030F\u0310\t\x19" + + "\x02\x02\u0310\xCA\x03\x02\x02\x02\u0311\u0312\t\x1A\x02\x02\u0312\xCC" + + "\x03\x02\x02\x02\u0313\u0314\t\x1B\x02\x02\u0314\xCE\x03\x02\x02\x02\u0315" + + "\u0316\t\x1C\x02\x02\u0316\xD0\x03\x02\x02\x02\u0317\u0318\t\x1D\x02\x02" + + "\u0318\xD2\x03\x02\x02\x02\u0319\u031A\t\x1E\x02\x02\u031A\xD4\x03\x02" + + "\x02\x02\u031B\u031C\t\x1F\x02\x02\u031C\xD6\x03\x02\x02\x02\u031D\u031E" + + "\t \x02\x02\u031E\xD8\x03\x02\x02\x02\u031F\u0320\t!\x02\x02\u0320\xDA" + + "\x03\x02\x02\x02\u0321\u0322\t\"\x02\x02\u0322\xDC\x03\x02\x02\x02\u0323" + + "\u0324\t#\x02\x02\u0324\xDE\x03\x02\x02\x02\u0325\u0326\t$\x02\x02\u0326" + + "\xE0\x03\x02\x02\x02\u0327\u0328\t%\x02\x02\u0328\xE2\x03\x02\x02\x02" + + "\u0329\u032A\t&\x02\x02\u032A\xE4\x03\x02\x02\x02\u032B\u032C\t\'\x02" + + "\x02\u032C\xE6\x03\x02\x02\x02\'\x02\x03\x04\u016B\u0175\u0179\u017C\u0185" + + "\u0187\u0192\u01A5\u01AA\u01AF\u01B1\u01BC\u01C4\u01C7\u01C9\u01CE\u01D3" + + "\u01D9\u01E0\u01E5\u01EB\u01EE\u01F6\u01FA\u028A\u028C\u0293\u0295\u0297" + + "\u029D\u029F\u02E0\u02E5\u02E9\v\x07\x03\x02\x07\x04\x02\x02\x03\x02\x06" + + "\x02\x02\t\x17\x02\t?\x02\t@\x02\t\x1F\x02\t\x1E\x02"; public static readonly _serializedATN: string = Utils.join( [ esql_lexer._serializedATNSegment0, esql_lexer._serializedATNSegment1, - esql_lexer._serializedATNSegment2, ], "", ); diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 index af48024e56cc9..aa2e86b6979e1 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.g4 @@ -20,8 +20,7 @@ query ; sourceCommand - : explainCommand - | fromCommand + : fromCommand | rowCommand | showCommand ; @@ -29,51 +28,30 @@ sourceCommand processingCommand : evalCommand | limitCommand - | projectCommand | keepCommand - | renameCommand - | dropCommand - | dissectCommand - | grokCommand | sortCommand | statsCommand | whereCommand - | mvExpandCommand + | dropCommand + | renameCommand + | dissectCommand + | grokCommand | enrichCommand - ; - -enrichCommand - : ENRICH policyName=enrichIdentifier (ON matchField=enrichFieldIdentifier)? (WITH enrichWithClause (COMMA enrichWithClause)*)? - ; - -enrichWithClause - : (newName=enrichFieldIdentifier ASSIGN)? enrichField=enrichFieldIdentifier - ; - -mvExpandCommand - : MV_EXPAND qualifiedNames + | mvExpandCommand ; whereCommand - : WHERE whereBooleanExpression - ; - -whereBooleanExpression - : NOT whereBooleanExpression - | valueExpression - | regexBooleanExpression - | left=whereBooleanExpression operator=AND right=whereBooleanExpression - | left=whereBooleanExpression operator=OR right=whereBooleanExpression - | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP - | (NOT)? WHERE_FUNCTIONS LP qualifiedName ((COMMA functionExpressionArgument)*)? RP - | valueExpression IS NOT? NULL + : WHERE booleanExpression ; booleanExpression - : NOT booleanExpression - | valueExpression - | left=booleanExpression operator=AND right=booleanExpression - | left=booleanExpression operator=OR right=booleanExpression + : NOT booleanExpression #logicalNot + | valueExpression #booleanDefault + | regexBooleanExpression #regexExpression + | left=booleanExpression operator=AND right=booleanExpression #logicalBinary + | left=booleanExpression operator=OR right=booleanExpression #logicalBinary + | valueExpression (NOT)? IN LP valueExpression (COMMA valueExpression)* RP #logicalIn + | valueExpression IS NOT? NULL #isNull ; regexBooleanExpression @@ -82,41 +60,26 @@ regexBooleanExpression ; valueExpression - : operatorExpression - | comparison + : operatorExpression #valueExpressionDefault + | left=operatorExpression comparisonOperator right=operatorExpression #comparison ; -comparison - : left=operatorExpression comparisonOperator right=operatorExpression - ; - -mathFn - : functionIdentifier LP (functionExpressionArgument (COMMA functionExpressionArgument)*)? RP - ; - -mathEvalFn - : mathFunctionIdentifier LP (mathFunctionExpressionArgument (COMMA mathFunctionExpressionArgument)*)? RP - ; - -dateExpression - : quantifier=number DATE_LITERAL - ; - operatorExpression - : primaryExpression - | mathFn - | mathEvalFn - | operator=(MINUS | PLUS) operatorExpression - | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression - | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression + : primaryExpression #operatorExpressionDefault + | operator=(MINUS | PLUS) operatorExpression #arithmeticUnary + | left=operatorExpression operator=(ASTERISK | SLASH | PERCENT) right=operatorExpression #arithmeticBinary + | left=operatorExpression operator=(PLUS | MINUS) right=operatorExpression #arithmeticBinary ; primaryExpression - : constant - | qualifiedName - | dateExpression - | LP booleanExpression RP - | identifier LP (booleanExpression (COMMA booleanExpression)*)? RP + : constant #constantDefault + | qualifiedName #dereference + | functionExpression #function + | LP booleanExpression RP #parenthesizedExpression + ; + +functionExpression + : identifier LP (ASTERISK | (booleanExpression (COMMA booleanExpression)*))? RP ; rowCommand @@ -129,18 +92,9 @@ fields field : booleanExpression - | userVariable ASSIGN booleanExpression + | qualifiedName ASSIGN booleanExpression ; -enrichFieldIdentifier - : ENR_UNQUOTED_IDENTIFIER - | ENR_QUOTED_IDENTIFIER - ; - -userVariable - : identifier - ; - fromCommand : FROM sourceIdentifier (COMMA sourceIdentifier)* metadata? ; @@ -154,7 +108,11 @@ evalCommand ; statsCommand - : STATS fields? (BY qualifiedNames)? + : STATS fields? (BY grouping)? + ; + +grouping + : qualifiedName (COMMA qualifiedName)* ; sourceIdentifier @@ -162,61 +120,26 @@ sourceIdentifier | SRC_QUOTED_IDENTIFIER ; -enrichIdentifier - : ENR_UNQUOTED_IDENTIFIER - | ENR_QUOTED_IDENTIFIER - ; - -functionExpressionArgument - : qualifiedName - | string - | number - ; - -mathFunctionExpressionArgument - : qualifiedName - | string - | number - | operatorExpression - | dateExpression - | comparison - ; - qualifiedName : identifier (DOT identifier)* ; -qualifiedNames - : qualifiedName (COMMA qualifiedName)* - ; - identifier : UNQUOTED_IDENTIFIER | QUOTED_IDENTIFIER - | ASTERISK - ; - -mathFunctionIdentifier - : MATH_FUNCTION - ; - -functionIdentifier - : UNARY_FUNCTION ; constant - : NULL - | numericValue - | booleanValue - | string - | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET - | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET - | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET - ; - -numericValue - : decimalValue - | integerValue + : NULL #nullLiteral + | integerValue UNQUOTED_IDENTIFIER #qualifiedIntegerLiteral + | decimalValue #decimalLiteral + | integerValue #integerLiteral + | booleanValue #booleanLiteral + | PARAM #inputParam + | string #stringLiteral + | OPENING_BRACKET numericValue (COMMA numericValue)* CLOSING_BRACKET #numericArrayLiteral + | OPENING_BRACKET booleanValue (COMMA booleanValue)* CLOSING_BRACKET #booleanArrayLiteral + | OPENING_BRACKET string (COMMA string)* CLOSING_BRACKET #stringArrayLiteral ; limitCommand @@ -228,40 +151,36 @@ sortCommand ; orderExpression - : booleanExpression (ORDERING)? (NULLS_ORDERING (NULLS_ORDERING_DIRECTION))? - ; - -projectCommand - : PROJECT qualifiedNames + : booleanExpression ordering=(ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; keepCommand - : KEEP qualifiedNames + : KEEP sourceIdentifier (COMMA sourceIdentifier)* + | PROJECT sourceIdentifier (COMMA sourceIdentifier)* ; - dropCommand - : DROP qualifiedNames + : DROP sourceIdentifier (COMMA sourceIdentifier)* ; -renameVariable - : identifier (DOT identifier)* - ; - renameCommand : RENAME renameClause (COMMA renameClause)* ; -renameClause - : qualifiedName AS renameVariable +renameClause: + oldName=sourceIdentifier AS newName=sourceIdentifier ; dissectCommand - : DISSECT qualifiedNames string commandOptions? + : DISSECT primaryExpression string commandOptions? ; grokCommand - : GROK qualifiedNames string + : GROK primaryExpression string + ; + +mvExpandCommand + : MV_EXPAND sourceIdentifier ; commandOptions @@ -273,20 +192,20 @@ commandOption ; booleanValue - : BOOLEAN_VALUE + : TRUE | FALSE ; -number - : DECIMAL_LITERAL #decimalLiteral - | INTEGER_LITERAL #integerLiteral +numericValue + : decimalValue + | integerValue ; decimalValue - : DECIMAL_LITERAL + : (PLUS | MINUS)? DECIMAL_LITERAL ; integerValue - : INTEGER_LITERAL + : (PLUS | MINUS)? INTEGER_LITERAL ; string @@ -294,18 +213,18 @@ string ; comparisonOperator - : COMPARISON_OPERATOR + : EQ | NEQ | LT | LTE | GT | GTE ; -explainCommand - : EXPLAIN subqueryExpression +showCommand + : SHOW INFO #showInfo + | SHOW FUNCTIONS #showFunctions ; -subqueryExpression - : OPENING_BRACKET query CLOSING_BRACKET +enrichCommand + : ENRICH policyName=sourceIdentifier (ON matchField=sourceIdentifier)? (WITH enrichWithClause (COMMA enrichWithClause)*)? ; -showCommand - : SHOW INFO - | SHOW FUNCTIONS - ; +enrichWithClause + : (newName=sourceIdentifier ASSIGN)? enrichField=sourceIdentifier + ; \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp index 378d85247dc13..649902a25536b 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.interp +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.interp @@ -27,46 +27,41 @@ null null null null -'by' null -'and' null null '.' +null +null +null '(' null -']' null null null null null null +'?' null -'or' ')' -'_' -'info' -'functions' null null +null +'_' +'==' +'!=' +'<' +'<=' +'>' +'>=' '+' '-' '*' '/' '%' -'10' -null -'nulls' -null -null -null -null -null -null -null -null null +']' null null null @@ -85,149 +80,128 @@ null token symbolic names: null DISSECT -GROK +DROP +ENRICH EVAL -EXPLAIN FROM -ROW -STATS -WHERE -SORT -MV_EXPAND +GROK +KEEP LIMIT +MV_EXPAND PROJECT -DROP RENAME +ROW SHOW -ENRICH -KEEP +SORT +STATS +WHERE +UNKNOWN_CMD LINE_COMMENT MULTILINE_COMMENT WS -EXPLAIN_WS -EXPLAIN_LINE_COMMENT -EXPLAIN_MULTILINE_COMMENT PIPE STRING INTEGER_LITERAL DECIMAL_LITERAL BY -DATE_LITERAL AND +ASC ASSIGN COMMA +DESC DOT +FALSE +FIRST +LAST LP -OPENING_BRACKET -CLOSING_BRACKET -NOT -LIKE -RLIKE IN IS -AS +LIKE +NOT NULL +NULLS OR +PARAM +RLIKE RP -UNDERSCORE +TRUE INFO FUNCTIONS -BOOLEAN_VALUE -COMPARISON_OPERATOR +UNDERSCORE +EQ +NEQ +LT +LTE +GT +GTE PLUS MINUS ASTERISK SLASH PERCENT -TEN -ORDERING -NULLS_ORDERING -NULLS_ORDERING_DIRECTION -MATH_FUNCTION -UNARY_FUNCTION -WHERE_FUNCTIONS +OPENING_BRACKET +CLOSING_BRACKET UNQUOTED_IDENTIFIER QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS +AS METADATA +ON +WITH SRC_UNQUOTED_IDENTIFIER SRC_QUOTED_IDENTIFIER SRC_LINE_COMMENT SRC_MULTILINE_COMMENT SRC_WS -ON -WITH -ENR_UNQUOTED_IDENTIFIER -ENR_QUOTED_IDENTIFIER -ENR_LINE_COMMENT -ENR_MULTILINE_COMMENT -ENR_WS -EXPLAIN_PIPE rule names: singleStatement query sourceCommand processingCommand -enrichCommand -enrichWithClause -mvExpandCommand whereCommand -whereBooleanExpression booleanExpression regexBooleanExpression valueExpression -comparison -mathFn -mathEvalFn -dateExpression operatorExpression primaryExpression +functionExpression rowCommand fields field -enrichFieldIdentifier -userVariable fromCommand metadata evalCommand statsCommand +grouping sourceIdentifier -enrichIdentifier -functionExpressionArgument -mathFunctionExpressionArgument qualifiedName -qualifiedNames identifier -mathFunctionIdentifier -functionIdentifier constant -numericValue limitCommand sortCommand orderExpression -projectCommand keepCommand dropCommand -renameVariable renameCommand renameClause dissectCommand grokCommand +mvExpandCommand commandOptions commandOption booleanValue -number +numericValue decimalValue integerValue string comparisonOperator -explainCommand -subqueryExpression showCommand +enrichCommand +enrichWithClause atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 83, 598, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 132, 10, 3, 12, 3, 14, 3, 135, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 141, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 156, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 162, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 168, 10, 6, 12, 6, 14, 6, 171, 11, 6, 5, 6, 173, 10, 6, 3, 7, 3, 7, 3, 7, 5, 7, 178, 10, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 195, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 202, 10, 10, 12, 10, 14, 10, 205, 11, 10, 3, 10, 3, 10, 3, 10, 5, 10, 210, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 217, 10, 10, 12, 10, 14, 10, 220, 11, 10, 5, 10, 222, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 229, 10, 10, 3, 10, 3, 10, 5, 10, 233, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 241, 10, 10, 12, 10, 14, 10, 244, 11, 10, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 250, 10, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 258, 10, 11, 12, 11, 14, 11, 261, 11, 11, 3, 12, 3, 12, 5, 12, 265, 10, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 272, 10, 12, 3, 12, 3, 12, 3, 12, 5, 12, 277, 10, 12, 3, 13, 3, 13, 5, 13, 281, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 7, 15, 292, 10, 15, 12, 15, 14, 15, 295, 11, 15, 5, 15, 297, 10, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 306, 10, 16, 12, 16, 14, 16, 309, 11, 16, 5, 16, 311, 10, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 5, 18, 324, 10, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 332, 10, 18, 12, 18, 14, 18, 335, 11, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 349, 10, 19, 12, 19, 14, 19, 352, 11, 19, 5, 19, 354, 10, 19, 3, 19, 3, 19, 5, 19, 358, 10, 19, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 7, 21, 366, 10, 21, 12, 21, 14, 21, 369, 11, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 376, 10, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 7, 25, 386, 10, 25, 12, 25, 14, 25, 389, 11, 25, 3, 25, 5, 25, 392, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 7, 26, 399, 10, 26, 12, 26, 14, 26, 402, 11, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 5, 28, 411, 10, 28, 3, 28, 3, 28, 5, 28, 415, 10, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 5, 31, 424, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 432, 10, 32, 3, 33, 3, 33, 3, 33, 7, 33, 437, 10, 33, 12, 33, 14, 33, 440, 11, 33, 3, 34, 3, 34, 3, 34, 7, 34, 445, 10, 34, 12, 34, 14, 34, 448, 11, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 464, 10, 38, 12, 38, 14, 38, 467, 11, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 475, 10, 38, 12, 38, 14, 38, 478, 11, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 7, 38, 486, 10, 38, 12, 38, 14, 38, 489, 11, 38, 3, 38, 3, 38, 5, 38, 493, 10, 38, 3, 39, 3, 39, 5, 39, 497, 10, 39, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 7, 41, 506, 10, 41, 12, 41, 14, 41, 509, 11, 41, 3, 42, 3, 42, 5, 42, 513, 10, 42, 3, 42, 3, 42, 5, 42, 517, 10, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 7, 46, 531, 10, 46, 12, 46, 14, 46, 534, 11, 46, 3, 47, 3, 47, 3, 47, 3, 47, 7, 47, 540, 10, 47, 12, 47, 14, 47, 543, 11, 47, 3, 48, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 5, 49, 553, 10, 49, 3, 50, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 7, 51, 562, 10, 51, 12, 51, 14, 51, 565, 11, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 54, 3, 54, 5, 54, 575, 10, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 5, 61, 596, 10, 61, 3, 61, 2, 2, 6, 4, 18, 20, 34, 62, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 80, 2, 82, 2, 84, 2, 86, 2, 88, 2, 90, 2, 92, 2, 94, 2, 96, 2, 98, 2, 100, 2, 102, 2, 104, 2, 106, 2, 108, 2, 110, 2, 112, 2, 114, 2, 116, 2, 118, 2, 120, 2, 2, 7, 3, 2, 53, 54, 3, 2, 55, 57, 3, 2, 78, 79, 3, 2, 71, 72, 4, 2, 55, 55, 65, 66, 2, 627, 2, 122, 3, 2, 2, 2, 4, 125, 3, 2, 2, 2, 6, 140, 3, 2, 2, 2, 8, 155, 3, 2, 2, 2, 10, 157, 3, 2, 2, 2, 12, 177, 3, 2, 2, 2, 14, 181, 3, 2, 2, 2, 16, 184, 3, 2, 2, 2, 18, 232, 3, 2, 2, 2, 20, 249, 3, 2, 2, 2, 22, 276, 3, 2, 2, 2, 24, 280, 3, 2, 2, 2, 26, 282, 3, 2, 2, 2, 28, 286, 3, 2, 2, 2, 30, 300, 3, 2, 2, 2, 32, 314, 3, 2, 2, 2, 34, 323, 3, 2, 2, 2, 36, 357, 3, 2, 2, 2, 38, 359, 3, 2, 2, 2, 40, 362, 3, 2, 2, 2, 42, 375, 3, 2, 2, 2, 44, 377, 3, 2, 2, 2, 46, 379, 3, 2, 2, 2, 48, 381, 3, 2, 2, 2, 50, 393, 3, 2, 2, 2, 52, 405, 3, 2, 2, 2, 54, 408, 3, 2, 2, 2, 56, 416, 3, 2, 2, 2, 58, 418, 3, 2, 2, 2, 60, 423, 3, 2, 2, 2, 62, 431, 3, 2, 2, 2, 64, 433, 3, 2, 2, 2, 66, 441, 3, 2, 2, 2, 68, 449, 3, 2, 2, 2, 70, 451, 3, 2, 2, 2, 72, 453, 3, 2, 2, 2, 74, 492, 3, 2, 2, 2, 76, 496, 3, 2, 2, 2, 78, 498, 3, 2, 2, 2, 80, 501, 3, 2, 2, 2, 82, 510, 3, 2, 2, 2, 84, 518, 3, 2, 2, 2, 86, 521, 3, 2, 2, 2, 88, 524, 3, 2, 2, 2, 90, 527, 3, 2, 2, 2, 92, 535, 3, 2, 2, 2, 94, 544, 3, 2, 2, 2, 96, 548, 3, 2, 2, 2, 98, 554, 3, 2, 2, 2, 100, 558, 3, 2, 2, 2, 102, 566, 3, 2, 2, 2, 104, 570, 3, 2, 2, 2, 106, 574, 3, 2, 2, 2, 108, 576, 3, 2, 2, 2, 110, 578, 3, 2, 2, 2, 112, 580, 3, 2, 2, 2, 114, 582, 3, 2, 2, 2, 116, 584, 3, 2, 2, 2, 118, 587, 3, 2, 2, 2, 120, 595, 3, 2, 2, 2, 122, 123, 5, 4, 3, 2, 123, 124, 7, 2, 2, 3, 124, 3, 3, 2, 2, 2, 125, 126, 8, 3, 1, 2, 126, 127, 5, 6, 4, 2, 127, 133, 3, 2, 2, 2, 128, 129, 12, 3, 2, 2, 129, 130, 7, 26, 2, 2, 130, 132, 5, 8, 5, 2, 131, 128, 3, 2, 2, 2, 132, 135, 3, 2, 2, 2, 133, 131, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 5, 3, 2, 2, 2, 135, 133, 3, 2, 2, 2, 136, 141, 5, 116, 59, 2, 137, 141, 5, 48, 25, 2, 138, 141, 5, 38, 20, 2, 139, 141, 5, 120, 61, 2, 140, 136, 3, 2, 2, 2, 140, 137, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 139, 3, 2, 2, 2, 141, 7, 3, 2, 2, 2, 142, 156, 5, 52, 27, 2, 143, 156, 5, 78, 40, 2, 144, 156, 5, 84, 43, 2, 145, 156, 5, 86, 44, 2, 146, 156, 5, 92, 47, 2, 147, 156, 5, 88, 45, 2, 148, 156, 5, 96, 49, 2, 149, 156, 5, 98, 50, 2, 150, 156, 5, 80, 41, 2, 151, 156, 5, 54, 28, 2, 152, 156, 5, 16, 9, 2, 153, 156, 5, 14, 8, 2, 154, 156, 5, 10, 6, 2, 155, 142, 3, 2, 2, 2, 155, 143, 3, 2, 2, 2, 155, 144, 3, 2, 2, 2, 155, 145, 3, 2, 2, 2, 155, 146, 3, 2, 2, 2, 155, 147, 3, 2, 2, 2, 155, 148, 3, 2, 2, 2, 155, 149, 3, 2, 2, 2, 155, 150, 3, 2, 2, 2, 155, 151, 3, 2, 2, 2, 155, 152, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 155, 154, 3, 2, 2, 2, 156, 9, 3, 2, 2, 2, 157, 158, 7, 18, 2, 2, 158, 161, 5, 58, 30, 2, 159, 160, 7, 76, 2, 2, 160, 162, 5, 44, 23, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 172, 3, 2, 2, 2, 163, 164, 7, 77, 2, 2, 164, 169, 5, 12, 7, 2, 165, 166, 7, 34, 2, 2, 166, 168, 5, 12, 7, 2, 167, 165, 3, 2, 2, 2, 168, 171, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 169, 170, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 172, 163, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 11, 3, 2, 2, 2, 174, 175, 5, 44, 23, 2, 175, 176, 7, 33, 2, 2, 176, 178, 3, 2, 2, 2, 177, 174, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 180, 5, 44, 23, 2, 180, 13, 3, 2, 2, 2, 181, 182, 7, 12, 2, 2, 182, 183, 5, 66, 34, 2, 183, 15, 3, 2, 2, 2, 184, 185, 7, 10, 2, 2, 185, 186, 5, 18, 10, 2, 186, 17, 3, 2, 2, 2, 187, 188, 8, 10, 1, 2, 188, 189, 7, 39, 2, 2, 189, 233, 5, 18, 10, 10, 190, 233, 5, 24, 13, 2, 191, 233, 5, 22, 12, 2, 192, 194, 5, 24, 13, 2, 193, 195, 7, 39, 2, 2, 194, 193, 3, 2, 2, 2, 194, 195, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196, 197, 7, 42, 2, 2, 197, 198, 7, 36, 2, 2, 198, 203, 5, 24, 13, 2, 199, 200, 7, 34, 2, 2, 200, 202, 5, 24, 13, 2, 201, 199, 3, 2, 2, 2, 202, 205, 3, 2, 2, 2, 203, 201, 3, 2, 2, 2, 203, 204, 3, 2, 2, 2, 204, 206, 3, 2, 2, 2, 205, 203, 3, 2, 2, 2, 206, 207, 7, 47, 2, 2, 207, 233, 3, 2, 2, 2, 208, 210, 7, 39, 2, 2, 209, 208, 3, 2, 2, 2, 209, 210, 3, 2, 2, 2, 210, 211, 3, 2, 2, 2, 211, 212, 7, 64, 2, 2, 212, 213, 7, 36, 2, 2, 213, 221, 5, 64, 33, 2, 214, 215, 7, 34, 2, 2, 215, 217, 5, 60, 31, 2, 216, 214, 3, 2, 2, 2, 217, 220, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 219, 222, 3, 2, 2, 2, 220, 218, 3, 2, 2, 2, 221, 218, 3, 2, 2, 2, 221, 222, 3, 2, 2, 2, 222, 223, 3, 2, 2, 2, 223, 224, 7, 47, 2, 2, 224, 233, 3, 2, 2, 2, 225, 226, 5, 24, 13, 2, 226, 228, 7, 43, 2, 2, 227, 229, 7, 39, 2, 2, 228, 227, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 3, 2, 2, 2, 230, 231, 7, 45, 2, 2, 231, 233, 3, 2, 2, 2, 232, 187, 3, 2, 2, 2, 232, 190, 3, 2, 2, 2, 232, 191, 3, 2, 2, 2, 232, 192, 3, 2, 2, 2, 232, 209, 3, 2, 2, 2, 232, 225, 3, 2, 2, 2, 233, 242, 3, 2, 2, 2, 234, 235, 12, 7, 2, 2, 235, 236, 7, 32, 2, 2, 236, 241, 5, 18, 10, 8, 237, 238, 12, 6, 2, 2, 238, 239, 7, 46, 2, 2, 239, 241, 5, 18, 10, 7, 240, 234, 3, 2, 2, 2, 240, 237, 3, 2, 2, 2, 241, 244, 3, 2, 2, 2, 242, 240, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 19, 3, 2, 2, 2, 244, 242, 3, 2, 2, 2, 245, 246, 8, 11, 1, 2, 246, 247, 7, 39, 2, 2, 247, 250, 5, 20, 11, 6, 248, 250, 5, 24, 13, 2, 249, 245, 3, 2, 2, 2, 249, 248, 3, 2, 2, 2, 250, 259, 3, 2, 2, 2, 251, 252, 12, 4, 2, 2, 252, 253, 7, 32, 2, 2, 253, 258, 5, 20, 11, 5, 254, 255, 12, 3, 2, 2, 255, 256, 7, 46, 2, 2, 256, 258, 5, 20, 11, 4, 257, 251, 3, 2, 2, 2, 257, 254, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 21, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 264, 5, 24, 13, 2, 263, 265, 7, 39, 2, 2, 264, 263, 3, 2, 2, 2, 264, 265, 3, 2, 2, 2, 265, 266, 3, 2, 2, 2, 266, 267, 7, 40, 2, 2, 267, 268, 5, 112, 57, 2, 268, 277, 3, 2, 2, 2, 269, 271, 5, 24, 13, 2, 270, 272, 7, 39, 2, 2, 271, 270, 3, 2, 2, 2, 271, 272, 3, 2, 2, 2, 272, 273, 3, 2, 2, 2, 273, 274, 7, 41, 2, 2, 274, 275, 5, 112, 57, 2, 275, 277, 3, 2, 2, 2, 276, 262, 3, 2, 2, 2, 276, 269, 3, 2, 2, 2, 277, 23, 3, 2, 2, 2, 278, 281, 5, 34, 18, 2, 279, 281, 5, 26, 14, 2, 280, 278, 3, 2, 2, 2, 280, 279, 3, 2, 2, 2, 281, 25, 3, 2, 2, 2, 282, 283, 5, 34, 18, 2, 283, 284, 5, 114, 58, 2, 284, 285, 5, 34, 18, 2, 285, 27, 3, 2, 2, 2, 286, 287, 5, 72, 37, 2, 287, 296, 7, 36, 2, 2, 288, 293, 5, 60, 31, 2, 289, 290, 7, 34, 2, 2, 290, 292, 5, 60, 31, 2, 291, 289, 3, 2, 2, 2, 292, 295, 3, 2, 2, 2, 293, 291, 3, 2, 2, 2, 293, 294, 3, 2, 2, 2, 294, 297, 3, 2, 2, 2, 295, 293, 3, 2, 2, 2, 296, 288, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 298, 3, 2, 2, 2, 298, 299, 7, 47, 2, 2, 299, 29, 3, 2, 2, 2, 300, 301, 5, 70, 36, 2, 301, 310, 7, 36, 2, 2, 302, 307, 5, 62, 32, 2, 303, 304, 7, 34, 2, 2, 304, 306, 5, 62, 32, 2, 305, 303, 3, 2, 2, 2, 306, 309, 3, 2, 2, 2, 307, 305, 3, 2, 2, 2, 307, 308, 3, 2, 2, 2, 308, 311, 3, 2, 2, 2, 309, 307, 3, 2, 2, 2, 310, 302, 3, 2, 2, 2, 310, 311, 3, 2, 2, 2, 311, 312, 3, 2, 2, 2, 312, 313, 7, 47, 2, 2, 313, 31, 3, 2, 2, 2, 314, 315, 5, 106, 54, 2, 315, 316, 7, 31, 2, 2, 316, 33, 3, 2, 2, 2, 317, 318, 8, 18, 1, 2, 318, 324, 5, 36, 19, 2, 319, 324, 5, 28, 15, 2, 320, 324, 5, 30, 16, 2, 321, 322, 9, 2, 2, 2, 322, 324, 5, 34, 18, 5, 323, 317, 3, 2, 2, 2, 323, 319, 3, 2, 2, 2, 323, 320, 3, 2, 2, 2, 323, 321, 3, 2, 2, 2, 324, 333, 3, 2, 2, 2, 325, 326, 12, 4, 2, 2, 326, 327, 9, 3, 2, 2, 327, 332, 5, 34, 18, 5, 328, 329, 12, 3, 2, 2, 329, 330, 9, 2, 2, 2, 330, 332, 5, 34, 18, 4, 331, 325, 3, 2, 2, 2, 331, 328, 3, 2, 2, 2, 332, 335, 3, 2, 2, 2, 333, 331, 3, 2, 2, 2, 333, 334, 3, 2, 2, 2, 334, 35, 3, 2, 2, 2, 335, 333, 3, 2, 2, 2, 336, 358, 5, 74, 38, 2, 337, 358, 5, 64, 33, 2, 338, 358, 5, 32, 17, 2, 339, 340, 7, 36, 2, 2, 340, 341, 5, 20, 11, 2, 341, 342, 7, 47, 2, 2, 342, 358, 3, 2, 2, 2, 343, 344, 5, 68, 35, 2, 344, 353, 7, 36, 2, 2, 345, 350, 5, 20, 11, 2, 346, 347, 7, 34, 2, 2, 347, 349, 5, 20, 11, 2, 348, 346, 3, 2, 2, 2, 349, 352, 3, 2, 2, 2, 350, 348, 3, 2, 2, 2, 350, 351, 3, 2, 2, 2, 351, 354, 3, 2, 2, 2, 352, 350, 3, 2, 2, 2, 353, 345, 3, 2, 2, 2, 353, 354, 3, 2, 2, 2, 354, 355, 3, 2, 2, 2, 355, 356, 7, 47, 2, 2, 356, 358, 3, 2, 2, 2, 357, 336, 3, 2, 2, 2, 357, 337, 3, 2, 2, 2, 357, 338, 3, 2, 2, 2, 357, 339, 3, 2, 2, 2, 357, 343, 3, 2, 2, 2, 358, 37, 3, 2, 2, 2, 359, 360, 7, 8, 2, 2, 360, 361, 5, 40, 21, 2, 361, 39, 3, 2, 2, 2, 362, 367, 5, 42, 22, 2, 363, 364, 7, 34, 2, 2, 364, 366, 5, 42, 22, 2, 365, 363, 3, 2, 2, 2, 366, 369, 3, 2, 2, 2, 367, 365, 3, 2, 2, 2, 367, 368, 3, 2, 2, 2, 368, 41, 3, 2, 2, 2, 369, 367, 3, 2, 2, 2, 370, 376, 5, 20, 11, 2, 371, 372, 5, 46, 24, 2, 372, 373, 7, 33, 2, 2, 373, 374, 5, 20, 11, 2, 374, 376, 3, 2, 2, 2, 375, 370, 3, 2, 2, 2, 375, 371, 3, 2, 2, 2, 376, 43, 3, 2, 2, 2, 377, 378, 9, 4, 2, 2, 378, 45, 3, 2, 2, 2, 379, 380, 5, 68, 35, 2, 380, 47, 3, 2, 2, 2, 381, 382, 7, 7, 2, 2, 382, 387, 5, 56, 29, 2, 383, 384, 7, 34, 2, 2, 384, 386, 5, 56, 29, 2, 385, 383, 3, 2, 2, 2, 386, 389, 3, 2, 2, 2, 387, 385, 3, 2, 2, 2, 387, 388, 3, 2, 2, 2, 388, 391, 3, 2, 2, 2, 389, 387, 3, 2, 2, 2, 390, 392, 5, 50, 26, 2, 391, 390, 3, 2, 2, 2, 391, 392, 3, 2, 2, 2, 392, 49, 3, 2, 2, 2, 393, 394, 7, 37, 2, 2, 394, 395, 7, 70, 2, 2, 395, 400, 5, 56, 29, 2, 396, 397, 7, 34, 2, 2, 397, 399, 5, 56, 29, 2, 398, 396, 3, 2, 2, 2, 399, 402, 3, 2, 2, 2, 400, 398, 3, 2, 2, 2, 400, 401, 3, 2, 2, 2, 401, 403, 3, 2, 2, 2, 402, 400, 3, 2, 2, 2, 403, 404, 7, 38, 2, 2, 404, 51, 3, 2, 2, 2, 405, 406, 7, 5, 2, 2, 406, 407, 5, 40, 21, 2, 407, 53, 3, 2, 2, 2, 408, 410, 7, 9, 2, 2, 409, 411, 5, 40, 21, 2, 410, 409, 3, 2, 2, 2, 410, 411, 3, 2, 2, 2, 411, 414, 3, 2, 2, 2, 412, 413, 7, 30, 2, 2, 413, 415, 5, 66, 34, 2, 414, 412, 3, 2, 2, 2, 414, 415, 3, 2, 2, 2, 415, 55, 3, 2, 2, 2, 416, 417, 9, 5, 2, 2, 417, 57, 3, 2, 2, 2, 418, 419, 9, 4, 2, 2, 419, 59, 3, 2, 2, 2, 420, 424, 5, 64, 33, 2, 421, 424, 5, 112, 57, 2, 422, 424, 5, 106, 54, 2, 423, 420, 3, 2, 2, 2, 423, 421, 3, 2, 2, 2, 423, 422, 3, 2, 2, 2, 424, 61, 3, 2, 2, 2, 425, 432, 5, 64, 33, 2, 426, 432, 5, 112, 57, 2, 427, 432, 5, 106, 54, 2, 428, 432, 5, 34, 18, 2, 429, 432, 5, 32, 17, 2, 430, 432, 5, 26, 14, 2, 431, 425, 3, 2, 2, 2, 431, 426, 3, 2, 2, 2, 431, 427, 3, 2, 2, 2, 431, 428, 3, 2, 2, 2, 431, 429, 3, 2, 2, 2, 431, 430, 3, 2, 2, 2, 432, 63, 3, 2, 2, 2, 433, 438, 5, 68, 35, 2, 434, 435, 7, 35, 2, 2, 435, 437, 5, 68, 35, 2, 436, 434, 3, 2, 2, 2, 437, 440, 3, 2, 2, 2, 438, 436, 3, 2, 2, 2, 438, 439, 3, 2, 2, 2, 439, 65, 3, 2, 2, 2, 440, 438, 3, 2, 2, 2, 441, 446, 5, 64, 33, 2, 442, 443, 7, 34, 2, 2, 443, 445, 5, 64, 33, 2, 444, 442, 3, 2, 2, 2, 445, 448, 3, 2, 2, 2, 446, 444, 3, 2, 2, 2, 446, 447, 3, 2, 2, 2, 447, 67, 3, 2, 2, 2, 448, 446, 3, 2, 2, 2, 449, 450, 9, 6, 2, 2, 450, 69, 3, 2, 2, 2, 451, 452, 7, 62, 2, 2, 452, 71, 3, 2, 2, 2, 453, 454, 7, 63, 2, 2, 454, 73, 3, 2, 2, 2, 455, 493, 7, 45, 2, 2, 456, 493, 5, 76, 39, 2, 457, 493, 5, 104, 53, 2, 458, 493, 5, 112, 57, 2, 459, 460, 7, 37, 2, 2, 460, 465, 5, 76, 39, 2, 461, 462, 7, 34, 2, 2, 462, 464, 5, 76, 39, 2, 463, 461, 3, 2, 2, 2, 464, 467, 3, 2, 2, 2, 465, 463, 3, 2, 2, 2, 465, 466, 3, 2, 2, 2, 466, 468, 3, 2, 2, 2, 467, 465, 3, 2, 2, 2, 468, 469, 7, 38, 2, 2, 469, 493, 3, 2, 2, 2, 470, 471, 7, 37, 2, 2, 471, 476, 5, 104, 53, 2, 472, 473, 7, 34, 2, 2, 473, 475, 5, 104, 53, 2, 474, 472, 3, 2, 2, 2, 475, 478, 3, 2, 2, 2, 476, 474, 3, 2, 2, 2, 476, 477, 3, 2, 2, 2, 477, 479, 3, 2, 2, 2, 478, 476, 3, 2, 2, 2, 479, 480, 7, 38, 2, 2, 480, 493, 3, 2, 2, 2, 481, 482, 7, 37, 2, 2, 482, 487, 5, 112, 57, 2, 483, 484, 7, 34, 2, 2, 484, 486, 5, 112, 57, 2, 485, 483, 3, 2, 2, 2, 486, 489, 3, 2, 2, 2, 487, 485, 3, 2, 2, 2, 487, 488, 3, 2, 2, 2, 488, 490, 3, 2, 2, 2, 489, 487, 3, 2, 2, 2, 490, 491, 7, 38, 2, 2, 491, 493, 3, 2, 2, 2, 492, 455, 3, 2, 2, 2, 492, 456, 3, 2, 2, 2, 492, 457, 3, 2, 2, 2, 492, 458, 3, 2, 2, 2, 492, 459, 3, 2, 2, 2, 492, 470, 3, 2, 2, 2, 492, 481, 3, 2, 2, 2, 493, 75, 3, 2, 2, 2, 494, 497, 5, 108, 55, 2, 495, 497, 5, 110, 56, 2, 496, 494, 3, 2, 2, 2, 496, 495, 3, 2, 2, 2, 497, 77, 3, 2, 2, 2, 498, 499, 7, 13, 2, 2, 499, 500, 7, 28, 2, 2, 500, 79, 3, 2, 2, 2, 501, 502, 7, 11, 2, 2, 502, 507, 5, 82, 42, 2, 503, 504, 7, 34, 2, 2, 504, 506, 5, 82, 42, 2, 505, 503, 3, 2, 2, 2, 506, 509, 3, 2, 2, 2, 507, 505, 3, 2, 2, 2, 507, 508, 3, 2, 2, 2, 508, 81, 3, 2, 2, 2, 509, 507, 3, 2, 2, 2, 510, 512, 5, 20, 11, 2, 511, 513, 7, 59, 2, 2, 512, 511, 3, 2, 2, 2, 512, 513, 3, 2, 2, 2, 513, 516, 3, 2, 2, 2, 514, 515, 7, 60, 2, 2, 515, 517, 7, 61, 2, 2, 516, 514, 3, 2, 2, 2, 516, 517, 3, 2, 2, 2, 517, 83, 3, 2, 2, 2, 518, 519, 7, 14, 2, 2, 519, 520, 5, 66, 34, 2, 520, 85, 3, 2, 2, 2, 521, 522, 7, 19, 2, 2, 522, 523, 5, 66, 34, 2, 523, 87, 3, 2, 2, 2, 524, 525, 7, 15, 2, 2, 525, 526, 5, 66, 34, 2, 526, 89, 3, 2, 2, 2, 527, 532, 5, 68, 35, 2, 528, 529, 7, 35, 2, 2, 529, 531, 5, 68, 35, 2, 530, 528, 3, 2, 2, 2, 531, 534, 3, 2, 2, 2, 532, 530, 3, 2, 2, 2, 532, 533, 3, 2, 2, 2, 533, 91, 3, 2, 2, 2, 534, 532, 3, 2, 2, 2, 535, 536, 7, 16, 2, 2, 536, 541, 5, 94, 48, 2, 537, 538, 7, 34, 2, 2, 538, 540, 5, 94, 48, 2, 539, 537, 3, 2, 2, 2, 540, 543, 3, 2, 2, 2, 541, 539, 3, 2, 2, 2, 541, 542, 3, 2, 2, 2, 542, 93, 3, 2, 2, 2, 543, 541, 3, 2, 2, 2, 544, 545, 5, 64, 33, 2, 545, 546, 7, 44, 2, 2, 546, 547, 5, 90, 46, 2, 547, 95, 3, 2, 2, 2, 548, 549, 7, 3, 2, 2, 549, 550, 5, 66, 34, 2, 550, 552, 5, 112, 57, 2, 551, 553, 5, 100, 51, 2, 552, 551, 3, 2, 2, 2, 552, 553, 3, 2, 2, 2, 553, 97, 3, 2, 2, 2, 554, 555, 7, 4, 2, 2, 555, 556, 5, 66, 34, 2, 556, 557, 5, 112, 57, 2, 557, 99, 3, 2, 2, 2, 558, 563, 5, 102, 52, 2, 559, 560, 7, 34, 2, 2, 560, 562, 5, 102, 52, 2, 561, 559, 3, 2, 2, 2, 562, 565, 3, 2, 2, 2, 563, 561, 3, 2, 2, 2, 563, 564, 3, 2, 2, 2, 564, 101, 3, 2, 2, 2, 565, 563, 3, 2, 2, 2, 566, 567, 5, 68, 35, 2, 567, 568, 7, 33, 2, 2, 568, 569, 5, 74, 38, 2, 569, 103, 3, 2, 2, 2, 570, 571, 7, 51, 2, 2, 571, 105, 3, 2, 2, 2, 572, 575, 7, 29, 2, 2, 573, 575, 7, 28, 2, 2, 574, 572, 3, 2, 2, 2, 574, 573, 3, 2, 2, 2, 575, 107, 3, 2, 2, 2, 576, 577, 7, 29, 2, 2, 577, 109, 3, 2, 2, 2, 578, 579, 7, 28, 2, 2, 579, 111, 3, 2, 2, 2, 580, 581, 7, 27, 2, 2, 581, 113, 3, 2, 2, 2, 582, 583, 7, 52, 2, 2, 583, 115, 3, 2, 2, 2, 584, 585, 7, 6, 2, 2, 585, 586, 5, 118, 60, 2, 586, 117, 3, 2, 2, 2, 587, 588, 7, 37, 2, 2, 588, 589, 5, 4, 3, 2, 589, 590, 7, 38, 2, 2, 590, 119, 3, 2, 2, 2, 591, 592, 7, 17, 2, 2, 592, 596, 7, 49, 2, 2, 593, 594, 7, 17, 2, 2, 594, 596, 7, 50, 2, 2, 595, 591, 3, 2, 2, 2, 595, 593, 3, 2, 2, 2, 596, 121, 3, 2, 2, 2, 60, 133, 140, 155, 161, 169, 172, 177, 194, 203, 209, 218, 221, 228, 232, 240, 242, 249, 257, 259, 264, 271, 276, 280, 293, 296, 307, 310, 323, 331, 333, 350, 353, 357, 367, 375, 387, 391, 400, 410, 414, 423, 431, 438, 446, 465, 476, 487, 492, 496, 507, 512, 516, 532, 541, 552, 563, 574, 595] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 78, 486, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 100, 10, 3, 12, 3, 14, 3, 103, 11, 3, 3, 4, 3, 4, 3, 4, 5, 4, 108, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 122, 10, 5, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 134, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 141, 10, 7, 12, 7, 14, 7, 144, 11, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 5, 7, 151, 10, 7, 3, 7, 3, 7, 5, 7, 155, 10, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 7, 7, 163, 10, 7, 12, 7, 14, 7, 166, 11, 7, 3, 8, 3, 8, 5, 8, 170, 10, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 177, 10, 8, 3, 8, 3, 8, 3, 8, 5, 8, 182, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 189, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 5, 10, 195, 10, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 203, 10, 10, 12, 10, 14, 10, 206, 11, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 5, 11, 215, 10, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 7, 12, 223, 10, 12, 12, 12, 14, 12, 226, 11, 12, 5, 12, 228, 10, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 238, 10, 14, 12, 14, 14, 14, 241, 11, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 5, 15, 248, 10, 15, 3, 16, 3, 16, 3, 16, 3, 16, 7, 16, 254, 10, 16, 12, 16, 14, 16, 257, 11, 16, 3, 16, 5, 16, 260, 10, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 267, 10, 17, 12, 17, 14, 17, 270, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 5, 19, 279, 10, 19, 3, 19, 3, 19, 5, 19, 283, 10, 19, 3, 20, 3, 20, 3, 20, 7, 20, 288, 10, 20, 12, 20, 14, 20, 291, 11, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 7, 22, 298, 10, 22, 12, 22, 14, 22, 301, 11, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 318, 10, 24, 12, 24, 14, 24, 321, 11, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 329, 10, 24, 12, 24, 14, 24, 332, 11, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 7, 24, 340, 10, 24, 12, 24, 14, 24, 343, 11, 24, 3, 24, 3, 24, 5, 24, 347, 10, 24, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 7, 26, 356, 10, 26, 12, 26, 14, 26, 359, 11, 26, 3, 27, 3, 27, 5, 27, 363, 10, 27, 3, 27, 3, 27, 5, 27, 367, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 373, 10, 28, 12, 28, 14, 28, 376, 11, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 382, 10, 28, 12, 28, 14, 28, 385, 11, 28, 5, 28, 387, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 7, 29, 393, 10, 29, 12, 29, 14, 29, 396, 11, 29, 3, 30, 3, 30, 3, 30, 3, 30, 7, 30, 402, 10, 30, 12, 30, 14, 30, 405, 11, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 415, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 7, 35, 427, 10, 35, 12, 35, 14, 35, 430, 11, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 5, 38, 440, 10, 38, 3, 39, 5, 39, 443, 10, 39, 3, 39, 3, 39, 3, 40, 5, 40, 448, 10, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 5, 43, 460, 10, 43, 3, 44, 3, 44, 3, 44, 3, 44, 5, 44, 466, 10, 44, 3, 44, 3, 44, 3, 44, 3, 44, 7, 44, 472, 10, 44, 12, 44, 14, 44, 475, 11, 44, 5, 44, 477, 10, 44, 3, 45, 3, 45, 3, 45, 5, 45, 482, 10, 45, 3, 45, 3, 45, 3, 45, 2, 2, 5, 4, 12, 18, 46, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 80, 2, 82, 2, 84, 2, 86, 2, 88, 2, 2, 10, 3, 2, 58, 59, 3, 2, 60, 62, 3, 2, 74, 75, 3, 2, 65, 66, 4, 2, 29, 29, 32, 32, 3, 2, 35, 36, 4, 2, 34, 34, 48, 48, 3, 2, 52, 57, 2, 516, 2, 90, 3, 2, 2, 2, 4, 93, 3, 2, 2, 2, 6, 107, 3, 2, 2, 2, 8, 121, 3, 2, 2, 2, 10, 123, 3, 2, 2, 2, 12, 154, 3, 2, 2, 2, 14, 181, 3, 2, 2, 2, 16, 188, 3, 2, 2, 2, 18, 194, 3, 2, 2, 2, 20, 214, 3, 2, 2, 2, 22, 216, 3, 2, 2, 2, 24, 231, 3, 2, 2, 2, 26, 234, 3, 2, 2, 2, 28, 247, 3, 2, 2, 2, 30, 249, 3, 2, 2, 2, 32, 261, 3, 2, 2, 2, 34, 273, 3, 2, 2, 2, 36, 276, 3, 2, 2, 2, 38, 284, 3, 2, 2, 2, 40, 292, 3, 2, 2, 2, 42, 294, 3, 2, 2, 2, 44, 302, 3, 2, 2, 2, 46, 346, 3, 2, 2, 2, 48, 348, 3, 2, 2, 2, 50, 351, 3, 2, 2, 2, 52, 360, 3, 2, 2, 2, 54, 386, 3, 2, 2, 2, 56, 388, 3, 2, 2, 2, 58, 397, 3, 2, 2, 2, 60, 406, 3, 2, 2, 2, 62, 410, 3, 2, 2, 2, 64, 416, 3, 2, 2, 2, 66, 420, 3, 2, 2, 2, 68, 423, 3, 2, 2, 2, 70, 431, 3, 2, 2, 2, 72, 435, 3, 2, 2, 2, 74, 439, 3, 2, 2, 2, 76, 442, 3, 2, 2, 2, 78, 447, 3, 2, 2, 2, 80, 451, 3, 2, 2, 2, 82, 453, 3, 2, 2, 2, 84, 459, 3, 2, 2, 2, 86, 461, 3, 2, 2, 2, 88, 481, 3, 2, 2, 2, 90, 91, 5, 4, 3, 2, 91, 92, 7, 2, 2, 3, 92, 3, 3, 2, 2, 2, 93, 94, 8, 3, 1, 2, 94, 95, 5, 6, 4, 2, 95, 101, 3, 2, 2, 2, 96, 97, 12, 3, 2, 2, 97, 98, 7, 23, 2, 2, 98, 100, 5, 8, 5, 2, 99, 96, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2, 2, 2, 101, 102, 3, 2, 2, 2, 102, 5, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2, 104, 108, 5, 30, 16, 2, 105, 108, 5, 24, 13, 2, 106, 108, 5, 84, 43, 2, 107, 104, 3, 2, 2, 2, 107, 105, 3, 2, 2, 2, 107, 106, 3, 2, 2, 2, 108, 7, 3, 2, 2, 2, 109, 122, 5, 34, 18, 2, 110, 122, 5, 48, 25, 2, 111, 122, 5, 54, 28, 2, 112, 122, 5, 50, 26, 2, 113, 122, 5, 36, 19, 2, 114, 122, 5, 10, 6, 2, 115, 122, 5, 56, 29, 2, 116, 122, 5, 58, 30, 2, 117, 122, 5, 62, 32, 2, 118, 122, 5, 64, 33, 2, 119, 122, 5, 86, 44, 2, 120, 122, 5, 66, 34, 2, 121, 109, 3, 2, 2, 2, 121, 110, 3, 2, 2, 2, 121, 111, 3, 2, 2, 2, 121, 112, 3, 2, 2, 2, 121, 113, 3, 2, 2, 2, 121, 114, 3, 2, 2, 2, 121, 115, 3, 2, 2, 2, 121, 116, 3, 2, 2, 2, 121, 117, 3, 2, 2, 2, 121, 118, 3, 2, 2, 2, 121, 119, 3, 2, 2, 2, 121, 120, 3, 2, 2, 2, 122, 9, 3, 2, 2, 2, 123, 124, 7, 18, 2, 2, 124, 125, 5, 12, 7, 2, 125, 11, 3, 2, 2, 2, 126, 127, 8, 7, 1, 2, 127, 128, 7, 41, 2, 2, 128, 155, 5, 12, 7, 9, 129, 155, 5, 16, 9, 2, 130, 155, 5, 14, 8, 2, 131, 133, 5, 16, 9, 2, 132, 134, 7, 41, 2, 2, 133, 132, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 136, 7, 38, 2, 2, 136, 137, 7, 37, 2, 2, 137, 142, 5, 16, 9, 2, 138, 139, 7, 31, 2, 2, 139, 141, 5, 16, 9, 2, 140, 138, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 145, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 146, 7, 47, 2, 2, 146, 155, 3, 2, 2, 2, 147, 148, 5, 16, 9, 2, 148, 150, 7, 39, 2, 2, 149, 151, 7, 41, 2, 2, 150, 149, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 152, 3, 2, 2, 2, 152, 153, 7, 42, 2, 2, 153, 155, 3, 2, 2, 2, 154, 126, 3, 2, 2, 2, 154, 129, 3, 2, 2, 2, 154, 130, 3, 2, 2, 2, 154, 131, 3, 2, 2, 2, 154, 147, 3, 2, 2, 2, 155, 164, 3, 2, 2, 2, 156, 157, 12, 6, 2, 2, 157, 158, 7, 28, 2, 2, 158, 163, 5, 12, 7, 7, 159, 160, 12, 5, 2, 2, 160, 161, 7, 44, 2, 2, 161, 163, 5, 12, 7, 6, 162, 156, 3, 2, 2, 2, 162, 159, 3, 2, 2, 2, 163, 166, 3, 2, 2, 2, 164, 162, 3, 2, 2, 2, 164, 165, 3, 2, 2, 2, 165, 13, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 167, 169, 5, 16, 9, 2, 168, 170, 7, 41, 2, 2, 169, 168, 3, 2, 2, 2, 169, 170, 3, 2, 2, 2, 170, 171, 3, 2, 2, 2, 171, 172, 7, 40, 2, 2, 172, 173, 5, 80, 41, 2, 173, 182, 3, 2, 2, 2, 174, 176, 5, 16, 9, 2, 175, 177, 7, 41, 2, 2, 176, 175, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 179, 7, 46, 2, 2, 179, 180, 5, 80, 41, 2, 180, 182, 3, 2, 2, 2, 181, 167, 3, 2, 2, 2, 181, 174, 3, 2, 2, 2, 182, 15, 3, 2, 2, 2, 183, 189, 5, 18, 10, 2, 184, 185, 5, 18, 10, 2, 185, 186, 5, 82, 42, 2, 186, 187, 5, 18, 10, 2, 187, 189, 3, 2, 2, 2, 188, 183, 3, 2, 2, 2, 188, 184, 3, 2, 2, 2, 189, 17, 3, 2, 2, 2, 190, 191, 8, 10, 1, 2, 191, 195, 5, 20, 11, 2, 192, 193, 9, 2, 2, 2, 193, 195, 5, 18, 10, 5, 194, 190, 3, 2, 2, 2, 194, 192, 3, 2, 2, 2, 195, 204, 3, 2, 2, 2, 196, 197, 12, 4, 2, 2, 197, 198, 9, 3, 2, 2, 198, 203, 5, 18, 10, 5, 199, 200, 12, 3, 2, 2, 200, 201, 9, 2, 2, 2, 201, 203, 5, 18, 10, 4, 202, 196, 3, 2, 2, 2, 202, 199, 3, 2, 2, 2, 203, 206, 3, 2, 2, 2, 204, 202, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 19, 3, 2, 2, 2, 206, 204, 3, 2, 2, 2, 207, 215, 5, 46, 24, 2, 208, 215, 5, 42, 22, 2, 209, 215, 5, 22, 12, 2, 210, 211, 7, 37, 2, 2, 211, 212, 5, 12, 7, 2, 212, 213, 7, 47, 2, 2, 213, 215, 3, 2, 2, 2, 214, 207, 3, 2, 2, 2, 214, 208, 3, 2, 2, 2, 214, 209, 3, 2, 2, 2, 214, 210, 3, 2, 2, 2, 215, 21, 3, 2, 2, 2, 216, 217, 5, 44, 23, 2, 217, 227, 7, 37, 2, 2, 218, 228, 7, 60, 2, 2, 219, 224, 5, 12, 7, 2, 220, 221, 7, 31, 2, 2, 221, 223, 5, 12, 7, 2, 222, 220, 3, 2, 2, 2, 223, 226, 3, 2, 2, 2, 224, 222, 3, 2, 2, 2, 224, 225, 3, 2, 2, 2, 225, 228, 3, 2, 2, 2, 226, 224, 3, 2, 2, 2, 227, 218, 3, 2, 2, 2, 227, 219, 3, 2, 2, 2, 227, 228, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 230, 7, 47, 2, 2, 230, 23, 3, 2, 2, 2, 231, 232, 7, 14, 2, 2, 232, 233, 5, 26, 14, 2, 233, 25, 3, 2, 2, 2, 234, 239, 5, 28, 15, 2, 235, 236, 7, 31, 2, 2, 236, 238, 5, 28, 15, 2, 237, 235, 3, 2, 2, 2, 238, 241, 3, 2, 2, 2, 239, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 27, 3, 2, 2, 2, 241, 239, 3, 2, 2, 2, 242, 248, 5, 12, 7, 2, 243, 244, 5, 42, 22, 2, 244, 245, 7, 30, 2, 2, 245, 246, 5, 12, 7, 2, 246, 248, 3, 2, 2, 2, 247, 242, 3, 2, 2, 2, 247, 243, 3, 2, 2, 2, 248, 29, 3, 2, 2, 2, 249, 250, 7, 7, 2, 2, 250, 255, 5, 40, 21, 2, 251, 252, 7, 31, 2, 2, 252, 254, 5, 40, 21, 2, 253, 251, 3, 2, 2, 2, 254, 257, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 259, 3, 2, 2, 2, 257, 255, 3, 2, 2, 2, 258, 260, 5, 32, 17, 2, 259, 258, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 31, 3, 2, 2, 2, 261, 262, 7, 63, 2, 2, 262, 263, 7, 71, 2, 2, 263, 268, 5, 40, 21, 2, 264, 265, 7, 31, 2, 2, 265, 267, 5, 40, 21, 2, 266, 264, 3, 2, 2, 2, 267, 270, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 268, 269, 3, 2, 2, 2, 269, 271, 3, 2, 2, 2, 270, 268, 3, 2, 2, 2, 271, 272, 7, 64, 2, 2, 272, 33, 3, 2, 2, 2, 273, 274, 7, 6, 2, 2, 274, 275, 5, 26, 14, 2, 275, 35, 3, 2, 2, 2, 276, 278, 7, 17, 2, 2, 277, 279, 5, 26, 14, 2, 278, 277, 3, 2, 2, 2, 278, 279, 3, 2, 2, 2, 279, 282, 3, 2, 2, 2, 280, 281, 7, 27, 2, 2, 281, 283, 5, 38, 20, 2, 282, 280, 3, 2, 2, 2, 282, 283, 3, 2, 2, 2, 283, 37, 3, 2, 2, 2, 284, 289, 5, 42, 22, 2, 285, 286, 7, 31, 2, 2, 286, 288, 5, 42, 22, 2, 287, 285, 3, 2, 2, 2, 288, 291, 3, 2, 2, 2, 289, 287, 3, 2, 2, 2, 289, 290, 3, 2, 2, 2, 290, 39, 3, 2, 2, 2, 291, 289, 3, 2, 2, 2, 292, 293, 9, 4, 2, 2, 293, 41, 3, 2, 2, 2, 294, 299, 5, 44, 23, 2, 295, 296, 7, 33, 2, 2, 296, 298, 5, 44, 23, 2, 297, 295, 3, 2, 2, 2, 298, 301, 3, 2, 2, 2, 299, 297, 3, 2, 2, 2, 299, 300, 3, 2, 2, 2, 300, 43, 3, 2, 2, 2, 301, 299, 3, 2, 2, 2, 302, 303, 9, 5, 2, 2, 303, 45, 3, 2, 2, 2, 304, 347, 7, 42, 2, 2, 305, 306, 5, 78, 40, 2, 306, 307, 7, 65, 2, 2, 307, 347, 3, 2, 2, 2, 308, 347, 5, 76, 39, 2, 309, 347, 5, 78, 40, 2, 310, 347, 5, 72, 37, 2, 311, 347, 7, 45, 2, 2, 312, 347, 5, 80, 41, 2, 313, 314, 7, 63, 2, 2, 314, 319, 5, 74, 38, 2, 315, 316, 7, 31, 2, 2, 316, 318, 5, 74, 38, 2, 317, 315, 3, 2, 2, 2, 318, 321, 3, 2, 2, 2, 319, 317, 3, 2, 2, 2, 319, 320, 3, 2, 2, 2, 320, 322, 3, 2, 2, 2, 321, 319, 3, 2, 2, 2, 322, 323, 7, 64, 2, 2, 323, 347, 3, 2, 2, 2, 324, 325, 7, 63, 2, 2, 325, 330, 5, 72, 37, 2, 326, 327, 7, 31, 2, 2, 327, 329, 5, 72, 37, 2, 328, 326, 3, 2, 2, 2, 329, 332, 3, 2, 2, 2, 330, 328, 3, 2, 2, 2, 330, 331, 3, 2, 2, 2, 331, 333, 3, 2, 2, 2, 332, 330, 3, 2, 2, 2, 333, 334, 7, 64, 2, 2, 334, 347, 3, 2, 2, 2, 335, 336, 7, 63, 2, 2, 336, 341, 5, 80, 41, 2, 337, 338, 7, 31, 2, 2, 338, 340, 5, 80, 41, 2, 339, 337, 3, 2, 2, 2, 340, 343, 3, 2, 2, 2, 341, 339, 3, 2, 2, 2, 341, 342, 3, 2, 2, 2, 342, 344, 3, 2, 2, 2, 343, 341, 3, 2, 2, 2, 344, 345, 7, 64, 2, 2, 345, 347, 3, 2, 2, 2, 346, 304, 3, 2, 2, 2, 346, 305, 3, 2, 2, 2, 346, 308, 3, 2, 2, 2, 346, 309, 3, 2, 2, 2, 346, 310, 3, 2, 2, 2, 346, 311, 3, 2, 2, 2, 346, 312, 3, 2, 2, 2, 346, 313, 3, 2, 2, 2, 346, 324, 3, 2, 2, 2, 346, 335, 3, 2, 2, 2, 347, 47, 3, 2, 2, 2, 348, 349, 7, 10, 2, 2, 349, 350, 7, 25, 2, 2, 350, 49, 3, 2, 2, 2, 351, 352, 7, 16, 2, 2, 352, 357, 5, 52, 27, 2, 353, 354, 7, 31, 2, 2, 354, 356, 5, 52, 27, 2, 355, 353, 3, 2, 2, 2, 356, 359, 3, 2, 2, 2, 357, 355, 3, 2, 2, 2, 357, 358, 3, 2, 2, 2, 358, 51, 3, 2, 2, 2, 359, 357, 3, 2, 2, 2, 360, 362, 5, 12, 7, 2, 361, 363, 9, 6, 2, 2, 362, 361, 3, 2, 2, 2, 362, 363, 3, 2, 2, 2, 363, 366, 3, 2, 2, 2, 364, 365, 7, 43, 2, 2, 365, 367, 9, 7, 2, 2, 366, 364, 3, 2, 2, 2, 366, 367, 3, 2, 2, 2, 367, 53, 3, 2, 2, 2, 368, 369, 7, 9, 2, 2, 369, 374, 5, 40, 21, 2, 370, 371, 7, 31, 2, 2, 371, 373, 5, 40, 21, 2, 372, 370, 3, 2, 2, 2, 373, 376, 3, 2, 2, 2, 374, 372, 3, 2, 2, 2, 374, 375, 3, 2, 2, 2, 375, 387, 3, 2, 2, 2, 376, 374, 3, 2, 2, 2, 377, 378, 7, 12, 2, 2, 378, 383, 5, 40, 21, 2, 379, 380, 7, 31, 2, 2, 380, 382, 5, 40, 21, 2, 381, 379, 3, 2, 2, 2, 382, 385, 3, 2, 2, 2, 383, 381, 3, 2, 2, 2, 383, 384, 3, 2, 2, 2, 384, 387, 3, 2, 2, 2, 385, 383, 3, 2, 2, 2, 386, 368, 3, 2, 2, 2, 386, 377, 3, 2, 2, 2, 387, 55, 3, 2, 2, 2, 388, 389, 7, 4, 2, 2, 389, 394, 5, 40, 21, 2, 390, 391, 7, 31, 2, 2, 391, 393, 5, 40, 21, 2, 392, 390, 3, 2, 2, 2, 393, 396, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 394, 395, 3, 2, 2, 2, 395, 57, 3, 2, 2, 2, 396, 394, 3, 2, 2, 2, 397, 398, 7, 13, 2, 2, 398, 403, 5, 60, 31, 2, 399, 400, 7, 31, 2, 2, 400, 402, 5, 60, 31, 2, 401, 399, 3, 2, 2, 2, 402, 405, 3, 2, 2, 2, 403, 401, 3, 2, 2, 2, 403, 404, 3, 2, 2, 2, 404, 59, 3, 2, 2, 2, 405, 403, 3, 2, 2, 2, 406, 407, 5, 40, 21, 2, 407, 408, 7, 70, 2, 2, 408, 409, 5, 40, 21, 2, 409, 61, 3, 2, 2, 2, 410, 411, 7, 3, 2, 2, 411, 412, 5, 20, 11, 2, 412, 414, 5, 80, 41, 2, 413, 415, 5, 68, 35, 2, 414, 413, 3, 2, 2, 2, 414, 415, 3, 2, 2, 2, 415, 63, 3, 2, 2, 2, 416, 417, 7, 8, 2, 2, 417, 418, 5, 20, 11, 2, 418, 419, 5, 80, 41, 2, 419, 65, 3, 2, 2, 2, 420, 421, 7, 11, 2, 2, 421, 422, 5, 40, 21, 2, 422, 67, 3, 2, 2, 2, 423, 428, 5, 70, 36, 2, 424, 425, 7, 31, 2, 2, 425, 427, 5, 70, 36, 2, 426, 424, 3, 2, 2, 2, 427, 430, 3, 2, 2, 2, 428, 426, 3, 2, 2, 2, 428, 429, 3, 2, 2, 2, 429, 69, 3, 2, 2, 2, 430, 428, 3, 2, 2, 2, 431, 432, 5, 44, 23, 2, 432, 433, 7, 30, 2, 2, 433, 434, 5, 46, 24, 2, 434, 71, 3, 2, 2, 2, 435, 436, 9, 8, 2, 2, 436, 73, 3, 2, 2, 2, 437, 440, 5, 76, 39, 2, 438, 440, 5, 78, 40, 2, 439, 437, 3, 2, 2, 2, 439, 438, 3, 2, 2, 2, 440, 75, 3, 2, 2, 2, 441, 443, 9, 2, 2, 2, 442, 441, 3, 2, 2, 2, 442, 443, 3, 2, 2, 2, 443, 444, 3, 2, 2, 2, 444, 445, 7, 26, 2, 2, 445, 77, 3, 2, 2, 2, 446, 448, 9, 2, 2, 2, 447, 446, 3, 2, 2, 2, 447, 448, 3, 2, 2, 2, 448, 449, 3, 2, 2, 2, 449, 450, 7, 25, 2, 2, 450, 79, 3, 2, 2, 2, 451, 452, 7, 24, 2, 2, 452, 81, 3, 2, 2, 2, 453, 454, 9, 9, 2, 2, 454, 83, 3, 2, 2, 2, 455, 456, 7, 15, 2, 2, 456, 460, 7, 49, 2, 2, 457, 458, 7, 15, 2, 2, 458, 460, 7, 50, 2, 2, 459, 455, 3, 2, 2, 2, 459, 457, 3, 2, 2, 2, 460, 85, 3, 2, 2, 2, 461, 462, 7, 5, 2, 2, 462, 465, 5, 40, 21, 2, 463, 464, 7, 72, 2, 2, 464, 466, 5, 40, 21, 2, 465, 463, 3, 2, 2, 2, 465, 466, 3, 2, 2, 2, 466, 476, 3, 2, 2, 2, 467, 468, 7, 73, 2, 2, 468, 473, 5, 88, 45, 2, 469, 470, 7, 31, 2, 2, 470, 472, 5, 88, 45, 2, 471, 469, 3, 2, 2, 2, 472, 475, 3, 2, 2, 2, 473, 471, 3, 2, 2, 2, 473, 474, 3, 2, 2, 2, 474, 477, 3, 2, 2, 2, 475, 473, 3, 2, 2, 2, 476, 467, 3, 2, 2, 2, 476, 477, 3, 2, 2, 2, 477, 87, 3, 2, 2, 2, 478, 479, 5, 40, 21, 2, 479, 480, 7, 30, 2, 2, 480, 482, 3, 2, 2, 2, 481, 478, 3, 2, 2, 2, 481, 482, 3, 2, 2, 2, 482, 483, 3, 2, 2, 2, 483, 484, 5, 40, 21, 2, 484, 89, 3, 2, 2, 2, 52, 101, 107, 121, 133, 142, 150, 154, 162, 164, 169, 176, 181, 188, 194, 202, 204, 214, 224, 227, 239, 247, 255, 259, 268, 278, 282, 289, 299, 319, 330, 341, 346, 357, 362, 366, 374, 383, 386, 394, 403, 414, 428, 439, 442, 447, 459, 465, 473, 476, 481] \ No newline at end of file diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens index b72e97b9a2961..c3160ce1f6472 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.tokens @@ -1,98 +1,93 @@ DISSECT=1 -GROK=2 -EVAL=3 -EXPLAIN=4 +DROP=2 +ENRICH=3 +EVAL=4 FROM=5 -ROW=6 -STATS=7 -WHERE=8 -SORT=9 -MV_EXPAND=10 -LIMIT=11 -PROJECT=12 -DROP=13 -RENAME=14 -SHOW=15 -ENRICH=16 -KEEP=17 +GROK=6 +KEEP=7 +LIMIT=8 +MV_EXPAND=9 +PROJECT=10 +RENAME=11 +ROW=12 +SHOW=13 +SORT=14 +STATS=15 +WHERE=16 +UNKNOWN_CMD=17 LINE_COMMENT=18 MULTILINE_COMMENT=19 WS=20 -EXPLAIN_WS=21 -EXPLAIN_LINE_COMMENT=22 -EXPLAIN_MULTILINE_COMMENT=23 -PIPE=24 -STRING=25 -INTEGER_LITERAL=26 -DECIMAL_LITERAL=27 -BY=28 -DATE_LITERAL=29 -AND=30 -ASSIGN=31 -COMMA=32 -DOT=33 -LP=34 -OPENING_BRACKET=35 -CLOSING_BRACKET=36 -NOT=37 +PIPE=21 +STRING=22 +INTEGER_LITERAL=23 +DECIMAL_LITERAL=24 +BY=25 +AND=26 +ASC=27 +ASSIGN=28 +COMMA=29 +DESC=30 +DOT=31 +FALSE=32 +FIRST=33 +LAST=34 +LP=35 +IN=36 +IS=37 LIKE=38 -RLIKE=39 -IN=40 -IS=41 -AS=42 -NULL=43 -OR=44 +NOT=39 +NULL=40 +NULLS=41 +OR=42 +PARAM=43 +RLIKE=44 RP=45 -UNDERSCORE=46 +TRUE=46 INFO=47 FUNCTIONS=48 -BOOLEAN_VALUE=49 -COMPARISON_OPERATOR=50 -PLUS=51 -MINUS=52 -ASTERISK=53 -SLASH=54 -PERCENT=55 -TEN=56 -ORDERING=57 -NULLS_ORDERING=58 -NULLS_ORDERING_DIRECTION=59 -MATH_FUNCTION=60 -UNARY_FUNCTION=61 -WHERE_FUNCTIONS=62 +UNDERSCORE=49 +EQ=50 +NEQ=51 +LT=52 +LTE=53 +GT=54 +GTE=55 +PLUS=56 +MINUS=57 +ASTERISK=58 +SLASH=59 +PERCENT=60 +OPENING_BRACKET=61 +CLOSING_BRACKET=62 UNQUOTED_IDENTIFIER=63 QUOTED_IDENTIFIER=64 EXPR_LINE_COMMENT=65 EXPR_MULTILINE_COMMENT=66 EXPR_WS=67 -METADATA=68 -SRC_UNQUOTED_IDENTIFIER=69 -SRC_QUOTED_IDENTIFIER=70 -SRC_LINE_COMMENT=71 -SRC_MULTILINE_COMMENT=72 -SRC_WS=73 -ON=74 -WITH=75 -ENR_UNQUOTED_IDENTIFIER=76 -ENR_QUOTED_IDENTIFIER=77 -ENR_LINE_COMMENT=78 -ENR_MULTILINE_COMMENT=79 -ENR_WS=80 -EXPLAIN_PIPE=81 -'by'=28 -'and'=30 -'.'=33 -'('=34 -']'=36 -'or'=44 +AS=68 +METADATA=69 +ON=70 +WITH=71 +SRC_UNQUOTED_IDENTIFIER=72 +SRC_QUOTED_IDENTIFIER=73 +SRC_LINE_COMMENT=74 +SRC_MULTILINE_COMMENT=75 +SRC_WS=76 +'.'=31 +'('=35 +'?'=43 ')'=45 -'_'=46 -'info'=47 -'functions'=48 -'+'=51 -'-'=52 -'*'=53 -'/'=54 -'%'=55 -'10'=56 -'nulls'=58 +'_'=49 +'=='=50 +'!='=51 +'<'=52 +'<='=53 +'>'=54 +'>='=55 +'+'=56 +'-'=57 +'*'=58 +'/'=59 +'%'=60 +']'=62 diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts index 494ffadd8aad9..8e0a4ca8199b8 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser.ts @@ -28,162 +28,136 @@ import { esql_parserListener } from "./esql_parserListener"; export class esql_parser extends Parser { public static readonly DISSECT = 1; - public static readonly GROK = 2; - public static readonly EVAL = 3; - public static readonly EXPLAIN = 4; + public static readonly DROP = 2; + public static readonly ENRICH = 3; + public static readonly EVAL = 4; public static readonly FROM = 5; - public static readonly ROW = 6; - public static readonly STATS = 7; - public static readonly WHERE = 8; - public static readonly SORT = 9; - public static readonly MV_EXPAND = 10; - public static readonly LIMIT = 11; - public static readonly PROJECT = 12; - public static readonly DROP = 13; - public static readonly RENAME = 14; - public static readonly SHOW = 15; - public static readonly ENRICH = 16; - public static readonly KEEP = 17; + public static readonly GROK = 6; + public static readonly KEEP = 7; + public static readonly LIMIT = 8; + public static readonly MV_EXPAND = 9; + public static readonly PROJECT = 10; + public static readonly RENAME = 11; + public static readonly ROW = 12; + public static readonly SHOW = 13; + public static readonly SORT = 14; + public static readonly STATS = 15; + public static readonly WHERE = 16; + public static readonly UNKNOWN_CMD = 17; public static readonly LINE_COMMENT = 18; public static readonly MULTILINE_COMMENT = 19; public static readonly WS = 20; - public static readonly EXPLAIN_WS = 21; - public static readonly EXPLAIN_LINE_COMMENT = 22; - public static readonly EXPLAIN_MULTILINE_COMMENT = 23; - public static readonly PIPE = 24; - public static readonly STRING = 25; - public static readonly INTEGER_LITERAL = 26; - public static readonly DECIMAL_LITERAL = 27; - public static readonly BY = 28; - public static readonly DATE_LITERAL = 29; - public static readonly AND = 30; - public static readonly ASSIGN = 31; - public static readonly COMMA = 32; - public static readonly DOT = 33; - public static readonly LP = 34; - public static readonly OPENING_BRACKET = 35; - public static readonly CLOSING_BRACKET = 36; - public static readonly NOT = 37; + public static readonly PIPE = 21; + public static readonly STRING = 22; + public static readonly INTEGER_LITERAL = 23; + public static readonly DECIMAL_LITERAL = 24; + public static readonly BY = 25; + public static readonly AND = 26; + public static readonly ASC = 27; + public static readonly ASSIGN = 28; + public static readonly COMMA = 29; + public static readonly DESC = 30; + public static readonly DOT = 31; + public static readonly FALSE = 32; + public static readonly FIRST = 33; + public static readonly LAST = 34; + public static readonly LP = 35; + public static readonly IN = 36; + public static readonly IS = 37; public static readonly LIKE = 38; - public static readonly RLIKE = 39; - public static readonly IN = 40; - public static readonly IS = 41; - public static readonly AS = 42; - public static readonly NULL = 43; - public static readonly OR = 44; + public static readonly NOT = 39; + public static readonly NULL = 40; + public static readonly NULLS = 41; + public static readonly OR = 42; + public static readonly PARAM = 43; + public static readonly RLIKE = 44; public static readonly RP = 45; - public static readonly UNDERSCORE = 46; + public static readonly TRUE = 46; public static readonly INFO = 47; public static readonly FUNCTIONS = 48; - public static readonly BOOLEAN_VALUE = 49; - public static readonly COMPARISON_OPERATOR = 50; - public static readonly PLUS = 51; - public static readonly MINUS = 52; - public static readonly ASTERISK = 53; - public static readonly SLASH = 54; - public static readonly PERCENT = 55; - public static readonly TEN = 56; - public static readonly ORDERING = 57; - public static readonly NULLS_ORDERING = 58; - public static readonly NULLS_ORDERING_DIRECTION = 59; - public static readonly MATH_FUNCTION = 60; - public static readonly UNARY_FUNCTION = 61; - public static readonly WHERE_FUNCTIONS = 62; + public static readonly UNDERSCORE = 49; + public static readonly EQ = 50; + public static readonly NEQ = 51; + public static readonly LT = 52; + public static readonly LTE = 53; + public static readonly GT = 54; + public static readonly GTE = 55; + public static readonly PLUS = 56; + public static readonly MINUS = 57; + public static readonly ASTERISK = 58; + public static readonly SLASH = 59; + public static readonly PERCENT = 60; + public static readonly OPENING_BRACKET = 61; + public static readonly CLOSING_BRACKET = 62; public static readonly UNQUOTED_IDENTIFIER = 63; public static readonly QUOTED_IDENTIFIER = 64; public static readonly EXPR_LINE_COMMENT = 65; public static readonly EXPR_MULTILINE_COMMENT = 66; public static readonly EXPR_WS = 67; - public static readonly METADATA = 68; - public static readonly SRC_UNQUOTED_IDENTIFIER = 69; - public static readonly SRC_QUOTED_IDENTIFIER = 70; - public static readonly SRC_LINE_COMMENT = 71; - public static readonly SRC_MULTILINE_COMMENT = 72; - public static readonly SRC_WS = 73; - public static readonly ON = 74; - public static readonly WITH = 75; - public static readonly ENR_UNQUOTED_IDENTIFIER = 76; - public static readonly ENR_QUOTED_IDENTIFIER = 77; - public static readonly ENR_LINE_COMMENT = 78; - public static readonly ENR_MULTILINE_COMMENT = 79; - public static readonly ENR_WS = 80; - public static readonly EXPLAIN_PIPE = 81; + public static readonly AS = 68; + public static readonly METADATA = 69; + public static readonly ON = 70; + public static readonly WITH = 71; + public static readonly SRC_UNQUOTED_IDENTIFIER = 72; + public static readonly SRC_QUOTED_IDENTIFIER = 73; + public static readonly SRC_LINE_COMMENT = 74; + public static readonly SRC_MULTILINE_COMMENT = 75; + public static readonly SRC_WS = 76; public static readonly RULE_singleStatement = 0; public static readonly RULE_query = 1; public static readonly RULE_sourceCommand = 2; public static readonly RULE_processingCommand = 3; - public static readonly RULE_enrichCommand = 4; - public static readonly RULE_enrichWithClause = 5; - public static readonly RULE_mvExpandCommand = 6; - public static readonly RULE_whereCommand = 7; - public static readonly RULE_whereBooleanExpression = 8; - public static readonly RULE_booleanExpression = 9; - public static readonly RULE_regexBooleanExpression = 10; - public static readonly RULE_valueExpression = 11; - public static readonly RULE_comparison = 12; - public static readonly RULE_mathFn = 13; - public static readonly RULE_mathEvalFn = 14; - public static readonly RULE_dateExpression = 15; - public static readonly RULE_operatorExpression = 16; - public static readonly RULE_primaryExpression = 17; - public static readonly RULE_rowCommand = 18; - public static readonly RULE_fields = 19; - public static readonly RULE_field = 20; - public static readonly RULE_enrichFieldIdentifier = 21; - public static readonly RULE_userVariable = 22; - public static readonly RULE_fromCommand = 23; - public static readonly RULE_metadata = 24; - public static readonly RULE_evalCommand = 25; - public static readonly RULE_statsCommand = 26; - public static readonly RULE_sourceIdentifier = 27; - public static readonly RULE_enrichIdentifier = 28; - public static readonly RULE_functionExpressionArgument = 29; - public static readonly RULE_mathFunctionExpressionArgument = 30; - public static readonly RULE_qualifiedName = 31; - public static readonly RULE_qualifiedNames = 32; - public static readonly RULE_identifier = 33; - public static readonly RULE_mathFunctionIdentifier = 34; - public static readonly RULE_functionIdentifier = 35; - public static readonly RULE_constant = 36; - public static readonly RULE_numericValue = 37; - public static readonly RULE_limitCommand = 38; - public static readonly RULE_sortCommand = 39; - public static readonly RULE_orderExpression = 40; - public static readonly RULE_projectCommand = 41; - public static readonly RULE_keepCommand = 42; - public static readonly RULE_dropCommand = 43; - public static readonly RULE_renameVariable = 44; - public static readonly RULE_renameCommand = 45; - public static readonly RULE_renameClause = 46; - public static readonly RULE_dissectCommand = 47; - public static readonly RULE_grokCommand = 48; - public static readonly RULE_commandOptions = 49; - public static readonly RULE_commandOption = 50; - public static readonly RULE_booleanValue = 51; - public static readonly RULE_number = 52; - public static readonly RULE_decimalValue = 53; - public static readonly RULE_integerValue = 54; - public static readonly RULE_string = 55; - public static readonly RULE_comparisonOperator = 56; - public static readonly RULE_explainCommand = 57; - public static readonly RULE_subqueryExpression = 58; - public static readonly RULE_showCommand = 59; + public static readonly RULE_whereCommand = 4; + public static readonly RULE_booleanExpression = 5; + public static readonly RULE_regexBooleanExpression = 6; + public static readonly RULE_valueExpression = 7; + public static readonly RULE_operatorExpression = 8; + public static readonly RULE_primaryExpression = 9; + public static readonly RULE_functionExpression = 10; + public static readonly RULE_rowCommand = 11; + public static readonly RULE_fields = 12; + public static readonly RULE_field = 13; + public static readonly RULE_fromCommand = 14; + public static readonly RULE_metadata = 15; + public static readonly RULE_evalCommand = 16; + public static readonly RULE_statsCommand = 17; + public static readonly RULE_grouping = 18; + public static readonly RULE_sourceIdentifier = 19; + public static readonly RULE_qualifiedName = 20; + public static readonly RULE_identifier = 21; + public static readonly RULE_constant = 22; + public static readonly RULE_limitCommand = 23; + public static readonly RULE_sortCommand = 24; + public static readonly RULE_orderExpression = 25; + public static readonly RULE_keepCommand = 26; + public static readonly RULE_dropCommand = 27; + public static readonly RULE_renameCommand = 28; + public static readonly RULE_renameClause = 29; + public static readonly RULE_dissectCommand = 30; + public static readonly RULE_grokCommand = 31; + public static readonly RULE_mvExpandCommand = 32; + public static readonly RULE_commandOptions = 33; + public static readonly RULE_commandOption = 34; + public static readonly RULE_booleanValue = 35; + public static readonly RULE_numericValue = 36; + public static readonly RULE_decimalValue = 37; + public static readonly RULE_integerValue = 38; + public static readonly RULE_string = 39; + public static readonly RULE_comparisonOperator = 40; + public static readonly RULE_showCommand = 41; + public static readonly RULE_enrichCommand = 42; + public static readonly RULE_enrichWithClause = 43; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ - "singleStatement", "query", "sourceCommand", "processingCommand", "enrichCommand", - "enrichWithClause", "mvExpandCommand", "whereCommand", "whereBooleanExpression", - "booleanExpression", "regexBooleanExpression", "valueExpression", "comparison", - "mathFn", "mathEvalFn", "dateExpression", "operatorExpression", "primaryExpression", - "rowCommand", "fields", "field", "enrichFieldIdentifier", "userVariable", - "fromCommand", "metadata", "evalCommand", "statsCommand", "sourceIdentifier", - "enrichIdentifier", "functionExpressionArgument", "mathFunctionExpressionArgument", - "qualifiedName", "qualifiedNames", "identifier", "mathFunctionIdentifier", - "functionIdentifier", "constant", "numericValue", "limitCommand", "sortCommand", - "orderExpression", "projectCommand", "keepCommand", "dropCommand", "renameVariable", - "renameCommand", "renameClause", "dissectCommand", "grokCommand", "commandOptions", - "commandOption", "booleanValue", "number", "decimalValue", "integerValue", - "string", "comparisonOperator", "explainCommand", "subqueryExpression", - "showCommand", + "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", + "booleanExpression", "regexBooleanExpression", "valueExpression", "operatorExpression", + "primaryExpression", "functionExpression", "rowCommand", "fields", "field", + "fromCommand", "metadata", "evalCommand", "statsCommand", "grouping", + "sourceIdentifier", "qualifiedName", "identifier", "constant", "limitCommand", + "sortCommand", "orderExpression", "keepCommand", "dropCommand", "renameCommand", + "renameClause", "dissectCommand", "grokCommand", "mvExpandCommand", "commandOptions", + "commandOption", "booleanValue", "numericValue", "decimalValue", "integerValue", + "string", "comparisonOperator", "showCommand", "enrichCommand", "enrichWithClause", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -191,27 +165,25 @@ export class esql_parser extends Parser { undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, - "'by'", undefined, "'and'", undefined, undefined, "'.'", "'('", undefined, - "']'", undefined, undefined, undefined, undefined, undefined, undefined, - undefined, "'or'", "')'", "'_'", "'info'", "'functions'", undefined, undefined, - "'+'", "'-'", "'*'", "'/'", "'%'", "'10'", undefined, "'nulls'", + undefined, undefined, undefined, "'.'", undefined, undefined, undefined, + "'('", undefined, undefined, undefined, undefined, undefined, undefined, + undefined, "'?'", undefined, "')'", undefined, undefined, undefined, "'_'", + "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'+'", "'-'", "'*'", "'/'", + "'%'", undefined, "']'", ]; private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "DISSECT", "GROK", "EVAL", "EXPLAIN", "FROM", "ROW", "STATS", - "WHERE", "SORT", "MV_EXPAND", "LIMIT", "PROJECT", "DROP", "RENAME", "SHOW", - "ENRICH", "KEEP", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "EXPLAIN_WS", - "EXPLAIN_LINE_COMMENT", "EXPLAIN_MULTILINE_COMMENT", "PIPE", "STRING", - "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "DATE_LITERAL", "AND", "ASSIGN", - "COMMA", "DOT", "LP", "OPENING_BRACKET", "CLOSING_BRACKET", "NOT", "LIKE", - "RLIKE", "IN", "IS", "AS", "NULL", "OR", "RP", "UNDERSCORE", "INFO", "FUNCTIONS", - "BOOLEAN_VALUE", "COMPARISON_OPERATOR", "PLUS", "MINUS", "ASTERISK", "SLASH", - "PERCENT", "TEN", "ORDERING", "NULLS_ORDERING", "NULLS_ORDERING_DIRECTION", - "MATH_FUNCTION", "UNARY_FUNCTION", "WHERE_FUNCTIONS", "UNQUOTED_IDENTIFIER", - "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "METADATA", "SRC_UNQUOTED_IDENTIFIER", "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", - "SRC_MULTILINE_COMMENT", "SRC_WS", "ON", "WITH", "ENR_UNQUOTED_IDENTIFIER", - "ENR_QUOTED_IDENTIFIER", "ENR_LINE_COMMENT", "ENR_MULTILINE_COMMENT", - "ENR_WS", "EXPLAIN_PIPE", + undefined, "DISSECT", "DROP", "ENRICH", "EVAL", "FROM", "GROK", "KEEP", + "LIMIT", "MV_EXPAND", "PROJECT", "RENAME", "ROW", "SHOW", "SORT", "STATS", + "WHERE", "UNKNOWN_CMD", "LINE_COMMENT", "MULTILINE_COMMENT", "WS", "PIPE", + "STRING", "INTEGER_LITERAL", "DECIMAL_LITERAL", "BY", "AND", "ASC", "ASSIGN", + "COMMA", "DESC", "DOT", "FALSE", "FIRST", "LAST", "LP", "IN", "IS", "LIKE", + "NOT", "NULL", "NULLS", "OR", "PARAM", "RLIKE", "RP", "TRUE", "INFO", + "FUNCTIONS", "UNDERSCORE", "EQ", "NEQ", "LT", "LTE", "GT", "GTE", "PLUS", + "MINUS", "ASTERISK", "SLASH", "PERCENT", "OPENING_BRACKET", "CLOSING_BRACKET", + "UNQUOTED_IDENTIFIER", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", + "EXPR_WS", "AS", "METADATA", "ON", "WITH", "SRC_UNQUOTED_IDENTIFIER", + "SRC_QUOTED_IDENTIFIER", "SRC_LINE_COMMENT", "SRC_MULTILINE_COMMENT", + "SRC_WS", ]; public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(esql_parser._LITERAL_NAMES, esql_parser._SYMBOLIC_NAMES, []); @@ -242,9 +214,9 @@ export class esql_parser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 120; + this.state = 88; this.query(0); - this.state = 121; + this.state = 89; this.match(esql_parser.EOF); } } @@ -286,11 +258,11 @@ export class esql_parser extends Parser { this._ctx = _localctx; _prevctx = _localctx; - this.state = 124; + this.state = 92; this.sourceCommand(); } this._ctx._stop = this._input.tryLT(-1); - this.state = 131; + this.state = 99; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -303,18 +275,18 @@ export class esql_parser extends Parser { { _localctx = new CompositeQueryContext(new QueryContext(_parentctx, _parentState)); this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_query); - this.state = 126; + this.state = 94; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 127; + this.state = 95; this.match(esql_parser.PIPE); - this.state = 128; + this.state = 96; this.processingCommand(); } } } - this.state = 133; + this.state = 101; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 0, this._ctx); } @@ -339,34 +311,27 @@ export class esql_parser extends Parser { let _localctx: SourceCommandContext = new SourceCommandContext(this._ctx, this.state); this.enterRule(_localctx, 4, esql_parser.RULE_sourceCommand); try { - this.state = 138; + this.state = 105; this._errHandler.sync(this); switch (this._input.LA(1)) { - case esql_parser.EXPLAIN: - this.enterOuterAlt(_localctx, 1); - { - this.state = 134; - this.explainCommand(); - } - break; case esql_parser.FROM: - this.enterOuterAlt(_localctx, 2); + this.enterOuterAlt(_localctx, 1); { - this.state = 135; + this.state = 102; this.fromCommand(); } break; case esql_parser.ROW: - this.enterOuterAlt(_localctx, 3); + this.enterOuterAlt(_localctx, 2); { - this.state = 136; + this.state = 103; this.rowCommand(); } break; case esql_parser.SHOW: - this.enterOuterAlt(_localctx, 4); + this.enterOuterAlt(_localctx, 3); { - this.state = 137; + this.state = 104; this.showCommand(); } break; @@ -393,100 +358,94 @@ export class esql_parser extends Parser { let _localctx: ProcessingCommandContext = new ProcessingCommandContext(this._ctx, this.state); this.enterRule(_localctx, 6, esql_parser.RULE_processingCommand); try { - this.state = 153; + this.state = 119; this._errHandler.sync(this); switch (this._input.LA(1)) { case esql_parser.EVAL: this.enterOuterAlt(_localctx, 1); { - this.state = 140; + this.state = 107; this.evalCommand(); } break; case esql_parser.LIMIT: this.enterOuterAlt(_localctx, 2); { - this.state = 141; + this.state = 108; this.limitCommand(); } break; + case esql_parser.KEEP: case esql_parser.PROJECT: this.enterOuterAlt(_localctx, 3); { - this.state = 142; - this.projectCommand(); + this.state = 109; + this.keepCommand(); } break; - case esql_parser.KEEP: + case esql_parser.SORT: this.enterOuterAlt(_localctx, 4); { - this.state = 143; - this.keepCommand(); + this.state = 110; + this.sortCommand(); } break; - case esql_parser.RENAME: + case esql_parser.STATS: this.enterOuterAlt(_localctx, 5); { - this.state = 144; - this.renameCommand(); + this.state = 111; + this.statsCommand(); } break; - case esql_parser.DROP: + case esql_parser.WHERE: this.enterOuterAlt(_localctx, 6); { - this.state = 145; - this.dropCommand(); + this.state = 112; + this.whereCommand(); } break; - case esql_parser.DISSECT: + case esql_parser.DROP: this.enterOuterAlt(_localctx, 7); { - this.state = 146; - this.dissectCommand(); + this.state = 113; + this.dropCommand(); } break; - case esql_parser.GROK: + case esql_parser.RENAME: this.enterOuterAlt(_localctx, 8); { - this.state = 147; - this.grokCommand(); + this.state = 114; + this.renameCommand(); } break; - case esql_parser.SORT: + case esql_parser.DISSECT: this.enterOuterAlt(_localctx, 9); { - this.state = 148; - this.sortCommand(); + this.state = 115; + this.dissectCommand(); } break; - case esql_parser.STATS: + case esql_parser.GROK: this.enterOuterAlt(_localctx, 10); { - this.state = 149; - this.statsCommand(); + this.state = 116; + this.grokCommand(); } break; - case esql_parser.WHERE: + case esql_parser.ENRICH: this.enterOuterAlt(_localctx, 11); { - this.state = 150; - this.whereCommand(); + this.state = 117; + this.enrichCommand(); } break; case esql_parser.MV_EXPAND: this.enterOuterAlt(_localctx, 12); { - this.state = 151; + this.state = 118; this.mvExpandCommand(); } break; - case esql_parser.ENRICH: - this.enterOuterAlt(_localctx, 13); - { - this.state = 152; - this.enrichCommand(); - } - break; default: throw new NoViableAltException(this); } @@ -506,150 +465,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichCommand(): EnrichCommandContext { - let _localctx: EnrichCommandContext = new EnrichCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 8, esql_parser.RULE_enrichCommand); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 155; - this.match(esql_parser.ENRICH); - this.state = 156; - _localctx._policyName = this.enrichIdentifier(); - this.state = 159; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 3, this._ctx) ) { - case 1: - { - this.state = 157; - this.match(esql_parser.ON); - this.state = 158; - _localctx._matchField = this.enrichFieldIdentifier(); - } - break; - } - this.state = 170; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 5, this._ctx) ) { - case 1: - { - this.state = 161; - this.match(esql_parser.WITH); - this.state = 162; - this.enrichWithClause(); - this.state = 167; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 163; - this.match(esql_parser.COMMA); - this.state = 164; - this.enrichWithClause(); - } - } - } - this.state = 169; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 4, this._ctx); - } - } - break; - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public enrichWithClause(): EnrichWithClauseContext { - let _localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this._ctx, this.state); - this.enterRule(_localctx, 10, esql_parser.RULE_enrichWithClause); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 175; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) { - case 1: - { - this.state = 172; - _localctx._newName = this.enrichFieldIdentifier(); - this.state = 173; - this.match(esql_parser.ASSIGN); - } - break; - } - this.state = 177; - _localctx._enrichField = this.enrichFieldIdentifier(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mvExpandCommand(): MvExpandCommandContext { - let _localctx: MvExpandCommandContext = new MvExpandCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 12, esql_parser.RULE_mvExpandCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 179; - this.match(esql_parser.MV_EXPAND); - this.state = 180; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public whereCommand(): WhereCommandContext { let _localctx: WhereCommandContext = new WhereCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 14, esql_parser.RULE_whereCommand); + this.enterRule(_localctx, 8, esql_parser.RULE_whereCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 182; + this.state = 121; this.match(esql_parser.WHERE); - this.state = 183; - this.whereBooleanExpression(0); + this.state = 122; + this.booleanExpression(0); } } catch (re) { @@ -667,164 +492,133 @@ export class esql_parser extends Parser { return _localctx; } - public whereBooleanExpression(): WhereBooleanExpressionContext; - public whereBooleanExpression(_p: number): WhereBooleanExpressionContext; + public booleanExpression(): BooleanExpressionContext; + public booleanExpression(_p: number): BooleanExpressionContext; // @RuleVersion(0) - public whereBooleanExpression(_p?: number): WhereBooleanExpressionContext { + public booleanExpression(_p?: number): BooleanExpressionContext { if (_p === undefined) { _p = 0; } let _parentctx: ParserRuleContext = this._ctx; let _parentState: number = this.state; - let _localctx: WhereBooleanExpressionContext = new WhereBooleanExpressionContext(this._ctx, _parentState); - let _prevctx: WhereBooleanExpressionContext = _localctx; - let _startState: number = 16; - this.enterRecursionRule(_localctx, 16, esql_parser.RULE_whereBooleanExpression, _p); + let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); + let _prevctx: BooleanExpressionContext = _localctx; + let _startState: number = 10; + this.enterRecursionRule(_localctx, 10, esql_parser.RULE_booleanExpression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 230; + this.state = 152; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 6, this._ctx) ) { case 1: { - this.state = 186; + _localctx = new LogicalNotContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + + this.state = 125; this.match(esql_parser.NOT); - this.state = 187; - this.whereBooleanExpression(8); + this.state = 126; + this.booleanExpression(7); } break; case 2: { - this.state = 188; + _localctx = new BooleanDefaultContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 127; this.valueExpression(); } break; case 3: { - this.state = 189; + _localctx = new RegexExpressionContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 128; this.regexBooleanExpression(); } break; case 4: { - this.state = 190; + _localctx = new LogicalInContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 129; this.valueExpression(); - this.state = 192; + this.state = 131; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 191; + this.state = 130; this.match(esql_parser.NOT); } } - this.state = 194; + this.state = 133; this.match(esql_parser.IN); - this.state = 195; + this.state = 134; this.match(esql_parser.LP); - this.state = 196; + this.state = 135; this.valueExpression(); - this.state = 201; + this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 197; + this.state = 136; this.match(esql_parser.COMMA); - this.state = 198; + this.state = 137; this.valueExpression(); } } - this.state = 203; + this.state = 142; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 204; + this.state = 143; this.match(esql_parser.RP); } break; case 5: { - this.state = 207; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === esql_parser.NOT) { - { - this.state = 206; - this.match(esql_parser.NOT); - } - } - - this.state = 209; - this.match(esql_parser.WHERE_FUNCTIONS); - this.state = 210; - this.match(esql_parser.LP); - this.state = 211; - this.qualifiedName(); - this.state = 219; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) { - case 1: - { - this.state = 216; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 212; - this.match(esql_parser.COMMA); - this.state = 213; - this.functionExpressionArgument(); - } - } - this.state = 218; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - break; - } - this.state = 221; - this.match(esql_parser.RP); - } - break; - - case 6: - { - this.state = 223; + _localctx = new IsNullContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 145; this.valueExpression(); - this.state = 224; + this.state = 146; this.match(esql_parser.IS); - this.state = 226; + this.state = 148; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 225; + this.state = 147; this.match(esql_parser.NOT); } } - this.state = 228; + this.state = 150; this.match(esql_parser.NULL); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 240; + this.state = 162; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 8, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -832,46 +626,46 @@ export class esql_parser extends Parser { } _prevctx = _localctx; { - this.state = 238; + this.state = 160; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 7, this._ctx) ) { case 1: { - _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); - this.state = 232; - if (!(this.precpred(this._ctx, 5))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 5)"); + _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); + (_localctx as LogicalBinaryContext)._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 154; + if (!(this.precpred(this._ctx, 4))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 4)"); } - this.state = 233; - _localctx._operator = this.match(esql_parser.AND); - this.state = 234; - _localctx._right = this.whereBooleanExpression(6); + this.state = 155; + (_localctx as LogicalBinaryContext)._operator = this.match(esql_parser.AND); + this.state = 156; + (_localctx as LogicalBinaryContext)._right = this.booleanExpression(5); } break; case 2: { - _localctx = new WhereBooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_whereBooleanExpression); - this.state = 235; - if (!(this.precpred(this._ctx, 4))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 4)"); + _localctx = new LogicalBinaryContext(new BooleanExpressionContext(_parentctx, _parentState)); + (_localctx as LogicalBinaryContext)._left = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); + this.state = 157; + if (!(this.precpred(this._ctx, 3))) { + throw new FailedPredicateException(this, "this.precpred(this._ctx, 3)"); } - this.state = 236; - _localctx._operator = this.match(esql_parser.OR); - this.state = 237; - _localctx._right = this.whereBooleanExpression(5); + this.state = 158; + (_localctx as LogicalBinaryContext)._operator = this.match(esql_parser.OR); + this.state = 159; + (_localctx as LogicalBinaryContext)._right = this.booleanExpression(4); } break; } } } - this.state = 242; + this.state = 164; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 8, this._ctx); } } } @@ -889,153 +683,33 @@ export class esql_parser extends Parser { } return _localctx; } - - public booleanExpression(): BooleanExpressionContext; - public booleanExpression(_p: number): BooleanExpressionContext; // @RuleVersion(0) - public booleanExpression(_p?: number): BooleanExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let _parentctx: ParserRuleContext = this._ctx; - let _parentState: number = this.state; - let _localctx: BooleanExpressionContext = new BooleanExpressionContext(this._ctx, _parentState); - let _prevctx: BooleanExpressionContext = _localctx; - let _startState: number = 18; - this.enterRecursionRule(_localctx, 18, esql_parser.RULE_booleanExpression, _p); + public regexBooleanExpression(): RegexBooleanExpressionContext { + let _localctx: RegexBooleanExpressionContext = new RegexBooleanExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 12, esql_parser.RULE_regexBooleanExpression); + let _la: number; try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 247; + this.state = 179; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.NOT: + switch ( this.interpreter.adaptivePredict(this._input, 11, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); { - this.state = 244; - this.match(esql_parser.NOT); - this.state = 245; - this.booleanExpression(4); - } - break; - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.OPENING_BRACKET: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.PLUS: - case esql_parser.MINUS: - case esql_parser.ASTERISK: - case esql_parser.MATH_FUNCTION: - case esql_parser.UNARY_FUNCTION: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: - { - this.state = 246; - this.valueExpression(); - } - break; - default: - throw new NoViableAltException(this); - } - this._ctx._stop = this._input.tryLT(-1); - this.state = 257; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - _prevctx = _localctx; - { - this.state = 255; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { - case 1: - { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 249; - if (!(this.precpred(this._ctx, 2))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); - } - this.state = 250; - _localctx._operator = this.match(esql_parser.AND); - this.state = 251; - _localctx._right = this.booleanExpression(3); - } - break; - - case 2: - { - _localctx = new BooleanExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; - this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 252; - if (!(this.precpred(this._ctx, 1))) { - throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); - } - this.state = 253; - _localctx._operator = this.match(esql_parser.OR); - this.state = 254; - _localctx._right = this.booleanExpression(2); - } - break; - } - } - } - this.state = 259; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.unrollRecursionContexts(_parentctx); - } - return _localctx; - } - // @RuleVersion(0) - public regexBooleanExpression(): RegexBooleanExpressionContext { - let _localctx: RegexBooleanExpressionContext = new RegexBooleanExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 20, esql_parser.RULE_regexBooleanExpression); - let _la: number; - try { - this.state = 274; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 21, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 260; + this.state = 165; this.valueExpression(); - this.state = 262; + this.state = 167; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 261; + this.state = 166; this.match(esql_parser.NOT); } } - this.state = 264; + this.state = 169; _localctx._kind = this.match(esql_parser.LIKE); - this.state = 265; + this.state = 170; _localctx._pattern = this.string(); } break; @@ -1043,21 +717,21 @@ export class esql_parser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 267; + this.state = 172; this.valueExpression(); - this.state = 269; + this.state = 174; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === esql_parser.NOT) { { - this.state = 268; + this.state = 173; this.match(esql_parser.NOT); } } - this.state = 271; + this.state = 176; _localctx._kind = this.match(esql_parser.RLIKE); - this.state = 272; + this.state = 177; _localctx._pattern = this.string(); } break; @@ -1080,24 +754,30 @@ export class esql_parser extends Parser { // @RuleVersion(0) public valueExpression(): ValueExpressionContext { let _localctx: ValueExpressionContext = new ValueExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 22, esql_parser.RULE_valueExpression); + this.enterRule(_localctx, 14, esql_parser.RULE_valueExpression); try { - this.state = 278; + this.state = 186; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 22, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: + _localctx = new ValueExpressionDefaultContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 276; + this.state = 181; this.operatorExpression(0); } break; case 2: + _localctx = new ComparisonContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 277; - this.comparison(); + this.state = 182; + (_localctx as ComparisonContext)._left = this.operatorExpression(0); + this.state = 183; + this.comparisonOperator(); + this.state = 184; + (_localctx as ComparisonContext)._right = this.operatorExpression(0); } break; } @@ -1116,174 +796,6 @@ export class esql_parser extends Parser { } return _localctx; } - // @RuleVersion(0) - public comparison(): ComparisonContext { - let _localctx: ComparisonContext = new ComparisonContext(this._ctx, this.state); - this.enterRule(_localctx, 24, esql_parser.RULE_comparison); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 280; - _localctx._left = this.operatorExpression(0); - this.state = 281; - this.comparisonOperator(); - this.state = 282; - _localctx._right = this.operatorExpression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathFn(): MathFnContext { - let _localctx: MathFnContext = new MathFnContext(this._ctx, this.state); - this.enterRule(_localctx, 26, esql_parser.RULE_mathFn); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 284; - this.functionIdentifier(); - this.state = 285; - this.match(esql_parser.LP); - this.state = 294; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0)) { - { - this.state = 286; - this.functionExpressionArgument(); - this.state = 291; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 287; - this.match(esql_parser.COMMA); - this.state = 288; - this.functionExpressionArgument(); - } - } - this.state = 293; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 296; - this.match(esql_parser.RP); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathEvalFn(): MathEvalFnContext { - let _localctx: MathEvalFnContext = new MathEvalFnContext(this._ctx, this.state); - this.enterRule(_localctx, 28, esql_parser.RULE_mathEvalFn); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 298; - this.mathFunctionIdentifier(); - this.state = 299; - this.match(esql_parser.LP); - this.state = 308; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { - { - this.state = 300; - this.mathFunctionExpressionArgument(); - this.state = 305; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 301; - this.match(esql_parser.COMMA); - this.state = 302; - this.mathFunctionExpressionArgument(); - } - } - this.state = 307; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 310; - this.match(esql_parser.RP); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public dateExpression(): DateExpressionContext { - let _localctx: DateExpressionContext = new DateExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 30, esql_parser.RULE_dateExpression); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 312; - _localctx._quantifier = this.number(); - this.state = 313; - this.match(esql_parser.DATE_LITERAL); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } public operatorExpression(): OperatorExpressionContext; public operatorExpression(_p: number): OperatorExpressionContext; @@ -1297,51 +809,37 @@ export class esql_parser extends Parser { let _parentState: number = this.state; let _localctx: OperatorExpressionContext = new OperatorExpressionContext(this._ctx, _parentState); let _prevctx: OperatorExpressionContext = _localctx; - let _startState: number = 32; - this.enterRecursionRule(_localctx, 32, esql_parser.RULE_operatorExpression, _p); + let _startState: number = 16; + this.enterRecursionRule(_localctx, 16, esql_parser.RULE_operatorExpression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 321; + this.state = 192; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.STRING: - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - case esql_parser.LP: - case esql_parser.OPENING_BRACKET: - case esql_parser.NULL: - case esql_parser.BOOLEAN_VALUE: - case esql_parser.ASTERISK: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: + switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { + case 1: { - this.state = 316; + _localctx = new OperatorExpressionDefaultContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + + this.state = 189; this.primaryExpression(); } break; - case esql_parser.UNARY_FUNCTION: - { - this.state = 317; - this.mathFn(); - } - break; - case esql_parser.MATH_FUNCTION: - { - this.state = 318; - this.mathEvalFn(); - } - break; - case esql_parser.PLUS: - case esql_parser.MINUS: + + case 2: { - this.state = 319; - _localctx._operator = this._input.LT(1); + _localctx = new ArithmeticUnaryContext(_localctx); + this._ctx = _localctx; + _prevctx = _localctx; + this.state = 190; + (_localctx as ArithmeticUnaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); + (_localctx as ArithmeticUnaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1350,17 +848,15 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 320; + this.state = 191; this.operatorExpression(3); } break; - default: - throw new NoViableAltException(this); } this._ctx._stop = this._input.tryLT(-1); - this.state = 331; + this.state = 202; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -1368,23 +864,23 @@ export class esql_parser extends Parser { } _prevctx = _localctx; { - this.state = 329; + this.state = 200; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 28, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { case 1: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); + (_localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 323; + this.state = 194; if (!(this.precpred(this._ctx, 2))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 2)"); } - this.state = 324; - _localctx._operator = this._input.LT(1); + this.state = 195; + (_localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); - if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.SLASH - 53)) | (1 << (esql_parser.PERCENT - 53)))) !== 0))) { - _localctx._operator = this._errHandler.recoverInline(this); + if (!(((((_la - 58)) & ~0x1F) === 0 && ((1 << (_la - 58)) & ((1 << (esql_parser.ASTERISK - 58)) | (1 << (esql_parser.SLASH - 58)) | (1 << (esql_parser.PERCENT - 58)))) !== 0))) { + (_localctx as ArithmeticBinaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1393,25 +889,25 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 325; - _localctx._right = this.operatorExpression(3); + this.state = 196; + (_localctx as ArithmeticBinaryContext)._right = this.operatorExpression(3); } break; case 2: { - _localctx = new OperatorExpressionContext(_parentctx, _parentState); - _localctx._left = _prevctx; + _localctx = new ArithmeticBinaryContext(new OperatorExpressionContext(_parentctx, _parentState)); + (_localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(_localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 326; + this.state = 197; if (!(this.precpred(this._ctx, 1))) { throw new FailedPredicateException(this, "this.precpred(this._ctx, 1)"); } - this.state = 327; - _localctx._operator = this._input.LT(1); + this.state = 198; + (_localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { - _localctx._operator = this._errHandler.recoverInline(this); + (_localctx as ArithmeticBinaryContext)._operator = this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { this.matchedEOF = true; @@ -1420,16 +916,16 @@ export class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 328; - _localctx._right = this.operatorExpression(2); + this.state = 199; + (_localctx as ArithmeticBinaryContext)._right = this.operatorExpression(2); } break; } } } - this.state = 333; + this.state = 204; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 29, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 15, this._ctx); } } } @@ -1450,85 +946,131 @@ export class esql_parser extends Parser { // @RuleVersion(0) public primaryExpression(): PrimaryExpressionContext { let _localctx: PrimaryExpressionContext = new PrimaryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 34, esql_parser.RULE_primaryExpression); - let _la: number; + this.enterRule(_localctx, 18, esql_parser.RULE_primaryExpression); try { - this.state = 355; + this.state = 212; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 32, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 16, this._ctx) ) { case 1: + _localctx = new ConstantDefaultContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 334; + this.state = 205; this.constant(); } break; case 2: + _localctx = new DereferenceContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 335; + this.state = 206; this.qualifiedName(); } break; case 3: + _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 336; - this.dateExpression(); + this.state = 207; + this.functionExpression(); } break; case 4: + _localctx = new ParenthesizedExpressionContext(_localctx); this.enterOuterAlt(_localctx, 4); { - this.state = 337; + this.state = 208; this.match(esql_parser.LP); - this.state = 338; + this.state = 209; this.booleanExpression(0); - this.state = 339; + this.state = 210; this.match(esql_parser.RP); } break; - - case 5: - this.enterOuterAlt(_localctx, 5); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public functionExpression(): FunctionExpressionContext { + let _localctx: FunctionExpressionContext = new FunctionExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 20, esql_parser.RULE_functionExpression); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 214; + this.identifier(); + this.state = 215; + this.match(esql_parser.LP); + this.state = 225; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.ASTERISK: { - this.state = 341; - this.identifier(); - this.state = 342; - this.match(esql_parser.LP); - this.state = 351; + this.state = 216; + this.match(esql_parser.ASTERISK); + } + break; + case esql_parser.STRING: + case esql_parser.INTEGER_LITERAL: + case esql_parser.DECIMAL_LITERAL: + case esql_parser.FALSE: + case esql_parser.LP: + case esql_parser.NOT: + case esql_parser.NULL: + case esql_parser.PARAM: + case esql_parser.TRUE: + case esql_parser.PLUS: + case esql_parser.MINUS: + case esql_parser.OPENING_BRACKET: + case esql_parser.UNQUOTED_IDENTIFIER: + case esql_parser.QUOTED_IDENTIFIER: + { + { + this.state = 217; + this.booleanExpression(0); + this.state = 222; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << esql_parser.STRING) | (1 << esql_parser.INTEGER_LITERAL) | (1 << esql_parser.DECIMAL_LITERAL))) !== 0) || ((((_la - 34)) & ~0x1F) === 0 && ((1 << (_la - 34)) & ((1 << (esql_parser.LP - 34)) | (1 << (esql_parser.OPENING_BRACKET - 34)) | (1 << (esql_parser.NOT - 34)) | (1 << (esql_parser.NULL - 34)) | (1 << (esql_parser.BOOLEAN_VALUE - 34)) | (1 << (esql_parser.PLUS - 34)) | (1 << (esql_parser.MINUS - 34)) | (1 << (esql_parser.ASTERISK - 34)) | (1 << (esql_parser.MATH_FUNCTION - 34)) | (1 << (esql_parser.UNARY_FUNCTION - 34)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 34)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 34)))) !== 0)) { + while (_la === esql_parser.COMMA) { { - this.state = 343; + { + this.state = 218; + this.match(esql_parser.COMMA); + this.state = 219; this.booleanExpression(0); - this.state = 348; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === esql_parser.COMMA) { - { - { - this.state = 344; - this.match(esql_parser.COMMA); - this.state = 345; - this.booleanExpression(0); - } - } - this.state = 350; - this._errHandler.sync(this); - _la = this._input.LA(1); } } + this.state = 224; + this._errHandler.sync(this); + _la = this._input.LA(1); + } } - - this.state = 353; - this.match(esql_parser.RP); } break; + case esql_parser.RP: + break; + default: + break; + } + this.state = 227; + this.match(esql_parser.RP); } } catch (re) { @@ -1548,13 +1090,13 @@ export class esql_parser extends Parser { // @RuleVersion(0) public rowCommand(): RowCommandContext { let _localctx: RowCommandContext = new RowCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 36, esql_parser.RULE_rowCommand); + this.enterRule(_localctx, 22, esql_parser.RULE_rowCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 357; + this.state = 229; this.match(esql_parser.ROW); - this.state = 358; + this.state = 230; this.fields(); } } @@ -1575,30 +1117,30 @@ export class esql_parser extends Parser { // @RuleVersion(0) public fields(): FieldsContext { let _localctx: FieldsContext = new FieldsContext(this._ctx, this.state); - this.enterRule(_localctx, 38, esql_parser.RULE_fields); + this.enterRule(_localctx, 24, esql_parser.RULE_fields); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 360; + this.state = 232; this.field(); - this.state = 365; + this.state = 237; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 361; + this.state = 233; this.match(esql_parser.COMMA); - this.state = 362; + this.state = 234; this.field(); } } } - this.state = 367; + this.state = 239; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 33, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); } } } @@ -1619,15 +1161,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public field(): FieldContext { let _localctx: FieldContext = new FieldContext(this._ctx, this.state); - this.enterRule(_localctx, 40, esql_parser.RULE_field); + this.enterRule(_localctx, 26, esql_parser.RULE_field); try { - this.state = 373; + this.state = 245; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 34, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 20, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 368; + this.state = 240; this.booleanExpression(0); } break; @@ -1635,11 +1177,11 @@ export class esql_parser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 369; - this.userVariable(); - this.state = 370; + this.state = 241; + this.qualifiedName(); + this.state = 242; this.match(esql_parser.ASSIGN); - this.state = 371; + this.state = 243; this.booleanExpression(0); } break; @@ -1660,102 +1202,41 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichFieldIdentifier(): EnrichFieldIdentifierContext { - let _localctx: EnrichFieldIdentifierContext = new EnrichFieldIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 42, esql_parser.RULE_enrichFieldIdentifier); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 375; - _la = this._input.LA(1); - if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public userVariable(): UserVariableContext { - let _localctx: UserVariableContext = new UserVariableContext(this._ctx, this.state); - this.enterRule(_localctx, 44, esql_parser.RULE_userVariable); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 377; - this.identifier(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public fromCommand(): FromCommandContext { let _localctx: FromCommandContext = new FromCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 46, esql_parser.RULE_fromCommand); + this.enterRule(_localctx, 28, esql_parser.RULE_fromCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 379; + this.state = 247; this.match(esql_parser.FROM); - this.state = 380; + this.state = 248; this.sourceIdentifier(); - this.state = 385; + this.state = 253; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 381; + this.state = 249; this.match(esql_parser.COMMA); - this.state = 382; + this.state = 250; this.sourceIdentifier(); } } } - this.state = 387; + this.state = 255; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 21, this._ctx); } - this.state = 389; + this.state = 257; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 36, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 22, this._ctx) ) { case 1: { - this.state = 388; + this.state = 256; this.metadata(); } break; @@ -1779,34 +1260,34 @@ export class esql_parser extends Parser { // @RuleVersion(0) public metadata(): MetadataContext { let _localctx: MetadataContext = new MetadataContext(this._ctx, this.state); - this.enterRule(_localctx, 48, esql_parser.RULE_metadata); + this.enterRule(_localctx, 30, esql_parser.RULE_metadata); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 391; + this.state = 259; this.match(esql_parser.OPENING_BRACKET); - this.state = 392; + this.state = 260; this.match(esql_parser.METADATA); - this.state = 393; + this.state = 261; this.sourceIdentifier(); - this.state = 398; + this.state = 266; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 394; + this.state = 262; this.match(esql_parser.COMMA); - this.state = 395; + this.state = 263; this.sourceIdentifier(); } } - this.state = 400; + this.state = 268; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 401; + this.state = 269; this.match(esql_parser.CLOSING_BRACKET); } } @@ -1827,13 +1308,13 @@ export class esql_parser extends Parser { // @RuleVersion(0) public evalCommand(): EvalCommandContext { let _localctx: EvalCommandContext = new EvalCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 50, esql_parser.RULE_evalCommand); + this.enterRule(_localctx, 32, esql_parser.RULE_evalCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 403; + this.state = 271; this.match(esql_parser.EVAL); - this.state = 404; + this.state = 272; this.fields(); } } @@ -1854,31 +1335,31 @@ export class esql_parser extends Parser { // @RuleVersion(0) public statsCommand(): StatsCommandContext { let _localctx: StatsCommandContext = new StatsCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 52, esql_parser.RULE_statsCommand); + this.enterRule(_localctx, 34, esql_parser.RULE_statsCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 406; + this.state = 274; this.match(esql_parser.STATS); - this.state = 408; + this.state = 276; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 38, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 24, this._ctx) ) { case 1: { - this.state = 407; + this.state = 275; this.fields(); } break; } - this.state = 412; + this.state = 280; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 25, this._ctx) ) { case 1: { - this.state = 410; + this.state = 278; this.match(esql_parser.BY); - this.state = 411; - this.qualifiedNames(); + this.state = 279; + this.grouping(); } break; } @@ -1899,24 +1380,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public sourceIdentifier(): SourceIdentifierContext { - let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 54, esql_parser.RULE_sourceIdentifier); - let _la: number; + public grouping(): GroupingContext { + let _localctx: GroupingContext = new GroupingContext(this._ctx, this.state); + this.enterRule(_localctx, 36, esql_parser.RULE_grouping); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 414; - _la = this._input.LA(1); - if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; + this.state = 282; + this.qualifiedName(); + this.state = 287; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 283; + this.match(esql_parser.COMMA); + this.state = 284; + this.qualifiedName(); + } + } } - - this._errHandler.reportMatch(this); - this.consume(); + this.state = 289; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 26, this._ctx); } } } @@ -1935,16 +1424,16 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public enrichIdentifier(): EnrichIdentifierContext { - let _localctx: EnrichIdentifierContext = new EnrichIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 56, esql_parser.RULE_enrichIdentifier); + public sourceIdentifier(): SourceIdentifierContext { + let _localctx: SourceIdentifierContext = new SourceIdentifierContext(this._ctx, this.state); + this.enterRule(_localctx, 38, esql_parser.RULE_sourceIdentifier); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 416; + this.state = 290; _la = this._input.LA(1); - if (!(_la === esql_parser.ENR_UNQUOTED_IDENTIFIER || _la === esql_parser.ENR_QUOTED_IDENTIFIER)) { + if (!(_la === esql_parser.SRC_UNQUOTED_IDENTIFIER || _la === esql_parser.SRC_QUOTED_IDENTIFIER)) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -1971,197 +1460,32 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public functionExpressionArgument(): FunctionExpressionArgumentContext { - let _localctx: FunctionExpressionArgumentContext = new FunctionExpressionArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 58, esql_parser.RULE_functionExpressionArgument); - try { - this.state = 421; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.ASTERISK: - case esql_parser.UNQUOTED_IDENTIFIER: - case esql_parser.QUOTED_IDENTIFIER: - this.enterOuterAlt(_localctx, 1); - { - this.state = 418; - this.qualifiedName(); - } - break; - case esql_parser.STRING: - this.enterOuterAlt(_localctx, 2); - { - this.state = 419; - this.string(); - } - break; - case esql_parser.INTEGER_LITERAL: - case esql_parser.DECIMAL_LITERAL: - this.enterOuterAlt(_localctx, 3); - { - this.state = 420; - this.number(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext { - let _localctx: MathFunctionExpressionArgumentContext = new MathFunctionExpressionArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 60, esql_parser.RULE_mathFunctionExpressionArgument); - try { - this.state = 429; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 41, this._ctx) ) { - case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 423; - this.qualifiedName(); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); - { - this.state = 424; - this.string(); - } - break; - - case 3: - this.enterOuterAlt(_localctx, 3); - { - this.state = 425; - this.number(); - } - break; - - case 4: - this.enterOuterAlt(_localctx, 4); - { - this.state = 426; - this.operatorExpression(0); - } - break; - - case 5: - this.enterOuterAlt(_localctx, 5); - { - this.state = 427; - this.dateExpression(); - } - break; - - case 6: - this.enterOuterAlt(_localctx, 6); - { - this.state = 428; - this.comparison(); - } - break; - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public qualifiedName(): QualifiedNameContext { let _localctx: QualifiedNameContext = new QualifiedNameContext(this._ctx, this.state); - this.enterRule(_localctx, 62, esql_parser.RULE_qualifiedName); + this.enterRule(_localctx, 40, esql_parser.RULE_qualifiedName); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 431; + this.state = 292; this.identifier(); - this.state = 436; + this.state = 297; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 27, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 432; + this.state = 293; this.match(esql_parser.DOT); - this.state = 433; + this.state = 294; this.identifier(); } } } - this.state = 438; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 42, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public qualifiedNames(): QualifiedNamesContext { - let _localctx: QualifiedNamesContext = new QualifiedNamesContext(this._ctx, this.state); - this.enterRule(_localctx, 64, esql_parser.RULE_qualifiedNames); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 439; - this.qualifiedName(); - this.state = 444; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 440; - this.match(esql_parser.COMMA); - this.state = 441; - this.qualifiedName(); - } - } - } - this.state = 446; + this.state = 299; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 43, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 27, this._ctx); } } } @@ -2182,14 +1506,14 @@ export class esql_parser extends Parser { // @RuleVersion(0) public identifier(): IdentifierContext { let _localctx: IdentifierContext = new IdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 66, esql_parser.RULE_identifier); + this.enterRule(_localctx, 42, esql_parser.RULE_identifier); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 447; + this.state = 300; _la = this._input.LA(1); - if (!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & ((1 << (esql_parser.ASTERISK - 53)) | (1 << (esql_parser.UNQUOTED_IDENTIFIER - 53)) | (1 << (esql_parser.QUOTED_IDENTIFIER - 53)))) !== 0))) { + if (!(_la === esql_parser.UNQUOTED_IDENTIFIER || _la === esql_parser.QUOTED_IDENTIFIER)) { this._errHandler.recoverInline(this); } else { if (this._input.LA(1) === Token.EOF) { @@ -2216,176 +1540,162 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public mathFunctionIdentifier(): MathFunctionIdentifierContext { - let _localctx: MathFunctionIdentifierContext = new MathFunctionIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 68, esql_parser.RULE_mathFunctionIdentifier); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 449; - this.match(esql_parser.MATH_FUNCTION); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public functionIdentifier(): FunctionIdentifierContext { - let _localctx: FunctionIdentifierContext = new FunctionIdentifierContext(this._ctx, this.state); - this.enterRule(_localctx, 70, esql_parser.RULE_functionIdentifier); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 451; - this.match(esql_parser.UNARY_FUNCTION); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 72, esql_parser.RULE_constant); + this.enterRule(_localctx, 44, esql_parser.RULE_constant); let _la: number; try { - this.state = 490; + this.state = 344; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 47, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 31, this._ctx) ) { case 1: + _localctx = new NullLiteralContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 453; + this.state = 302; this.match(esql_parser.NULL); } break; case 2: + _localctx = new QualifiedIntegerLiteralContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 454; - this.numericValue(); + this.state = 303; + this.integerValue(); + this.state = 304; + this.match(esql_parser.UNQUOTED_IDENTIFIER); } break; case 3: + _localctx = new DecimalLiteralContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 455; - this.booleanValue(); + this.state = 306; + this.decimalValue(); } break; case 4: + _localctx = new IntegerLiteralContext(_localctx); this.enterOuterAlt(_localctx, 4); { - this.state = 456; + this.state = 307; + this.integerValue(); + } + break; + + case 5: + _localctx = new BooleanLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 5); + { + this.state = 308; + this.booleanValue(); + } + break; + + case 6: + _localctx = new InputParamContext(_localctx); + this.enterOuterAlt(_localctx, 6); + { + this.state = 309; + this.match(esql_parser.PARAM); + } + break; + + case 7: + _localctx = new StringLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 7); + { + this.state = 310; this.string(); } break; - case 5: - this.enterOuterAlt(_localctx, 5); + case 8: + _localctx = new NumericArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 8); { - this.state = 457; + this.state = 311; this.match(esql_parser.OPENING_BRACKET); - this.state = 458; + this.state = 312; this.numericValue(); - this.state = 463; + this.state = 317; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 459; + this.state = 313; this.match(esql_parser.COMMA); - this.state = 460; + this.state = 314; this.numericValue(); } } - this.state = 465; + this.state = 319; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 466; + this.state = 320; this.match(esql_parser.CLOSING_BRACKET); } break; - case 6: - this.enterOuterAlt(_localctx, 6); + case 9: + _localctx = new BooleanArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 9); { - this.state = 468; + this.state = 322; this.match(esql_parser.OPENING_BRACKET); - this.state = 469; + this.state = 323; this.booleanValue(); - this.state = 474; + this.state = 328; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 470; + this.state = 324; this.match(esql_parser.COMMA); - this.state = 471; + this.state = 325; this.booleanValue(); } } - this.state = 476; + this.state = 330; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 477; + this.state = 331; this.match(esql_parser.CLOSING_BRACKET); } break; - case 7: - this.enterOuterAlt(_localctx, 7); + case 10: + _localctx = new StringArrayLiteralContext(_localctx); + this.enterOuterAlt(_localctx, 10); { - this.state = 479; + this.state = 333; this.match(esql_parser.OPENING_BRACKET); - this.state = 480; + this.state = 334; this.string(); - this.state = 485; + this.state = 339; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === esql_parser.COMMA) { { { - this.state = 481; + this.state = 335; this.match(esql_parser.COMMA); - this.state = 482; + this.state = 336; this.string(); } } - this.state = 487; + this.state = 341; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 488; + this.state = 342; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2406,55 +1716,15 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public numericValue(): NumericValueContext { - let _localctx: NumericValueContext = new NumericValueContext(this._ctx, this.state); - this.enterRule(_localctx, 74, esql_parser.RULE_numericValue); - try { - this.state = 494; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.DECIMAL_LITERAL: - this.enterOuterAlt(_localctx, 1); - { - this.state = 492; - this.decimalValue(); - } - break; - case esql_parser.INTEGER_LITERAL: - this.enterOuterAlt(_localctx, 2); - { - this.state = 493; - this.integerValue(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public limitCommand(): LimitCommandContext { let _localctx: LimitCommandContext = new LimitCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 76, esql_parser.RULE_limitCommand); + this.enterRule(_localctx, 46, esql_parser.RULE_limitCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 496; + this.state = 346; this.match(esql_parser.LIMIT); - this.state = 497; + this.state = 347; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2475,32 +1745,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public sortCommand(): SortCommandContext { let _localctx: SortCommandContext = new SortCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 78, esql_parser.RULE_sortCommand); + this.enterRule(_localctx, 48, esql_parser.RULE_sortCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 499; + this.state = 349; this.match(esql_parser.SORT); - this.state = 500; + this.state = 350; this.orderExpression(); - this.state = 505; + this.state = 355; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 501; + this.state = 351; this.match(esql_parser.COMMA); - this.state = 502; + this.state = 352; this.orderExpression(); } } } - this.state = 507; + this.state = 357; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 49, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 32, this._ctx); } } } @@ -2521,32 +1791,53 @@ export class esql_parser extends Parser { // @RuleVersion(0) public orderExpression(): OrderExpressionContext { let _localctx: OrderExpressionContext = new OrderExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 80, esql_parser.RULE_orderExpression); + this.enterRule(_localctx, 50, esql_parser.RULE_orderExpression); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 508; + this.state = 358; this.booleanExpression(0); - this.state = 510; + this.state = 360; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 50, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 33, this._ctx) ) { case 1: { - this.state = 509; - this.match(esql_parser.ORDERING); + this.state = 359; + _localctx._ordering = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.ASC || _la === esql_parser.DESC)) { + _localctx._ordering = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } break; } - this.state = 514; + this.state = 364; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 51, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 34, this._ctx) ) { case 1: { - this.state = 512; - this.match(esql_parser.NULLS_ORDERING); - { - this.state = 513; - this.match(esql_parser.NULLS_ORDERING_DIRECTION); + this.state = 362; + this.match(esql_parser.NULLS); + this.state = 363; + _localctx._nullOrdering = this._input.LT(1); + _la = this._input.LA(1); + if (!(_la === esql_parser.FIRST || _la === esql_parser.LAST)) { + _localctx._nullOrdering = this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); } } break; @@ -2568,43 +1859,70 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public projectCommand(): ProjectCommandContext { - let _localctx: ProjectCommandContext = new ProjectCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 82, esql_parser.RULE_projectCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 516; - this.match(esql_parser.PROJECT); - this.state = 517; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) public keepCommand(): KeepCommandContext { let _localctx: KeepCommandContext = new KeepCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 84, esql_parser.RULE_keepCommand); + this.enterRule(_localctx, 52, esql_parser.RULE_keepCommand); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 519; - this.match(esql_parser.KEEP); - this.state = 520; - this.qualifiedNames(); + let _alt: number; + this.state = 384; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case esql_parser.KEEP: + this.enterOuterAlt(_localctx, 1); + { + this.state = 366; + this.match(esql_parser.KEEP); + this.state = 367; + this.sourceIdentifier(); + this.state = 372; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 368; + this.match(esql_parser.COMMA); + this.state = 369; + this.sourceIdentifier(); + } + } + } + this.state = 374; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 35, this._ctx); + } + } + break; + case esql_parser.PROJECT: + this.enterOuterAlt(_localctx, 2); + { + this.state = 375; + this.match(esql_parser.PROJECT); + this.state = 376; + this.sourceIdentifier(); + this.state = 381; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 36, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 377; + this.match(esql_parser.COMMA); + this.state = 378; + this.sourceIdentifier(); + } + } + } + this.state = 383; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 36, this._ctx); + } + } + break; + default: + throw new NoViableAltException(this); } } catch (re) { @@ -2624,57 +1942,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public dropCommand(): DropCommandContext { let _localctx: DropCommandContext = new DropCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 86, esql_parser.RULE_dropCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 522; - this.match(esql_parser.DROP); - this.state = 523; - this.qualifiedNames(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public renameVariable(): RenameVariableContext { - let _localctx: RenameVariableContext = new RenameVariableContext(this._ctx, this.state); - this.enterRule(_localctx, 88, esql_parser.RULE_renameVariable); + this.enterRule(_localctx, 54, esql_parser.RULE_dropCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 525; - this.identifier(); - this.state = 530; + this.state = 386; + this.match(esql_parser.DROP); + this.state = 387; + this.sourceIdentifier(); + this.state = 392; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 38, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 526; - this.match(esql_parser.DOT); - this.state = 527; - this.identifier(); + this.state = 388; + this.match(esql_parser.COMMA); + this.state = 389; + this.sourceIdentifier(); } } } - this.state = 532; + this.state = 394; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 52, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 38, this._ctx); } } } @@ -2695,32 +1988,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public renameCommand(): RenameCommandContext { let _localctx: RenameCommandContext = new RenameCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 90, esql_parser.RULE_renameCommand); + this.enterRule(_localctx, 56, esql_parser.RULE_renameCommand); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 533; + this.state = 395; this.match(esql_parser.RENAME); - this.state = 534; + this.state = 396; this.renameClause(); - this.state = 539; + this.state = 401; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 39, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 535; + this.state = 397; this.match(esql_parser.COMMA); - this.state = 536; + this.state = 398; this.renameClause(); } } } - this.state = 541; + this.state = 403; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 53, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 39, this._ctx); } } } @@ -2741,16 +2034,16 @@ export class esql_parser extends Parser { // @RuleVersion(0) public renameClause(): RenameClauseContext { let _localctx: RenameClauseContext = new RenameClauseContext(this._ctx, this.state); - this.enterRule(_localctx, 92, esql_parser.RULE_renameClause); + this.enterRule(_localctx, 58, esql_parser.RULE_renameClause); try { this.enterOuterAlt(_localctx, 1); { - this.state = 542; - this.qualifiedName(); - this.state = 543; + this.state = 404; + _localctx._oldName = this.sourceIdentifier(); + this.state = 405; this.match(esql_parser.AS); - this.state = 544; - this.renameVariable(); + this.state = 406; + _localctx._newName = this.sourceIdentifier(); } } catch (re) { @@ -2770,22 +2063,22 @@ export class esql_parser extends Parser { // @RuleVersion(0) public dissectCommand(): DissectCommandContext { let _localctx: DissectCommandContext = new DissectCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 94, esql_parser.RULE_dissectCommand); + this.enterRule(_localctx, 60, esql_parser.RULE_dissectCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 546; + this.state = 408; this.match(esql_parser.DISSECT); - this.state = 547; - this.qualifiedNames(); - this.state = 548; + this.state = 409; + this.primaryExpression(); + this.state = 410; this.string(); - this.state = 550; + this.state = 412; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 54, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 40, this._ctx) ) { case 1: { - this.state = 549; + this.state = 411; this.commandOptions(); } break; @@ -2809,15 +2102,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public grokCommand(): GrokCommandContext { let _localctx: GrokCommandContext = new GrokCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 96, esql_parser.RULE_grokCommand); + this.enterRule(_localctx, 62, esql_parser.RULE_grokCommand); try { this.enterOuterAlt(_localctx, 1); { - this.state = 552; + this.state = 414; this.match(esql_parser.GROK); - this.state = 553; - this.qualifiedNames(); - this.state = 554; + this.state = 415; + this.primaryExpression(); + this.state = 416; this.string(); } } @@ -2836,32 +2129,59 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) + public mvExpandCommand(): MvExpandCommandContext { + let _localctx: MvExpandCommandContext = new MvExpandCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 64, esql_parser.RULE_mvExpandCommand); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 418; + this.match(esql_parser.MV_EXPAND); + this.state = 419; + this.sourceIdentifier(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) public commandOptions(): CommandOptionsContext { let _localctx: CommandOptionsContext = new CommandOptionsContext(this._ctx, this.state); - this.enterRule(_localctx, 98, esql_parser.RULE_commandOptions); + this.enterRule(_localctx, 66, esql_parser.RULE_commandOptions); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 556; + this.state = 421; this.commandOption(); - this.state = 561; + this.state = 426; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 41, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 557; + this.state = 422; this.match(esql_parser.COMMA); - this.state = 558; + this.state = 423; this.commandOption(); } } } - this.state = 563; + this.state = 428; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 55, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 41, this._ctx); } } } @@ -2882,15 +2202,15 @@ export class esql_parser extends Parser { // @RuleVersion(0) public commandOption(): CommandOptionContext { let _localctx: CommandOptionContext = new CommandOptionContext(this._ctx, this.state); - this.enterRule(_localctx, 100, esql_parser.RULE_commandOption); + this.enterRule(_localctx, 68, esql_parser.RULE_commandOption); try { this.enterOuterAlt(_localctx, 1); { - this.state = 564; + this.state = 429; this.identifier(); - this.state = 565; + this.state = 430; this.match(esql_parser.ASSIGN); - this.state = 566; + this.state = 431; this.constant(); } } @@ -2911,12 +2231,23 @@ export class esql_parser extends Parser { // @RuleVersion(0) public booleanValue(): BooleanValueContext { let _localctx: BooleanValueContext = new BooleanValueContext(this._ctx, this.state); - this.enterRule(_localctx, 102, esql_parser.RULE_booleanValue); + this.enterRule(_localctx, 70, esql_parser.RULE_booleanValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 568; - this.match(esql_parser.BOOLEAN_VALUE); + this.state = 433; + _la = this._input.LA(1); + if (!(_la === esql_parser.FALSE || _la === esql_parser.TRUE)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -2934,31 +2265,28 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public number(): NumberContext { - let _localctx: NumberContext = new NumberContext(this._ctx, this.state); - this.enterRule(_localctx, 104, esql_parser.RULE_number); + public numericValue(): NumericValueContext { + let _localctx: NumericValueContext = new NumericValueContext(this._ctx, this.state); + this.enterRule(_localctx, 72, esql_parser.RULE_numericValue); try { - this.state = 572; + this.state = 437; this._errHandler.sync(this); - switch (this._input.LA(1)) { - case esql_parser.DECIMAL_LITERAL: - _localctx = new DecimalLiteralContext(_localctx); + switch ( this.interpreter.adaptivePredict(this._input, 42, this._ctx) ) { + case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 570; - this.match(esql_parser.DECIMAL_LITERAL); + this.state = 435; + this.decimalValue(); } break; - case esql_parser.INTEGER_LITERAL: - _localctx = new IntegerLiteralContext(_localctx); + + case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 571; - this.match(esql_parser.INTEGER_LITERAL); + this.state = 436; + this.integerValue(); } break; - default: - throw new NoViableAltException(this); } } catch (re) { @@ -2978,11 +2306,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public decimalValue(): DecimalValueContext { let _localctx: DecimalValueContext = new DecimalValueContext(this._ctx, this.state); - this.enterRule(_localctx, 106, esql_parser.RULE_decimalValue); + this.enterRule(_localctx, 74, esql_parser.RULE_decimalValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 574; + this.state = 440; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.PLUS || _la === esql_parser.MINUS) { + { + this.state = 439; + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + + this.state = 442; this.match(esql_parser.DECIMAL_LITERAL); } } @@ -3003,11 +2352,32 @@ export class esql_parser extends Parser { // @RuleVersion(0) public integerValue(): IntegerValueContext { let _localctx: IntegerValueContext = new IntegerValueContext(this._ctx, this.state); - this.enterRule(_localctx, 108, esql_parser.RULE_integerValue); + this.enterRule(_localctx, 76, esql_parser.RULE_integerValue); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 576; + this.state = 445; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === esql_parser.PLUS || _la === esql_parser.MINUS) { + { + this.state = 444; + _la = this._input.LA(1); + if (!(_la === esql_parser.PLUS || _la === esql_parser.MINUS)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + + this.state = 447; this.match(esql_parser.INTEGER_LITERAL); } } @@ -3028,11 +2398,11 @@ export class esql_parser extends Parser { // @RuleVersion(0) public string(): StringContext { let _localctx: StringContext = new StringContext(this._ctx, this.state); - this.enterRule(_localctx, 110, esql_parser.RULE_string); + this.enterRule(_localctx, 78, esql_parser.RULE_string); try { this.enterOuterAlt(_localctx, 1); { - this.state = 578; + this.state = 449; this.match(esql_parser.STRING); } } @@ -3053,12 +2423,23 @@ export class esql_parser extends Parser { // @RuleVersion(0) public comparisonOperator(): ComparisonOperatorContext { let _localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 112, esql_parser.RULE_comparisonOperator); + this.enterRule(_localctx, 80, esql_parser.RULE_comparisonOperator); + let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 580; - this.match(esql_parser.COMPARISON_OPERATOR); + this.state = 451; + _la = this._input.LA(1); + if (!(((((_la - 50)) & ~0x1F) === 0 && ((1 << (_la - 50)) & ((1 << (esql_parser.EQ - 50)) | (1 << (esql_parser.NEQ - 50)) | (1 << (esql_parser.LT - 50)) | (1 << (esql_parser.LTE - 50)) | (1 << (esql_parser.GT - 50)) | (1 << (esql_parser.GTE - 50)))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -3076,16 +2457,34 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public explainCommand(): ExplainCommandContext { - let _localctx: ExplainCommandContext = new ExplainCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 114, esql_parser.RULE_explainCommand); + public showCommand(): ShowCommandContext { + let _localctx: ShowCommandContext = new ShowCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 82, esql_parser.RULE_showCommand); try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 582; - this.match(esql_parser.EXPLAIN); - this.state = 583; - this.subqueryExpression(); + this.state = 457; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 45, this._ctx) ) { + case 1: + _localctx = new ShowInfoContext(_localctx); + this.enterOuterAlt(_localctx, 1); + { + this.state = 453; + this.match(esql_parser.SHOW); + this.state = 454; + this.match(esql_parser.INFO); + } + break; + + case 2: + _localctx = new ShowFunctionsContext(_localctx); + this.enterOuterAlt(_localctx, 2); + { + this.state = 455; + this.match(esql_parser.SHOW); + this.state = 456; + this.match(esql_parser.FUNCTIONS); + } + break; } } catch (re) { @@ -3103,18 +2502,59 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public subqueryExpression(): SubqueryExpressionContext { - let _localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 116, esql_parser.RULE_subqueryExpression); + public enrichCommand(): EnrichCommandContext { + let _localctx: EnrichCommandContext = new EnrichCommandContext(this._ctx, this.state); + this.enterRule(_localctx, 84, esql_parser.RULE_enrichCommand); try { + let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 585; - this.match(esql_parser.OPENING_BRACKET); - this.state = 586; - this.query(0); - this.state = 587; - this.match(esql_parser.CLOSING_BRACKET); + this.state = 459; + this.match(esql_parser.ENRICH); + this.state = 460; + _localctx._policyName = this.sourceIdentifier(); + this.state = 463; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 46, this._ctx) ) { + case 1: + { + this.state = 461; + this.match(esql_parser.ON); + this.state = 462; + _localctx._matchField = this.sourceIdentifier(); + } + break; + } + this.state = 474; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 48, this._ctx) ) { + case 1: + { + this.state = 465; + this.match(esql_parser.WITH); + this.state = 466; + this.enrichWithClause(); + this.state = 471; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 47, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + { + { + this.state = 467; + this.match(esql_parser.COMMA); + this.state = 468; + this.enrichWithClause(); + } + } + } + this.state = 473; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 47, this._ctx); + } + } + break; + } } } catch (re) { @@ -3132,33 +2572,27 @@ export class esql_parser extends Parser { return _localctx; } // @RuleVersion(0) - public showCommand(): ShowCommandContext { - let _localctx: ShowCommandContext = new ShowCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 118, esql_parser.RULE_showCommand); + public enrichWithClause(): EnrichWithClauseContext { + let _localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this._ctx, this.state); + this.enterRule(_localctx, 86, esql_parser.RULE_enrichWithClause); try { - this.state = 593; + this.enterOuterAlt(_localctx, 1); + { + this.state = 479; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 57, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 49, this._ctx) ) { case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 589; - this.match(esql_parser.SHOW); - this.state = 590; - this.match(esql_parser.INFO); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); { - this.state = 591; - this.match(esql_parser.SHOW); - this.state = 592; - this.match(esql_parser.FUNCTIONS); + this.state = 476; + _localctx._newName = this.sourceIdentifier(); + this.state = 477; + this.match(esql_parser.ASSIGN); } break; } + this.state = 481; + _localctx._enrichField = this.sourceIdentifier(); + } } catch (re) { if (re instanceof RecognitionException) { @@ -3180,13 +2614,10 @@ export class esql_parser extends Parser { case 1: return this.query_sempred(_localctx as QueryContext, predIndex); - case 8: - return this.whereBooleanExpression_sempred(_localctx as WhereBooleanExpressionContext, predIndex); - - case 9: + case 5: return this.booleanExpression_sempred(_localctx as BooleanExpressionContext, predIndex); - case 16: + case 8: return this.operatorExpression_sempred(_localctx as OperatorExpressionContext, predIndex); } return true; @@ -3198,17 +2629,17 @@ export class esql_parser extends Parser { } return true; } - private whereBooleanExpression_sempred(_localctx: WhereBooleanExpressionContext, predIndex: number): boolean { + private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { switch (predIndex) { case 1: - return this.precpred(this._ctx, 5); + return this.precpred(this._ctx, 4); case 2: - return this.precpred(this._ctx, 4); + return this.precpred(this._ctx, 3); } return true; } - private booleanExpression_sempred(_localctx: BooleanExpressionContext, predIndex: number): boolean { + private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { switch (predIndex) { case 3: return this.precpred(this._ctx, 2); @@ -3218,20 +2649,9 @@ export class esql_parser extends Parser { } return true; } - private operatorExpression_sempred(_localctx: OperatorExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 5: - return this.precpred(this._ctx, 2); - - case 6: - return this.precpred(this._ctx, 1); - } - return true; - } - private static readonly _serializedATNSegments: number = 2; - private static readonly _serializedATNSegment0: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03S\u0256\x04\x02" + + public static readonly _serializedATN: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03N\u01E6\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + @@ -3239,293 +2659,233 @@ export class esql_parser extends Parser { "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t)\x04*\t*\x04+\t+" + - "\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x040\t0\x041\t1\x042\t2\x043\t3\x044" + - "\t4\x045\t5\x046\t6\x047\t7\x048\t8\x049\t9\x04:\t:\x04;\t;\x04<\t<\x04" + - "=\t=\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x07\x03\x84\n\x03\f\x03\x0E\x03\x87\v\x03\x03\x04\x03\x04\x03\x04" + - "\x03\x04\x05\x04\x8D\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05\x9C" + - "\n\x05\x03\x06\x03\x06\x03\x06\x03\x06\x05\x06\xA2\n\x06\x03\x06\x03\x06" + - "\x03\x06\x03\x06\x07\x06\xA8\n\x06\f\x06\x0E\x06\xAB\v\x06\x05\x06\xAD" + - "\n\x06\x03\x07\x03\x07\x03\x07\x05\x07\xB2\n\x07\x03\x07\x03\x07\x03\b" + - "\x03\b\x03\b\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03" + - "\n\x05\n\xC3\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x07\n\xCA\n\n\f\n\x0E\n" + - "\xCD\v\n\x03\n\x03\n\x03\n\x05\n\xD2\n\n\x03\n\x03\n\x03\n\x03\n\x03\n" + - "\x07\n\xD9\n\n\f\n\x0E\n\xDC\v\n\x05\n\xDE\n\n\x03\n\x03\n\x03\n\x03\n" + - "\x03\n\x05\n\xE5\n\n\x03\n\x03\n\x05\n\xE9\n\n\x03\n\x03\n\x03\n\x03\n" + - "\x03\n\x03\n\x07\n\xF1\n\n\f\n\x0E\n\xF4\v\n\x03\v\x03\v\x03\v\x03\v\x05" + - "\v\xFA\n\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x07\v\u0102\n\v\f\v\x0E" + - "\v\u0105\v\v\x03\f\x03\f\x05\f\u0109\n\f\x03\f\x03\f\x03\f\x03\f\x03\f" + - "\x05\f\u0110\n\f\x03\f\x03\f\x03\f\x05\f\u0115\n\f\x03\r\x03\r\x05\r\u0119" + - "\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03" + - "\x0F\x07\x0F\u0124\n\x0F\f\x0F\x0E\x0F\u0127\v\x0F\x05\x0F\u0129\n\x0F" + - "\x03\x0F\x03\x0F\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x07\x10\u0132" + - "\n\x10\f\x10\x0E\x10\u0135\v\x10\x05\x10\u0137\n\x10\x03\x10\x03\x10\x03" + - "\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x05" + - "\x12\u0144\n\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x07\x12" + - "\u014C\n\x12\f\x12\x0E\x12\u014F\v\x12\x03\x13\x03\x13\x03\x13\x03\x13" + - "\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13\x07\x13" + - "\u015D\n\x13\f\x13\x0E\x13\u0160\v\x13\x05\x13\u0162\n\x13\x03\x13\x03" + - "\x13\x05\x13\u0166\n\x13\x03\x14\x03\x14\x03\x14\x03\x15\x03\x15\x03\x15" + - "\x07\x15\u016E\n\x15\f\x15\x0E\x15\u0171\v\x15\x03\x16\x03\x16\x03\x16" + - "\x03\x16\x03\x16\x05\x16\u0178\n\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03" + - "\x19\x03\x19\x03\x19\x03\x19\x07\x19\u0182\n\x19\f\x19\x0E\x19\u0185\v" + - "\x19\x03\x19\x05\x19\u0188\n\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A" + - "\x07\x1A\u018F\n\x1A\f\x1A\x0E\x1A\u0192\v\x1A\x03\x1A\x03\x1A\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x05\x1C\u019B\n\x1C\x03\x1C\x03\x1C\x05" + - "\x1C\u019F\n\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F" + - "\x05\x1F\u01A8\n\x1F\x03 \x03 \x03 \x03 \x03 \x03 \x05 \u01B0\n \x03!" + - "\x03!\x03!\x07!\u01B5\n!\f!\x0E!\u01B8\v!\x03\"\x03\"\x03\"\x07\"\u01BD" + - "\n\"\f\"\x0E\"\u01C0\v\"\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x03&\x03&" + - "\x03&\x03&\x03&\x03&\x03&\x07&\u01D0\n&\f&\x0E&\u01D3\v&\x03&\x03&\x03" + - "&\x03&\x03&\x03&\x07&\u01DB\n&\f&\x0E&\u01DE\v&\x03&\x03&\x03&\x03&\x03" + - "&\x03&\x07&\u01E6\n&\f&\x0E&\u01E9\v&\x03&\x03&\x05&\u01ED\n&\x03\'\x03" + - "\'\x05\'\u01F1\n\'\x03(\x03(\x03(\x03)\x03)\x03)\x03)\x07)\u01FA\n)\f" + - ")\x0E)\u01FD\v)\x03*\x03*\x05*\u0201\n*\x03*\x03*\x05*\u0205\n*\x03+\x03" + - "+\x03+\x03,\x03,\x03,\x03-\x03-\x03-\x03.\x03.\x03.\x07.\u0213\n.\f.\x0E" + - ".\u0216\v.\x03/\x03/\x03/\x03/\x07/\u021C\n/\f/\x0E/\u021F\v/\x030\x03" + - "0\x030\x030\x031\x031\x031\x031\x051\u0229\n1\x032\x032\x032\x032\x03" + - "3\x033\x033\x073\u0232\n3\f3\x0E3\u0235\v3\x034\x034\x034\x034\x035\x03" + - "5\x036\x036\x056\u023F\n6\x037\x037\x038\x038\x039\x039\x03:\x03:\x03" + - ";\x03;\x03;\x03<\x03<\x03<\x03<\x03=\x03=\x03=\x03=\x05=\u0254\n=\x03" + - "=\x02\x02\x06\x04\x12\x14\">\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02" + - "\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02" + - " \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02" + - "<\x02>\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02P\x02R\x02T\x02V\x02" + - "X\x02Z\x02\\\x02^\x02`\x02b\x02d\x02f\x02h\x02j\x02l\x02n\x02p\x02r\x02" + - "t\x02v\x02x\x02\x02\x07\x03\x0256\x03\x0279\x03\x02NO\x03\x02GH\x04\x02" + - "77AB\x02\u0273\x02z\x03\x02\x02\x02\x04}\x03\x02\x02\x02\x06\x8C\x03\x02" + - "\x02\x02\b\x9B\x03\x02\x02\x02\n\x9D\x03\x02\x02\x02\f\xB1\x03\x02\x02" + - "\x02\x0E\xB5\x03\x02\x02\x02\x10\xB8\x03\x02\x02\x02\x12\xE8\x03\x02\x02" + - "\x02\x14\xF9\x03\x02\x02\x02\x16\u0114\x03\x02\x02\x02\x18\u0118\x03\x02" + - "\x02\x02\x1A\u011A\x03\x02\x02\x02\x1C\u011E\x03\x02\x02\x02\x1E\u012C" + - "\x03\x02\x02\x02 \u013A\x03\x02\x02\x02\"\u0143\x03\x02\x02\x02$\u0165" + - "\x03\x02\x02\x02&\u0167\x03\x02\x02\x02(\u016A\x03\x02\x02\x02*\u0177" + - "\x03\x02\x02\x02,\u0179\x03\x02\x02\x02.\u017B\x03\x02\x02\x020\u017D" + - "\x03\x02\x02\x022\u0189\x03\x02\x02\x024\u0195\x03\x02\x02\x026\u0198" + - "\x03\x02\x02\x028\u01A0\x03\x02\x02\x02:\u01A2\x03\x02\x02\x02<\u01A7" + - "\x03\x02\x02\x02>\u01AF\x03\x02\x02\x02@\u01B1\x03\x02\x02\x02B\u01B9" + - "\x03\x02\x02\x02D\u01C1\x03\x02\x02\x02F\u01C3\x03\x02\x02\x02H\u01C5" + - "\x03\x02\x02\x02J\u01EC\x03\x02\x02\x02L\u01F0\x03\x02\x02\x02N\u01F2" + - "\x03\x02\x02\x02P\u01F5\x03\x02\x02\x02R\u01FE\x03\x02\x02\x02T\u0206" + - "\x03\x02\x02\x02V\u0209\x03\x02\x02\x02X\u020C\x03\x02\x02\x02Z\u020F" + - "\x03\x02\x02\x02\\\u0217\x03\x02\x02\x02^\u0220\x03\x02\x02\x02`\u0224" + - "\x03\x02\x02\x02b\u022A\x03\x02\x02\x02d\u022E\x03\x02\x02\x02f\u0236" + - "\x03\x02\x02\x02h\u023A\x03\x02\x02\x02j\u023E\x03\x02\x02\x02l\u0240" + - "\x03\x02\x02\x02n\u0242\x03\x02\x02\x02p\u0244\x03\x02\x02\x02r\u0246" + - "\x03\x02\x02\x02t\u0248\x03\x02\x02\x02v\u024B\x03\x02\x02\x02x\u0253" + - "\x03\x02\x02\x02z{\x05\x04\x03\x02{|\x07\x02\x02\x03|\x03\x03\x02\x02" + - "\x02}~\b\x03\x01\x02~\x7F\x05\x06\x04\x02\x7F\x85\x03\x02\x02\x02\x80" + - "\x81\f\x03\x02\x02\x81\x82\x07\x1A\x02\x02\x82\x84\x05\b\x05\x02\x83\x80" + - "\x03\x02\x02\x02\x84\x87\x03\x02\x02\x02\x85\x83\x03\x02\x02\x02\x85\x86" + - "\x03\x02\x02\x02\x86\x05\x03\x02\x02\x02\x87\x85\x03\x02\x02\x02\x88\x8D" + - "\x05t;\x02\x89\x8D\x050\x19\x02\x8A\x8D\x05&\x14\x02\x8B\x8D\x05x=\x02" + - "\x8C\x88\x03\x02\x02\x02\x8C\x89\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02" + - "\x8C\x8B\x03\x02\x02\x02\x8D\x07\x03\x02\x02\x02\x8E\x9C\x054\x1B\x02" + - "\x8F\x9C\x05N(\x02\x90\x9C\x05T+\x02\x91\x9C\x05V,\x02\x92\x9C\x05\\/" + - "\x02\x93\x9C\x05X-\x02\x94\x9C\x05`1\x02\x95\x9C\x05b2\x02\x96\x9C\x05" + - "P)\x02\x97\x9C\x056\x1C\x02\x98\x9C\x05\x10\t\x02\x99\x9C\x05\x0E\b\x02" + - "\x9A\x9C\x05\n\x06\x02\x9B\x8E\x03\x02\x02\x02\x9B\x8F\x03\x02\x02\x02" + - "\x9B\x90\x03\x02\x02\x02\x9B\x91\x03\x02\x02\x02\x9B\x92\x03\x02\x02\x02" + - "\x9B\x93\x03\x02\x02\x02\x9B\x94\x03\x02\x02\x02\x9B\x95\x03\x02\x02\x02" + - "\x9B\x96\x03\x02\x02\x02\x9B\x97\x03\x02\x02\x02\x9B\x98\x03\x02\x02\x02" + - "\x9B\x99\x03\x02\x02\x02\x9B\x9A\x03\x02\x02\x02\x9C\t\x03\x02\x02\x02" + - "\x9D\x9E\x07\x12\x02\x02\x9E\xA1\x05:\x1E\x02\x9F\xA0\x07L\x02\x02\xA0" + - "\xA2\x05,\x17\x02\xA1\x9F\x03\x02\x02\x02\xA1\xA2\x03\x02\x02\x02\xA2" + - "\xAC\x03\x02\x02\x02\xA3\xA4\x07M\x02\x02\xA4\xA9\x05\f\x07\x02\xA5\xA6" + - "\x07\"\x02\x02\xA6\xA8\x05\f\x07\x02\xA7\xA5\x03\x02\x02\x02\xA8\xAB\x03" + - "\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xA9\xAA\x03\x02\x02\x02\xAA\xAD\x03" + - "\x02\x02\x02\xAB\xA9\x03\x02\x02\x02\xAC\xA3\x03\x02\x02\x02\xAC\xAD\x03" + - "\x02\x02\x02\xAD\v\x03\x02\x02\x02\xAE\xAF\x05,\x17\x02\xAF\xB0\x07!\x02" + - "\x02\xB0\xB2\x03\x02\x02\x02\xB1\xAE\x03\x02\x02\x02\xB1\xB2\x03\x02\x02" + - "\x02\xB2\xB3\x03\x02\x02\x02\xB3\xB4\x05,\x17\x02\xB4\r\x03\x02\x02\x02" + - "\xB5\xB6\x07\f\x02\x02\xB6\xB7\x05B\"\x02\xB7\x0F\x03\x02\x02\x02\xB8" + - "\xB9\x07\n\x02\x02\xB9\xBA\x05\x12\n\x02\xBA\x11\x03\x02\x02\x02\xBB\xBC" + - "\b\n\x01\x02\xBC\xBD\x07\'\x02\x02\xBD\xE9\x05\x12\n\n\xBE\xE9\x05\x18" + - "\r\x02\xBF\xE9\x05\x16\f\x02\xC0\xC2\x05\x18\r\x02\xC1\xC3\x07\'\x02\x02" + - "\xC2\xC1\x03\x02\x02\x02\xC2\xC3\x03\x02\x02\x02\xC3\xC4\x03\x02\x02\x02" + - "\xC4\xC5\x07*\x02\x02\xC5\xC6\x07$\x02\x02\xC6\xCB\x05\x18\r\x02\xC7\xC8" + - "\x07\"\x02\x02\xC8\xCA\x05\x18\r\x02\xC9\xC7\x03\x02\x02\x02\xCA\xCD\x03" + - "\x02\x02\x02\xCB\xC9\x03\x02\x02\x02\xCB\xCC\x03\x02\x02\x02\xCC\xCE\x03" + - "\x02\x02\x02\xCD\xCB\x03\x02\x02\x02\xCE\xCF\x07/\x02\x02\xCF\xE9\x03" + - "\x02\x02\x02\xD0\xD2\x07\'\x02\x02\xD1\xD0\x03\x02\x02\x02\xD1\xD2\x03" + - "\x02\x02\x02\xD2\xD3\x03\x02\x02\x02\xD3\xD4\x07@\x02\x02\xD4\xD5\x07" + - "$\x02\x02\xD5\xDD\x05@!\x02\xD6\xD7\x07\"\x02\x02\xD7\xD9\x05<\x1F\x02" + - "\xD8\xD6\x03\x02\x02\x02\xD9\xDC\x03\x02\x02\x02\xDA\xD8\x03\x02\x02\x02" + - "\xDA\xDB\x03\x02\x02\x02\xDB\xDE\x03\x02\x02\x02\xDC\xDA\x03\x02\x02\x02" + - "\xDD\xDA\x03\x02\x02\x02\xDD\xDE\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02" + - "\xDF\xE0\x07/\x02\x02\xE0\xE9\x03\x02\x02\x02\xE1\xE2\x05\x18\r\x02\xE2" + - "\xE4\x07+\x02\x02\xE3\xE5\x07\'\x02\x02\xE4\xE3\x03\x02\x02\x02\xE4\xE5" + - "\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE7\x07-\x02\x02\xE7\xE9" + - "\x03\x02\x02\x02\xE8\xBB\x03\x02\x02\x02\xE8\xBE\x03\x02\x02\x02\xE8\xBF" + - "\x03\x02\x02\x02\xE8\xC0\x03\x02\x02\x02\xE8\xD1\x03\x02\x02\x02\xE8\xE1" + - "\x03\x02\x02\x02\xE9\xF2\x03\x02\x02\x02\xEA\xEB\f\x07\x02\x02\xEB\xEC" + - "\x07 \x02\x02\xEC\xF1\x05\x12\n\b\xED\xEE\f\x06\x02\x02\xEE\xEF\x07.\x02" + - "\x02\xEF\xF1\x05\x12\n\x07\xF0\xEA\x03\x02\x02\x02\xF0\xED\x03\x02\x02" + - "\x02\xF1\xF4\x03\x02\x02\x02\xF2\xF0\x03\x02\x02\x02\xF2\xF3\x03\x02\x02" + - "\x02\xF3\x13\x03\x02\x02\x02\xF4\xF2\x03\x02\x02\x02\xF5\xF6\b\v\x01\x02" + - "\xF6\xF7\x07\'\x02\x02\xF7\xFA\x05\x14\v\x06\xF8\xFA\x05\x18\r\x02\xF9" + - "\xF5\x03\x02\x02\x02\xF9\xF8\x03\x02\x02\x02\xFA\u0103\x03\x02\x02\x02" + - "\xFB\xFC\f\x04\x02\x02\xFC\xFD\x07 \x02\x02\xFD\u0102\x05\x14\v\x05\xFE" + - "\xFF\f\x03\x02\x02\xFF\u0100\x07.\x02\x02\u0100\u0102\x05\x14\v\x04\u0101" + - "\xFB\x03\x02\x02\x02\u0101\xFE\x03\x02\x02\x02\u0102\u0105\x03\x02\x02" + - "\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104\x15" + - "\x03\x02\x02\x02\u0105\u0103\x03\x02\x02\x02\u0106\u0108\x05\x18\r\x02" + - "\u0107\u0109\x07\'\x02\x02\u0108\u0107\x03\x02\x02\x02\u0108\u0109\x03" + - "\x02\x02\x02\u0109\u010A\x03\x02\x02\x02\u010A\u010B\x07(\x02\x02\u010B" + - "\u010C\x05p9\x02\u010C\u0115\x03\x02\x02\x02\u010D\u010F\x05\x18\r\x02" + - "\u010E\u0110\x07\'\x02\x02\u010F\u010E\x03\x02\x02\x02\u010F\u0110\x03" + - "\x02\x02\x02\u0110\u0111\x03\x02\x02\x02\u0111\u0112\x07)\x02\x02\u0112" + - "\u0113\x05p9\x02\u0113\u0115\x03\x02\x02\x02\u0114\u0106\x03\x02\x02\x02" + - "\u0114\u010D\x03\x02\x02\x02\u0115\x17\x03\x02\x02\x02\u0116\u0119\x05" + - "\"\x12\x02\u0117\u0119\x05\x1A\x0E\x02\u0118\u0116\x03\x02\x02\x02\u0118" + - "\u0117\x03\x02\x02\x02\u0119\x19\x03\x02\x02\x02\u011A\u011B\x05\"\x12" + - "\x02\u011B\u011C\x05r:\x02\u011C\u011D\x05\"\x12\x02\u011D\x1B\x03\x02" + - "\x02\x02\u011E\u011F\x05H%\x02\u011F\u0128\x07$\x02\x02\u0120\u0125\x05" + - "<\x1F\x02\u0121\u0122\x07\"\x02\x02\u0122\u0124\x05<\x1F\x02\u0123\u0121" + - "\x03\x02\x02\x02\u0124\u0127\x03\x02\x02\x02\u0125\u0123\x03\x02\x02\x02" + - "\u0125\u0126\x03\x02\x02\x02\u0126\u0129\x03\x02\x02\x02\u0127\u0125\x03" + - "\x02\x02\x02\u0128\u0120\x03\x02\x02\x02\u0128\u0129\x03\x02\x02\x02\u0129" + - "\u012A\x03\x02\x02\x02\u012A\u012B\x07/\x02\x02\u012B\x1D\x03\x02\x02" + - "\x02\u012C\u012D\x05F$\x02\u012D\u0136\x07$\x02\x02\u012E\u0133\x05> " + - "\x02\u012F\u0130\x07\"\x02\x02\u0130\u0132\x05> \x02\u0131\u012F\x03\x02" + - "\x02\x02\u0132\u0135\x03\x02\x02\x02\u0133\u0131\x03\x02\x02\x02\u0133" + - "\u0134\x03\x02\x02\x02\u0134\u0137\x03\x02\x02\x02\u0135\u0133\x03\x02" + - "\x02\x02\u0136\u012E\x03\x02\x02\x02\u0136\u0137\x03\x02\x02\x02\u0137" + - "\u0138\x03\x02\x02\x02\u0138\u0139\x07/\x02\x02\u0139\x1F\x03\x02\x02" + - "\x02\u013A\u013B\x05j6\x02\u013B\u013C\x07\x1F\x02\x02\u013C!\x03\x02" + - "\x02\x02\u013D\u013E\b\x12\x01\x02\u013E\u0144\x05$\x13\x02\u013F\u0144" + - "\x05\x1C\x0F\x02\u0140\u0144\x05\x1E\x10\x02\u0141\u0142\t\x02\x02\x02" + - "\u0142\u0144\x05\"\x12\x05\u0143\u013D\x03\x02\x02\x02\u0143\u013F\x03" + - "\x02\x02\x02\u0143\u0140\x03\x02\x02\x02\u0143\u0141\x03\x02\x02\x02\u0144" + - "\u014D\x03\x02\x02\x02\u0145\u0146\f\x04\x02\x02\u0146\u0147\t\x03\x02" + - "\x02\u0147\u014C\x05\"\x12\x05\u0148\u0149\f\x03\x02\x02\u0149\u014A\t" + - "\x02\x02\x02\u014A\u014C\x05\"\x12\x04\u014B\u0145\x03\x02\x02\x02\u014B" + - "\u0148\x03\x02\x02\x02\u014C\u014F\x03\x02\x02\x02\u014D\u014B\x03\x02" + - "\x02\x02\u014D\u014E\x03\x02\x02\x02\u014E#\x03\x02\x02\x02\u014F\u014D" + - "\x03\x02\x02\x02\u0150\u0166\x05J&\x02\u0151\u0166\x05@!\x02\u0152\u0166" + - "\x05 \x11\x02\u0153\u0154\x07$\x02\x02\u0154\u0155\x05\x14\v\x02\u0155" + - "\u0156\x07/\x02\x02\u0156\u0166\x03\x02\x02\x02\u0157\u0158\x05D#\x02" + - "\u0158\u0161\x07$\x02\x02\u0159\u015E\x05\x14\v\x02\u015A\u015B\x07\"" + - "\x02\x02\u015B\u015D\x05\x14\v\x02\u015C\u015A\x03\x02\x02\x02\u015D\u0160" + - "\x03\x02\x02\x02\u015E\u015C\x03\x02\x02\x02\u015E\u015F\x03\x02\x02\x02" + - "\u015F\u0162\x03\x02\x02\x02\u0160\u015E\x03\x02\x02\x02\u0161\u0159\x03" + - "\x02\x02\x02\u0161\u0162\x03\x02\x02\x02\u0162\u0163\x03\x02\x02\x02\u0163" + - "\u0164\x07/\x02\x02\u0164\u0166\x03\x02\x02\x02\u0165\u0150\x03\x02\x02" + - "\x02\u0165\u0151\x03\x02\x02\x02\u0165\u0152\x03\x02\x02\x02\u0165\u0153" + - "\x03\x02\x02\x02\u0165\u0157\x03\x02\x02\x02\u0166%\x03\x02\x02\x02\u0167" + - "\u0168\x07\b\x02\x02\u0168\u0169\x05(\x15\x02\u0169\'\x03\x02\x02\x02" + - "\u016A\u016F\x05*\x16\x02\u016B\u016C\x07\"\x02\x02\u016C\u016E\x05*\x16" + - "\x02\u016D\u016B\x03\x02\x02\x02\u016E\u0171\x03\x02\x02\x02\u016F\u016D" + - "\x03\x02\x02\x02\u016F\u0170\x03\x02\x02\x02\u0170)\x03\x02\x02\x02\u0171" + - "\u016F\x03\x02\x02\x02\u0172\u0178\x05\x14\v\x02\u0173\u0174\x05.\x18" + - "\x02\u0174\u0175\x07!\x02\x02\u0175\u0176\x05\x14\v\x02\u0176\u0178\x03" + - "\x02\x02\x02\u0177\u0172\x03\x02\x02\x02\u0177\u0173\x03\x02\x02\x02\u0178" + - "+\x03\x02\x02\x02\u0179\u017A\t\x04\x02\x02\u017A-\x03\x02\x02\x02\u017B" + - "\u017C\x05D#\x02\u017C/\x03\x02\x02\x02\u017D\u017E\x07\x07\x02\x02\u017E" + - "\u0183\x058\x1D\x02\u017F\u0180\x07\"\x02\x02\u0180\u0182\x058\x1D\x02" + - "\u0181\u017F\x03\x02\x02\x02\u0182\u0185\x03\x02\x02\x02\u0183\u0181\x03" + - "\x02\x02\x02\u0183\u0184\x03\x02\x02\x02\u0184\u0187\x03\x02\x02\x02\u0185" + - "\u0183\x03\x02\x02\x02\u0186\u0188\x052\x1A\x02\u0187\u0186\x03\x02\x02" + - "\x02\u0187\u0188\x03\x02\x02\x02\u01881\x03\x02\x02\x02\u0189\u018A\x07" + - "%\x02\x02\u018A\u018B\x07F\x02\x02\u018B\u0190\x058\x1D\x02\u018C\u018D" + - "\x07\"\x02\x02\u018D\u018F\x058\x1D\x02\u018E\u018C\x03\x02\x02\x02\u018F" + - "\u0192\x03\x02\x02\x02\u0190\u018E\x03\x02\x02\x02\u0190\u0191\x03\x02" + - "\x02\x02\u0191\u0193\x03\x02\x02\x02\u0192\u0190\x03\x02\x02\x02\u0193" + - "\u0194\x07&\x02\x02\u01943\x03\x02\x02\x02\u0195\u0196\x07\x05\x02\x02" + - "\u0196\u0197\x05(\x15\x02\u01975\x03\x02\x02\x02\u0198\u019A\x07\t\x02" + - "\x02\u0199\u019B\x05(\x15\x02\u019A\u0199\x03\x02\x02\x02\u019A\u019B" + - "\x03\x02\x02\x02\u019B\u019E\x03\x02\x02\x02\u019C\u019D\x07\x1E\x02\x02" + - "\u019D\u019F\x05B\"\x02\u019E\u019C\x03\x02\x02\x02\u019E\u019F\x03\x02" + - "\x02\x02\u019F7\x03\x02\x02\x02\u01A0\u01A1\t\x05\x02\x02\u01A19\x03\x02" + - "\x02\x02\u01A2\u01A3\t\x04\x02\x02\u01A3;\x03\x02\x02\x02\u01A4\u01A8" + - "\x05@!\x02\u01A5\u01A8\x05p9\x02\u01A6\u01A8\x05j6\x02\u01A7\u01A4\x03" + - "\x02\x02\x02\u01A7\u01A5\x03\x02\x02\x02\u01A7\u01A6\x03\x02\x02\x02\u01A8" + - "=\x03\x02\x02\x02\u01A9\u01B0\x05@!\x02\u01AA\u01B0\x05p9\x02\u01AB\u01B0" + - "\x05j6\x02\u01AC\u01B0\x05\"\x12\x02\u01AD\u01B0\x05 \x11\x02\u01AE\u01B0" + - "\x05\x1A\x0E\x02\u01AF\u01A9\x03\x02\x02\x02\u01AF\u01AA\x03\x02\x02\x02" + - "\u01AF\u01AB\x03\x02\x02\x02\u01AF\u01AC\x03\x02\x02\x02\u01AF\u01AD\x03" + - "\x02\x02\x02\u01AF\u01AE\x03\x02\x02\x02\u01B0?\x03\x02\x02\x02\u01B1" + - "\u01B6\x05D#\x02\u01B2\u01B3\x07#\x02\x02\u01B3\u01B5\x05D#\x02\u01B4" + - "\u01B2\x03\x02\x02\x02\u01B5\u01B8\x03\x02\x02\x02\u01B6\u01B4\x03\x02" + - "\x02\x02\u01B6\u01B7\x03\x02\x02\x02\u01B7A\x03\x02\x02\x02\u01B8\u01B6" + - "\x03\x02\x02\x02\u01B9\u01BE\x05@!\x02\u01BA\u01BB\x07\"\x02\x02\u01BB" + - "\u01BD\x05@!\x02\u01BC\u01BA\x03\x02\x02\x02\u01BD\u01C0\x03\x02\x02\x02" + - "\u01BE\u01BC\x03\x02\x02\x02\u01BE\u01BF\x03\x02\x02\x02\u01BFC\x03\x02" + - "\x02\x02\u01C0\u01BE\x03\x02\x02\x02\u01C1\u01C2\t\x06\x02\x02\u01C2E" + - "\x03\x02\x02\x02\u01C3\u01C4\x07>\x02\x02\u01C4G\x03\x02\x02\x02\u01C5" + - "\u01C6\x07?\x02\x02\u01C6I\x03\x02\x02\x02\u01C7\u01ED\x07-\x02\x02\u01C8" + - "\u01ED\x05L\'\x02\u01C9\u01ED\x05h5\x02\u01CA\u01ED\x05p9\x02\u01CB\u01CC" + - "\x07%\x02\x02\u01CC\u01D1\x05L\'\x02\u01CD\u01CE\x07\"\x02\x02\u01CE\u01D0" + - "\x05L\'\x02\u01CF\u01CD\x03\x02\x02\x02\u01D0\u01D3\x03\x02\x02\x02\u01D1" + - "\u01CF\x03\x02\x02\x02\u01D1\u01D2\x03\x02\x02\x02\u01D2\u01D4\x03\x02" + - "\x02\x02\u01D3\u01D1\x03\x02\x02\x02\u01D4\u01D5\x07&\x02\x02\u01D5\u01ED" + - "\x03\x02\x02\x02\u01D6\u01D7\x07%\x02\x02\u01D7\u01DC\x05h5\x02\u01D8" + - "\u01D9\x07\"\x02\x02\u01D9\u01DB\x05h5\x02\u01DA\u01D8\x03\x02\x02\x02" + - "\u01DB\u01DE\x03\x02\x02\x02\u01DC\u01DA\x03\x02\x02\x02\u01DC\u01DD\x03" + - "\x02\x02\x02\u01DD\u01DF\x03\x02\x02\x02\u01DE\u01DC\x03\x02\x02\x02\u01DF" + - "\u01E0\x07&\x02\x02\u01E0\u01ED\x03\x02\x02\x02\u01E1\u01E2\x07%\x02\x02" + - "\u01E2\u01E7\x05p9\x02\u01E3\u01E4\x07\"\x02\x02\u01E4\u01E6\x05p9\x02" + - "\u01E5\u01E3\x03\x02\x02\x02\u01E6\u01E9\x03\x02\x02\x02\u01E7\u01E5\x03" + - "\x02\x02\x02\u01E7\u01E8\x03\x02\x02\x02\u01E8\u01EA\x03\x02\x02\x02\u01E9" + - "\u01E7\x03\x02\x02\x02\u01EA\u01EB\x07&\x02\x02\u01EB\u01ED\x03\x02\x02" + - "\x02\u01EC\u01C7\x03\x02\x02\x02\u01EC\u01C8\x03\x02\x02\x02\u01EC\u01C9" + - "\x03\x02\x02\x02\u01EC\u01CA\x03\x02\x02\x02\u01EC\u01CB\x03\x02\x02\x02" + - "\u01EC\u01D6\x03\x02\x02\x02\u01EC\u01E1\x03\x02\x02\x02\u01EDK\x03\x02" + - "\x02\x02\u01EE\u01F1\x05l7\x02\u01EF\u01F1\x05n8\x02\u01F0\u01EE\x03\x02" + - "\x02\x02\u01F0\u01EF\x03\x02\x02\x02\u01F1M\x03\x02\x02\x02\u01F2\u01F3" + - "\x07\r\x02\x02\u01F3\u01F4\x07\x1C\x02\x02\u01F4O\x03\x02\x02\x02\u01F5" + - "\u01F6\x07\v\x02\x02\u01F6\u01FB\x05R*\x02\u01F7\u01F8\x07\"\x02\x02\u01F8" + - "\u01FA\x05R*\x02\u01F9\u01F7\x03\x02\x02\x02\u01FA\u01FD\x03\x02\x02\x02" + - "\u01FB\u01F9\x03\x02\x02\x02\u01FB\u01FC\x03\x02\x02\x02\u01FCQ\x03\x02" + - "\x02\x02\u01FD\u01FB\x03\x02\x02\x02\u01FE\u0200\x05\x14\v\x02\u01FF\u0201" + - "\x07;\x02\x02\u0200\u01FF\x03\x02\x02\x02\u0200\u0201\x03\x02\x02\x02" + - "\u0201\u0204\x03\x02\x02\x02\u0202\u0203\x07<\x02\x02\u0203\u0205\x07" + - "=\x02\x02\u0204\u0202\x03\x02\x02\x02\u0204\u0205\x03\x02\x02\x02\u0205" + - "S\x03\x02\x02\x02\u0206\u0207\x07\x0E\x02\x02\u0207\u0208\x05B\"\x02\u0208" + - "U\x03\x02\x02\x02\u0209\u020A\x07\x13\x02\x02\u020A\u020B\x05B\"\x02\u020B" + - "W\x03\x02\x02\x02\u020C\u020D\x07\x0F\x02\x02\u020D\u020E\x05B\"\x02\u020E" + - "Y\x03\x02\x02\x02\u020F\u0214\x05D#\x02\u0210\u0211\x07#\x02\x02\u0211" + - "\u0213\x05D#\x02\u0212\u0210\x03\x02\x02\x02\u0213\u0216\x03\x02\x02\x02" + - "\u0214\u0212\x03\x02\x02\x02\u0214\u0215\x03\x02\x02\x02\u0215[\x03\x02" + - "\x02\x02\u0216\u0214\x03\x02\x02\x02\u0217\u0218\x07\x10\x02\x02\u0218" + - "\u021D\x05^0\x02\u0219\u021A\x07\"\x02\x02\u021A\u021C\x05^0\x02\u021B" + - "\u0219\x03\x02\x02\x02\u021C\u021F\x03\x02\x02\x02\u021D\u021B\x03\x02" + - "\x02\x02\u021D\u021E\x03\x02\x02\x02\u021E]\x03\x02\x02\x02\u021F\u021D" + - "\x03\x02\x02\x02\u0220\u0221\x05@!\x02\u0221\u0222\x07,\x02\x02\u0222" + - "\u0223\x05Z.\x02\u0223_\x03\x02\x02\x02\u0224\u0225\x07\x03\x02\x02\u0225" + - "\u0226\x05B\"\x02\u0226\u0228\x05p9\x02\u0227\u0229\x05d3\x02\u0228\u0227" + - "\x03\x02\x02\x02\u0228\u0229\x03\x02\x02\x02\u0229a\x03\x02\x02\x02\u022A" + - "\u022B\x07\x04\x02\x02\u022B\u022C\x05B\"\x02\u022C\u022D\x05p9\x02\u022D" + - "c\x03\x02\x02\x02\u022E\u0233\x05f4\x02\u022F\u0230\x07\"\x02\x02\u0230" + - "\u0232\x05f4\x02\u0231\u022F\x03\x02\x02\x02\u0232\u0235\x03\x02\x02\x02" + - "\u0233\u0231\x03\x02\x02\x02\u0233\u0234\x03\x02\x02\x02\u0234e\x03\x02" + - "\x02\x02\u0235\u0233\x03\x02\x02\x02\u0236\u0237\x05D#\x02\u0237\u0238" + - "\x07!\x02\x02\u0238"; - private static readonly _serializedATNSegment1: string = - "\u0239\x05J&\x02\u0239g\x03\x02\x02\x02\u023A\u023B\x073\x02\x02\u023B" + - "i\x03\x02\x02\x02\u023C\u023F\x07\x1D\x02\x02\u023D\u023F\x07\x1C\x02" + - "\x02\u023E\u023C\x03\x02\x02\x02\u023E\u023D\x03\x02\x02\x02\u023Fk\x03" + - "\x02\x02\x02\u0240\u0241\x07\x1D\x02\x02\u0241m\x03\x02\x02\x02\u0242" + - "\u0243\x07\x1C\x02\x02\u0243o\x03\x02\x02\x02\u0244\u0245\x07\x1B\x02" + - "\x02\u0245q\x03\x02\x02\x02\u0246\u0247\x074\x02\x02\u0247s\x03\x02\x02" + - "\x02\u0248\u0249\x07\x06\x02\x02\u0249\u024A\x05v<\x02\u024Au\x03\x02" + - "\x02\x02\u024B\u024C\x07%\x02\x02\u024C\u024D\x05\x04\x03\x02\u024D\u024E" + - "\x07&\x02\x02\u024Ew\x03\x02\x02\x02\u024F\u0250\x07\x11\x02\x02\u0250" + - "\u0254\x071\x02\x02\u0251\u0252\x07\x11\x02\x02\u0252\u0254\x072\x02\x02" + - "\u0253\u024F\x03\x02\x02\x02\u0253\u0251\x03\x02\x02\x02\u0254y\x03\x02" + - "\x02\x02<\x85\x8C\x9B\xA1\xA9\xAC\xB1\xC2\xCB\xD1\xDA\xDD\xE4\xE8\xF0" + - "\xF2\xF9\u0101\u0103\u0108\u010F\u0114\u0118\u0125\u0128\u0133\u0136\u0143" + - "\u014B\u014D\u015E\u0161\u0165\u016F\u0177\u0183\u0187\u0190\u019A\u019E" + - "\u01A7\u01AF\u01B6\u01BE\u01D1\u01DC\u01E7\u01EC\u01F0\u01FB\u0200\u0204" + - "\u0214\u021D\u0228\u0233\u023E\u0253"; - public static readonly _serializedATN: string = Utils.join( - [ - esql_parser._serializedATNSegment0, - esql_parser._serializedATNSegment1, - ], - "", - ); + "\x04,\t,\x04-\t-\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x07\x03d\n\x03\f\x03\x0E\x03g\v\x03\x03\x04\x03\x04\x03" + + "\x04\x05\x04l\n\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05z\n\x05\x03\x06\x03" + + "\x06\x03\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05" + + "\x07\x86\n\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x07\x07\x8D\n\x07" + + "\f\x07\x0E\x07\x90\v\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x05\x07" + + "\x97\n\x07\x03\x07\x03\x07\x05\x07\x9B\n\x07\x03\x07\x03\x07\x03\x07\x03" + + "\x07\x03\x07\x03\x07\x07\x07\xA3\n\x07\f\x07\x0E\x07\xA6\v\x07\x03\b\x03" + + "\b\x05\b\xAA\n\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b\xB1\n\b\x03\b\x03" + + "\b\x03\b\x05\b\xB6\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x05\t\xBD\n\t\x03" + + "\n\x03\n\x03\n\x03\n\x05\n\xC3\n\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n" + + "\x07\n\xCB\n\n\f\n\x0E\n\xCE\v\n\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03" + + "\v\x05\v\xD7\n\v\x03\f\x03\f\x03\f\x03\f\x03\f\x03\f\x07\f\xDF\n\f\f\f" + + "\x0E\f\xE2\v\f\x05\f\xE4\n\f\x03\f\x03\f\x03\r\x03\r\x03\r\x03\x0E\x03" + + "\x0E\x03\x0E\x07\x0E\xEE\n\x0E\f\x0E\x0E\x0E\xF1\v\x0E\x03\x0F\x03\x0F" + + "\x03\x0F\x03\x0F\x03\x0F\x05\x0F\xF8\n\x0F\x03\x10\x03\x10\x03\x10\x03" + + "\x10\x07\x10\xFE\n\x10\f\x10\x0E\x10\u0101\v\x10\x03\x10\x05\x10\u0104" + + "\n\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\u010B\n\x11\f\x11" + + "\x0E\x11\u010E\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x13\x03" + + "\x13\x05\x13\u0117\n\x13\x03\x13\x03\x13\x05\x13\u011B\n\x13\x03\x14\x03" + + "\x14\x03\x14\x07\x14\u0120\n\x14\f\x14\x0E\x14\u0123\v\x14\x03\x15\x03" + + "\x15\x03\x16\x03\x16\x03\x16\x07\x16\u012A\n\x16\f\x16\x0E\x16\u012D\v" + + "\x16\x03\x17\x03\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03" + + "\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x07\x18\u013E\n\x18" + + "\f\x18\x0E\x18\u0141\v\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03" + + "\x18\x07\x18\u0149\n\x18\f\x18\x0E\x18\u014C\v\x18\x03\x18\x03\x18\x03" + + "\x18\x03\x18\x03\x18\x03\x18\x07\x18\u0154\n\x18\f\x18\x0E\x18\u0157\v" + + "\x18\x03\x18\x03\x18\x05\x18\u015B\n\x18\x03\x19\x03\x19\x03\x19\x03\x1A" + + "\x03\x1A\x03\x1A\x03\x1A\x07\x1A\u0164\n\x1A\f\x1A\x0E\x1A\u0167\v\x1A" + + "\x03\x1B\x03\x1B\x05\x1B\u016B\n\x1B\x03\x1B\x03\x1B\x05\x1B\u016F\n\x1B" + + "\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u0175\n\x1C\f\x1C\x0E\x1C\u0178" + + "\v\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u017E\n\x1C\f\x1C\x0E\x1C" + + "\u0181\v\x1C\x05\x1C\u0183\n\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x07\x1D" + + "\u0189\n\x1D\f\x1D\x0E\x1D\u018C\v\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E" + + "\x07\x1E\u0192\n\x1E\f\x1E\x0E\x1E\u0195\v\x1E\x03\x1F\x03\x1F\x03\x1F" + + "\x03\x1F\x03 \x03 \x03 \x03 \x05 \u019F\n \x03!\x03!\x03!\x03!\x03\"\x03" + + "\"\x03\"\x03#\x03#\x03#\x07#\u01AB\n#\f#\x0E#\u01AE\v#\x03$\x03$\x03$" + + "\x03$\x03%\x03%\x03&\x03&\x05&\u01B8\n&\x03\'\x05\'\u01BB\n\'\x03\'\x03" + + "\'\x03(\x05(\u01C0\n(\x03(\x03(\x03)\x03)\x03*\x03*\x03+\x03+\x03+\x03" + + "+\x05+\u01CC\n+\x03,\x03,\x03,\x03,\x05,\u01D2\n,\x03,\x03,\x03,\x03," + + "\x07,\u01D8\n,\f,\x0E,\u01DB\v,\x05,\u01DD\n,\x03-\x03-\x03-\x05-\u01E2" + + "\n-\x03-\x03-\x03-\x02\x02\x05\x04\f\x12.\x02\x02\x04\x02\x06\x02\b\x02" + + "\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C" + + "\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026" + + "\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02P\x02" + + "R\x02T\x02V\x02X\x02\x02\n\x03\x02:;\x03\x02<>\x03\x02JK\x03\x02AB\x04" + + "\x02\x1D\x1D \x03\x02#$\x04\x02\"\"00\x03\x0249\x02\u0204\x02Z\x03\x02" + + "\x02\x02\x04]\x03\x02\x02\x02\x06k\x03\x02\x02\x02\by\x03\x02\x02\x02" + + "\n{\x03\x02\x02\x02\f\x9A\x03\x02\x02\x02\x0E\xB5\x03\x02\x02\x02\x10" + + "\xBC\x03\x02\x02\x02\x12\xC2\x03\x02\x02\x02\x14\xD6\x03\x02\x02\x02\x16" + + "\xD8\x03\x02\x02\x02\x18\xE7\x03\x02\x02\x02\x1A\xEA\x03\x02\x02\x02\x1C" + + "\xF7\x03\x02\x02\x02\x1E\xF9\x03\x02\x02\x02 \u0105\x03\x02\x02\x02\"" + + "\u0111\x03\x02\x02\x02$\u0114\x03\x02\x02\x02&\u011C\x03\x02\x02\x02(" + + "\u0124\x03\x02\x02\x02*\u0126\x03\x02\x02\x02,\u012E\x03\x02\x02\x02." + + "\u015A\x03\x02\x02\x020\u015C\x03\x02\x02\x022\u015F\x03\x02\x02\x024" + + "\u0168\x03\x02\x02\x026\u0182\x03\x02\x02\x028\u0184\x03\x02\x02\x02:" + + "\u018D\x03\x02\x02\x02<\u0196\x03\x02\x02\x02>\u019A\x03\x02\x02\x02@" + + "\u01A0\x03\x02\x02\x02B\u01A4\x03\x02\x02\x02D\u01A7\x03\x02\x02\x02F" + + "\u01AF\x03\x02\x02\x02H\u01B3\x03\x02\x02\x02J\u01B7\x03\x02\x02\x02L" + + "\u01BA\x03\x02\x02\x02N\u01BF\x03\x02\x02\x02P\u01C3\x03\x02\x02\x02R" + + "\u01C5\x03\x02\x02\x02T\u01CB\x03\x02\x02\x02V\u01CD\x03\x02\x02\x02X" + + "\u01E1\x03\x02\x02\x02Z[\x05\x04\x03\x02[\\\x07\x02\x02\x03\\\x03\x03" + + "\x02\x02\x02]^\b\x03\x01\x02^_\x05\x06\x04\x02_e\x03\x02\x02\x02`a\f\x03" + + "\x02\x02ab\x07\x17\x02\x02bd\x05\b\x05\x02c`\x03\x02\x02\x02dg\x03\x02" + + "\x02\x02ec\x03\x02\x02\x02ef\x03\x02\x02\x02f\x05\x03\x02\x02\x02ge\x03" + + "\x02\x02\x02hl\x05\x1E\x10\x02il\x05\x18\r\x02jl\x05T+\x02kh\x03\x02\x02" + + "\x02ki\x03\x02\x02\x02kj\x03\x02\x02\x02l\x07\x03\x02\x02\x02mz\x05\"" + + "\x12\x02nz\x050\x19\x02oz\x056\x1C\x02pz\x052\x1A\x02qz\x05$\x13\x02r" + + "z\x05\n\x06\x02sz\x058\x1D\x02tz\x05:\x1E\x02uz\x05> \x02vz\x05@!\x02" + + "wz\x05V,\x02xz\x05B\"\x02ym\x03\x02\x02\x02yn\x03\x02\x02\x02yo\x03\x02" + + "\x02\x02yp\x03\x02\x02\x02yq\x03\x02\x02\x02yr\x03\x02\x02\x02ys\x03\x02" + + "\x02\x02yt\x03\x02\x02\x02yu\x03\x02\x02\x02yv\x03\x02\x02\x02yw\x03\x02" + + "\x02\x02yx\x03\x02\x02\x02z\t\x03\x02\x02\x02{|\x07\x12\x02\x02|}\x05" + + "\f\x07\x02}\v\x03\x02\x02\x02~\x7F\b\x07\x01\x02\x7F\x80\x07)\x02\x02" + + "\x80\x9B\x05\f\x07\t\x81\x9B\x05\x10\t\x02\x82\x9B\x05\x0E\b\x02\x83\x85" + + "\x05\x10\t\x02\x84\x86\x07)\x02\x02\x85\x84\x03\x02\x02\x02\x85\x86\x03" + + "\x02\x02\x02\x86\x87\x03\x02\x02\x02\x87\x88\x07&\x02\x02\x88\x89\x07" + + "%\x02\x02\x89\x8E\x05\x10\t\x02\x8A\x8B\x07\x1F\x02\x02\x8B\x8D\x05\x10" + + "\t\x02\x8C\x8A\x03\x02\x02\x02\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02" + + "\x02\x02\x8E\x8F\x03\x02\x02\x02\x8F\x91\x03\x02\x02\x02\x90\x8E\x03\x02" + + "\x02\x02\x91\x92\x07/\x02\x02\x92\x9B\x03\x02\x02\x02\x93\x94\x05\x10" + + "\t\x02\x94\x96\x07\'\x02\x02\x95\x97\x07)\x02\x02\x96\x95\x03\x02\x02" + + "\x02\x96\x97\x03\x02\x02\x02\x97\x98\x03\x02\x02\x02\x98\x99\x07*\x02" + + "\x02\x99\x9B\x03\x02\x02\x02\x9A~\x03\x02\x02\x02\x9A\x81\x03\x02\x02" + + "\x02\x9A\x82\x03\x02\x02\x02\x9A\x83\x03\x02\x02\x02\x9A\x93\x03\x02\x02" + + "\x02\x9B\xA4\x03\x02\x02\x02\x9C\x9D\f\x06\x02\x02\x9D\x9E\x07\x1C\x02" + + "\x02\x9E\xA3\x05\f\x07\x07\x9F\xA0\f\x05\x02\x02\xA0\xA1\x07,\x02\x02" + + "\xA1\xA3\x05\f\x07\x06\xA2\x9C\x03\x02\x02\x02\xA2\x9F\x03\x02\x02\x02" + + "\xA3\xA6\x03\x02\x02\x02\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02" + + "\xA5\r\x03\x02\x02\x02\xA6\xA4\x03\x02\x02\x02\xA7\xA9\x05\x10\t\x02\xA8" + + "\xAA\x07)\x02\x02\xA9\xA8\x03\x02\x02\x02\xA9\xAA\x03\x02\x02\x02\xAA" + + "\xAB\x03\x02\x02\x02\xAB\xAC\x07(\x02\x02\xAC\xAD\x05P)\x02\xAD\xB6\x03" + + "\x02\x02\x02\xAE\xB0\x05\x10\t\x02\xAF\xB1\x07)\x02\x02\xB0\xAF\x03\x02" + + "\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2\xB3\x07." + + "\x02\x02\xB3\xB4\x05P)\x02\xB4\xB6\x03\x02\x02\x02\xB5\xA7\x03\x02\x02" + + "\x02\xB5\xAE\x03\x02\x02\x02\xB6\x0F\x03\x02\x02\x02\xB7\xBD\x05\x12\n" + + "\x02\xB8\xB9\x05\x12\n\x02\xB9\xBA\x05R*\x02\xBA\xBB\x05\x12\n\x02\xBB" + + "\xBD\x03\x02\x02\x02\xBC\xB7\x03\x02\x02\x02\xBC\xB8\x03\x02\x02\x02\xBD" + + "\x11\x03\x02\x02\x02\xBE\xBF\b\n\x01\x02\xBF\xC3\x05\x14\v\x02\xC0\xC1" + + "\t\x02\x02\x02\xC1\xC3\x05\x12\n\x05\xC2\xBE\x03\x02\x02\x02\xC2\xC0\x03" + + "\x02\x02\x02\xC3\xCC\x03\x02\x02\x02\xC4\xC5\f\x04\x02\x02\xC5\xC6\t\x03" + + "\x02\x02\xC6\xCB\x05\x12\n\x05\xC7\xC8\f\x03\x02\x02\xC8\xC9\t\x02\x02" + + "\x02\xC9\xCB\x05\x12\n\x04\xCA\xC4\x03\x02\x02\x02\xCA\xC7\x03\x02\x02" + + "\x02\xCB\xCE\x03\x02\x02\x02\xCC\xCA\x03\x02\x02\x02\xCC\xCD\x03\x02\x02" + + "\x02\xCD\x13\x03\x02\x02\x02\xCE\xCC\x03\x02\x02\x02\xCF\xD7\x05.\x18" + + "\x02\xD0\xD7\x05*\x16\x02\xD1\xD7\x05\x16\f\x02\xD2\xD3\x07%\x02\x02\xD3" + + "\xD4\x05\f\x07\x02\xD4\xD5\x07/\x02\x02\xD5\xD7\x03\x02\x02\x02\xD6\xCF" + + "\x03\x02\x02\x02\xD6\xD0\x03\x02\x02\x02\xD6\xD1\x03\x02\x02\x02\xD6\xD2" + + "\x03\x02\x02\x02\xD7\x15\x03\x02\x02\x02\xD8\xD9\x05,\x17\x02\xD9\xE3" + + "\x07%\x02\x02\xDA\xE4\x07<\x02\x02\xDB\xE0\x05\f\x07\x02\xDC\xDD\x07\x1F" + + "\x02\x02\xDD\xDF\x05\f\x07\x02\xDE\xDC\x03\x02\x02\x02\xDF\xE2\x03\x02" + + "\x02\x02\xE0\xDE\x03\x02\x02\x02\xE0\xE1\x03\x02\x02\x02\xE1\xE4\x03\x02" + + "\x02\x02\xE2\xE0\x03\x02\x02\x02\xE3\xDA\x03\x02\x02\x02\xE3\xDB\x03\x02" + + "\x02\x02\xE3\xE4\x03\x02\x02\x02\xE4\xE5\x03\x02\x02\x02\xE5\xE6\x07/" + + "\x02\x02\xE6\x17\x03\x02\x02\x02\xE7\xE8\x07\x0E\x02\x02\xE8\xE9\x05\x1A" + + "\x0E\x02\xE9\x19\x03\x02\x02\x02\xEA\xEF\x05\x1C\x0F\x02\xEB\xEC\x07\x1F" + + "\x02\x02\xEC\xEE\x05\x1C\x0F\x02\xED\xEB\x03\x02\x02\x02\xEE\xF1\x03\x02" + + "\x02\x02\xEF\xED\x03\x02\x02\x02\xEF\xF0\x03\x02\x02\x02\xF0\x1B\x03\x02" + + "\x02\x02\xF1\xEF\x03\x02\x02\x02\xF2\xF8\x05\f\x07\x02\xF3\xF4\x05*\x16" + + "\x02\xF4\xF5\x07\x1E\x02\x02\xF5\xF6\x05\f\x07\x02\xF6\xF8\x03\x02\x02" + + "\x02\xF7\xF2\x03\x02\x02\x02\xF7\xF3\x03\x02\x02\x02\xF8\x1D\x03\x02\x02" + + "\x02\xF9\xFA\x07\x07\x02\x02\xFA\xFF\x05(\x15\x02\xFB\xFC\x07\x1F\x02" + + "\x02\xFC\xFE\x05(\x15\x02\xFD\xFB\x03\x02\x02\x02\xFE\u0101\x03\x02\x02" + + "\x02\xFF\xFD\x03\x02\x02\x02\xFF\u0100\x03\x02\x02\x02\u0100\u0103\x03" + + "\x02\x02\x02\u0101\xFF\x03\x02\x02\x02\u0102\u0104\x05 \x11\x02\u0103" + + "\u0102\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104\x1F\x03\x02\x02" + + "\x02\u0105\u0106\x07?\x02\x02\u0106\u0107\x07G\x02\x02\u0107\u010C\x05" + + "(\x15\x02\u0108\u0109\x07\x1F\x02\x02\u0109\u010B\x05(\x15\x02\u010A\u0108" + + "\x03\x02\x02\x02\u010B\u010E\x03\x02\x02\x02\u010C\u010A\x03\x02\x02\x02" + + "\u010C\u010D\x03\x02\x02\x02\u010D\u010F\x03\x02\x02\x02\u010E\u010C\x03" + + "\x02\x02\x02\u010F\u0110\x07@\x02\x02\u0110!\x03\x02\x02\x02\u0111\u0112" + + "\x07\x06\x02\x02\u0112\u0113\x05\x1A\x0E\x02\u0113#\x03\x02\x02\x02\u0114" + + "\u0116\x07\x11\x02\x02\u0115\u0117\x05\x1A\x0E\x02\u0116\u0115\x03\x02" + + "\x02\x02\u0116\u0117\x03\x02\x02\x02\u0117\u011A\x03\x02\x02\x02\u0118" + + "\u0119\x07\x1B\x02\x02\u0119\u011B\x05&\x14\x02\u011A\u0118\x03\x02\x02" + + "\x02\u011A\u011B\x03\x02\x02\x02\u011B%\x03\x02\x02\x02\u011C\u0121\x05" + + "*\x16\x02\u011D\u011E\x07\x1F\x02\x02\u011E\u0120\x05*\x16\x02\u011F\u011D" + + "\x03\x02\x02\x02\u0120\u0123\x03\x02\x02\x02\u0121\u011F\x03\x02\x02\x02" + + "\u0121\u0122\x03\x02\x02\x02\u0122\'\x03\x02\x02\x02\u0123\u0121\x03\x02" + + "\x02\x02\u0124\u0125\t\x04\x02\x02\u0125)\x03\x02\x02\x02\u0126\u012B" + + "\x05,\x17\x02\u0127\u0128\x07!\x02\x02\u0128\u012A\x05,\x17\x02\u0129" + + "\u0127\x03\x02\x02\x02\u012A\u012D\x03\x02\x02\x02\u012B\u0129\x03\x02" + + "\x02\x02\u012B\u012C\x03\x02\x02\x02\u012C+\x03\x02\x02\x02\u012D\u012B" + + "\x03\x02\x02\x02\u012E\u012F\t\x05\x02\x02\u012F-\x03\x02\x02\x02\u0130" + + "\u015B\x07*\x02\x02\u0131\u0132\x05N(\x02\u0132\u0133\x07A\x02\x02\u0133" + + "\u015B\x03\x02\x02\x02\u0134\u015B\x05L\'\x02\u0135\u015B\x05N(\x02\u0136" + + "\u015B\x05H%\x02\u0137\u015B\x07-\x02\x02\u0138\u015B\x05P)\x02\u0139" + + "\u013A\x07?\x02\x02\u013A\u013F\x05J&\x02\u013B\u013C\x07\x1F\x02\x02" + + "\u013C\u013E\x05J&\x02\u013D\u013B\x03\x02\x02\x02\u013E\u0141\x03\x02" + + "\x02\x02\u013F\u013D\x03\x02\x02\x02\u013F\u0140\x03\x02\x02\x02\u0140" + + "\u0142\x03\x02\x02\x02\u0141\u013F\x03\x02\x02\x02\u0142\u0143\x07@\x02" + + "\x02\u0143\u015B\x03\x02\x02\x02\u0144\u0145\x07?\x02\x02\u0145\u014A" + + "\x05H%\x02\u0146\u0147\x07\x1F\x02\x02\u0147\u0149\x05H%\x02\u0148\u0146" + + "\x03\x02\x02\x02\u0149\u014C\x03\x02\x02\x02\u014A\u0148\x03\x02\x02\x02" + + "\u014A\u014B\x03\x02\x02\x02\u014B\u014D\x03\x02\x02\x02\u014C\u014A\x03" + + "\x02\x02\x02\u014D\u014E\x07@\x02\x02\u014E\u015B\x03\x02\x02\x02\u014F" + + "\u0150\x07?\x02\x02\u0150\u0155\x05P)\x02\u0151\u0152\x07\x1F\x02\x02" + + "\u0152\u0154\x05P)\x02\u0153\u0151\x03\x02\x02\x02\u0154\u0157\x03\x02" + + "\x02\x02\u0155\u0153\x03\x02\x02\x02\u0155\u0156\x03\x02\x02\x02\u0156" + + "\u0158\x03\x02\x02\x02\u0157\u0155\x03\x02\x02\x02\u0158\u0159\x07@\x02" + + "\x02\u0159\u015B\x03\x02\x02\x02\u015A\u0130\x03\x02\x02\x02\u015A\u0131" + + "\x03\x02\x02\x02\u015A\u0134\x03\x02\x02\x02\u015A\u0135\x03\x02\x02\x02" + + "\u015A\u0136\x03\x02\x02\x02\u015A\u0137\x03\x02\x02\x02\u015A\u0138\x03" + + "\x02\x02\x02\u015A\u0139\x03\x02\x02\x02\u015A\u0144\x03\x02\x02\x02\u015A" + + "\u014F\x03\x02\x02\x02\u015B/\x03\x02\x02\x02\u015C\u015D\x07\n\x02\x02" + + "\u015D\u015E\x07\x19\x02\x02\u015E1\x03\x02\x02\x02\u015F\u0160\x07\x10" + + "\x02\x02\u0160\u0165\x054\x1B\x02\u0161\u0162\x07\x1F\x02\x02\u0162\u0164" + + "\x054\x1B\x02\u0163\u0161\x03\x02\x02\x02\u0164\u0167\x03\x02\x02\x02" + + "\u0165\u0163\x03\x02\x02\x02\u0165\u0166\x03\x02\x02\x02\u01663\x03\x02" + + "\x02\x02\u0167\u0165\x03\x02\x02\x02\u0168\u016A\x05\f\x07\x02\u0169\u016B" + + "\t\x06\x02\x02\u016A\u0169\x03\x02\x02\x02\u016A\u016B\x03\x02\x02\x02" + + "\u016B\u016E\x03\x02\x02\x02\u016C\u016D\x07+\x02\x02\u016D\u016F\t\x07" + + "\x02\x02\u016E\u016C\x03\x02\x02\x02\u016E\u016F\x03\x02\x02\x02\u016F" + + "5\x03\x02\x02\x02\u0170\u0171\x07\t\x02\x02\u0171\u0176\x05(\x15\x02\u0172" + + "\u0173\x07\x1F\x02\x02\u0173\u0175\x05(\x15\x02\u0174\u0172\x03\x02\x02" + + "\x02\u0175\u0178\x03\x02\x02\x02\u0176\u0174\x03\x02\x02\x02\u0176\u0177" + + "\x03\x02\x02\x02\u0177\u0183\x03\x02\x02\x02\u0178\u0176\x03\x02\x02\x02" + + "\u0179\u017A\x07\f\x02\x02\u017A\u017F\x05(\x15\x02\u017B\u017C\x07\x1F" + + "\x02\x02\u017C\u017E\x05(\x15\x02\u017D\u017B\x03\x02\x02\x02\u017E\u0181" + + "\x03\x02\x02\x02\u017F\u017D\x03\x02\x02\x02\u017F\u0180\x03\x02\x02\x02" + + "\u0180\u0183\x03\x02\x02\x02\u0181\u017F\x03\x02\x02\x02\u0182\u0170\x03" + + "\x02\x02\x02\u0182\u0179\x03\x02\x02\x02\u01837\x03\x02\x02\x02\u0184" + + "\u0185\x07\x04\x02\x02\u0185\u018A\x05(\x15\x02\u0186\u0187\x07\x1F\x02" + + "\x02\u0187\u0189\x05(\x15\x02\u0188\u0186\x03\x02\x02\x02\u0189\u018C" + + "\x03\x02\x02\x02\u018A\u0188\x03\x02\x02\x02\u018A\u018B\x03\x02\x02\x02" + + "\u018B9\x03\x02\x02\x02\u018C\u018A\x03\x02\x02\x02\u018D\u018E\x07\r" + + "\x02\x02\u018E\u0193\x05<\x1F\x02\u018F\u0190\x07\x1F\x02\x02\u0190\u0192" + + "\x05<\x1F\x02\u0191\u018F\x03\x02\x02\x02\u0192\u0195\x03\x02\x02\x02" + + "\u0193\u0191\x03\x02\x02\x02\u0193\u0194\x03\x02\x02\x02\u0194;\x03\x02" + + "\x02\x02\u0195\u0193\x03\x02\x02\x02\u0196\u0197\x05(\x15\x02\u0197\u0198" + + "\x07F\x02\x02\u0198\u0199\x05(\x15\x02\u0199=\x03\x02\x02\x02\u019A\u019B" + + "\x07\x03\x02\x02\u019B\u019C\x05\x14\v\x02\u019C\u019E\x05P)\x02\u019D" + + "\u019F\x05D#\x02\u019E\u019D\x03\x02\x02\x02\u019E\u019F\x03\x02\x02\x02" + + "\u019F?\x03\x02\x02\x02\u01A0\u01A1\x07\b\x02\x02\u01A1\u01A2\x05\x14" + + "\v\x02\u01A2\u01A3\x05P)\x02\u01A3A\x03\x02\x02\x02\u01A4\u01A5\x07\v" + + "\x02\x02\u01A5\u01A6\x05(\x15\x02\u01A6C\x03\x02\x02\x02\u01A7\u01AC\x05" + + "F$\x02\u01A8\u01A9\x07\x1F\x02\x02\u01A9\u01AB\x05F$\x02\u01AA\u01A8\x03" + + "\x02\x02\x02\u01AB\u01AE\x03\x02\x02\x02\u01AC\u01AA\x03\x02\x02\x02\u01AC" + + "\u01AD\x03\x02\x02\x02\u01ADE\x03\x02\x02\x02\u01AE\u01AC\x03\x02\x02" + + "\x02\u01AF\u01B0\x05,\x17\x02\u01B0\u01B1\x07\x1E\x02\x02\u01B1\u01B2" + + "\x05.\x18\x02\u01B2G\x03\x02\x02\x02\u01B3\u01B4\t\b\x02\x02\u01B4I\x03" + + "\x02\x02\x02\u01B5\u01B8\x05L\'\x02\u01B6\u01B8\x05N(\x02\u01B7\u01B5" + + "\x03\x02\x02\x02\u01B7\u01B6\x03\x02\x02\x02\u01B8K\x03\x02\x02\x02\u01B9" + + "\u01BB\t\x02\x02\x02\u01BA\u01B9\x03\x02\x02\x02\u01BA\u01BB\x03\x02\x02" + + "\x02\u01BB\u01BC\x03\x02\x02\x02\u01BC\u01BD\x07\x1A\x02\x02\u01BDM\x03" + + "\x02\x02\x02\u01BE\u01C0\t\x02\x02\x02\u01BF\u01BE\x03\x02\x02\x02\u01BF" + + "\u01C0\x03\x02\x02\x02\u01C0\u01C1\x03\x02\x02\x02\u01C1\u01C2\x07\x19" + + "\x02\x02\u01C2O\x03\x02\x02\x02\u01C3\u01C4\x07\x18\x02\x02\u01C4Q\x03" + + "\x02\x02\x02\u01C5\u01C6\t\t\x02\x02\u01C6S\x03\x02\x02\x02\u01C7\u01C8" + + "\x07\x0F\x02\x02\u01C8\u01CC\x071\x02\x02\u01C9\u01CA\x07\x0F\x02\x02" + + "\u01CA\u01CC\x072\x02\x02\u01CB\u01C7\x03\x02\x02\x02\u01CB\u01C9\x03" + + "\x02\x02\x02\u01CCU\x03\x02\x02\x02\u01CD\u01CE\x07\x05\x02\x02\u01CE" + + "\u01D1\x05(\x15\x02\u01CF\u01D0\x07H\x02\x02\u01D0\u01D2\x05(\x15\x02" + + "\u01D1\u01CF\x03\x02\x02\x02\u01D1\u01D2\x03\x02\x02\x02\u01D2\u01DC\x03" + + "\x02\x02\x02\u01D3\u01D4\x07I\x02\x02\u01D4\u01D9\x05X-\x02\u01D5\u01D6" + + "\x07\x1F\x02\x02\u01D6\u01D8\x05X-\x02\u01D7\u01D5\x03\x02\x02\x02\u01D8" + + "\u01DB\x03\x02\x02\x02\u01D9\u01D7\x03\x02\x02\x02\u01D9\u01DA\x03\x02" + + "\x02\x02\u01DA\u01DD\x03\x02\x02\x02\u01DB\u01D9\x03\x02\x02\x02\u01DC" + + "\u01D3\x03\x02\x02\x02\u01DC\u01DD\x03\x02\x02\x02\u01DDW\x03\x02\x02" + + "\x02\u01DE\u01DF\x05(\x15\x02\u01DF\u01E0\x07\x1E\x02\x02\u01E0\u01E2" + + "\x03\x02\x02\x02\u01E1\u01DE\x03\x02\x02\x02\u01E1\u01E2\x03\x02\x02\x02" + + "\u01E2\u01E3\x03\x02\x02\x02\u01E3\u01E4\x05(\x15\x02\u01E4Y\x03\x02\x02" + + "\x024eky\x85\x8E\x96\x9A\xA2\xA4\xA9\xB0\xB5\xBC\xC2\xCA\xCC\xD6\xE0\xE3" + + "\xEF\xF7\xFF\u0103\u010C\u0116\u011A\u0121\u012B\u013F\u014A\u0155\u015A" + + "\u0165\u016A\u016E\u0176\u017F\u0182\u018A\u0193\u019E\u01AC\u01B7\u01BA" + + "\u01BF\u01CB\u01D1\u01D9\u01DC\u01E1"; public static __ATN: ATN; public static get _ATN(): ATN { if (!esql_parser.__ATN) { @@ -3621,9 +2981,6 @@ export class CompositeQueryContext extends QueryContext { export class SourceCommandContext extends ParserRuleContext { - public explainCommand(): ExplainCommandContext | undefined { - return this.tryGetRuleContext(0, ExplainCommandContext); - } public fromCommand(): FromCommandContext | undefined { return this.tryGetRuleContext(0, FromCommandContext); } @@ -3660,39 +3017,36 @@ export class ProcessingCommandContext extends ParserRuleContext { public limitCommand(): LimitCommandContext | undefined { return this.tryGetRuleContext(0, LimitCommandContext); } - public projectCommand(): ProjectCommandContext | undefined { - return this.tryGetRuleContext(0, ProjectCommandContext); - } public keepCommand(): KeepCommandContext | undefined { return this.tryGetRuleContext(0, KeepCommandContext); } - public renameCommand(): RenameCommandContext | undefined { - return this.tryGetRuleContext(0, RenameCommandContext); + public sortCommand(): SortCommandContext | undefined { + return this.tryGetRuleContext(0, SortCommandContext); + } + public statsCommand(): StatsCommandContext | undefined { + return this.tryGetRuleContext(0, StatsCommandContext); + } + public whereCommand(): WhereCommandContext | undefined { + return this.tryGetRuleContext(0, WhereCommandContext); } public dropCommand(): DropCommandContext | undefined { return this.tryGetRuleContext(0, DropCommandContext); } + public renameCommand(): RenameCommandContext | undefined { + return this.tryGetRuleContext(0, RenameCommandContext); + } public dissectCommand(): DissectCommandContext | undefined { return this.tryGetRuleContext(0, DissectCommandContext); } public grokCommand(): GrokCommandContext | undefined { return this.tryGetRuleContext(0, GrokCommandContext); } - public sortCommand(): SortCommandContext | undefined { - return this.tryGetRuleContext(0, SortCommandContext); - } - public statsCommand(): StatsCommandContext | undefined { - return this.tryGetRuleContext(0, StatsCommandContext); - } - public whereCommand(): WhereCommandContext | undefined { - return this.tryGetRuleContext(0, WhereCommandContext); + public enrichCommand(): EnrichCommandContext | undefined { + return this.tryGetRuleContext(0, EnrichCommandContext); } public mvExpandCommand(): MvExpandCommandContext | undefined { return this.tryGetRuleContext(0, MvExpandCommandContext); } - public enrichCommand(): EnrichCommandContext | undefined { - return this.tryGetRuleContext(0, EnrichCommandContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -3713,153 +3067,138 @@ export class ProcessingCommandContext extends ParserRuleContext { } -export class EnrichCommandContext extends ParserRuleContext { - public _policyName: EnrichIdentifierContext; - public _matchField: EnrichFieldIdentifierContext; - public ENRICH(): TerminalNode { return this.getToken(esql_parser.ENRICH, 0); } - public enrichIdentifier(): EnrichIdentifierContext { - return this.getRuleContext(0, EnrichIdentifierContext); - } - public ON(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ON, 0); } - public WITH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WITH, 0); } - public enrichWithClause(): EnrichWithClauseContext[]; - public enrichWithClause(i: number): EnrichWithClauseContext; - public enrichWithClause(i?: number): EnrichWithClauseContext | EnrichWithClauseContext[] { - if (i === undefined) { - return this.getRuleContexts(EnrichWithClauseContext); - } else { - return this.getRuleContext(i, EnrichWithClauseContext); - } - } - public enrichFieldIdentifier(): EnrichFieldIdentifierContext | undefined { - return this.tryGetRuleContext(0, EnrichFieldIdentifierContext); - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } +export class WhereCommandContext extends ParserRuleContext { + public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichCommand; } + public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichCommand) { - listener.enterEnrichCommand(this); + if (listener.enterWhereCommand) { + listener.enterWhereCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichCommand) { - listener.exitEnrichCommand(this); + if (listener.exitWhereCommand) { + listener.exitWhereCommand(this); } } } -export class EnrichWithClauseContext extends ParserRuleContext { - public _newName: EnrichFieldIdentifierContext; - public _enrichField: EnrichFieldIdentifierContext; - public enrichFieldIdentifier(): EnrichFieldIdentifierContext[]; - public enrichFieldIdentifier(i: number): EnrichFieldIdentifierContext; - public enrichFieldIdentifier(i?: number): EnrichFieldIdentifierContext | EnrichFieldIdentifierContext[] { - if (i === undefined) { - return this.getRuleContexts(EnrichFieldIdentifierContext); - } else { - return this.getRuleContext(i, EnrichFieldIdentifierContext); - } - } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } +export class BooleanExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichWithClause; } + public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } + public copyFrom(ctx: BooleanExpressionContext): void { + super.copyFrom(ctx); + } +} +export class LogicalNotContext extends BooleanExpressionContext { + public NOT(): TerminalNode { return this.getToken(esql_parser.NOT, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); + } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichWithClause) { - listener.enterEnrichWithClause(this); + if (listener.enterLogicalNot) { + listener.enterLogicalNot(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichWithClause) { - listener.exitEnrichWithClause(this); + if (listener.exitLogicalNot) { + listener.exitLogicalNot(this); } } } - - -export class MvExpandCommandContext extends ParserRuleContext { - public MV_EXPAND(): TerminalNode { return this.getToken(esql_parser.MV_EXPAND, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); +export class BooleanDefaultContext extends BooleanExpressionContext { + public valueExpression(): ValueExpressionContext { + return this.getRuleContext(0, ValueExpressionContext); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mvExpandCommand; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterBooleanDefault) { + listener.enterBooleanDefault(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitBooleanDefault) { + listener.exitBooleanDefault(this); + } + } +} +export class RegexExpressionContext extends BooleanExpressionContext { + public regexBooleanExpression(): RegexBooleanExpressionContext { + return this.getRuleContext(0, RegexBooleanExpressionContext); + } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMvExpandCommand) { - listener.enterMvExpandCommand(this); + if (listener.enterRegexExpression) { + listener.enterRegexExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMvExpandCommand) { - listener.exitMvExpandCommand(this); + if (listener.exitRegexExpression) { + listener.exitRegexExpression(this); } } } - - -export class WhereCommandContext extends ParserRuleContext { - public WHERE(): TerminalNode { return this.getToken(esql_parser.WHERE, 0); } - public whereBooleanExpression(): WhereBooleanExpressionContext { - return this.getRuleContext(0, WhereBooleanExpressionContext); +export class LogicalBinaryContext extends BooleanExpressionContext { + public _left: BooleanExpressionContext; + public _operator: Token; + public _right: BooleanExpressionContext; + public booleanExpression(): BooleanExpressionContext[]; + public booleanExpression(i: number): BooleanExpressionContext; + public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(BooleanExpressionContext); + } else { + return this.getRuleContext(i, BooleanExpressionContext); + } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } + public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_whereCommand; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterWhereCommand) { - listener.enterWhereCommand(this); + if (listener.enterLogicalBinary) { + listener.enterLogicalBinary(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitWhereCommand) { - listener.exitWhereCommand(this); + if (listener.exitLogicalBinary) { + listener.exitLogicalBinary(this); } } } - - -export class WhereBooleanExpressionContext extends ParserRuleContext { - public _left: WhereBooleanExpressionContext; - public _operator: Token; - public _right: WhereBooleanExpressionContext; - public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } - public whereBooleanExpression(): WhereBooleanExpressionContext[]; - public whereBooleanExpression(i: number): WhereBooleanExpressionContext; - public whereBooleanExpression(i?: number): WhereBooleanExpressionContext | WhereBooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(WhereBooleanExpressionContext); - } else { - return this.getRuleContext(i, WhereBooleanExpressionContext); - } - } +export class LogicalInContext extends BooleanExpressionContext { public valueExpression(): ValueExpressionContext[]; public valueExpression(i: number): ValueExpressionContext; public valueExpression(i?: number): ValueExpressionContext | ValueExpressionContext[] { @@ -3869,14 +3208,10 @@ export class WhereBooleanExpressionContext extends ParserRuleContext { return this.getRuleContext(i, ValueExpressionContext); } } - public regexBooleanExpression(): RegexBooleanExpressionContext | undefined { - return this.tryGetRuleContext(0, RegexBooleanExpressionContext); - } - public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } - public IN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IN, 0); } - public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } - public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } + public IN(): TerminalNode { return this.getToken(esql_parser.IN, 0); } + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -3886,75 +3221,44 @@ export class WhereBooleanExpressionContext extends ParserRuleContext { return this.getToken(esql_parser.COMMA, i); } } - public WHERE_FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WHERE_FUNCTIONS, 0); } - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public functionExpressionArgument(): FunctionExpressionArgumentContext[]; - public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; - public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, FunctionExpressionArgumentContext); - } - } - public IS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.IS, 0); } - public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_whereBooleanExpression; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterWhereBooleanExpression) { - listener.enterWhereBooleanExpression(this); + if (listener.enterLogicalIn) { + listener.enterLogicalIn(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitWhereBooleanExpression) { - listener.exitWhereBooleanExpression(this); + if (listener.exitLogicalIn) { + listener.exitLogicalIn(this); } } } - - -export class BooleanExpressionContext extends ParserRuleContext { - public _left: BooleanExpressionContext; - public _operator: Token; - public _right: BooleanExpressionContext; - public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } - public booleanExpression(): BooleanExpressionContext[]; - public booleanExpression(i: number): BooleanExpressionContext; - public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(BooleanExpressionContext); - } else { - return this.getRuleContext(i, BooleanExpressionContext); - } - } - public valueExpression(): ValueExpressionContext | undefined { - return this.tryGetRuleContext(0, ValueExpressionContext); +export class IsNullContext extends BooleanExpressionContext { + public valueExpression(): ValueExpressionContext { + return this.getRuleContext(0, ValueExpressionContext); } - public AND(): TerminalNode | undefined { return this.tryGetToken(esql_parser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OR, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public IS(): TerminalNode { return this.getToken(esql_parser.IS, 0); } + public NULL(): TerminalNode { return this.getToken(esql_parser.NULL, 0); } + public NOT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NOT, 0); } + constructor(ctx: BooleanExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_booleanExpression; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterBooleanExpression) { - listener.enterBooleanExpression(this); + if (listener.enterIsNull) { + listener.enterIsNull(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitBooleanExpression) { - listener.exitBooleanExpression(this); + if (listener.exitIsNull) { + listener.exitIsNull(this); } } } @@ -3993,33 +3297,37 @@ export class RegexBooleanExpressionContext extends ParserRuleContext { export class ValueExpressionContext extends ParserRuleContext { - public operatorExpression(): OperatorExpressionContext | undefined { - return this.tryGetRuleContext(0, OperatorExpressionContext); - } - public comparison(): ComparisonContext | undefined { - return this.tryGetRuleContext(0, ComparisonContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override public get ruleIndex(): number { return esql_parser.RULE_valueExpression; } + public copyFrom(ctx: ValueExpressionContext): void { + super.copyFrom(ctx); + } +} +export class ValueExpressionDefaultContext extends ValueExpressionContext { + public operatorExpression(): OperatorExpressionContext { + return this.getRuleContext(0, OperatorExpressionContext); + } + constructor(ctx: ValueExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterValueExpression) { - listener.enterValueExpression(this); + if (listener.enterValueExpressionDefault) { + listener.enterValueExpressionDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitValueExpression) { - listener.exitValueExpression(this); + if (listener.exitValueExpressionDefault) { + listener.exitValueExpressionDefault(this); } } } - - -export class ComparisonContext extends ParserRuleContext { +export class ComparisonContext extends ValueExpressionContext { public _left: OperatorExpressionContext; public _right: OperatorExpressionContext; public comparisonOperator(): ComparisonOperatorContext { @@ -4034,12 +3342,11 @@ export class ComparisonContext extends ParserRuleContext { return this.getRuleContext(i, OperatorExpressionContext); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ValueExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_comparison; } - // @Override public enterRule(listener: esql_parserListener): void { if (listener.enterComparison) { listener.enterComparison(this); @@ -4054,178 +3361,203 @@ export class ComparisonContext extends ParserRuleContext { } -export class MathFnContext extends ParserRuleContext { - public functionIdentifier(): FunctionIdentifierContext { - return this.getRuleContext(0, FunctionIdentifierContext); - } - public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } - public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } - public functionExpressionArgument(): FunctionExpressionArgumentContext[]; - public functionExpressionArgument(i: number): FunctionExpressionArgumentContext; - public functionExpressionArgument(i?: number): FunctionExpressionArgumentContext | FunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, FunctionExpressionArgumentContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } - } +export class OperatorExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFn; } + public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + public copyFrom(ctx: OperatorExpressionContext): void { + super.copyFrom(ctx); + } +} +export class OperatorExpressionDefaultContext extends OperatorExpressionContext { + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); + } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFn) { - listener.enterMathFn(this); + if (listener.enterOperatorExpressionDefault) { + listener.enterOperatorExpressionDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFn) { - listener.exitMathFn(this); + if (listener.exitOperatorExpressionDefault) { + listener.exitOperatorExpressionDefault(this); } } } - - -export class MathEvalFnContext extends ParserRuleContext { - public mathFunctionIdentifier(): MathFunctionIdentifierContext { - return this.getRuleContext(0, MathFunctionIdentifierContext); +export class ArithmeticUnaryContext extends OperatorExpressionContext { + public _operator: Token; + public operatorExpression(): OperatorExpressionContext { + return this.getRuleContext(0, OperatorExpressionContext); } - public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } - public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } - public mathFunctionExpressionArgument(): MathFunctionExpressionArgumentContext[]; - public mathFunctionExpressionArgument(i: number): MathFunctionExpressionArgumentContext; - public mathFunctionExpressionArgument(i?: number): MathFunctionExpressionArgumentContext | MathFunctionExpressionArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(MathFunctionExpressionArgumentContext); - } else { - return this.getRuleContext(i, MathFunctionExpressionArgumentContext); + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterArithmeticUnary) { + listener.enterArithmeticUnary(this); } } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitArithmeticUnary) { + listener.exitArithmeticUnary(this); + } + } +} +export class ArithmeticBinaryContext extends OperatorExpressionContext { + public _left: OperatorExpressionContext; + public _operator: Token; + public _right: OperatorExpressionContext; + public operatorExpression(): OperatorExpressionContext[]; + public operatorExpression(i: number): OperatorExpressionContext; + public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { if (i === undefined) { - return this.getTokens(esql_parser.COMMA); + return this.getRuleContexts(OperatorExpressionContext); } else { - return this.getToken(esql_parser.COMMA, i); + return this.getRuleContext(i, OperatorExpressionContext); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } + public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } + public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } + constructor(ctx: OperatorExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathEvalFn; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathEvalFn) { - listener.enterMathEvalFn(this); + if (listener.enterArithmeticBinary) { + listener.enterArithmeticBinary(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathEvalFn) { - listener.exitMathEvalFn(this); + if (listener.exitArithmeticBinary) { + listener.exitArithmeticBinary(this); } } } -export class DateExpressionContext extends ParserRuleContext { - public _quantifier: NumberContext; - public DATE_LITERAL(): TerminalNode { return this.getToken(esql_parser.DATE_LITERAL, 0); } - public number(): NumberContext { - return this.getRuleContext(0, NumberContext); - } +export class PrimaryExpressionContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_dateExpression; } + public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + public copyFrom(ctx: PrimaryExpressionContext): void { + super.copyFrom(ctx); + } +} +export class ConstantDefaultContext extends PrimaryExpressionContext { + public constant(): ConstantContext { + return this.getRuleContext(0, ConstantContext); + } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterDateExpression) { - listener.enterDateExpression(this); + if (listener.enterConstantDefault) { + listener.enterConstantDefault(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitDateExpression) { - listener.exitDateExpression(this); + if (listener.exitConstantDefault) { + listener.exitConstantDefault(this); } } } - - -export class OperatorExpressionContext extends ParserRuleContext { - public _left: OperatorExpressionContext; - public _operator: Token; - public _right: OperatorExpressionContext; - public primaryExpression(): PrimaryExpressionContext | undefined { - return this.tryGetRuleContext(0, PrimaryExpressionContext); +export class DereferenceContext extends PrimaryExpressionContext { + public qualifiedName(): QualifiedNameContext { + return this.getRuleContext(0, QualifiedNameContext); } - public mathFn(): MathFnContext | undefined { - return this.tryGetRuleContext(0, MathFnContext); + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } - public mathEvalFn(): MathEvalFnContext | undefined { - return this.tryGetRuleContext(0, MathEvalFnContext); + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterDereference) { + listener.enterDereference(this); + } } - public operatorExpression(): OperatorExpressionContext[]; - public operatorExpression(i: number): OperatorExpressionContext; - public operatorExpression(i?: number): OperatorExpressionContext | OperatorExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(OperatorExpressionContext); - } else { - return this.getRuleContext(i, OperatorExpressionContext); + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitDereference) { + listener.exitDereference(this); } } - public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } - public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } - public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } - public SLASH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SLASH, 0); } - public PERCENT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PERCENT, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +} +export class FunctionContext extends PrimaryExpressionContext { + public functionExpression(): FunctionExpressionContext { + return this.getRuleContext(0, FunctionExpressionContext); + } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_operatorExpression; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterFunction) { + listener.enterFunction(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitFunction) { + listener.exitFunction(this); + } + } +} +export class ParenthesizedExpressionContext extends PrimaryExpressionContext { + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public booleanExpression(): BooleanExpressionContext { + return this.getRuleContext(0, BooleanExpressionContext); + } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + constructor(ctx: PrimaryExpressionContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterOperatorExpression) { - listener.enterOperatorExpression(this); + if (listener.enterParenthesizedExpression) { + listener.enterParenthesizedExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitOperatorExpression) { - listener.exitOperatorExpression(this); + if (listener.exitParenthesizedExpression) { + listener.exitParenthesizedExpression(this); } } } -export class PrimaryExpressionContext extends ParserRuleContext { - public constant(): ConstantContext | undefined { - return this.tryGetRuleContext(0, ConstantContext); - } - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public dateExpression(): DateExpressionContext | undefined { - return this.tryGetRuleContext(0, DateExpressionContext); +export class FunctionExpressionContext extends ParserRuleContext { + public identifier(): IdentifierContext { + return this.getRuleContext(0, IdentifierContext); } - public LP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LP, 0); } + public LP(): TerminalNode { return this.getToken(esql_parser.LP, 0); } + public RP(): TerminalNode { return this.getToken(esql_parser.RP, 0); } + public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } public booleanExpression(): BooleanExpressionContext[]; public booleanExpression(i: number): BooleanExpressionContext; public booleanExpression(i?: number): BooleanExpressionContext | BooleanExpressionContext[] { @@ -4235,10 +3567,6 @@ export class PrimaryExpressionContext extends ParserRuleContext { return this.getRuleContext(i, BooleanExpressionContext); } } - public RP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.RP, 0); } - public identifier(): IdentifierContext | undefined { - return this.tryGetRuleContext(0, IdentifierContext); - } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -4252,17 +3580,17 @@ export class PrimaryExpressionContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_primaryExpression; } + public get ruleIndex(): number { return esql_parser.RULE_functionExpression; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterPrimaryExpression) { - listener.enterPrimaryExpression(this); + if (listener.enterFunctionExpression) { + listener.enterFunctionExpression(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitPrimaryExpression) { - listener.exitPrimaryExpression(this); + if (listener.exitFunctionExpression) { + listener.exitFunctionExpression(this); } } } @@ -4336,72 +3664,25 @@ export class FieldContext extends ParserRuleContext { public booleanExpression(): BooleanExpressionContext { return this.getRuleContext(0, BooleanExpressionContext); } - public userVariable(): UserVariableContext | undefined { - return this.tryGetRuleContext(0, UserVariableContext); - } - public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_field; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterField) { - listener.enterField(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitField) { - listener.exitField(this); - } - } -} - - -export class EnrichFieldIdentifierContext extends ParserRuleContext { - public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } - public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichFieldIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichFieldIdentifier) { - listener.enterEnrichFieldIdentifier(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichFieldIdentifier) { - listener.exitEnrichFieldIdentifier(this); - } - } -} - - -export class UserVariableContext extends ParserRuleContext { - public identifier(): IdentifierContext { - return this.getRuleContext(0, IdentifierContext); + public qualifiedName(): QualifiedNameContext | undefined { + return this.tryGetRuleContext(0, QualifiedNameContext); } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_userVariable; } + public get ruleIndex(): number { return esql_parser.RULE_field; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterUserVariable) { - listener.enterUserVariable(this); + if (listener.enterField) { + listener.enterField(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitUserVariable) { - listener.exitUserVariable(this); + if (listener.exitField) { + listener.exitField(this); } } } @@ -4523,8 +3804,8 @@ export class StatsCommandContext extends ParserRuleContext { return this.tryGetRuleContext(0, FieldsContext); } public BY(): TerminalNode | undefined { return this.tryGetToken(esql_parser.BY, 0); } - public qualifiedNames(): QualifiedNamesContext | undefined { - return this.tryGetRuleContext(0, QualifiedNamesContext); + public grouping(): GroupingContext | undefined { + return this.tryGetRuleContext(0, GroupingContext); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); @@ -4546,116 +3827,63 @@ export class StatsCommandContext extends ParserRuleContext { } -export class SourceIdentifierContext extends ParserRuleContext { - public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } - public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterSourceIdentifier) { - listener.enterSourceIdentifier(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitSourceIdentifier) { - listener.exitSourceIdentifier(this); - } - } -} - - -export class EnrichIdentifierContext extends ParserRuleContext { - public ENR_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_UNQUOTED_IDENTIFIER, 0); } - public ENR_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ENR_QUOTED_IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_enrichIdentifier; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterEnrichIdentifier) { - listener.enterEnrichIdentifier(this); +export class GroupingContext extends ParserRuleContext { + public qualifiedName(): QualifiedNameContext[]; + public qualifiedName(i: number): QualifiedNameContext; + public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { + if (i === undefined) { + return this.getRuleContexts(QualifiedNameContext); + } else { + return this.getRuleContext(i, QualifiedNameContext); } } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitEnrichIdentifier) { - listener.exitEnrichIdentifier(this); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); } } -} - - -export class FunctionExpressionArgumentContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public string(): StringContext | undefined { - return this.tryGetRuleContext(0, StringContext); - } - public number(): NumberContext | undefined { - return this.tryGetRuleContext(0, NumberContext); - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionExpressionArgument; } + public get ruleIndex(): number { return esql_parser.RULE_grouping; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionExpressionArgument) { - listener.enterFunctionExpressionArgument(this); + if (listener.enterGrouping) { + listener.enterGrouping(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionExpressionArgument) { - listener.exitFunctionExpressionArgument(this); + if (listener.exitGrouping) { + listener.exitGrouping(this); } } } -export class MathFunctionExpressionArgumentContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext | undefined { - return this.tryGetRuleContext(0, QualifiedNameContext); - } - public string(): StringContext | undefined { - return this.tryGetRuleContext(0, StringContext); - } - public number(): NumberContext | undefined { - return this.tryGetRuleContext(0, NumberContext); - } - public operatorExpression(): OperatorExpressionContext | undefined { - return this.tryGetRuleContext(0, OperatorExpressionContext); - } - public dateExpression(): DateExpressionContext | undefined { - return this.tryGetRuleContext(0, DateExpressionContext); - } - public comparison(): ComparisonContext | undefined { - return this.tryGetRuleContext(0, ComparisonContext); - } +export class SourceIdentifierContext extends ParserRuleContext { + public SRC_UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_UNQUOTED_IDENTIFIER, 0); } + public SRC_QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.SRC_QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFunctionExpressionArgument; } + public get ruleIndex(): number { return esql_parser.RULE_sourceIdentifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFunctionExpressionArgument) { - listener.enterMathFunctionExpressionArgument(this); + if (listener.enterSourceIdentifier) { + listener.enterSourceIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFunctionExpressionArgument) { - listener.exitMathFunctionExpressionArgument(this); + if (listener.exitSourceIdentifier) { + listener.exitSourceIdentifier(this); } } } @@ -4700,115 +3928,185 @@ export class QualifiedNameContext extends ParserRuleContext { } -export class QualifiedNamesContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext[]; - public qualifiedName(i: number): QualifiedNameContext; - public qualifiedName(i?: number): QualifiedNameContext | QualifiedNameContext[] { - if (i === undefined) { - return this.getRuleContexts(QualifiedNameContext); - } else { - return this.getRuleContext(i, QualifiedNameContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(esql_parser.COMMA); - } else { - return this.getToken(esql_parser.COMMA, i); - } - } +export class IdentifierContext extends ParserRuleContext { + public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } + public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_qualifiedNames; } + public get ruleIndex(): number { return esql_parser.RULE_identifier; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterQualifiedNames) { - listener.enterQualifiedNames(this); + if (listener.enterIdentifier) { + listener.enterIdentifier(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitQualifiedNames) { - listener.exitQualifiedNames(this); + if (listener.exitIdentifier) { + listener.exitIdentifier(this); } } } -export class IdentifierContext extends ParserRuleContext { - public UNQUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } - public QUOTED_IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(esql_parser.QUOTED_IDENTIFIER, 0); } - public ASTERISK(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASTERISK, 0); } +export class ConstantContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_identifier; } + public get ruleIndex(): number { return esql_parser.RULE_constant; } + public copyFrom(ctx: ConstantContext): void { + super.copyFrom(ctx); + } +} +export class NullLiteralContext extends ConstantContext { + public NULL(): TerminalNode { return this.getToken(esql_parser.NULL, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterIdentifier) { - listener.enterIdentifier(this); + if (listener.enterNullLiteral) { + listener.enterNullLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitIdentifier) { - listener.exitIdentifier(this); + if (listener.exitNullLiteral) { + listener.exitNullLiteral(this); } } } - - -export class MathFunctionIdentifierContext extends ParserRuleContext { - public MATH_FUNCTION(): TerminalNode { return this.getToken(esql_parser.MATH_FUNCTION, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +export class QualifiedIntegerLiteralContext extends ConstantContext { + public integerValue(): IntegerValueContext { + return this.getRuleContext(0, IntegerValueContext); + } + public UNQUOTED_IDENTIFIER(): TerminalNode { return this.getToken(esql_parser.UNQUOTED_IDENTIFIER, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_mathFunctionIdentifier; } + public enterRule(listener: esql_parserListener): void { + if (listener.enterQualifiedIntegerLiteral) { + listener.enterQualifiedIntegerLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitQualifiedIntegerLiteral) { + listener.exitQualifiedIntegerLiteral(this); + } + } +} +export class DecimalLiteralContext extends ConstantContext { + public decimalValue(): DecimalValueContext { + return this.getRuleContext(0, DecimalValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterMathFunctionIdentifier) { - listener.enterMathFunctionIdentifier(this); + if (listener.enterDecimalLiteral) { + listener.enterDecimalLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitMathFunctionIdentifier) { - listener.exitMathFunctionIdentifier(this); + if (listener.exitDecimalLiteral) { + listener.exitDecimalLiteral(this); } } } - - -export class FunctionIdentifierContext extends ParserRuleContext { - public UNARY_FUNCTION(): TerminalNode { return this.getToken(esql_parser.UNARY_FUNCTION, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); +export class IntegerLiteralContext extends ConstantContext { + public integerValue(): IntegerValueContext { + return this.getRuleContext(0, IntegerValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterIntegerLiteral) { + listener.enterIntegerLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitIntegerLiteral) { + listener.exitIntegerLiteral(this); + } + } +} +export class BooleanLiteralContext extends ConstantContext { + public booleanValue(): BooleanValueContext { + return this.getRuleContext(0, BooleanValueContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } } // @Override - public get ruleIndex(): number { return esql_parser.RULE_functionIdentifier; } + public exitRule(listener: esql_parserListener): void { + if (listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } +} +export class InputParamContext extends ConstantContext { + public PARAM(): TerminalNode { return this.getToken(esql_parser.PARAM, 0); } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterFunctionIdentifier) { - listener.enterFunctionIdentifier(this); + if (listener.enterInputParam) { + listener.enterInputParam(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitFunctionIdentifier) { - listener.exitFunctionIdentifier(this); + if (listener.exitInputParam) { + listener.exitInputParam(this); } } } - - -export class ConstantContext extends ParserRuleContext { - public NULL(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULL, 0); } +export class StringLiteralContext extends ConstantContext { + public string(): StringContext { + return this.getRuleContext(0, StringContext); + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterStringLiteral) { + listener.enterStringLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitStringLiteral) { + listener.exitStringLiteral(this); + } + } +} +export class NumericArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } public numericValue(): NumericValueContext[]; public numericValue(i: number): NumericValueContext; public numericValue(i?: number): NumericValueContext | NumericValueContext[] { @@ -4818,6 +4116,35 @@ export class ConstantContext extends ParserRuleContext { return this.getRuleContext(i, NumericValueContext); } } + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } + } + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterNumericArrayLiteral) { + listener.enterNumericArrayLiteral(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitNumericArrayLiteral) { + listener.exitNumericArrayLiteral(this); + } + } +} +export class BooleanArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } public booleanValue(): BooleanValueContext[]; public booleanValue(i: number): BooleanValueContext; public booleanValue(i?: number): BooleanValueContext | BooleanValueContext[] { @@ -4827,17 +4154,7 @@ export class ConstantContext extends ParserRuleContext { return this.getRuleContext(i, BooleanValueContext); } } - public string(): StringContext[]; - public string(i: number): StringContext; - public string(i?: number): StringContext | StringContext[] { - if (i === undefined) { - return this.getRuleContexts(StringContext); - } else { - return this.getRuleContext(i, StringContext); - } - } - public OPENING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.OPENING_BRACKET, 0); } - public CLOSING_BRACKET(): TerminalNode | undefined { return this.tryGetToken(esql_parser.CLOSING_BRACKET, 0); } + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } public COMMA(): TerminalNode[]; public COMMA(i: number): TerminalNode; public COMMA(i?: number): TerminalNode | TerminalNode[] { @@ -4847,48 +4164,58 @@ export class ConstantContext extends ParserRuleContext { return this.getToken(esql_parser.COMMA, i); } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_constant; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterConstant) { - listener.enterConstant(this); + if (listener.enterBooleanArrayLiteral) { + listener.enterBooleanArrayLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitConstant) { - listener.exitConstant(this); + if (listener.exitBooleanArrayLiteral) { + listener.exitBooleanArrayLiteral(this); } } } - - -export class NumericValueContext extends ParserRuleContext { - public decimalValue(): DecimalValueContext | undefined { - return this.tryGetRuleContext(0, DecimalValueContext); +export class StringArrayLiteralContext extends ConstantContext { + public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } + public string(): StringContext[]; + public string(i: number): StringContext; + public string(i?: number): StringContext | StringContext[] { + if (i === undefined) { + return this.getRuleContexts(StringContext); + } else { + return this.getRuleContext(i, StringContext); + } } - public integerValue(): IntegerValueContext | undefined { - return this.tryGetRuleContext(0, IntegerValueContext); + public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + constructor(ctx: ConstantContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_numericValue; } - // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterNumericValue) { - listener.enterNumericValue(this); + if (listener.enterStringArrayLiteral) { + listener.enterStringArrayLiteral(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitNumericValue) { - listener.exitNumericValue(this); + if (listener.exitStringArrayLiteral) { + listener.exitStringArrayLiteral(this); } } } @@ -4958,12 +4285,16 @@ export class SortCommandContext extends ParserRuleContext { export class OrderExpressionContext extends ParserRuleContext { + public _ordering: Token; + public _nullOrdering: Token; public booleanExpression(): BooleanExpressionContext { return this.getRuleContext(0, BooleanExpressionContext); } - public ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ORDERING, 0); } - public NULLS_ORDERING(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING, 0); } - public NULLS_ORDERING_DIRECTION(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS_ORDERING_DIRECTION, 0); } + public NULLS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NULLS, 0); } + public ASC(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASC, 0); } + public DESC(): TerminalNode | undefined { return this.tryGetToken(esql_parser.DESC, 0); } + public FIRST(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FIRST, 0); } + public LAST(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LAST, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -4984,36 +4315,27 @@ export class OrderExpressionContext extends ParserRuleContext { } -export class ProjectCommandContext extends ParserRuleContext { - public PROJECT(): TerminalNode { return this.getToken(esql_parser.PROJECT, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_projectCommand; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterProjectCommand) { - listener.enterProjectCommand(this); +export class KeepCommandContext extends ParserRuleContext { + public KEEP(): TerminalNode | undefined { return this.tryGetToken(esql_parser.KEEP, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); } } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitProjectCommand) { - listener.exitProjectCommand(this); + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); } } -} - - -export class KeepCommandContext extends ParserRuleContext { - public KEEP(): TerminalNode { return this.getToken(esql_parser.KEEP, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } + public PROJECT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PROJECT, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5036,63 +4358,39 @@ export class KeepCommandContext extends ParserRuleContext { export class DropCommandContext extends ParserRuleContext { public DROP(): TerminalNode { return this.getToken(esql_parser.DROP, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_dropCommand; } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterDropCommand) { - listener.enterDropCommand(this); - } - } - // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitDropCommand) { - listener.exitDropCommand(this); - } - } -} - - -export class RenameVariableContext extends ParserRuleContext { - public identifier(): IdentifierContext[]; - public identifier(i: number): IdentifierContext; - public identifier(i?: number): IdentifierContext | IdentifierContext[] { + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { if (i === undefined) { - return this.getRuleContexts(IdentifierContext); + return this.getRuleContexts(SourceIdentifierContext); } else { - return this.getRuleContext(i, IdentifierContext); + return this.getRuleContext(i, SourceIdentifierContext); } } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { if (i === undefined) { - return this.getTokens(esql_parser.DOT); + return this.getTokens(esql_parser.COMMA); } else { - return this.getToken(esql_parser.DOT, i); + return this.getToken(esql_parser.COMMA, i); } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_renameVariable; } + public get ruleIndex(): number { return esql_parser.RULE_dropCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterRenameVariable) { - listener.enterRenameVariable(this); + if (listener.enterDropCommand) { + listener.enterDropCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitRenameVariable) { - listener.exitRenameVariable(this); + if (listener.exitDropCommand) { + listener.exitDropCommand(this); } } } @@ -5139,12 +4437,17 @@ export class RenameCommandContext extends ParserRuleContext { export class RenameClauseContext extends ParserRuleContext { - public qualifiedName(): QualifiedNameContext { - return this.getRuleContext(0, QualifiedNameContext); - } + public _oldName: SourceIdentifierContext; + public _newName: SourceIdentifierContext; public AS(): TerminalNode { return this.getToken(esql_parser.AS, 0); } - public renameVariable(): RenameVariableContext { - return this.getRuleContext(0, RenameVariableContext); + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); @@ -5168,8 +4471,8 @@ export class RenameClauseContext extends ParserRuleContext { export class DissectCommandContext extends ParserRuleContext { public DISSECT(): TerminalNode { return this.getToken(esql_parser.DISSECT, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); } public string(): StringContext { return this.getRuleContext(0, StringContext); @@ -5199,8 +4502,8 @@ export class DissectCommandContext extends ParserRuleContext { export class GrokCommandContext extends ParserRuleContext { public GROK(): TerminalNode { return this.getToken(esql_parser.GROK, 0); } - public qualifiedNames(): QualifiedNamesContext { - return this.getRuleContext(0, QualifiedNamesContext); + public primaryExpression(): PrimaryExpressionContext { + return this.getRuleContext(0, PrimaryExpressionContext); } public string(): StringContext { return this.getRuleContext(0, StringContext); @@ -5225,6 +4528,31 @@ export class GrokCommandContext extends ParserRuleContext { } +export class MvExpandCommandContext extends ParserRuleContext { + public MV_EXPAND(): TerminalNode { return this.getToken(esql_parser.MV_EXPAND, 0); } + public sourceIdentifier(): SourceIdentifierContext { + return this.getRuleContext(0, SourceIdentifierContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public get ruleIndex(): number { return esql_parser.RULE_mvExpandCommand; } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterMvExpandCommand) { + listener.enterMvExpandCommand(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitMvExpandCommand) { + listener.exitMvExpandCommand(this); + } + } +} + + export class CommandOptionsContext extends ParserRuleContext { public commandOption(): CommandOptionContext[]; public commandOption(i: number): CommandOptionContext; @@ -5293,7 +4621,8 @@ export class CommandOptionContext extends ParserRuleContext { export class BooleanValueContext extends ParserRuleContext { - public BOOLEAN_VALUE(): TerminalNode { return this.getToken(esql_parser.BOOLEAN_VALUE, 0); } + public TRUE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.TRUE, 0); } + public FALSE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FALSE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5314,51 +4643,28 @@ export class BooleanValueContext extends ParserRuleContext { } -export class NumberContext extends ParserRuleContext { - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public get ruleIndex(): number { return esql_parser.RULE_number; } - public copyFrom(ctx: NumberContext): void { - super.copyFrom(ctx); +export class NumericValueContext extends ParserRuleContext { + public decimalValue(): DecimalValueContext | undefined { + return this.tryGetRuleContext(0, DecimalValueContext); } -} -export class DecimalLiteralContext extends NumberContext { - public DECIMAL_LITERAL(): TerminalNode { return this.getToken(esql_parser.DECIMAL_LITERAL, 0); } - constructor(ctx: NumberContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + public integerValue(): IntegerValueContext | undefined { + return this.tryGetRuleContext(0, IntegerValueContext); } - // @Override - public enterRule(listener: esql_parserListener): void { - if (listener.enterDecimalLiteral) { - listener.enterDecimalLiteral(this); - } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override - public exitRule(listener: esql_parserListener): void { - if (listener.exitDecimalLiteral) { - listener.exitDecimalLiteral(this); - } - } -} -export class IntegerLiteralContext extends NumberContext { - public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } - constructor(ctx: NumberContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } + public get ruleIndex(): number { return esql_parser.RULE_numericValue; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterIntegerLiteral) { - listener.enterIntegerLiteral(this); + if (listener.enterNumericValue) { + listener.enterNumericValue(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitIntegerLiteral) { - listener.exitIntegerLiteral(this); + if (listener.exitNumericValue) { + listener.exitNumericValue(this); } } } @@ -5366,6 +4672,8 @@ export class IntegerLiteralContext extends NumberContext { export class DecimalValueContext extends ParserRuleContext { public DECIMAL_LITERAL(): TerminalNode { return this.getToken(esql_parser.DECIMAL_LITERAL, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5388,6 +4696,8 @@ export class DecimalValueContext extends ParserRuleContext { export class IntegerValueContext extends ParserRuleContext { public INTEGER_LITERAL(): TerminalNode { return this.getToken(esql_parser.INTEGER_LITERAL, 0); } + public PLUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.MINUS, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5431,7 +4741,12 @@ export class StringContext extends ParserRuleContext { export class ComparisonOperatorContext extends ParserRuleContext { - public COMPARISON_OPERATOR(): TerminalNode { return this.getToken(esql_parser.COMPARISON_OPERATOR, 0); } + public EQ(): TerminalNode | undefined { return this.tryGetToken(esql_parser.EQ, 0); } + public NEQ(): TerminalNode | undefined { return this.tryGetToken(esql_parser.NEQ, 0); } + public LT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LT, 0); } + public LTE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.LTE, 0); } + public GT(): TerminalNode | undefined { return this.tryGetToken(esql_parser.GT, 0); } + public GTE(): TerminalNode | undefined { return this.tryGetToken(esql_parser.GTE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -5452,76 +4767,139 @@ export class ComparisonOperatorContext extends ParserRuleContext { } -export class ExplainCommandContext extends ParserRuleContext { - public EXPLAIN(): TerminalNode { return this.getToken(esql_parser.EXPLAIN, 0); } - public subqueryExpression(): SubqueryExpressionContext { - return this.getRuleContext(0, SubqueryExpressionContext); - } +export class ShowCommandContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_explainCommand; } + public get ruleIndex(): number { return esql_parser.RULE_showCommand; } + public copyFrom(ctx: ShowCommandContext): void { + super.copyFrom(ctx); + } +} +export class ShowInfoContext extends ShowCommandContext { + public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } + public INFO(): TerminalNode { return this.getToken(esql_parser.INFO, 0); } + constructor(ctx: ShowCommandContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public enterRule(listener: esql_parserListener): void { + if (listener.enterShowInfo) { + listener.enterShowInfo(this); + } + } + // @Override + public exitRule(listener: esql_parserListener): void { + if (listener.exitShowInfo) { + listener.exitShowInfo(this); + } + } +} +export class ShowFunctionsContext extends ShowCommandContext { + public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } + public FUNCTIONS(): TerminalNode { return this.getToken(esql_parser.FUNCTIONS, 0); } + constructor(ctx: ShowCommandContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterExplainCommand) { - listener.enterExplainCommand(this); + if (listener.enterShowFunctions) { + listener.enterShowFunctions(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitExplainCommand) { - listener.exitExplainCommand(this); + if (listener.exitShowFunctions) { + listener.exitShowFunctions(this); } } } -export class SubqueryExpressionContext extends ParserRuleContext { - public OPENING_BRACKET(): TerminalNode { return this.getToken(esql_parser.OPENING_BRACKET, 0); } - public query(): QueryContext { - return this.getRuleContext(0, QueryContext); +export class EnrichCommandContext extends ParserRuleContext { + public _policyName: SourceIdentifierContext; + public _matchField: SourceIdentifierContext; + public ENRICH(): TerminalNode { return this.getToken(esql_parser.ENRICH, 0); } + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } + } + public ON(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ON, 0); } + public WITH(): TerminalNode | undefined { return this.tryGetToken(esql_parser.WITH, 0); } + public enrichWithClause(): EnrichWithClauseContext[]; + public enrichWithClause(i: number): EnrichWithClauseContext; + public enrichWithClause(i?: number): EnrichWithClauseContext | EnrichWithClauseContext[] { + if (i === undefined) { + return this.getRuleContexts(EnrichWithClauseContext); + } else { + return this.getRuleContext(i, EnrichWithClauseContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(esql_parser.COMMA); + } else { + return this.getToken(esql_parser.COMMA, i); + } } - public CLOSING_BRACKET(): TerminalNode { return this.getToken(esql_parser.CLOSING_BRACKET, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_subqueryExpression; } + public get ruleIndex(): number { return esql_parser.RULE_enrichCommand; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterSubqueryExpression) { - listener.enterSubqueryExpression(this); + if (listener.enterEnrichCommand) { + listener.enterEnrichCommand(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitSubqueryExpression) { - listener.exitSubqueryExpression(this); + if (listener.exitEnrichCommand) { + listener.exitEnrichCommand(this); } } } -export class ShowCommandContext extends ParserRuleContext { - public SHOW(): TerminalNode { return this.getToken(esql_parser.SHOW, 0); } - public INFO(): TerminalNode | undefined { return this.tryGetToken(esql_parser.INFO, 0); } - public FUNCTIONS(): TerminalNode | undefined { return this.tryGetToken(esql_parser.FUNCTIONS, 0); } +export class EnrichWithClauseContext extends ParserRuleContext { + public _newName: SourceIdentifierContext; + public _enrichField: SourceIdentifierContext; + public sourceIdentifier(): SourceIdentifierContext[]; + public sourceIdentifier(i: number): SourceIdentifierContext; + public sourceIdentifier(i?: number): SourceIdentifierContext | SourceIdentifierContext[] { + if (i === undefined) { + return this.getRuleContexts(SourceIdentifierContext); + } else { + return this.getRuleContext(i, SourceIdentifierContext); + } + } + public ASSIGN(): TerminalNode | undefined { return this.tryGetToken(esql_parser.ASSIGN, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public get ruleIndex(): number { return esql_parser.RULE_showCommand; } + public get ruleIndex(): number { return esql_parser.RULE_enrichWithClause; } // @Override public enterRule(listener: esql_parserListener): void { - if (listener.enterShowCommand) { - listener.enterShowCommand(this); + if (listener.enterEnrichWithClause) { + listener.enterEnrichWithClause(this); } } // @Override public exitRule(listener: esql_parserListener): void { - if (listener.exitShowCommand) { - listener.exitShowCommand(this); + if (listener.exitEnrichWithClause) { + listener.exitEnrichWithClause(this); } } } diff --git a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts index f131d4072b773..ff67f81aeab09 100644 --- a/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts +++ b/packages/kbn-monaco/src/esql/antlr/esql_parser_listener.ts @@ -4,70 +4,79 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { ValueExpressionDefaultContext } from "./esql_parser"; +import { ComparisonContext } from "./esql_parser"; +import { NullLiteralContext } from "./esql_parser"; +import { QualifiedIntegerLiteralContext } from "./esql_parser"; import { DecimalLiteralContext } from "./esql_parser"; import { IntegerLiteralContext } from "./esql_parser"; +import { BooleanLiteralContext } from "./esql_parser"; +import { InputParamContext } from "./esql_parser"; +import { StringLiteralContext } from "./esql_parser"; +import { NumericArrayLiteralContext } from "./esql_parser"; +import { BooleanArrayLiteralContext } from "./esql_parser"; +import { StringArrayLiteralContext } from "./esql_parser"; +import { ShowInfoContext } from "./esql_parser"; +import { ShowFunctionsContext } from "./esql_parser"; +import { ConstantDefaultContext } from "./esql_parser"; +import { DereferenceContext } from "./esql_parser"; +import { FunctionContext } from "./esql_parser"; +import { ParenthesizedExpressionContext } from "./esql_parser"; import { SingleCommandQueryContext } from "./esql_parser"; import { CompositeQueryContext } from "./esql_parser"; +import { LogicalNotContext } from "./esql_parser"; +import { BooleanDefaultContext } from "./esql_parser"; +import { RegexExpressionContext } from "./esql_parser"; +import { LogicalBinaryContext } from "./esql_parser"; +import { LogicalInContext } from "./esql_parser"; +import { IsNullContext } from "./esql_parser"; +import { OperatorExpressionDefaultContext } from "./esql_parser"; +import { ArithmeticUnaryContext } from "./esql_parser"; +import { ArithmeticBinaryContext } from "./esql_parser"; import { SingleStatementContext } from "./esql_parser"; import { QueryContext } from "./esql_parser"; import { SourceCommandContext } from "./esql_parser"; import { ProcessingCommandContext } from "./esql_parser"; -import { EnrichCommandContext } from "./esql_parser"; -import { EnrichWithClauseContext } from "./esql_parser"; -import { MvExpandCommandContext } from "./esql_parser"; import { WhereCommandContext } from "./esql_parser"; -import { WhereBooleanExpressionContext } from "./esql_parser"; import { BooleanExpressionContext } from "./esql_parser"; import { RegexBooleanExpressionContext } from "./esql_parser"; import { ValueExpressionContext } from "./esql_parser"; -import { ComparisonContext } from "./esql_parser"; -import { MathFnContext } from "./esql_parser"; -import { MathEvalFnContext } from "./esql_parser"; -import { DateExpressionContext } from "./esql_parser"; import { OperatorExpressionContext } from "./esql_parser"; import { PrimaryExpressionContext } from "./esql_parser"; +import { FunctionExpressionContext } from "./esql_parser"; import { RowCommandContext } from "./esql_parser"; import { FieldsContext } from "./esql_parser"; import { FieldContext } from "./esql_parser"; -import { EnrichFieldIdentifierContext } from "./esql_parser"; -import { UserVariableContext } from "./esql_parser"; import { FromCommandContext } from "./esql_parser"; import { MetadataContext } from "./esql_parser"; import { EvalCommandContext } from "./esql_parser"; import { StatsCommandContext } from "./esql_parser"; +import { GroupingContext } from "./esql_parser"; import { SourceIdentifierContext } from "./esql_parser"; -import { EnrichIdentifierContext } from "./esql_parser"; -import { FunctionExpressionArgumentContext } from "./esql_parser"; -import { MathFunctionExpressionArgumentContext } from "./esql_parser"; import { QualifiedNameContext } from "./esql_parser"; -import { QualifiedNamesContext } from "./esql_parser"; import { IdentifierContext } from "./esql_parser"; -import { MathFunctionIdentifierContext } from "./esql_parser"; -import { FunctionIdentifierContext } from "./esql_parser"; import { ConstantContext } from "./esql_parser"; -import { NumericValueContext } from "./esql_parser"; import { LimitCommandContext } from "./esql_parser"; import { SortCommandContext } from "./esql_parser"; import { OrderExpressionContext } from "./esql_parser"; -import { ProjectCommandContext } from "./esql_parser"; import { KeepCommandContext } from "./esql_parser"; import { DropCommandContext } from "./esql_parser"; -import { RenameVariableContext } from "./esql_parser"; import { RenameCommandContext } from "./esql_parser"; import { RenameClauseContext } from "./esql_parser"; import { DissectCommandContext } from "./esql_parser"; import { GrokCommandContext } from "./esql_parser"; +import { MvExpandCommandContext } from "./esql_parser"; import { CommandOptionsContext } from "./esql_parser"; import { CommandOptionContext } from "./esql_parser"; import { BooleanValueContext } from "./esql_parser"; -import { NumberContext } from "./esql_parser"; +import { NumericValueContext } from "./esql_parser"; import { DecimalValueContext } from "./esql_parser"; import { IntegerValueContext } from "./esql_parser"; import { StringContext } from "./esql_parser"; import { ComparisonOperatorContext } from "./esql_parser"; -import { ExplainCommandContext } from "./esql_parser"; -import { SubqueryExpressionContext } from "./esql_parser"; import { ShowCommandContext } from "./esql_parser"; +import { EnrichCommandContext } from "./esql_parser"; +import { EnrichWithClauseContext } from "./esql_parser"; /** @@ -75,32 +84,240 @@ import { ShowCommandContext } from "./esql_parser"; * `esql_parser`. */ export interface esql_parserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by the `valueExpressionDefault` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + enterValueExpressionDefault?: (ctx: ValueExpressionDefaultContext) => void; + /** + * Exit a parse tree produced by the `valueExpressionDefault` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + exitValueExpressionDefault?: (ctx: ValueExpressionDefaultContext) => void; + + /** + * Enter a parse tree produced by the `comparison` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + enterComparison?: (ctx: ComparisonContext) => void; + /** + * Exit a parse tree produced by the `comparison` + * labeled alternative in `esql_parser.valueExpression`. + * @param ctx the parse tree + */ + exitComparison?: (ctx: ComparisonContext) => void; + + /** + * Enter a parse tree produced by the `nullLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterNullLiteral?: (ctx: NullLiteralContext) => void; + /** + * Exit a parse tree produced by the `nullLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitNullLiteral?: (ctx: NullLiteralContext) => void; + + /** + * Enter a parse tree produced by the `qualifiedIntegerLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterQualifiedIntegerLiteral?: (ctx: QualifiedIntegerLiteralContext) => void; + /** + * Exit a parse tree produced by the `qualifiedIntegerLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitQualifiedIntegerLiteral?: (ctx: QualifiedIntegerLiteralContext) => void; + /** * Enter a parse tree produced by the `decimalLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ enterDecimalLiteral?: (ctx: DecimalLiteralContext) => void; /** * Exit a parse tree produced by the `decimalLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ exitDecimalLiteral?: (ctx: DecimalLiteralContext) => void; /** * Enter a parse tree produced by the `integerLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ enterIntegerLiteral?: (ctx: IntegerLiteralContext) => void; /** * Exit a parse tree produced by the `integerLiteral` - * labeled alternative in `esql_parser.number`. + * labeled alternative in `esql_parser.constant`. * @param ctx the parse tree */ exitIntegerLiteral?: (ctx: IntegerLiteralContext) => void; + /** + * Enter a parse tree produced by the `booleanLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by the `booleanLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + + /** + * Enter a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterInputParam?: (ctx: InputParamContext) => void; + /** + * Exit a parse tree produced by the `inputParam` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitInputParam?: (ctx: InputParamContext) => void; + + /** + * Enter a parse tree produced by the `stringLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterStringLiteral?: (ctx: StringLiteralContext) => void; + /** + * Exit a parse tree produced by the `stringLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitStringLiteral?: (ctx: StringLiteralContext) => void; + + /** + * Enter a parse tree produced by the `numericArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterNumericArrayLiteral?: (ctx: NumericArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `numericArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitNumericArrayLiteral?: (ctx: NumericArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `booleanArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterBooleanArrayLiteral?: (ctx: BooleanArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `booleanArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitBooleanArrayLiteral?: (ctx: BooleanArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `stringArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + enterStringArrayLiteral?: (ctx: StringArrayLiteralContext) => void; + /** + * Exit a parse tree produced by the `stringArrayLiteral` + * labeled alternative in `esql_parser.constant`. + * @param ctx the parse tree + */ + exitStringArrayLiteral?: (ctx: StringArrayLiteralContext) => void; + + /** + * Enter a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowInfo?: (ctx: ShowInfoContext) => void; + /** + * Exit a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowInfo?: (ctx: ShowInfoContext) => void; + + /** + * Enter a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowFunctions?: (ctx: ShowFunctionsContext) => void; + /** + * Exit a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowFunctions?: (ctx: ShowFunctionsContext) => void; + + /** + * Enter a parse tree produced by the `constantDefault` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterConstantDefault?: (ctx: ConstantDefaultContext) => void; + /** + * Exit a parse tree produced by the `constantDefault` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitConstantDefault?: (ctx: ConstantDefaultContext) => void; + + /** + * Enter a parse tree produced by the `dereference` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterDereference?: (ctx: DereferenceContext) => void; + /** + * Exit a parse tree produced by the `dereference` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitDereference?: (ctx: DereferenceContext) => void; + + /** + * Enter a parse tree produced by the `function` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterFunction?: (ctx: FunctionContext) => void; + /** + * Exit a parse tree produced by the `function` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitFunction?: (ctx: FunctionContext) => void; + + /** + * Enter a parse tree produced by the `parenthesizedExpression` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + enterParenthesizedExpression?: (ctx: ParenthesizedExpressionContext) => void; + /** + * Exit a parse tree produced by the `parenthesizedExpression` + * labeled alternative in `esql_parser.primaryExpression`. + * @param ctx the parse tree + */ + exitParenthesizedExpression?: (ctx: ParenthesizedExpressionContext) => void; + /** * Enter a parse tree produced by the `singleCommandQuery` * labeled alternative in `esql_parser.query`. @@ -128,180 +345,209 @@ export interface esql_parserListener extends ParseTreeListener { exitCompositeQuery?: (ctx: CompositeQueryContext) => void; /** - * Enter a parse tree produced by `esql_parser.singleStatement`. + * Enter a parse tree produced by the `logicalNot` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterSingleStatement?: (ctx: SingleStatementContext) => void; + enterLogicalNot?: (ctx: LogicalNotContext) => void; /** - * Exit a parse tree produced by `esql_parser.singleStatement`. + * Exit a parse tree produced by the `logicalNot` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitSingleStatement?: (ctx: SingleStatementContext) => void; + exitLogicalNot?: (ctx: LogicalNotContext) => void; /** - * Enter a parse tree produced by `esql_parser.query`. + * Enter a parse tree produced by the `booleanDefault` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterQuery?: (ctx: QueryContext) => void; + enterBooleanDefault?: (ctx: BooleanDefaultContext) => void; /** - * Exit a parse tree produced by `esql_parser.query`. + * Exit a parse tree produced by the `booleanDefault` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitQuery?: (ctx: QueryContext) => void; + exitBooleanDefault?: (ctx: BooleanDefaultContext) => void; /** - * Enter a parse tree produced by `esql_parser.sourceCommand`. + * Enter a parse tree produced by the `regexExpression` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterSourceCommand?: (ctx: SourceCommandContext) => void; + enterRegexExpression?: (ctx: RegexExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.sourceCommand`. + * Exit a parse tree produced by the `regexExpression` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitSourceCommand?: (ctx: SourceCommandContext) => void; + exitRegexExpression?: (ctx: RegexExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.processingCommand`. + * Enter a parse tree produced by the `logicalBinary` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterProcessingCommand?: (ctx: ProcessingCommandContext) => void; + enterLogicalBinary?: (ctx: LogicalBinaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.processingCommand`. + * Exit a parse tree produced by the `logicalBinary` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitProcessingCommand?: (ctx: ProcessingCommandContext) => void; + exitLogicalBinary?: (ctx: LogicalBinaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.enrichCommand`. + * Enter a parse tree produced by the `logicalIn` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterEnrichCommand?: (ctx: EnrichCommandContext) => void; + enterLogicalIn?: (ctx: LogicalInContext) => void; /** - * Exit a parse tree produced by `esql_parser.enrichCommand`. + * Exit a parse tree produced by the `logicalIn` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitEnrichCommand?: (ctx: EnrichCommandContext) => void; + exitLogicalIn?: (ctx: LogicalInContext) => void; /** - * Enter a parse tree produced by `esql_parser.enrichWithClause`. + * Enter a parse tree produced by the `isNull` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + enterIsNull?: (ctx: IsNullContext) => void; /** - * Exit a parse tree produced by `esql_parser.enrichWithClause`. + * Exit a parse tree produced by the `isNull` + * labeled alternative in `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; + exitIsNull?: (ctx: IsNullContext) => void; /** - * Enter a parse tree produced by `esql_parser.mvExpandCommand`. + * Enter a parse tree produced by the `operatorExpressionDefault` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + enterOperatorExpressionDefault?: (ctx: OperatorExpressionDefaultContext) => void; /** - * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * Exit a parse tree produced by the `operatorExpressionDefault` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + exitOperatorExpressionDefault?: (ctx: OperatorExpressionDefaultContext) => void; /** - * Enter a parse tree produced by `esql_parser.whereCommand`. + * Enter a parse tree produced by the `arithmeticUnary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterWhereCommand?: (ctx: WhereCommandContext) => void; + enterArithmeticUnary?: (ctx: ArithmeticUnaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.whereCommand`. + * Exit a parse tree produced by the `arithmeticUnary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitWhereCommand?: (ctx: WhereCommandContext) => void; + exitArithmeticUnary?: (ctx: ArithmeticUnaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.whereBooleanExpression`. + * Enter a parse tree produced by the `arithmeticBinary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - enterWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + enterArithmeticBinary?: (ctx: ArithmeticBinaryContext) => void; /** - * Exit a parse tree produced by `esql_parser.whereBooleanExpression`. + * Exit a parse tree produced by the `arithmeticBinary` + * labeled alternative in `esql_parser.operatorExpression`. * @param ctx the parse tree */ - exitWhereBooleanExpression?: (ctx: WhereBooleanExpressionContext) => void; + exitArithmeticBinary?: (ctx: ArithmeticBinaryContext) => void; /** - * Enter a parse tree produced by `esql_parser.booleanExpression`. + * Enter a parse tree produced by `esql_parser.singleStatement`. * @param ctx the parse tree */ - enterBooleanExpression?: (ctx: BooleanExpressionContext) => void; + enterSingleStatement?: (ctx: SingleStatementContext) => void; /** - * Exit a parse tree produced by `esql_parser.booleanExpression`. + * Exit a parse tree produced by `esql_parser.singleStatement`. * @param ctx the parse tree */ - exitBooleanExpression?: (ctx: BooleanExpressionContext) => void; + exitSingleStatement?: (ctx: SingleStatementContext) => void; /** - * Enter a parse tree produced by `esql_parser.regexBooleanExpression`. + * Enter a parse tree produced by `esql_parser.query`. * @param ctx the parse tree */ - enterRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + enterQuery?: (ctx: QueryContext) => void; /** - * Exit a parse tree produced by `esql_parser.regexBooleanExpression`. + * Exit a parse tree produced by `esql_parser.query`. * @param ctx the parse tree */ - exitRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; + exitQuery?: (ctx: QueryContext) => void; /** - * Enter a parse tree produced by `esql_parser.valueExpression`. + * Enter a parse tree produced by `esql_parser.sourceCommand`. * @param ctx the parse tree */ - enterValueExpression?: (ctx: ValueExpressionContext) => void; + enterSourceCommand?: (ctx: SourceCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.valueExpression`. + * Exit a parse tree produced by `esql_parser.sourceCommand`. * @param ctx the parse tree */ - exitValueExpression?: (ctx: ValueExpressionContext) => void; + exitSourceCommand?: (ctx: SourceCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.comparison`. + * Enter a parse tree produced by `esql_parser.processingCommand`. * @param ctx the parse tree */ - enterComparison?: (ctx: ComparisonContext) => void; + enterProcessingCommand?: (ctx: ProcessingCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.comparison`. + * Exit a parse tree produced by `esql_parser.processingCommand`. * @param ctx the parse tree */ - exitComparison?: (ctx: ComparisonContext) => void; + exitProcessingCommand?: (ctx: ProcessingCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathFn`. + * Enter a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + enterWhereCommand?: (ctx: WhereCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + exitWhereCommand?: (ctx: WhereCommandContext) => void; + + /** + * Enter a parse tree produced by `esql_parser.booleanExpression`. * @param ctx the parse tree */ - enterMathFn?: (ctx: MathFnContext) => void; + enterBooleanExpression?: (ctx: BooleanExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathFn`. + * Exit a parse tree produced by `esql_parser.booleanExpression`. * @param ctx the parse tree */ - exitMathFn?: (ctx: MathFnContext) => void; + exitBooleanExpression?: (ctx: BooleanExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathEvalFn`. + * Enter a parse tree produced by `esql_parser.regexBooleanExpression`. * @param ctx the parse tree */ - enterMathEvalFn?: (ctx: MathEvalFnContext) => void; + enterRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathEvalFn`. + * Exit a parse tree produced by `esql_parser.regexBooleanExpression`. * @param ctx the parse tree */ - exitMathEvalFn?: (ctx: MathEvalFnContext) => void; + exitRegexBooleanExpression?: (ctx: RegexBooleanExpressionContext) => void; /** - * Enter a parse tree produced by `esql_parser.dateExpression`. + * Enter a parse tree produced by `esql_parser.valueExpression`. * @param ctx the parse tree */ - enterDateExpression?: (ctx: DateExpressionContext) => void; + enterValueExpression?: (ctx: ValueExpressionContext) => void; /** - * Exit a parse tree produced by `esql_parser.dateExpression`. + * Exit a parse tree produced by `esql_parser.valueExpression`. * @param ctx the parse tree */ - exitDateExpression?: (ctx: DateExpressionContext) => void; + exitValueExpression?: (ctx: ValueExpressionContext) => void; /** * Enter a parse tree produced by `esql_parser.operatorExpression`. @@ -325,6 +571,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitPrimaryExpression?: (ctx: PrimaryExpressionContext) => void; + /** + * Enter a parse tree produced by `esql_parser.functionExpression`. + * @param ctx the parse tree + */ + enterFunctionExpression?: (ctx: FunctionExpressionContext) => void; + /** + * Exit a parse tree produced by `esql_parser.functionExpression`. + * @param ctx the parse tree + */ + exitFunctionExpression?: (ctx: FunctionExpressionContext) => void; + /** * Enter a parse tree produced by `esql_parser.rowCommand`. * @param ctx the parse tree @@ -358,28 +615,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitField?: (ctx: FieldContext) => void; - /** - * Enter a parse tree produced by `esql_parser.enrichFieldIdentifier`. - * @param ctx the parse tree - */ - enterEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.enrichFieldIdentifier`. - * @param ctx the parse tree - */ - exitEnrichFieldIdentifier?: (ctx: EnrichFieldIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.userVariable`. - * @param ctx the parse tree - */ - enterUserVariable?: (ctx: UserVariableContext) => void; - /** - * Exit a parse tree produced by `esql_parser.userVariable`. - * @param ctx the parse tree - */ - exitUserVariable?: (ctx: UserVariableContext) => void; - /** * Enter a parse tree produced by `esql_parser.fromCommand`. * @param ctx the parse tree @@ -425,48 +660,26 @@ export interface esql_parserListener extends ParseTreeListener { exitStatsCommand?: (ctx: StatsCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.sourceIdentifier`. - * @param ctx the parse tree - */ - enterSourceIdentifier?: (ctx: SourceIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.sourceIdentifier`. - * @param ctx the parse tree - */ - exitSourceIdentifier?: (ctx: SourceIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.enrichIdentifier`. - * @param ctx the parse tree - */ - enterEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.enrichIdentifier`. - * @param ctx the parse tree - */ - exitEnrichIdentifier?: (ctx: EnrichIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.functionExpressionArgument`. + * Enter a parse tree produced by `esql_parser.grouping`. * @param ctx the parse tree */ - enterFunctionExpressionArgument?: (ctx: FunctionExpressionArgumentContext) => void; + enterGrouping?: (ctx: GroupingContext) => void; /** - * Exit a parse tree produced by `esql_parser.functionExpressionArgument`. + * Exit a parse tree produced by `esql_parser.grouping`. * @param ctx the parse tree */ - exitFunctionExpressionArgument?: (ctx: FunctionExpressionArgumentContext) => void; + exitGrouping?: (ctx: GroupingContext) => void; /** - * Enter a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * Enter a parse tree produced by `esql_parser.sourceIdentifier`. * @param ctx the parse tree */ - enterMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + enterSourceIdentifier?: (ctx: SourceIdentifierContext) => void; /** - * Exit a parse tree produced by `esql_parser.mathFunctionExpressionArgument`. + * Exit a parse tree produced by `esql_parser.sourceIdentifier`. * @param ctx the parse tree */ - exitMathFunctionExpressionArgument?: (ctx: MathFunctionExpressionArgumentContext) => void; + exitSourceIdentifier?: (ctx: SourceIdentifierContext) => void; /** * Enter a parse tree produced by `esql_parser.qualifiedName`. @@ -479,17 +692,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitQualifiedName?: (ctx: QualifiedNameContext) => void; - /** - * Enter a parse tree produced by `esql_parser.qualifiedNames`. - * @param ctx the parse tree - */ - enterQualifiedNames?: (ctx: QualifiedNamesContext) => void; - /** - * Exit a parse tree produced by `esql_parser.qualifiedNames`. - * @param ctx the parse tree - */ - exitQualifiedNames?: (ctx: QualifiedNamesContext) => void; - /** * Enter a parse tree produced by `esql_parser.identifier`. * @param ctx the parse tree @@ -501,28 +703,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitIdentifier?: (ctx: IdentifierContext) => void; - /** - * Enter a parse tree produced by `esql_parser.mathFunctionIdentifier`. - * @param ctx the parse tree - */ - enterMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.mathFunctionIdentifier`. - * @param ctx the parse tree - */ - exitMathFunctionIdentifier?: (ctx: MathFunctionIdentifierContext) => void; - - /** - * Enter a parse tree produced by `esql_parser.functionIdentifier`. - * @param ctx the parse tree - */ - enterFunctionIdentifier?: (ctx: FunctionIdentifierContext) => void; - /** - * Exit a parse tree produced by `esql_parser.functionIdentifier`. - * @param ctx the parse tree - */ - exitFunctionIdentifier?: (ctx: FunctionIdentifierContext) => void; - /** * Enter a parse tree produced by `esql_parser.constant`. * @param ctx the parse tree @@ -534,17 +714,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitConstant?: (ctx: ConstantContext) => void; - /** - * Enter a parse tree produced by `esql_parser.numericValue`. - * @param ctx the parse tree - */ - enterNumericValue?: (ctx: NumericValueContext) => void; - /** - * Exit a parse tree produced by `esql_parser.numericValue`. - * @param ctx the parse tree - */ - exitNumericValue?: (ctx: NumericValueContext) => void; - /** * Enter a parse tree produced by `esql_parser.limitCommand`. * @param ctx the parse tree @@ -578,17 +747,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitOrderExpression?: (ctx: OrderExpressionContext) => void; - /** - * Enter a parse tree produced by `esql_parser.projectCommand`. - * @param ctx the parse tree - */ - enterProjectCommand?: (ctx: ProjectCommandContext) => void; - /** - * Exit a parse tree produced by `esql_parser.projectCommand`. - * @param ctx the parse tree - */ - exitProjectCommand?: (ctx: ProjectCommandContext) => void; - /** * Enter a parse tree produced by `esql_parser.keepCommand`. * @param ctx the parse tree @@ -611,17 +769,6 @@ export interface esql_parserListener extends ParseTreeListener { */ exitDropCommand?: (ctx: DropCommandContext) => void; - /** - * Enter a parse tree produced by `esql_parser.renameVariable`. - * @param ctx the parse tree - */ - enterRenameVariable?: (ctx: RenameVariableContext) => void; - /** - * Exit a parse tree produced by `esql_parser.renameVariable`. - * @param ctx the parse tree - */ - exitRenameVariable?: (ctx: RenameVariableContext) => void; - /** * Enter a parse tree produced by `esql_parser.renameCommand`. * @param ctx the parse tree @@ -666,6 +813,17 @@ export interface esql_parserListener extends ParseTreeListener { */ exitGrokCommand?: (ctx: GrokCommandContext) => void; + /** + * Enter a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + enterMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** + * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + exitMvExpandCommand?: (ctx: MvExpandCommandContext) => void; + /** * Enter a parse tree produced by `esql_parser.commandOptions`. * @param ctx the parse tree @@ -700,15 +858,15 @@ export interface esql_parserListener extends ParseTreeListener { exitBooleanValue?: (ctx: BooleanValueContext) => void; /** - * Enter a parse tree produced by `esql_parser.number`. + * Enter a parse tree produced by `esql_parser.numericValue`. * @param ctx the parse tree */ - enterNumber?: (ctx: NumberContext) => void; + enterNumericValue?: (ctx: NumericValueContext) => void; /** - * Exit a parse tree produced by `esql_parser.number`. + * Exit a parse tree produced by `esql_parser.numericValue`. * @param ctx the parse tree */ - exitNumber?: (ctx: NumberContext) => void; + exitNumericValue?: (ctx: NumericValueContext) => void; /** * Enter a parse tree produced by `esql_parser.decimalValue`. @@ -755,36 +913,36 @@ export interface esql_parserListener extends ParseTreeListener { exitComparisonOperator?: (ctx: ComparisonOperatorContext) => void; /** - * Enter a parse tree produced by `esql_parser.explainCommand`. + * Enter a parse tree produced by `esql_parser.showCommand`. * @param ctx the parse tree */ - enterExplainCommand?: (ctx: ExplainCommandContext) => void; + enterShowCommand?: (ctx: ShowCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.explainCommand`. + * Exit a parse tree produced by `esql_parser.showCommand`. * @param ctx the parse tree */ - exitExplainCommand?: (ctx: ExplainCommandContext) => void; + exitShowCommand?: (ctx: ShowCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.subqueryExpression`. + * Enter a parse tree produced by `esql_parser.enrichCommand`. * @param ctx the parse tree */ - enterSubqueryExpression?: (ctx: SubqueryExpressionContext) => void; + enterEnrichCommand?: (ctx: EnrichCommandContext) => void; /** - * Exit a parse tree produced by `esql_parser.subqueryExpression`. + * Exit a parse tree produced by `esql_parser.enrichCommand`. * @param ctx the parse tree */ - exitSubqueryExpression?: (ctx: SubqueryExpressionContext) => void; + exitEnrichCommand?: (ctx: EnrichCommandContext) => void; /** - * Enter a parse tree produced by `esql_parser.showCommand`. + * Enter a parse tree produced by `esql_parser.enrichWithClause`. * @param ctx the parse tree */ - enterShowCommand?: (ctx: ShowCommandContext) => void; + enterEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; /** - * Exit a parse tree produced by `esql_parser.showCommand`. + * Exit a parse tree produced by `esql_parser.enrichWithClause`. * @param ctx the parse tree */ - exitShowCommand?: (ctx: ShowCommandContext) => void; + exitEnrichWithClause?: (ctx: EnrichWithClauseContext) => void; } diff --git a/packages/kbn-monaco/src/esql/index.ts b/packages/kbn-monaco/src/esql/index.ts index 46ae9fe7f6bcb..a3b5f3bec666d 100644 --- a/packages/kbn-monaco/src/esql/index.ts +++ b/packages/kbn-monaco/src/esql/index.ts @@ -8,5 +8,5 @@ export { ESQL_LANG_ID, ESQL_THEME_ID } from './lib/constants'; export { ESQLLang } from './language'; -export type { ESQLCustomAutocompleteCallbacks } from './lib/autocomplete/types'; +export type { ESQLCallbacks } from './lib/ast/shared/types'; export { buildESQlTheme } from './lib/monaco/esql_theme'; diff --git a/packages/kbn-monaco/src/esql/language.ts b/packages/kbn-monaco/src/esql/language.ts index cca4cb3718f06..956baa4405e0a 100644 --- a/packages/kbn-monaco/src/esql/language.ts +++ b/packages/kbn-monaco/src/esql/language.ts @@ -15,12 +15,12 @@ import type { ESQLWorker } from './worker/esql_worker'; import { DiagnosticsAdapter } from '../common/diagnostics_adapter'; import { WorkerProxyService } from '../common/worker_proxy'; -import { ESQLCompletionAdapter } from './lib/monaco/esql_completion_provider'; -import type { ESQLCustomAutocompleteCallbacks } from './lib/autocomplete/types'; +import type { ESQLCallbacks } from './lib/ast/shared/types'; +import { ESQLAstAdapter } from './lib/monaco/esql_ast_provider'; const workerProxyService = new WorkerProxyService(); -export const ESQLLang: CustomLangModuleType = { +export const ESQLLang: CustomLangModuleType = { ID: ESQL_LANG_ID, async onLanguage() { const { ESQLTokensProvider } = await import('./lib/monaco'); @@ -29,12 +29,18 @@ export const ESQLLang: CustomLangModuleType = { monaco.languages.setTokensProvider(ESQL_LANG_ID, new ESQLTokensProvider()); + // handle syntax errors via the diagnostic adapter + // but then enrich them via the separate validate function new DiagnosticsAdapter(ESQL_LANG_ID, (...uris) => workerProxyService.getWorker(uris)); }, languageConfiguration: { - brackets: [['(', ')']], + brackets: [ + ['(', ')'], + ['[', ']'], + ], autoClosingPairs: [ { open: '(', close: ')' }, + { open: '[', close: ']' }, { open: `'`, close: `'` }, { open: '"', close: '"' }, ], @@ -44,8 +50,65 @@ export const ESQLLang: CustomLangModuleType = { { open: '"', close: '"' }, ], }, - - getSuggestionProvider(callbacks?: ESQLCustomAutocompleteCallbacks) { - return new ESQLCompletionAdapter((...uris) => workerProxyService.getWorker(uris), callbacks); + validate: async (model: monaco.editor.ITextModel, code: string, callbacks?: ESQLCallbacks) => { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return await astAdapter.validate(model, code); + }, + getSignatureProvider: (callbacks?: ESQLCallbacks): monaco.languages.SignatureHelpProvider => { + return { + signatureHelpTriggerCharacters: [' ', '('], + async provideSignatureHelp( + model: monaco.editor.ITextModel, + position: monaco.Position, + _token: monaco.CancellationToken, + context: monaco.languages.SignatureHelpContext + ) { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return astAdapter.suggestSignature(model, position, context); + }, + }; + }, + getHoverProvider: (callbacks?: ESQLCallbacks): monaco.languages.HoverProvider => { + return { + async provideHover( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken + ) { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + return astAdapter.getHover(model, position, token); + }, + }; + }, + getSuggestionProvider: (callbacks?: ESQLCallbacks): monaco.languages.CompletionItemProvider => { + return { + triggerCharacters: [',', '(', '=', ' ', ''], + async provideCompletionItems( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext + ): Promise { + const astAdapter = new ESQLAstAdapter( + (...uris) => workerProxyService.getWorker(uris), + callbacks + ); + const suggestionEntries = await astAdapter.autocomplete(model, position, context); + return { + suggestions: suggestionEntries.suggestions.map((suggestion) => ({ + ...suggestion, + range: undefined as unknown as monaco.IRange, + })), + }; + }, + }; }, }; diff --git a/packages/kbn-monaco/src/esql/lib/antlr_facade.ts b/packages/kbn-monaco/src/esql/lib/antlr_facade.ts index e6bf97e443140..ffa69ba2a8f4c 100644 --- a/packages/kbn-monaco/src/esql/lib/antlr_facade.ts +++ b/packages/kbn-monaco/src/esql/lib/antlr_facade.ts @@ -6,19 +6,17 @@ * Side Public License, v 1. */ -import { CommonTokenStream, CodePointCharStream } from 'antlr4ts'; +import { CommonTokenStream, type CodePointCharStream, type ANTLRErrorListener } from 'antlr4ts'; import { esql_lexer as ESQLLexer } from '../antlr/esql_lexer'; import { esql_parser as ESQLParser } from '../antlr/esql_parser'; import type { esql_parserListener as ESQLParserListener } from '../antlr/esql_parser_listener'; -import type { ANTLREErrorListener } from '../../common/error_listener'; - export const ROOT_STATEMENT = 'singleStatement'; export const getParser = ( inputStream: CodePointCharStream, - errorListener: ANTLREErrorListener, + errorListener: ANTLRErrorListener, parseListener?: ESQLParserListener ) => { const lexer = getLexer(inputStream, errorListener); @@ -35,7 +33,10 @@ export const getParser = ( return parser; }; -export const getLexer = (inputStream: CodePointCharStream, errorListener: ANTLREErrorListener) => { +export const getLexer = ( + inputStream: CodePointCharStream, + errorListener: ANTLRErrorListener +) => { const lexer = new ESQLLexer(inputStream); lexer.removeErrorListeners(); diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts new file mode 100644 index 0000000000000..01d16a46b2502 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_errors.ts @@ -0,0 +1,50 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { RecognitionException } from 'antlr4ts'; +import { esql_parser } from '../../antlr/esql_parser'; +import { getPosition } from './ast_position_utils'; + +function getExpectedSymbols(expectedTokens: RecognitionException['expectedTokens']) { + const tokenIds = expectedTokens?.toIntegerList().toArray() || []; + const list = []; + for (const tokenId of tokenIds) { + if (esql_parser.VOCABULARY.getSymbolicName(tokenId)) { + const symbol = esql_parser.VOCABULARY.getSymbolicName(tokenId); + list.push(symbol === 'EOF' ? `<${symbol}>` : symbol); + } + } + return list; +} + +export function createError(exception: RecognitionException) { + const token = exception.getOffendingToken(); + if (token) { + const expectedSymbols = getExpectedSymbols(exception.expectedTokens); + if ( + ['ASTERISK', 'UNQUOTED_IDENTIFIER', 'QUOTED_IDENTIFIER'].every( + (s, i) => expectedSymbols[i] === s + ) + ) { + return { + type: 'error' as const, + text: `Unknown column ${token.text}`, + location: getPosition(token), + }; + } + } + return { + type: 'error' as const, + text: token + ? `SyntaxError: expected {${getExpectedSymbols(exception.expectedTokens).join( + ', ' + )}} but found "${token.text}"` + : exception.message, + location: getPosition(token), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts new file mode 100644 index 0000000000000..939d6d764f513 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_factory.ts @@ -0,0 +1,249 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { + type ShowInfoContext, + type ShowFunctionsContext, + type SingleStatementContext, + type RowCommandContext, + type FromCommandContext, + type EvalCommandContext, + type StatsCommandContext, + type LimitCommandContext, + type SortCommandContext, + type KeepCommandContext, + type DropCommandContext, + type RenameCommandContext, + type DissectCommandContext, + type GrokCommandContext, + type MvExpandCommandContext, + type ShowCommandContext, + type EnrichCommandContext, + type WhereCommandContext, + esql_parser, +} from '../../antlr/esql_parser'; +import { esql_parserListener as ESQLParserListener } from '../../antlr/esql_parser_listener'; +import { createCommand, createFunction, createOption, createLiteral } from './ast_helpers'; +import { getPosition } from './ast_position_utils'; +import { + collectAllSourceIdentifiers, + collectAllFieldsStatements, + visitByOption, + collectAllColumnIdentifiers, + visitRenameClauses, + visitDissect, + visitGrok, + collectBooleanExpression, + visitOrderExpression, + getPolicyName, + getMatchField, + getEnrichClauses, +} from './ast_walker'; +import type { ESQLAst } from './types'; + +export class AstListener implements ESQLParserListener { + private ast: ESQLAst = []; + + public getAst() { + return { ast: this.ast }; + } + + /** + * Exit a parse tree produced by the `showInfo` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowInfo(ctx: ShowInfoContext) { + const commandAst = createCommand('show', ctx); + + this.ast.push(commandAst); + commandAst.text = ctx.text; + commandAst?.args.push(createFunction('info', ctx, getPosition(ctx.INFO().symbol))); + } + + /** + * Exit a parse tree produced by the `showFunctions` + * labeled alternative in `esql_parser.showCommand`. + * @param ctx the parse tree + */ + exitShowFunctions(ctx: ShowFunctionsContext) { + const commandAst = createCommand('show', ctx); + this.ast.push(commandAst); + // update the text + commandAst.text = ctx.text; + commandAst?.args.push(createFunction('functions', ctx, getPosition(ctx.FUNCTIONS().symbol))); + } + + /** + * Enter a parse tree produced by `esql_parser.singleStatement`. + * @param ctx the parse tree + */ + enterSingleStatement(ctx: SingleStatementContext) { + this.ast = []; + } + + /** + * Exit a parse tree produced by `esql_parser.whereCommand`. + * @param ctx the parse tree + */ + exitWhereCommand(ctx: WhereCommandContext) { + const command = createCommand('where', ctx); + this.ast.push(command); + command.args.push(...collectBooleanExpression(ctx.booleanExpression())); + } + + /** + * Exit a parse tree produced by `esql_parser.rowCommand`. + * @param ctx the parse tree + */ + exitRowCommand(ctx: RowCommandContext) { + const command = createCommand('row', ctx); + this.ast.push(command); + command.args.push(...collectAllFieldsStatements(ctx.fields())); + } + + /** + * Exit a parse tree produced by `esql_parser.fromCommand`. + * @param ctx the parse tree + */ + exitFromCommand(ctx: FromCommandContext) { + const commandAst = createCommand('from', ctx); + this.ast.push(commandAst); + commandAst.args.push(...collectAllSourceIdentifiers(ctx)); + const metadataContext = ctx.metadata(); + if (metadataContext) { + const option = createOption(metadataContext.METADATA().text.toLowerCase(), metadataContext); + commandAst.args.push(option); + // skip for the moment as there's no easy way to get meta fields right now + // option.args.push(...collectAllColumnIdentifiers(metadataContext)); + } + } + + /** + * Exit a parse tree produced by `esql_parser.evalCommand`. + * @param ctx the parse tree + */ + exitEvalCommand(ctx: EvalCommandContext) { + const commandAst = createCommand('eval', ctx); + this.ast.push(commandAst); + commandAst.args.push(...collectAllFieldsStatements(ctx.fields())); + } + + /** + * Exit a parse tree produced by `esql_parser.statsCommand`. + * @param ctx the parse tree + */ + exitStatsCommand(ctx: StatsCommandContext) { + const command = createCommand('stats', ctx); + this.ast.push(command); + command.args.push(...collectAllFieldsStatements(ctx.fields()), ...visitByOption(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.limitCommand`. + * @param ctx the parse tree + */ + exitLimitCommand(ctx: LimitCommandContext) { + const command = createCommand('limit', ctx); + this.ast.push(command); + if (ctx.tryGetToken(esql_parser.INTEGER_LITERAL, 0)) { + const literal = createLiteral('number', ctx.INTEGER_LITERAL()); + if (literal) { + command.args.push(literal); + } + } + } + + /** + * Exit a parse tree produced by `esql_parser.sortCommand`. + * @param ctx the parse tree + */ + exitSortCommand(ctx: SortCommandContext) { + const command = createCommand('sort', ctx); + this.ast.push(command); + command.args.push(...visitOrderExpression(ctx.orderExpression())); + } + + /** + * Exit a parse tree produced by `esql_parser.keepCommand`. + * @param ctx the parse tree + */ + exitKeepCommand(ctx: KeepCommandContext) { + const command = createCommand('keep', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.dropCommand`. + * @param ctx the parse tree + */ + exitDropCommand(ctx: DropCommandContext) { + const command = createCommand('drop', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.renameCommand`. + * @param ctx the parse tree + */ + exitRenameCommand(ctx: RenameCommandContext) { + const command = createCommand('rename', ctx); + this.ast.push(command); + command.args.push(...visitRenameClauses(ctx.renameClause())); + } + + /** + * Exit a parse tree produced by `esql_parser.dissectCommand`. + * @param ctx the parse tree + */ + exitDissectCommand(ctx: DissectCommandContext) { + const command = createCommand('dissect', ctx); + this.ast.push(command); + command.args.push(...visitDissect(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.grokCommand`. + * @param ctx the parse tree + */ + exitGrokCommand(ctx: GrokCommandContext) { + const command = createCommand('grok', ctx); + this.ast.push(command); + command.args.push(...visitGrok(ctx)); + } + + /** + * Exit a parse tree produced by `esql_parser.mvExpandCommand`. + * @param ctx the parse tree + */ + exitMvExpandCommand(ctx: MvExpandCommandContext) { + const command = createCommand('mv_expand', ctx); + this.ast.push(command); + command.args.push(...collectAllColumnIdentifiers(ctx)); + } + + /** + * Enter a parse tree produced by `esql_parser.showCommand`. + * @param ctx the parse tree + */ + enterShowCommand(ctx: ShowCommandContext) { + const command = createCommand('show', ctx); + this.ast.push(command); + } + /** + * Exit a parse tree produced by `esql_parser.enrichCommand`. + * @param ctx the parse tree + */ + exitEnrichCommand(ctx: EnrichCommandContext) { + const command = createCommand('enrich', ctx); + this.ast.push(command); + command.args.push(...getPolicyName(ctx), ...getMatchField(ctx), ...getEnrichClauses(ctx)); + } +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts new file mode 100644 index 0000000000000..d6e8ea7d0a038 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_helpers.ts @@ -0,0 +1,240 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; +import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; +import type { TerminalNode } from 'antlr4ts/tree/TerminalNode'; +import type { + ArithmeticUnaryContext, + DecimalValueContext, + IntegerValueContext, + QualifiedIntegerLiteralContext, +} from '../../antlr/esql_parser'; +import { getPosition } from './ast_position_utils'; +import type { + ESQLCommand, + ESQLLiteral, + ESQLList, + ESQLTimeInterval, + ESQLLocation, + ESQLFunction, + ESQLSource, + ESQLColumn, + ESQLCommandOption, + ESQLAstItem, +} from './types'; + +export function nonNullable(v: T): v is NonNullable { + return v != null; +} + +export function createCommand(name: string, ctx: ParserRuleContext): ESQLCommand { + return { + type: 'command', + name, + text: ctx.text, + args: [], + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createList(ctx: ParserRuleContext, values: ESQLLiteral[]): ESQLList { + return { + type: 'list', + name: ctx.text, + values, + text: ctx.text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createNumericLiteral(ctx: DecimalValueContext | IntegerValueContext): ESQLLiteral { + const text = ctx.text; + return { + type: 'literal', + literalType: 'number', + text, + name: text, + value: Number(text), + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createFakeMultiplyLiteral(ctx: ArithmeticUnaryContext): ESQLLiteral { + return { + type: 'literal', + literalType: 'number', + text: ctx.text, + name: ctx.text, + value: ctx.PLUS() ? 1 : -1, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception), + }; +} + +export function createLiteral( + type: ESQLLiteral['literalType'], + node: TerminalNode | undefined +): ESQLLiteral | undefined { + if (!node) { + return; + } + const text = node.text; + return { + type: 'literal', + literalType: type, + text, + name: text, + value: type === 'number' ? Number(text) : text, + location: getPosition(node.symbol), + incomplete: / number +) { + let nextArg: ESQLAstItem | undefined = args[getNextItemIndex(args)]; + const location = { ...initialLocation }; + while (Array.isArray(nextArg) || nextArg) { + if (Array.isArray(nextArg)) { + nextArg = nextArg[getNextItemIndex(nextArg)]; + } else { + location[prop] = Math[prop](location[prop], nextArg.location[prop]); + if (nextArg.type === 'function') { + nextArg = nextArg.args[getNextItemIndex(nextArg.args)]; + } else { + nextArg = undefined; + } + } + } + return location[prop]; +} + +export function computeLocationExtends(fn: ESQLFunction) { + const location = fn.location; + if (fn.args) { + // get min location navigating in depth keeping the left/first arg + location.min = walkFunctionStructure(fn.args, location, 'min', () => 0); + // get max location navigating in depth keeping the right/last arg + location.max = walkFunctionStructure(fn.args, location, 'max', (args) => args.length - 1); + } + return location; +} + +// Note: do not import esql_parser or bundle size will grow up by ~500 kb +function getQuotedText(ctx: ParserRuleContext) { + return ( + ctx.tryGetToken(73 /* esql_parser.SRC_QUOTED_IDENTIFIER*/, 0) || + ctx.tryGetToken(64 /* esql_parser.QUOTED_IDENTIFIER */, 0) + ); +} + +function getUnquotedText(ctx: ParserRuleContext) { + return ( + ctx.tryGetToken(72 /* esql_parser.SRC_UNQUOTED_IDENTIFIER */, 0) || + ctx.tryGetToken(63 /* esql_parser.UNQUOTED_IDENTIFIER */, 0) + ); +} + +const TICKS_REGEX = /(`)/g; + +function isQuoted(text: string | undefined) { + return text && TICKS_REGEX.test(text); +} + +export function sanifyIdentifierString(ctx: ParserRuleContext) { + return ( + getUnquotedText(ctx)?.text || + getQuotedText(ctx)?.text.replace(TICKS_REGEX, '') || + ctx.text.replace(TICKS_REGEX, '') // for some reason some quoted text is not detected correctly by the parser + ); +} + +export function createSource( + ctx: ParserRuleContext, + type: 'index' | 'policy' = 'index' +): ESQLSource { + const text = sanifyIdentifierString(ctx); + return { + type: 'source', + name: text, + sourceType: type, + text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception || text === ''), + }; +} + +export function createColumnStar(ctx: TerminalNode): ESQLColumn { + return { + type: 'column', + name: ctx.text, + text: ctx.text, + location: getPosition(ctx.symbol), + incomplete: ctx.text === '', + quoted: false, + }; +} + +export function createColumn(ctx: ParserRuleContext): ESQLColumn { + const text = sanifyIdentifierString(ctx); + const hasQuotes = Boolean(getQuotedText(ctx) || isQuoted(ctx.text)); + return { + type: 'column', + name: text, + text, + location: getPosition(ctx.start, ctx.stop), + incomplete: Boolean(ctx.exception || text === ''), + quoted: hasQuotes, + }; +} + +export function createOption(name: string, ctx: ParserRuleContext): ESQLCommandOption { + return { + type: 'option', + name, + text: ctx.text, + location: getPosition(ctx.start, ctx.stop), + args: [], + incomplete: Boolean(ctx.exception || ctx.children?.some((c) => c instanceof ErrorNode)), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts new file mode 100644 index 0000000000000..73745b12f4908 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_position_utils.ts @@ -0,0 +1,22 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { Token } from 'antlr4ts'; + +export function getPosition(token: Token | undefined, lastToken?: Token | undefined) { + if (!token || token.startIndex < 0) { + return { min: 0, max: 0 }; + } + const endFirstToken = + token.stopIndex > -1 ? Math.max(token.stopIndex + 1, token.startIndex) : undefined; + const endLastToken = lastToken?.stopIndex; + return { + min: token.startIndex, + max: endLastToken ?? endFirstToken ?? Infinity, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts b/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts new file mode 100644 index 0000000000000..677bc4694e05a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/ast_walker.ts @@ -0,0 +1,544 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { + ArithmeticBinaryContext, + ArithmeticUnaryContext, + BooleanArrayLiteralContext, + BooleanDefaultContext, + type BooleanExpressionContext, + BooleanLiteralContext, + BooleanValueContext, + type CommandOptionsContext, + ComparisonContext, + type ComparisonOperatorContext, + type ConstantContext, + ConstantDefaultContext, + DecimalLiteralContext, + DereferenceContext, + type DissectCommandContext, + type DropCommandContext, + type EnrichCommandContext, + esql_parser, + type FieldContext, + type FieldsContext, + type FromCommandContext, + FunctionContext, + type GrokCommandContext, + IntegerLiteralContext, + IsNullContext, + type KeepCommandContext, + LogicalBinaryContext, + LogicalInContext, + LogicalNotContext, + type MetadataContext, + type MvExpandCommandContext, + NullLiteralContext, + NumericArrayLiteralContext, + NumericValueContext, + type OperatorExpressionContext, + OperatorExpressionDefaultContext, + type OrderExpressionContext, + ParenthesizedExpressionContext, + type PrimaryExpressionContext, + QualifiedIntegerLiteralContext, + RegexBooleanExpressionContext, + type RenameClauseContext, + SourceIdentifierContext, + type StatsCommandContext, + StringArrayLiteralContext, + StringContext, + StringLiteralContext, + type ValueExpressionContext, + ValueExpressionDefaultContext, +} from '../../antlr/esql_parser'; +import { + createSource, + createColumn, + createOption, + nonNullable, + createFunction, + createLiteral, + createTimeUnit, + createFakeMultiplyLiteral, + createList, + createNumericLiteral, + sanifyIdentifierString, + computeLocationExtends, + createColumnStar, +} from './ast_helpers'; +import { getPosition } from './ast_position_utils'; +import type { + ESQLLiteral, + ESQLColumn, + ESQLFunction, + ESQLCommandOption, + ESQLAstItem, +} from './types'; + +export function collectAllSourceIdentifiers(ctx: FromCommandContext): ESQLAstItem[] { + return ctx.getRuleContexts(SourceIdentifierContext).map((sourceCtx) => createSource(sourceCtx)); +} + +export function collectAllColumnIdentifiers( + ctx: KeepCommandContext | DropCommandContext | MvExpandCommandContext | MetadataContext +): ESQLAstItem[] { + const identifiers = ( + Array.isArray(ctx.sourceIdentifier()) ? ctx.sourceIdentifier() : [ctx.sourceIdentifier()] + ) as SourceIdentifierContext[]; + const args: ESQLColumn[] = + identifiers + .filter((child) => child.text) + .map((sourceContext) => { + return createColumn(sourceContext); + }) ?? []; + return args; +} + +export function getPolicyName(ctx: EnrichCommandContext) { + if (!ctx._policyName) { + return []; + } + return [createSource(ctx._policyName, 'policy')]; +} + +export function getMatchField(ctx: EnrichCommandContext) { + if (!ctx._matchField) { + return []; + } + const identifier = ctx.sourceIdentifier(1); + if (identifier) { + const fn = createOption(ctx.ON()!.text.toLowerCase(), ctx); + if (identifier.text) { + fn.args.push(createColumn(identifier)); + } + // overwrite the location inferring the correct position + fn.location = getPosition(ctx.ON()!.symbol, ctx.WITH()?.symbol); + return [fn]; + } + return []; +} + +export function getEnrichClauses(ctx: EnrichCommandContext) { + const ast: ESQLCommandOption[] = []; + if (ctx.WITH()) { + const option = createOption(ctx.WITH()!.text.toLowerCase(), ctx); + ast.push(option); + const clauses = ctx.enrichWithClause(); + for (const clause of clauses) { + if (clause._enrichField) { + const args = [ + // if an explicit assign is not set, create a fake assign with + // both left and right value with the same column + clause.ASSIGN() ? createColumn(clause._newName) : createColumn(clause._enrichField), + createColumn(clause._enrichField), + ].filter(nonNullable); + if (args.length) { + const fn = createFunction('=', clause); + fn.args.push(args[0], [args[1]]); + option.args.push(fn); + } + } + } + option.location = getPosition(ctx.WITH()?.symbol); + } + + return ast; +} + +function visitLogicalNot(ctx: LogicalNotContext) { + const fn = createFunction('not', ctx); + fn.args.push(...collectBooleanExpression(ctx.booleanExpression())); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function visitLogicalAndsOrs(ctx: LogicalBinaryContext) { + const fn = createFunction(ctx.AND() ? 'and' : 'or', ctx); + fn.args.push(...collectBooleanExpression(ctx._left), ...collectBooleanExpression(ctx._right)); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function visitLogicalIns(ctx: LogicalInContext) { + const fn = createFunction(ctx.NOT() ? 'not_in' : 'in', ctx); + const [left, ...list] = ctx.valueExpression(); + const values = [visitValueExpression(left), list.map((ve) => visitValueExpression(ve))]; + for (const arg of values) { + if (arg) { + const filteredArgs = Array.isArray(arg) ? arg.filter(nonNullable) : [arg]; + fn.args.push(filteredArgs); + } + } + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; +} + +function getMathOperation(ctx: ArithmeticBinaryContext) { + return ( + ctx.PLUS()?.text || + ctx.MINUS()?.text || + ctx.ASTERISK()?.text || + ctx.SLASH()?.text || + ctx.PERCENT()?.text || + '' + ); +} + +function getComparisonName(ctx: ComparisonOperatorContext) { + return ( + ctx.EQ()?.text || + ctx.NEQ()?.text || + ctx.LT()?.text || + ctx.LTE()?.text || + ctx.GT()?.text || + ctx.GTE()?.text || + '' + ); +} + +function visitValueExpression(ctx: ValueExpressionContext) { + if (ctx instanceof ValueExpressionDefaultContext) { + return visitOperatorExpression(ctx.operatorExpression()); + } + if (ctx instanceof ComparisonContext) { + const comparisonNode = ctx.comparisonOperator(); + const comparisonFn = createFunction(getComparisonName(comparisonNode), comparisonNode); + comparisonFn.args.push( + visitOperatorExpression(ctx._left)!, + visitOperatorExpression(ctx._right)! + ); + // update the location of the comparisonFn based on arguments + const argsLocationExtends = computeLocationExtends(comparisonFn); + comparisonFn.location = argsLocationExtends; + + return comparisonFn; + } +} + +function visitOperatorExpression( + ctx: OperatorExpressionContext +): ESQLAstItem | ESQLAstItem[] | undefined { + if (ctx instanceof ArithmeticUnaryContext) { + const arg = visitOperatorExpression(ctx.operatorExpression()); + // this is a number sign thing + const fn = createFunction('multiply', ctx); + fn.args.push(createFakeMultiplyLiteral(ctx)); + if (arg) { + fn.args.push(arg); + } + return fn; + } + if (ctx instanceof ArithmeticBinaryContext) { + const fn = createFunction(getMathOperation(ctx), ctx); + const args = [visitOperatorExpression(ctx._left), visitOperatorExpression(ctx._right)]; + for (const arg of args) { + if (arg) { + fn.args.push(arg); + } + } + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return fn; + } + if (ctx instanceof OperatorExpressionDefaultContext) { + return visitPrimaryExpression(ctx.primaryExpression()); + } +} + +function getBooleanValue(ctx: BooleanLiteralContext | BooleanValueContext) { + const parentNode = ctx instanceof BooleanLiteralContext ? ctx.booleanValue() : ctx; + const booleanTerminalNode = parentNode.TRUE() || parentNode.FALSE(); + return createLiteral('boolean', booleanTerminalNode!); +} + +function getConstant(ctx: ConstantContext | undefined): ESQLAstItem | undefined { + if (ctx instanceof NullLiteralContext) { + return createLiteral('string', ctx.NULL()); + } + if (ctx instanceof QualifiedIntegerLiteralContext) { + // despite the generic name, this is a date unit constant: + // e.g. 1 year, 15 months + return createTimeUnit(ctx); + } + if (ctx instanceof DecimalLiteralContext) { + return createNumericLiteral(ctx.decimalValue()); + } + if (ctx instanceof IntegerLiteralContext) { + return createNumericLiteral(ctx.integerValue()); + } + if (ctx instanceof BooleanLiteralContext) { + return getBooleanValue(ctx); + } + if (ctx instanceof StringLiteralContext) { + return createLiteral('string', ctx.string().STRING()); + } + if ( + ctx instanceof NumericArrayLiteralContext || + ctx instanceof BooleanArrayLiteralContext || + ctx instanceof StringArrayLiteralContext + ) { + const values: ESQLLiteral[] = []; + for (const numericValue of ctx.getRuleContexts(NumericValueContext)) { + const value = numericValue.decimalValue() || numericValue.integerValue(); + values.push(createNumericLiteral(value!)); + } + for (const booleanValue of ctx.getRuleContexts(BooleanValueContext)) { + values.push(getBooleanValue(booleanValue)!); + } + for (const string of ctx.getRuleContexts(StringContext)) { + const literal = createLiteral('string', string.STRING()); + if (literal) { + values.push(literal); + } + } + return createList(ctx, values); + } +} + +export function visitRenameClauses(clausesCtx: RenameClauseContext[]): ESQLAstItem[] { + return clausesCtx + .map((clause) => { + const asToken = clause.tryGetToken(esql_parser.AS, 0); + if (asToken) { + const fn = createOption(asToken.text.toLowerCase(), clause); + for (const arg of [clause._oldName, clause._newName]) { + if (arg?.text) { + fn.args.push(createColumn(arg)); + } + } + return fn; + } else if (clause._oldName?.text) { + return createColumn(clause._oldName); + } + }) + .filter(nonNullable); +} + +export function visitPrimaryExpression( + ctx: PrimaryExpressionContext +): ESQLAstItem | ESQLAstItem[] | undefined { + if (ctx instanceof ConstantDefaultContext) { + return getConstant(ctx.constant()); + } + if (ctx instanceof DereferenceContext) { + return createColumn(ctx.qualifiedName()); + } + if (ctx instanceof ParenthesizedExpressionContext) { + return collectBooleanExpression(ctx.booleanExpression()); + } + if (ctx instanceof FunctionContext) { + const functionExpressionCtx = ctx.functionExpression(); + const fn = createFunction(functionExpressionCtx.identifier().text.toLowerCase(), ctx); + const asteriskArg = functionExpressionCtx.ASTERISK() + ? createColumnStar(functionExpressionCtx.ASTERISK()!) + : undefined; + if (asteriskArg) { + fn.args.push(asteriskArg); + } + const functionArgs = functionExpressionCtx + .booleanExpression() + .flatMap(collectBooleanExpression) + .filter(nonNullable); + if (functionArgs.length) { + fn.args.push(...functionArgs); + } + return fn; + } +} + +export function collectLogicalExpression(ctx: BooleanExpressionContext) { + if (ctx instanceof LogicalNotContext) { + return [visitLogicalNot(ctx)]; + } + if (ctx instanceof LogicalBinaryContext) { + return [visitLogicalAndsOrs(ctx)]; + } + if (ctx instanceof LogicalInContext) { + return [visitLogicalIns(ctx)]; + } + return []; +} + +function collectRegexExpression(ctx: BooleanExpressionContext): ESQLFunction[] { + const regexes = ctx.getRuleContexts(RegexBooleanExpressionContext); + const ret: ESQLFunction[] = []; + return ret.concat( + regexes.map((regex) => { + const negate = regex.NOT(); + const likeType = regex._kind.text?.toLowerCase() || ''; + const fnName = `${negate ? 'not_' : ''}${likeType}`; + const fn = createFunction(fnName, regex); + const arg = visitValueExpression(regex.valueExpression()); + if (arg) { + fn.args.push(arg); + const literal = createLiteral('string', regex._pattern.STRING()); + if (literal) { + fn.args.push(literal); + } + } + return fn; + }) + ); +} + +function collectIsNullExpression(ctx: BooleanExpressionContext) { + if (!(ctx instanceof IsNullContext)) { + return []; + } + const negate = ctx.NOT(); + const fnName = `${negate ? 'not_' : ''}is_null`; + const fn = createFunction(fnName, ctx); + const arg = visitValueExpression(ctx.valueExpression()); + if (arg) { + fn.args.push(arg); + } + return [fn]; +} + +function collectDefaultExpression(ctx: BooleanExpressionContext) { + if (!(ctx instanceof BooleanDefaultContext)) { + return []; + } + const arg = visitValueExpression(ctx.valueExpression()); + return arg ? [arg] : []; +} + +export function collectBooleanExpression(ctx: BooleanExpressionContext | undefined): ESQLAstItem[] { + const ast: ESQLAstItem[] = []; + if (!ctx) { + return ast; + } + return ast.concat( + collectLogicalExpression(ctx), + collectRegexExpression(ctx), + collectIsNullExpression(ctx), + collectDefaultExpression(ctx) + ); +} + +export function visitField(ctx: FieldContext) { + if (ctx.qualifiedName() && ctx.ASSIGN()) { + const fn = createFunction(ctx.ASSIGN()!.text, ctx); + fn.args.push( + createColumn(ctx.qualifiedName()!), + collectBooleanExpression(ctx.booleanExpression()) + ); + // update the location of the assign based on arguments + const argsLocationExtends = computeLocationExtends(fn); + fn.location = argsLocationExtends; + return [fn]; + } + return collectBooleanExpression(ctx.booleanExpression()); +} + +export function collectAllFieldsStatements(ctx: FieldsContext | undefined): ESQLAstItem[] { + const ast: ESQLAstItem[] = []; + if (!ctx) { + return ast; + } + try { + for (const field of ctx.field()) { + ast.push(...visitField(field)); + } + } catch (e) { + // do nothing + } + return ast; +} + +export function visitByOption(ctx: StatsCommandContext) { + if (!ctx.BY()) { + return []; + } + const option = createOption(ctx.BY()!.text.toLowerCase(), ctx); + for (const qnCtx of ctx.grouping()?.qualifiedName() || []) { + if (qnCtx?.text?.length) { + option.args.push(createColumn(qnCtx)); + } + } + return [option]; +} + +export function visitOrderExpression(ctx: OrderExpressionContext[]) { + const ast = []; + for (const orderCtx of ctx) { + const expression = collectBooleanExpression(orderCtx.booleanExpression()); + if (orderCtx._ordering) { + const terminalNode = + orderCtx.tryGetToken(esql_parser.ASC, 0) || orderCtx.tryGetToken(esql_parser.DESC, 0); + const literal = createLiteral('string', terminalNode); + if (literal) { + expression.push(literal); + } + } + if (orderCtx.NULLS()) { + expression.push(createLiteral('string', orderCtx.NULLS()!)!); + if (orderCtx._nullOrdering) { + const innerTerminalNode = + orderCtx.tryGetToken(esql_parser.FIRST, 0) || orderCtx.tryGetToken(esql_parser.LAST, 0); + const literal = createLiteral('string', innerTerminalNode); + if (literal) { + expression.push(literal); + } + } + } + + if (expression.length) { + ast.push(...expression); + } + } + return ast; +} + +export function visitDissect(ctx: DissectCommandContext) { + const pattern = ctx.string().tryGetToken(esql_parser.STRING, 0); + return [ + visitPrimaryExpression(ctx.primaryExpression()), + createLiteral('string', pattern), + ...visitDissectOptions(ctx.commandOptions()), + ].filter(nonNullable); +} + +export function visitGrok(ctx: GrokCommandContext) { + const pattern = ctx.string().tryGetToken(esql_parser.STRING, 0); + return [visitPrimaryExpression(ctx.primaryExpression()), createLiteral('string', pattern)].filter( + nonNullable + ); +} + +function visitDissectOptions(ctx: CommandOptionsContext | undefined) { + if (!ctx) { + return []; + } + const options: ESQLCommandOption[] = []; + for (const optionCtx of ctx.commandOption()) { + const option = createOption( + sanifyIdentifierString(optionCtx.identifier()).toLowerCase(), + optionCtx + ); + options.push(option); + // it can throw while accessing constant for incomplete commands, so try catch it + try { + const optionValue = getConstant(optionCtx.constant()); + if (optionValue != null) { + option.args.push(optionValue); + } + } catch (e) { + // do nothing here + } + } + return options; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts new file mode 100644 index 0000000000000..bfb9ecaee8d80 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.test.ts @@ -0,0 +1,780 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../../monaco_imports'; +import { CharStreams } from 'antlr4ts'; +import { suggest } from './autocomplete'; +import { getParser, ROOT_STATEMENT } from '../../antlr_facade'; +import { ESQLErrorListener } from '../../monaco/esql_error_listener'; +import { AstListener } from '../ast_factory'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { builtinFunctions } from '../definitions/builtin'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { commandDefinitions } from '../definitions/commands'; + +const triggerCharacters = [',', '(', '=', ' ']; + +const fields = [ + ...['string', 'number', 'date', 'boolean', 'ip'].map((type) => ({ + name: `${type}Field`, + type, + })), + { name: 'any#Char$ field', type: 'number' }, + { name: 'kubernetes.something.something', type: 'number' }, + { + name: `listField`, + type: `list`, + }, +]; + +const indexes = ['a', 'index', 'otherIndex', '.secretIndex'].map((name) => ({ + name, + hidden: name.startsWith('.'), +})); +const policies = [ + { + name: 'policy', + sourceIndices: ['enrichIndex1'], + matchField: 'otherStringField', + enrichFields: ['otherField', 'yetAnotherField'], + }, +]; + +/** + * 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 + * @param command current command context + * @param expectedReturnType the expected type returned by the function + * @param functionCategories + * @param paramsTypes the function argument types (optional) + * @returns + */ +function getFunctionSignaturesByReturnType( + command: string, + expectedReturnType: string, + { agg, evalMath, builtin }: { agg?: boolean; evalMath?: boolean; builtin?: boolean } = {}, + paramsTypes?: string[], + ignored?: string[] +) { + const list = []; + if (agg) { + list.push(...statsAggregationFunctionDefinitions); + } + // eval functions (eval is a special keyword in JS) + if (evalMath) { + list.push(...evalFunctionsDefinitions); + } + if (builtin) { + list.push(...builtinFunctions); + } + return list + .filter(({ signatures, ignoreAsSuggestion, supportedCommands }) => { + if (ignoreAsSuggestion) { + return false; + } + if (!supportedCommands.includes(command)) { + return false; + } + const filteredByReturnType = signatures.some( + ({ returnType }) => expectedReturnType === 'any' || returnType === expectedReturnType + ); + if (!filteredByReturnType) { + return false; + } + if (paramsTypes?.length) { + return signatures.some(({ params }) => + paramsTypes.every( + (expectedType, i) => expectedType === 'any' || expectedType === params[i].type + ) + ); + } + return true; + }) + .filter(({ name }) => { + if (ignored?.length) { + return !ignored?.includes(name); + } + return true; + }) + .map(({ builtin: isBuiltinFn, name, signatures, ...defRest }) => + isBuiltinFn ? `${name} $0` : `${name}($0)` + ); +} + +function getFieldNamesByType(requestedType: string) { + return fields + .filter(({ type }) => requestedType === 'any' || type === requestedType) + .map(({ name }) => name); +} + +function getLiteralsByType(type: string) { + if (type === 'time_literal') { + // return only singular + return timeLiterals.map(({ name }) => `1 ${name}`).filter((s) => !/s$/.test(s)); + } + if (type === 'chrono_literal') { + return chronoLiterals.map(({ name }) => name); + } + return []; +} + +function createCustomCallbackMocks( + customFields: Array<{ name: string; type: string }> | undefined, + customSources: Array<{ name: string; hidden: boolean }> | undefined, + customPolicies: + | Array<{ + name: string; + sourceIndices: string[]; + matchField: string; + enrichFields: string[]; + }> + | undefined +) { + const finalFields = customFields || fields; + const finalSources = customSources || indexes; + const finalPolicies = customPolicies || policies; + return { + getFieldsFor: jest.fn(async () => finalFields), + getSources: jest.fn(async () => finalSources), + getPolicies: jest.fn(async () => finalPolicies), + }; +} + +function createModelAndPosition(text: string, offset: number) { + return { + model: { getValue: () => text } as monaco.editor.ITextModel, + position: { lineNumber: 1, column: offset } as monaco.Position, + }; +} + +function createSuggestContext(text: string, triggerCharacter?: string) { + if (triggerCharacter) { + return { triggerCharacter, triggerKind: 1 }; // any number is fine here + } + const foundTriggerCharIndexes = triggerCharacters.map((char) => text.lastIndexOf(char)); + const maxIndex = Math.max(...foundTriggerCharIndexes); + return { + triggerCharacter: text[maxIndex], + triggerKind: 1, + }; +} + +function getPolicyFields(policyName: string) { + return policies + .filter(({ name }) => name === policyName) + .flatMap(({ enrichFields }) => enrichFields); +} + +describe('autocomplete', () => { + const getAstAndErrors = async (text: string) => { + const errorListener = new ESQLErrorListener(); + const parseListener = new AstListener(); + const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); + + parser[ROOT_STATEMENT](); + + return { ...parseListener.getAst(), errors: [] }; + }; + + type TestArgs = [ + string, + string[], + (string | number)?, + Parameters? + ]; + + const testSuggestionsFn = ( + statement: string, + expected: string[], + triggerCharacter: string | number = '', + customCallbacksArgs: Parameters = [ + undefined, + undefined, + undefined, + ], + { only, skip }: { only?: boolean; skip?: boolean } = {} + ) => { + const triggerCharacterString = + triggerCharacter == null || typeof triggerCharacter === 'string' + ? triggerCharacter + : statement[triggerCharacter + 1]; + const context = createSuggestContext(statement, triggerCharacterString); + const offset = + typeof triggerCharacter === 'string' + ? statement.lastIndexOf(context.triggerCharacter) + 2 + : triggerCharacter; + const testFn = only ? test.only : skip ? test.skip : test; + + testFn( + `${statement} (triggerChar: "${context.triggerCharacter}" @ ${offset})=> ["${expected.join( + '","' + )}"]`, + async () => { + const callbackMocks = createCustomCallbackMocks(...customCallbacksArgs); + const { model, position } = createModelAndPosition(statement, offset); + const suggestions = await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(suggestions.map((i) => i.insertText)).toEqual(expected); + } + ); + }; + + // Enrich the function to work with .only and .skip as regular test function + const testSuggestions = Object.assign(testSuggestionsFn, { + skip: (...args: TestArgs) => { + const paddingArgs = ['', [undefined, undefined, undefined]].slice(args.length - 2); + return testSuggestionsFn( + ...((args.length > 1 ? [...args, ...paddingArgs] : args) as TestArgs), + { + skip: true, + } + ); + }, + only: (...args: TestArgs) => { + const paddingArgs = ['', [undefined, undefined, undefined]].slice(args.length - 2); + return testSuggestionsFn( + ...((args.length > 1 ? [...args, ...paddingArgs] : args) as TestArgs), + { + only: true, + } + ); + }, + }); + + const sourceCommands = ['row', 'from', 'show']; + + describe('New command', () => { + testSuggestions(' ', sourceCommands); + testSuggestions( + 'from a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a [metadata _id] | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a | eval var0 = a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + testSuggestions( + 'from a [metadata _id] | eval var0 = a | ', + commandDefinitions + .filter(({ name }) => !sourceCommands.includes(name)) + .map(({ name }) => name) + ); + }); + + describe('from', () => { + const suggestedIndexes = indexes.filter(({ hidden }) => !hidden).map(({ name }) => name); + // Monaco will filter further down here + testSuggestions('f', sourceCommands); + testSuggestions('from ', suggestedIndexes); + testSuggestions('from a,', suggestedIndexes); + testSuggestions('from a, b ', ['[metadata $0 ]', '|', ',']); + testSuggestions('from *,', suggestedIndexes); + }); + + describe('where', () => { + const allEvalFns = getFunctionSignaturesByReturnType('where', 'any', { + evalMath: true, + }); + testSuggestions('from a | where ', [...getFieldNamesByType('any'), ...allEvalFns]); + testSuggestions('from a | eval var0 = 1 | where ', [ + ...getFieldNamesByType('any'), + ...allEvalFns, + 'var0', + ]); + testSuggestions('from a | where stringField ', [ + // all functions compatible with a stringField type + ...getFunctionSignaturesByReturnType( + 'where', + 'boolean', + { + builtin: true, + }, + ['string'] + ), + ]); + testSuggestions('from a | where stringField >= ', [ + ...getFieldNamesByType('string'), + ...getFunctionSignaturesByReturnType('where', 'string', { evalMath: true }), + ]); + testSuggestions('from a | where stringField >= stringField ', [ + ...getFunctionSignaturesByReturnType( + 'where', + 'boolean', + { + builtin: true, + }, + ['boolean'] + ), + '|', + ]); + for (const op of ['and', 'or']) { + testSuggestions(`from a | where stringField >= stringField ${op} `, [ + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('where', 'any', { evalMath: true }), + ]); + testSuggestions(`from a | where stringField >= stringField ${op} numberField `, [ + ...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['number']), + ]); + testSuggestions(`from a | where stringField >= stringField ${op} numberField == `, [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }), + ]); + } + testSuggestions('from a | stats a=avg(numberField) | where a ', [ + ...getFunctionSignaturesByReturnType('where', 'any', { builtin: true }, ['number']), + ]); + // Mind this test: suggestion is aware of previous commands when checking for fields + // in this case the numberField has been wiped by the STATS command and suggest cannot find it's type + // @TODO: verify this is the correct behaviour in this case or if we want a "generic" suggestion anyway + testSuggestions( + 'from a | stats a=avg(numberField) | where numberField ', + [], + '', + // make the fields suggest aware of the previous STATS, leave the other callbacks untouched + [[{ name: 'a', type: 'number' }], undefined, undefined] + ); + // The editor automatically inject the final bracket, so it is not useful to test with just open bracket + testSuggestions( + 'from a | where log10()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }, undefined, [ + 'log10', + ]), + ], + '(' + ); + testSuggestions('from a | where log10(numberField) ', [ + ...getFunctionSignaturesByReturnType('where', 'number', { builtin: true }, ['number']), + ...getFunctionSignaturesByReturnType('where', 'boolean', { builtin: true }, ['number']), + ]); + testSuggestions( + 'from a | WHERE pow(numberField, )', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('where', 'number', { evalMath: true }, undefined, [ + 'pow', + ]), + ], + ',' + ); + }); + + describe('sort', () => { + testSuggestions('from a | sort ', getFieldNamesByType('any')); + testSuggestions('from a | sort stringField ', ['asc', 'desc', '|', ',']); + testSuggestions('from a | sort stringField desc ', ['nulls first', 'nulls last', '|', ',']); + // @TODO: improve here + // testSuggestions('from a | sort stringField desc ', ['first', 'last']); + }); + + describe('limit', () => { + testSuggestions('from a | limit ', ['10', '100', '1000']); + testSuggestions('from a | limit 4 ', ['|']); + }); + + describe('mv_expand', () => { + testSuggestions('from a | mv_expand ', ['listField']); + testSuggestions('from a | mv_expand a ', ['|']); + }); + + describe('rename', () => { + testSuggestions('from a | rename ', getFieldNamesByType('any')); + testSuggestions('from a | rename stringField ', ['as']); + testSuggestions('from a | rename stringField as ', ['var0']); + }); + + for (const command of ['keep', 'drop', 'project']) { + describe(command, () => { + testSuggestions(`from a | ${command} `, getFieldNamesByType('any')); + testSuggestions( + `from a | ${command} stringField, `, + getFieldNamesByType('any').filter((name) => name !== 'stringField') + ); + }); + } + + describe('stats', () => { + const allAggFunctions = getFunctionSignaturesByReturnType('stats', 'any', { + agg: true, + }); + testSuggestions('from a | stats ', ['var0 =', ...allAggFunctions]); + testSuggestions('from a | stats a ', ['= $0']); + testSuggestions('from a | stats a=', [...allAggFunctions]); + testSuggestions('from a | stats a=max(b) by ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=max(b) BY ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=c by d ', ['|', ',']); + testSuggestions('from a | stats a=c by d, ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=max(b), ', ['var0 =', ...allAggFunctions]); + testSuggestions( + 'from a | stats a=min()', + fields.filter(({ type }) => type === 'number').map(({ name }) => name), + '(' + ); + testSuggestions('from a | stats a=min(b) ', ['by', '|', ',']); + testSuggestions('from a | stats a=min(b) by ', getFieldNamesByType('any')); + testSuggestions('from a | stats a=min(b),', ['var0 =', ...allAggFunctions]); + testSuggestions('from a | stats var0=min(b),var1=c,', ['var2 =', ...allAggFunctions]); + testSuggestions( + 'from a | stats a=min(b), b=max()', + fields.filter(({ type }) => type === 'number').map(({ name }) => name) + ); + // @TODO: remove last 2 suggestions if possible + testSuggestions('from a | eval var0=round(b), var1=round(c) | stats ', [ + 'var2 =', + ...allAggFunctions, + 'var0', + 'var1', + ]); + + // smoke testing with suggestions not at the end of the string + testSuggestions( + 'from a | stats a = min(b) | sort b', + ['by', '|', ','], + 27 /* " " after min(b) */ + ); + testSuggestions( + 'from a | stats avg(b) by stringField', + getFieldNamesByType('number'), + 21 /* b column in avg */ + ); + }); + + describe('enrich', () => { + for (const prevCommand of [ + '', + '| enrich other-policy ', + '| enrich other-policy on b ', + '| enrich other-policy with c ', + ]) { + testSuggestions(`from a ${prevCommand}| enrich `, ['policy']); + testSuggestions(`from a ${prevCommand}| enrich policy `, ['on', 'with', '|']); + testSuggestions(`from a ${prevCommand}| enrich policy on `, [ + 'stringField', + 'numberField', + 'dateField', + 'booleanField', + 'ipField', + 'any#Char$ field', + 'kubernetes.something.something', + 'listField', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b `, ['with', '|', ',']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with `, [ + 'var0 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 `, ['= $0', '|', ',']); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = `, [ + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField `, [ + '|', + ',', + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField, `, [ + 'var1 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = stringField, var1 `, [ + '= $0', + '|', + ',', + ]); + testSuggestions( + `from a ${prevCommand}| enrich policy on b with var0 = stringField, var1 = `, + [...getPolicyFields('policy')] + ); + testSuggestions(`from a ${prevCommand}| enrich policy with `, [ + 'var0 =', + ...getPolicyFields('policy'), + ]); + testSuggestions(`from a ${prevCommand}| enrich policy with stringField `, ['= $0', '|', ',']); + } + }); + + describe('eval', () => { + testSuggestions('from a | eval ', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval numberField ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ]); + testSuggestions('from a | eval a=', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval a=abs(numberField), b= ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + ]); + testSuggestions('from a | eval a=numberField, ', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + 'a', + ]); + testSuggestions( + 'from a | eval a=round()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + testSuggestions('from a | eval a=round(numberField) ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ]); + testSuggestions('from a | eval a=round(numberField),', [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + 'a', + ]); + testSuggestions('from a | eval a=round(numberField) + ', [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }), + 'a', // @TODO remove this + ]); + testSuggestions( + 'from a | stats avg(numberField) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + ], + ' ', + // make aware EVAL of the previous STATS command + [[], undefined, undefined] + ); + testSuggestions( + 'from a | eval abs(numberField) + 1 | eval ', + [ + 'var0 =', + ...getFieldNamesByType('any'), + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + // @TODO: leverage the location data to get the original text + // For now return back the trimmed version: + // the ANTLR parser trims all text so that's what it's stored in the AST + '`abs(numberField)+1`', + ], + ' ' + ); + testSuggestions( + 'from a | stats avg(numberField) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + ], + ' ', + // make aware EVAL of the previous STATS command with the buggy field name from expression + [[{ name: 'avg_numberField_', type: 'number' }], undefined, undefined] + ); + testSuggestions( + 'from a | stats avg(numberField), avg(kubernetes.something.something) by stringField | eval ', + [ + 'var0 =', + ...getFunctionSignaturesByReturnType('eval', 'any', { evalMath: true }), + '`avg(numberField)`', + '`avg(kubernetes.something.something)`', + ], + ' ', + // make aware EVAL of the previous STATS command with the buggy field name from expression + [ + [ + { name: 'avg_numberField_', type: 'number' }, + { name: 'avg_kubernetes.something.something_', type: 'number' }, + ], + undefined, + undefined, + ] + ); + testSuggestions( + 'from a | eval a=round(numberField), b=round()', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + // test deep function nesting suggestions (and check that the same function is not suggested) + // round(round( + // round(round(round( + // etc... + for (const nesting of [1, 2, 3, 4]) { + testSuggestions( + `from a | eval a=${Array(nesting).fill('round(').join('')}`, + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'round', + ]), + ], + '(' + ); + } + + // Smoke testing for suggestions in previous position than the end of the statement + testSuggestions( + 'from a | eval var0 = abs(numberField) | eval abs(var0)', + [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + '|', + ',', + ], + 38 /* " " after abs(b) */ + ); + testSuggestions( + 'from a | eval var0 = abs(b) | eval abs(var0)', + [ + ...getFieldNamesByType('number'), + ...getFunctionSignaturesByReturnType('eval', 'number', { evalMath: true }, undefined, [ + 'abs', + ]), + ], + 26 /* b column in abs */ + ); + + // Test suggestions for each possible param, within each signature variation, for each function + for (const fn of evalFunctionsDefinitions) { + // skip this fn for the moment as it's quite hard to test + if (fn.name !== 'auto_bucket') { + for (const signature of fn.signatures) { + signature.params.forEach((param, i) => { + if (i < signature.params.length - 1) { + const canHaveMoreArgs = + signature.params.filter(({ optional }, j) => !optional && j > i).length > i; + testSuggestions( + `from a | eval ${fn.name}(${Array(i).fill('field').join(', ')}${i ? ',' : ''} )`, + [ + ...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), + ...getFunctionSignaturesByReturnType( + 'eval', + param.type, + { evalMath: true }, + undefined, + [fn.name] + ).map((l) => (canHaveMoreArgs ? `${l},` : l)), + ...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), + ] + ); + testSuggestions( + `from a | eval var0 = ${fn.name}(${Array(i).fill('field').join(', ')}${ + i ? ',' : '' + } )`, + [ + ...getFieldNamesByType(param.type).map((f) => (canHaveMoreArgs ? `${f},` : f)), + ...getFunctionSignaturesByReturnType( + 'eval', + param.type, + { evalMath: true }, + undefined, + [fn.name] + ).map((l) => (canHaveMoreArgs ? `${l},` : l)), + ...getLiteralsByType(param.type).map((d) => (canHaveMoreArgs ? `${d},` : d)), + ] + ); + } + }); + } + } + } + + describe('date math', () => { + const dateSuggestions = timeLiterals.map(({ name }) => name); + // If a literal number is detected then suggest also date period keywords + testSuggestions('from a | eval a = 1 ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + ...dateSuggestions, + '|', + ',', + ]); + testSuggestions('from a | eval a = 1 year ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['time_interval']), + '|', + ',', + ]); + testSuggestions('from a | eval a = 1 day + 2 ', [ + ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true }, ['number']), + ...dateSuggestions, + '|', + ',', + ]); + testSuggestions( + 'from a | eval var0=date_trunc()', + [...getLiteralsByType('time_literal').map((t) => `${t},`)], + '(' + ); + testSuggestions('from a | eval var0=date_trunc(2 )', [ + ...dateSuggestions.map((t) => `${t},`), + ',', + ]); + }); + }); + + describe('callbacks', () => { + it('should send the fields query without the last command', async () => { + const callbackMocks = createCustomCallbackMocks(undefined, undefined, undefined); + const statement = 'from a | drop stringField | eval var0 = abs(numberField) '; + const triggerOffset = statement.lastIndexOf(' '); + const context = createSuggestContext(statement, statement[triggerOffset]); + const { model, position } = createModelAndPosition(statement, triggerOffset + 2); + await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledWith({ + query: 'from a | drop stringField', + }); + }); + it('should send the fields query aware of the location', async () => { + const callbackMocks = createCustomCallbackMocks(undefined, undefined, undefined); + const statement = 'from a | drop | eval var0 = abs(numberField) '; + const triggerOffset = statement.lastIndexOf('p') + 1; // drop + const context = createSuggestContext(statement, statement[triggerOffset]); + const { model, position } = createModelAndPosition(statement, triggerOffset + 2); + await suggest( + model, + position, + context, + async (text) => (text ? await getAstAndErrors(text) : { ast: [], errors: [] }), + callbackMocks + ); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledWith({ query: 'from a' }); + }); + }); +}); diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts new file mode 100644 index 0000000000000..de1b07b39bed5 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/autocomplete.ts @@ -0,0 +1,1098 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import uniqBy from 'lodash/uniqBy'; +import type { monaco } from '../../../../monaco_imports'; +import type { AutocompleteCommandDefinition } from './types'; +import { nonNullable } from '../ast_helpers'; +import { + columnExists, + getColumnHit, + getCommandDefinition, + getCommandOption, + getFunctionDefinition, + isAssignment, + isAssignmentComplete, + isColumnItem, + isFunctionItem, + isIncompleteItem, + isLiteralItem, + isOptionItem, + isRestartingExpression, + isSourceItem, + isTimeIntervalItem, + monacoPositionToOffset, +} from '../shared/helpers'; +import { collectVariables, excludeVariablesFromCurrentCommand } from '../shared/variables'; +import type { + AstProviderFn, + ESQLAst, + ESQLAstItem, + ESQLCommand, + ESQLCommandOption, + ESQLFunction, + ESQLSingleAstItem, +} from '../types'; +import type { ESQLPolicy, ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; +import { + commaCompleteItem, + commandAutocompleteDefinitions, + getAssignmentDefinitionCompletitionItem, + getBuiltinCompatibleFunctionDefinition, + mathCommandDefinition, + pipeCompleteItem, +} from './complete_items'; +import { + buildFieldsDefinitions, + buildPoliciesDefinitions, + buildSourcesDefinitions, + buildNewVarDefinition, + buildNoPoliciesAvailableDefinition, + getCompatibleFunctionDefinition, + buildMatchingFieldsDefinition, + getCompatibleLiterals, + buildConstantsDefinitions, + buildVariablesDefinitions, + buildOptionDefinition, + TRIGGER_SUGGESTION_COMMAND, +} from './factories'; +import { EDITOR_MARKER } from '../shared/constants'; +import { getAstContext, removeMarkerArgFromArgsList } from '../shared/context'; +import { + getFieldsByTypeHelper, + getPolicyHelper, + getSourcesHelper, +} from '../shared/resources_helpers'; +import { ESQLCallbacks } from '../shared/types'; + +type GetSourceFn = () => Promise; +type GetFieldsByTypeFn = ( + type: string | string[], + ignored?: string[] +) => Promise; +type GetFieldsMapFn = () => Promise>; +type GetPoliciesFn = () => Promise; +type GetPolicyMetadataFn = (name: string) => Promise; + +function hasSameArgBothSides(assignFn: ESQLFunction) { + if (assignFn.name === '=' && isColumnItem(assignFn.args[0]) && assignFn.args[1]) { + const assignValue = assignFn.args[1]; + if (Array.isArray(assignValue) && isColumnItem(assignValue[0])) { + return assignFn.args[0].name === assignValue[0].name; + } + } +} + +function appendEnrichFields( + fieldsMap: Map, + policyMetadata: ESQLPolicy | undefined +) { + if (!policyMetadata) { + return fieldsMap; + } + // @TODO: improve this + const newMap: Map = new Map(fieldsMap); + for (const field of policyMetadata.enrichFields) { + newMap.set(field, { name: field, type: 'number' }); + } + return newMap; +} + +function getFinalSuggestions({ comma }: { comma?: boolean } = { comma: true }) { + const finalSuggestions = [pipeCompleteItem]; + if (comma) { + finalSuggestions.push(commaCompleteItem); + } + return finalSuggestions; +} + +function isMathFunction(char: string) { + return ['+', '-', '*', '/', '%', '='].some((op) => char === op); +} + +function isComma(char: string) { + return char === ','; +} + +function isSourceCommand({ label }: AutocompleteCommandDefinition) { + return ['from', 'row', 'show'].includes(String(label)); +} +/** + * This function count the number of unclosed brackets in order to + * locally fix the queryString to generate a valid AST + * A known limitation of this is that is not aware of commas "," or pipes "|" + * so it is not yet helpful on a multiple commands errors (a workaround it to pass each command here...) + * @param bracketType + * @param text + * @returns + */ +function countBracketsUnclosed(bracketType: '(' | '[', text: string) { + const stack = []; + const closingBrackets = { '(': ')', '[': ']' }; + for (const char of text) { + if (char === bracketType) { + stack.push(bracketType); + } else if (char === closingBrackets[bracketType]) { + stack.pop(); + } + } + return stack.length; +} + +export async function suggest( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext, + astProvider: AstProviderFn, + resourceRetriever?: ESQLCallbacks +): Promise { + // take the full text but then slice it to the current position + const fullText = model.getValue(); + const offset = monacoPositionToOffset(fullText, position); + const innerText = fullText.substring(0, offset); + + let finalText = innerText; + + // check if all brackets are closed, otherwise close them + const unclosedBrackets = countBracketsUnclosed('(', finalText); + // if it's a comma by the user or a forced trigger by a function argument suggestion + // add a marker to make the expression still valid + if ( + context.triggerCharacter === ',' || + (context.triggerKind === 0 && unclosedBrackets === 0) || + (context.triggerCharacter === ' ' && + // make this more robust + (isMathFunction(innerText[offset - 2]) || isComma(innerText[offset - 2]))) + ) { + finalText = `${innerText.substring(0, offset)}${EDITOR_MARKER}${innerText.substring(offset)}`; + } + if (unclosedBrackets > 0) { + // inject the closing brackets + finalText += Array(unclosedBrackets).fill(')').join(''); + } + + const { ast } = await astProvider(finalText); + + const astContext = getAstContext(innerText, ast, offset); + // build the correct query to fetch the list of fields + const queryForFields = buildQueryForFields(ast, finalText); + const { getFieldsByType, getFieldsMap } = getFieldsByTypeRetriever( + queryForFields, + resourceRetriever + ); + const getSources = getSourcesRetriever(resourceRetriever); + const { getPolicies, getPolicyMetadata } = getPolicyRetriever(resourceRetriever); + + if (astContext.type === 'newCommand') { + // propose main commands here + // filter source commands if already defined + const suggestions = commandAutocompleteDefinitions; + if (!ast.length) { + return suggestions.filter(isSourceCommand); + } + return suggestions.filter((def) => !isSourceCommand(def)); + } + + if (astContext.type === 'expression') { + // suggest next possible argument, or option + // otherwise a variable + return getExpressionSuggestionsByType( + innerText, + ast, + astContext, + getSources, + getFieldsByType, + getFieldsMap, + getPolicies, + getPolicyMetadata + ); + } + if (astContext.type === 'option') { + // need this wrap/unwrap thing to make TS happy + const { option, ...rest } = astContext; + if (option && isOptionItem(option)) { + return getOptionArgsSuggestions( + innerText, + ast, + { option, ...rest }, + getFieldsByType, + getFieldsMap, + getPolicyMetadata + ); + } + } + if (astContext.type === 'function') { + return getFunctionArgsSuggestions( + innerText, + ast, + astContext, + getFieldsByType, + getFieldsMap, + getPolicyMetadata + ); + } + return []; +} + +export function buildQueryForFields(ast: ESQLAst, queryString: string) { + const prevCommand = ast[Math.max(ast.length - 2, 0)]; + return prevCommand ? queryString.substring(0, prevCommand.location.max + 1) : queryString; +} + +function getFieldsByTypeRetriever(queryString: string, resourceRetriever?: ESQLCallbacks) { + const helpers = getFieldsByTypeHelper(queryString, resourceRetriever); + return { + getFieldsByType: async (expectedType: string | string[] = 'any', ignored: string[] = []) => { + const fields = await helpers.getFieldsByType(expectedType, ignored); + return buildFieldsDefinitions(fields); + }, + getFieldsMap: helpers.getFieldsMap, + }; +} + +function getPolicyRetriever(resourceRetriever?: ESQLCallbacks) { + const helpers = getPolicyHelper(resourceRetriever); + return { + getPolicies: async () => { + const policies = await helpers.getPolicies(); + return buildPoliciesDefinitions(policies); + }, + getPolicyMetadata: helpers.getPolicyMetadata, + }; +} + +function getSourcesRetriever(resourceRetriever?: ESQLCallbacks) { + const helper = getSourcesHelper(resourceRetriever); + return async () => { + const list = (await helper()) || []; + // hide indexes that start with . + return buildSourcesDefinitions(list.filter(({ hidden }) => !hidden).map(({ name }) => name)); + }; +} + +function findNewVariable(variables: Map) { + let autoGeneratedVariableCounter = 0; + let name = `var${autoGeneratedVariableCounter++}`; + while (variables.has(name)) { + name = `var${autoGeneratedVariableCounter++}`; + } + return name; +} + +function areCurrentArgsValid( + command: ESQLCommand, + node: ESQLAstItem, + references: Pick +) { + // unfortunately here we need to bake some command-specific logic + if (command.name === 'stats') { + if (node) { + // consider the following expressions not complete yet + // ... | stats a + // ... | stats a = + if (isColumnItem(node) || (isAssignment(node) && !isAssignmentComplete(node))) { + return false; + } + } + } + if (command.name === 'eval') { + if (node) { + if (isFunctionItem(node)) { + if (isAssignment(node)) { + return isAssignmentComplete(node); + } else { + return isFunctionArgComplete(node, references).complete; + } + } + } + } + if (command.name === 'where') { + if (node) { + if ( + isColumnItem(node) || + (isFunctionItem(node) && !isFunctionArgComplete(node, references).complete) + ) { + return false; + } else { + return ( + extractFinalTypeFromArg(node, references) === + getCommandDefinition(command.name).signature.params[0].type + ); + } + } + } + if (command.name === 'rename') { + if (node) { + if (isColumnItem(node)) { + return true; + } + } + } + return true; +} + +function extractFinalTypeFromArg( + arg: ESQLAstItem, + references: Pick +): string | undefined { + if (Array.isArray(arg)) { + return extractFinalTypeFromArg(arg[0], references); + } + if (isColumnItem(arg) || isLiteralItem(arg)) { + if (isLiteralItem(arg)) { + return arg.literalType; + } + if (isColumnItem(arg)) { + const hit = getColumnHit(arg.name, references); + if (hit) { + return hit.type; + } + } + } + if (isTimeIntervalItem(arg)) { + return arg.type; + } + if (isFunctionItem(arg)) { + const fnDef = getFunctionDefinition(arg.name); + if (fnDef) { + // @TODO: improve this to better filter down the correct return type based on existing arguments + // just mind that this can be highly recursive... + return fnDef.signatures[0].returnType; + } + } +} + +// @TODO: refactor this to be shared with validation +function isFunctionArgComplete( + arg: ESQLFunction, + references: Pick +) { + const fnDefinition = getFunctionDefinition(arg.name)!; + const cleanedArgs = removeMarkerArgFromArgsList(arg)!.args; + const argLengthCheck = fnDefinition.signatures.some((def) => { + if (def.infiniteParams && cleanedArgs.length > 0) { + return true; + } + if (def.minParams && cleanedArgs.length >= def.minParams) { + return true; + } + if (cleanedArgs.length === def.params.length) { + return true; + } + return cleanedArgs.length >= def.params.filter(({ optional }) => !optional).length; + }); + if (!argLengthCheck) { + return { complete: false, reason: 'fewArgs' }; + } + const hasCorrectTypes = fnDefinition.signatures.some((def) => { + return arg.args.every((a, index) => { + if (def.infiniteParams) { + return true; + } + return def.params[index].type === extractFinalTypeFromArg(a, references); + }); + }); + if (!hasCorrectTypes) { + return { complete: false, reason: 'wrongTypes' }; + } + return { complete: true }; +} + +async function getExpressionSuggestionsByType( + innerText: string, + commands: ESQLCommand[], + { + command, + node, + }: { + command: ESQLCommand; + node: ESQLSingleAstItem | undefined; + }, + getSources: GetSourceFn, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMap: GetFieldsMapFn, + getPolicies: GetPoliciesFn, + getPolicyMetadata: GetPolicyMetadataFn +) { + const commandDef = getCommandDefinition(command.name); + // get the argument position + let argIndex = command.args.length; + const prevIndex = Math.max(argIndex - 1, 0); + const lastArg = removeMarkerArgFromArgsList(command)!.args[prevIndex]; + if (isIncompleteItem(lastArg)) { + argIndex = prevIndex; + } + + // if a node is not specified use the lastArg + // mind to give priority to node as lastArg might be a function root + // => "a > b and c == d" gets translated into and( gt(a, b) , eq(c, d) ) => hence "and" is lastArg + const nodeArg = node || lastArg; + // A new expression is considered either + // * just after a command name => i.e. ... | STATS + // * or after a comma => i.e. STATS fieldA, + const isNewExpression = isRestartingExpression(innerText) || argIndex === 0; + + // Are options already declared? This is useful to suggest only new ones + const optionsAlreadyDeclared = ( + command.args.filter((arg) => isOptionItem(arg)) as ESQLCommandOption[] + ).map(({ name }) => ({ + name, + index: commandDef.options.findIndex(({ name: defName }) => defName === name), + })); + const optionsAvailable = commandDef.options.filter(({ name }, index) => { + const optArg = optionsAlreadyDeclared.find(({ name: optionName }) => optionName === name); + return (!optArg && !optionsAlreadyDeclared.length) || (optArg && index > optArg.index); + }); + // get the next definition for the given command + let argDef = commandDef.signature.params[argIndex]; + // tune it for the variadic case + if (!argDef) { + // this is the case of a comma argument + if (commandDef.signature.multipleParams) { + if (isNewExpression || (isAssignment(lastArg) && !isAssignmentComplete(lastArg))) { + // i.e. ... | a, + // i.e. ... | a = ..., b = + argDef = commandDef.signature.params[0]; + } + } + + // this is the case where there's an argument, but it's of the wrong type + // i.e. ... | WHERE numberField (WHERE wants a boolean expression!) + // i.e. ... | STATS numberfield (STATS wants a function expression!) + if (!isNewExpression && nodeArg && !Array.isArray(nodeArg)) { + const prevArg = commandDef.signature.params[prevIndex]; + // in some cases we do not want to go back as the command only accepts a literal + // i.e. LIMIT 5 -> that's it, so no argDef should be assigned + + // make an exception for STATS (STATS is the only command who accept a function type as arg) + if ( + prevArg && + (prevArg.type === 'function' || (!Array.isArray(nodeArg) && prevArg.type !== nodeArg.type)) + ) { + if (!isLiteralItem(nodeArg) || !prevArg.literalOnly) { + argDef = prevArg; + } + } + } + } + + // collect all fields + variables to suggest + const fieldsMap: Map = await (argDef ? getFieldsMap() : new Map()); + const anyVariables = collectVariables(commands, fieldsMap); + + // enrich with assignment has some special rules who are handled somewhere else + const canHaveAssignments = ['eval', 'stats', 'row'].includes(command.name); + + const references = { fields: fieldsMap, variables: anyVariables }; + + const suggestions: AutocompleteCommandDefinition[] = []; + + // in this flow there's a clear plan here from argument definitions so try to follow it + if (argDef) { + if (argDef.type === 'column' || argDef.type === 'any' || argDef.type === 'function') { + if (isNewExpression && canHaveAssignments) { + // i.e. + // ... | ROW + // ... | STATS + // ... | STATS ..., + // ... | EVAL + // ... | EVAL ..., + suggestions.push(buildNewVarDefinition(findNewVariable(anyVariables))); + } + } + // Suggest fields or variables + if (argDef.type === 'column' || argDef.type === 'any') { + // ... | + if (!nodeArg || (isNewExpression && commandDef.signature.multipleParams)) { + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + [argDef.innerType || 'any'], + command.name, + getFieldsByType, + { + functions: canHaveAssignments, + fields: true, + variables: anyVariables, + }, + { + ignoreFields: isNewExpression + ? command.args.filter(isColumnItem).map(({ name }) => name) + : [], + } + )) + ); + } + } + if (argDef.type === 'function' || argDef.type === 'any') { + if (isColumnItem(nodeArg)) { + // ... | STATS a + // ... | EVAL a + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + if (nodeArgType) { + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType)); + } else { + suggestions.push(getAssignmentDefinitionCompletitionItem()); + } + } + if (isNewExpression || (isAssignment(nodeArg) && !isAssignmentComplete(nodeArg))) { + // ... | STATS a = + // ... | EVAL a = + // ... | STATS a = ..., + // ... | EVAL a = ..., + // ... | STATS a = ..., b = + // ... | EVAL a = ..., b = + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions(['any'], command.name, getFieldsByType, { + functions: true, + fields: false, + variables: nodeArg ? undefined : anyVariables, + })) + ); + } + } + + if (argDef.type === 'any') { + // ... | EVAL var = field + // ... | EVAL var = fn(field) + // make sure we're still in the same assignment context and there's no comma (newExpression ensures that) + if (!isNewExpression) { + if (isAssignment(nodeArg) && isAssignmentComplete(nodeArg)) { + const [rightArg] = nodeArg.args[1] as [ESQLSingleAstItem]; + const nodeArgType = extractFinalTypeFromArg(rightArg, references); + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType || 'any') + ); + if (nodeArgType === 'number' && isLiteralItem(rightArg)) { + // ... EVAL var = 1 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + if (isFunctionItem(rightArg)) { + if (rightArg.args.some(isTimeIntervalItem)) { + const lastFnArg = rightArg.args[rightArg.args.length - 1]; + const lastFnArgType = extractFinalTypeFromArg(lastFnArg, references); + if (lastFnArgType === 'number' && isLiteralItem(lastFnArg)) + // ... EVAL var = 1 year + 2 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + } + } else { + if (isFunctionItem(nodeArg)) { + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + suggestions.push( + ...(await getBuiltinFunctionNextArgument( + command, + argDef, + nodeArg, + nodeArgType || 'any', + references, + getFieldsByType + )) + ); + if (nodeArg.args.some(isTimeIntervalItem)) { + const lastFnArg = nodeArg.args[nodeArg.args.length - 1]; + const lastFnArgType = extractFinalTypeFromArg(lastFnArg, references); + if (lastFnArgType === 'number' && isLiteralItem(lastFnArg)) + // ... EVAL var = 1 year + 2 + suggestions.push(...getCompatibleLiterals(command.name, ['time_literal_unit'])); + } + } + } + } + } + + // if the definition includes a list of constants, suggest them + if (argDef.values) { + // ... | ... + suggestions.push(...buildConstantsDefinitions(argDef.values)); + } + // If the type is specified try to dig deeper in the definition to suggest the best candidate + if (['string', 'number', 'boolean'].includes(argDef.type) && !argDef.values) { + // it can be just literal values (i.e. "string") + if (argDef.literalOnly) { + // ... | ... + suggestions.push(...getCompatibleLiterals(command.name, [argDef.type], [argDef.name])); + } else { + // or it can be anything else as long as it is of the right type and the end (i.e. column or function) + if (!nodeArg) { + // ... | + // In this case start suggesting something not strictly based on type + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions(['any'], command.name, getFieldsByType, { + functions: true, + fields: true, + variables: anyVariables, + })) + ); + } else { + // if something is already present, leverage its type to suggest something in context + const nodeArgType = extractFinalTypeFromArg(nodeArg, references); + // These cases can happen here, so need to identify each and provide the right suggestion + // i.e. ... | field + // i.e. ... | field + + // i.e. ... | field >= + // i.e. ... | field > 0 + // i.e. ... | field + otherN + + if (nodeArgType) { + if (isFunctionItem(nodeArg)) { + suggestions.push( + ...(await getBuiltinFunctionNextArgument( + command, + argDef, + nodeArg, + nodeArgType, + references, + getFieldsByType + )) + ); + } else { + // i.e. ... | field + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType) + ); + } + } + } + } + } + if (argDef.type === 'source') { + if (argDef.innerType === 'policy') { + // ... | ENRICH + const policies = await getPolicies(); + suggestions.push(...(policies.length ? policies : [buildNoPoliciesAvailableDefinition()])); + } else { + // FROM + // @TODO: filter down the suggestions here based on other existing sources defined + suggestions.push(...(await getSources())); + } + } + } + + const nonOptionArgs = command.args.filter( + (arg) => !isOptionItem(arg) && !Array.isArray(arg) && !arg.incomplete + ); + // Perform some checks on mandatory arguments + const mandatoryArgsAlreadyPresent = + (commandDef.signature.multipleParams && nonOptionArgs.length > 1) || + nonOptionArgs.length >= + commandDef.signature.params.filter(({ optional }) => !optional).length || + argDef?.type === 'function'; + + // check if declared args are fully valid for the given command + const currentArgsAreValidForCommand = areCurrentArgsValid(command, nodeArg, references); + + // latest suggestions: options and final ones + if ( + (!isNewExpression && mandatoryArgsAlreadyPresent && currentArgsAreValidForCommand) || + optionsAlreadyDeclared.length + ) { + // suggest some command options + if (optionsAvailable.length) { + suggestions.push(...optionsAvailable.map(buildOptionDefinition)); + } + + if (!optionsAvailable.length || optionsAvailable.every(({ optional }) => optional)) { + // now suggest pipe or comma + suggestions.push( + ...getFinalSuggestions({ + comma: + commandDef.signature.multipleParams && + optionsAvailable.length === commandDef.options.length, + }) + ); + } + } + // Due to some logic overlapping functions can be repeated + // so dedupe here based on insertText string (it can differ from name) + return uniqBy(suggestions, (suggestion) => suggestion.insertText); +} + +async function getBuiltinFunctionNextArgument( + command: ESQLCommand, + argDef: { type: string }, + nodeArg: ESQLFunction, + nodeArgType: string, + references: Pick, + getFieldsByType: GetFieldsByTypeFn +) { + const suggestions = []; + const isFnComplete = isFunctionArgComplete(nodeArg, references); + if (isFnComplete.complete) { + // i.e. ... | field > 0 + // i.e. ... | field + otherN + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, nodeArgType || 'any')); + } else { + // i.e. ... | field >= + // i.e. ... | field + + // i.e. ... | field and + + // Because it's an incomplete function, need to extract the type of the current argument + // and suggest the next argument based on types + + // pick the last arg and check its type to verify whether is incomplete for the given function + const cleanedArgs = removeMarkerArgFromArgsList(nodeArg)!.args; + const nestedType = extractFinalTypeFromArg(nodeArg.args[cleanedArgs.length - 1], references); + + if (isFnComplete.reason === 'fewArgs') { + const finalType = nestedType || nodeArgType || 'any'; + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + // this is a special case with AND/OR + // expression AND/OR + // technically another boolean value should be suggested, but it is a better experience + // to actually suggest a wider set of fields/functions + [ + finalType === 'boolean' && getFunctionDefinition(nodeArg.name)?.builtin + ? 'any' + : finalType, + ], + command.name, + getFieldsByType, + { + functions: true, + fields: true, + variables: references.variables, + } + )) + ); + } + if (isFnComplete.reason === 'wrongTypes') { + if (nestedType) { + // suggest something to complete the builtin function + if (nestedType !== argDef.type) { + suggestions.push( + ...getBuiltinCompatibleFunctionDefinition(command.name, nestedType, [argDef.type]) + ); + } + } + } + } + return suggestions; +} + +async function getFieldsOrFunctionsSuggestions( + types: string[], + commandName: string, + getFieldsByType: GetFieldsByTypeFn, + { + functions, + fields, + variables, + }: { + functions: boolean; + fields: boolean; + variables?: Map; + }, + { + ignoreFn = [], + ignoreFields = [], + }: { + ignoreFn?: string[]; + ignoreFields?: string[]; + } = {} +): Promise { + const filteredFieldsByType = (await (fields + ? getFieldsByType(types, ignoreFields) + : [])) as AutocompleteCommandDefinition[]; + + const filteredVariablesByType: string[] = []; + if (variables) { + for (const variable of variables.values()) { + if (types.includes('any') || types.includes(variable[0].type)) { + filteredVariablesByType.push(variable[0].name); + } + } + // due to a bug on the ES|QL table side, filter out fields list with underscored variable names (??) + // avg( numberField ) => avg_numberField_ + if ( + filteredVariablesByType.length && + filteredVariablesByType.some((v) => /[^a-zA-Z\d]/.test(v)) + ) { + for (const variable of filteredVariablesByType) { + const underscoredName = variable.replace(/[^a-zA-Z\d]/g, '_'); + const index = filteredFieldsByType.findIndex(({ label }) => underscoredName === label); + if (index >= 0) { + filteredFieldsByType.splice(index); + } + } + } + } + + const suggestions = filteredFieldsByType.concat( + functions ? getCompatibleFunctionDefinition(commandName, types, ignoreFn) : [], + variables ? buildVariablesDefinitions(filteredVariablesByType) : [], + getCompatibleLiterals(commandName, types) // literals are handled internally + ); + + // rewrite the sortText here to have literals first, then fields, last functions + return suggestions.map(({ sortText, kind, ...rest }) => ({ + ...rest, + kind, + sortText: String.fromCharCode(97 - kind), + command: TRIGGER_SUGGESTION_COMMAND, + })); +} + +async function getFunctionArgsSuggestions( + innerText: string, + commands: ESQLCommand[], + { + command, + node, + }: { + command: ESQLCommand; + node: ESQLFunction; + }, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMap: GetFieldsMapFn, + getPolicyMetadata: GetPolicyMetadataFn +): Promise { + const fnDefinition = getFunctionDefinition(node.name); + if (fnDefinition) { + const fieldsMap: Map = await getFieldsMap(); + const variablesExcludingCurrentCommandOnes = excludeVariablesFromCurrentCommand( + commands, + command, + fieldsMap + ); + // pick the type of the next arg + const shouldGetNextArgument = node.text.includes(EDITOR_MARKER); + let argIndex = Math.max(node.args.length, 0); + if (!shouldGetNextArgument && argIndex) { + argIndex -= 1; + } + const types = fnDefinition.signatures.flatMap((signature) => { + if (signature.params.length > argIndex) { + return signature.params[argIndex].type; + } + if (signature.infiniteParams) { + return signature.params[0].type; + } + return []; + }); + + const arg = node.args[argIndex]; + + const hasMoreMandatoryArgs = + fnDefinition.signatures[0].params.filter( + ({ optional }, index) => !optional && index > argIndex + ).length > argIndex; + + const suggestions = []; + const noArgDefined = !arg; + const isUnknownColumn = + arg && + isColumnItem(arg) && + !columnExists(arg, { fields: fieldsMap, variables: variablesExcludingCurrentCommandOnes }) + .hit; + if (noArgDefined || isUnknownColumn) { + // ... | EVAL fn( ) + // ... | EVAL fn( field, ) + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + types, + command.name, + getFieldsByType, + { + functions: command.name !== 'stats', + fields: true, + variables: variablesExcludingCurrentCommandOnes, + }, + // do not repropose the same function as arg + // i.e. avoid cases like abs(abs(abs(...))) with suggestions + { ignoreFn: [node.name] } + )) + ); + } + + // for eval and row commands try also to complete numeric literals with time intervals where possible + if (arg) { + if (command.name !== 'stats') { + if (isLiteralItem(arg) && arg.literalType === 'number') { + // ... | EVAL fn(2 ) + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + ['time_literal_unit'], + command.name, + getFieldsByType, + { + functions: false, + fields: false, + variables: variablesExcludingCurrentCommandOnes, + } + )) + ); + } + } + if (hasMoreMandatoryArgs) { + // suggest a comma if there's another argument for the function + suggestions.push(commaCompleteItem); + } + // if there are other arguments in the function, inject automatically a comma after each suggestion + return suggestions.map((suggestion) => + suggestion !== commaCompleteItem + ? { + ...suggestion, + insertText: + hasMoreMandatoryArgs && !fnDefinition.builtin + ? `${suggestion.insertText},` + : suggestion.insertText, + } + : suggestion + ); + } + + return suggestions.map(({ insertText, ...rest }) => ({ + ...rest, + insertText: hasMoreMandatoryArgs && !fnDefinition.builtin ? `${insertText},` : insertText, + })); + } + return mathCommandDefinition; +} + +async function getOptionArgsSuggestions( + innerText: string, + commands: ESQLCommand[], + { + command, + option, + node, + }: { + command: ESQLCommand; + option: ESQLCommandOption; + node: ESQLSingleAstItem | undefined; + }, + getFieldsByType: GetFieldsByTypeFn, + getFieldsMaps: GetFieldsMapFn, + getPolicyMetadata: GetPolicyMetadataFn +) { + const optionDef = getCommandOption(option.name); + const suggestions = []; + const isNewExpression = isRestartingExpression(innerText) || option.args.length === 0; + if (command.name === 'enrich') { + if (option.name === 'on') { + // if it's a new expression, suggest fields to match on + if (isNewExpression || (option && isAssignment(option.args[0]) && !option.args[1])) { + const policyName = isSourceItem(command.args[0]) ? command.args[0].name : undefined; + if (policyName) { + const [policyMetadata, fieldsMap] = await Promise.all([ + getPolicyMetadata(policyName), + getFieldsMaps(), + ]); + if (policyMetadata) { + suggestions.push( + ...buildMatchingFieldsDefinition( + policyMetadata.matchField, + Array.from(fieldsMap.keys()) + ) + ); + } + } + } else { + // propose the with option + suggestions.push( + buildOptionDefinition(getCommandOption('with')!), + ...getFinalSuggestions({ + comma: true, + }) + ); + } + } + if (option.name === 'with') { + let argIndex = option.args.length; + let lastArg = option.args[Math.max(argIndex - 1, 0)]; + if (isIncompleteItem(lastArg)) { + argIndex = Math.max(argIndex - 1, 0); + lastArg = option.args[argIndex]; + } + const policyName = isSourceItem(command.args[0]) ? command.args[0].name : undefined; + if (policyName) { + const [policyMetadata, fieldsMap] = await Promise.all([ + getPolicyMetadata(policyName), + getFieldsMaps(), + ]); + const anyVariables = collectVariables( + commands, + appendEnrichFields(fieldsMap, policyMetadata) + ); + + if (isNewExpression) { + suggestions.push(buildNewVarDefinition(findNewVariable(anyVariables))); + } + + // make sure to remove the marker arg from the assign fn + const assignFn = isAssignment(lastArg) + ? (removeMarkerArgFromArgsList(lastArg) as ESQLFunction) + : undefined; + + if (policyMetadata) { + if (isNewExpression || (assignFn && !isAssignmentComplete(assignFn))) { + // ... | ENRICH ... WITH a = + suggestions.push(...buildFieldsDefinitions(policyMetadata.enrichFields)); + } + } + if ( + assignFn && + hasSameArgBothSides(assignFn) && + !isNewExpression && + !isIncompleteItem(assignFn) + ) { + // ... | ENRICH ... WITH a + // effectively only assign will apper + suggestions.push(...getBuiltinCompatibleFunctionDefinition(command.name, 'any')); + } + + if ( + assignFn && + (isAssignmentComplete(assignFn) || hasSameArgBothSides(assignFn)) && + !isNewExpression + ) { + suggestions.push( + ...getFinalSuggestions({ + comma: true, + }) + ); + } + } + } + } + if (command.name === 'rename') { + if (option.args.length < 2) { + const fieldsMap = await getFieldsMaps(); + const anyVariables = collectVariables(commands, fieldsMap); + suggestions.push(...buildVariablesDefinitions([findNewVariable(anyVariables)])); + } + } + + if (optionDef) { + if (!suggestions.length) { + const argIndex = Math.max(option.args.length - 1, 0); + const types = [optionDef.signature.params[argIndex].type].filter(nonNullable); + if (option.args.length && !isRestartingExpression(innerText)) { + suggestions.push( + ...getFinalSuggestions({ + comma: true, + }) + ); + } else if (!option.args.length || isRestartingExpression(innerText)) { + suggestions.push( + ...(await getFieldsOrFunctionsSuggestions( + types[0] === 'column' ? ['any'] : types, + command.name, + getFieldsByType, + { + functions: false, + fields: true, + } + )) + ); + } + } + } + return suggestions; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts new file mode 100644 index 0000000000000..cfa0e9fa74b3f --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/complete_items.ts @@ -0,0 +1,80 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { AutocompleteCommandDefinition } from './types'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { builtinFunctions } from '../definitions/builtin'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getAllCommands } from '../shared/helpers'; +import { + getAutocompleteFunctionDefinition, + getAutocompleteBuiltinDefinition, + getAutocompleteCommandDefinition, +} from './factories'; + +export const mathCommandDefinition: AutocompleteCommandDefinition[] = evalFunctionsDefinitions.map( + getAutocompleteFunctionDefinition +); + +export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = + statsAggregationFunctionDefinitions.map(getAutocompleteFunctionDefinition); + +export function getAssignmentDefinitionCompletitionItem() { + const assignFn = builtinFunctions.find(({ name }) => name === '=')!; + return getAutocompleteBuiltinDefinition(assignFn); +} + +export const getBuiltinCompatibleFunctionDefinition = ( + command: string, + argType: string, + returnTypes?: string[] +): AutocompleteCommandDefinition[] => { + const compatibleFunctions = builtinFunctions.filter( + ({ name, supportedCommands, signatures, ignoreAsSuggestion }) => + !ignoreAsSuggestion && + !/not_/.test(name) && + supportedCommands.includes(command) && + signatures.some(({ params }) => params.some((pArg) => pArg.type === argType)) + ); + + if (!returnTypes) { + return compatibleFunctions.map(getAutocompleteBuiltinDefinition); + } + return compatibleFunctions + .filter((mathDefinition) => + mathDefinition.signatures.some( + (signature) => returnTypes[0] === 'any' || returnTypes.includes(signature.returnType) + ) + ) + .map(getAutocompleteBuiltinDefinition); +}; + +export const commandAutocompleteDefinitions: AutocompleteCommandDefinition[] = getAllCommands().map( + getAutocompleteCommandDefinition +); + +export const pipeCompleteItem: AutocompleteCommandDefinition = { + label: '|', + insertText: '|', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.pipeDoc', { + defaultMessage: 'Pipe (|)', + }), + sortText: 'B', +}; + +export const commaCompleteItem: AutocompleteCommandDefinition = { + label: ',', + insertText: ',', + kind: 1, + detail: i18n.translate('monaco.esql.autocomplete.commaDoc', { + defaultMessage: 'Comma (,)', + }), + sortText: 'C', +}; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/utils.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/documentation_util.ts similarity index 100% rename from packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/utils.ts rename to packages/kbn-monaco/src/esql/lib/ast/autocomplete/documentation_util.ts diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts new file mode 100644 index 0000000000000..fc136a87b23da --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/factories.ts @@ -0,0 +1,268 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { AutocompleteCommandDefinition } from './types'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures, getCommandSignature } from '../definitions/helpers'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { + FunctionDefinition, + CommandDefinition, + CommandOptionsDefinition, +} from '../definitions/types'; +import { getCommandDefinition } from '../shared/helpers'; +import { buildDocumentation, buildFunctionDocumentation } from './documentation_util'; + +const allFunctions = statsAggregationFunctionDefinitions.concat(evalFunctionsDefinitions); + +export const TRIGGER_SUGGESTION_COMMAND = { + title: 'Trigger Suggestion Dialog', + id: 'editor.action.triggerSuggest', +}; + +export function getAutocompleteFunctionDefinition(fn: FunctionDefinition) { + const fullSignatures = getFunctionSignatures(fn); + return { + label: fullSignatures[0].declaration, + insertText: `${fn.name}($0)`, + insertTextRules: 4, // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + kind: 1, + detail: fn.description, + documentation: { + value: buildFunctionDocumentation(fullSignatures), + }, + sortText: 'C', + }; +} + +export function getAutocompleteBuiltinDefinition(fn: FunctionDefinition) { + return { + label: fn.name, + insertText: `${fn.name} $0`, + insertTextRules: 4, // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, + kind: 11, + detail: fn.description, + documentation: { + value: '', + }, + sortText: 'D', + command: TRIGGER_SUGGESTION_COMMAND, + }; +} + +export const isCompatibleFunctionName = (fnName: string, command: string) => { + const fnSupportedByCommand = allFunctions.filter(({ supportedCommands }) => + supportedCommands.includes(command) + ); + return fnSupportedByCommand.some(({ name }) => name === fnName); +}; + +export const getCompatibleFunctionDefinition = ( + command: string, + returnTypes?: string[], + ignored: string[] = [] +): AutocompleteCommandDefinition[] => { + const fnSupportedByCommand = allFunctions.filter( + ({ name, supportedCommands }) => supportedCommands.includes(command) && !ignored.includes(name) + ); + if (!returnTypes) { + return fnSupportedByCommand.map(getAutocompleteFunctionDefinition); + } + return fnSupportedByCommand + .filter((mathDefinition) => + mathDefinition.signatures.some( + (signature) => returnTypes[0] === 'any' || returnTypes.includes(signature.returnType) + ) + ) + .map(getAutocompleteFunctionDefinition); +}; + +export function getAutocompleteCommandDefinition( + command: CommandDefinition +): AutocompleteCommandDefinition { + const commandDefinition = getCommandDefinition(command.name); + const commandSignature = getCommandSignature(commandDefinition); + return { + label: commandDefinition.name, + insertText: commandDefinition.name, + kind: 0, + detail: commandDefinition.description, + documentation: { + value: buildDocumentation(commandSignature.declaration, commandSignature.examples), + }, + sortText: 'A', + }; +} + +export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDefinition[] => + fields.map((label) => ({ + label, + insertText: label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.fieldDefinition', { + defaultMessage: `Field specified by the input table`, + }), + sortText: 'D', + })); + +export const buildVariablesDefinitions = (variables: string[]): AutocompleteCommandDefinition[] => + variables.map((label) => ({ + label, + insertText: /[^a-zA-Z\d]/.test(label) ? `\`${label}\`` : label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.variableDefinition', { + defaultMessage: `Variable specified by the user within the ES|QL query`, + }), + sortText: 'D', + })); + +export const buildSourcesDefinitions = (sources: string[]): AutocompleteCommandDefinition[] => + sources.map((label) => ({ + label, + insertText: label, + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.sourceDefinition', { + defaultMessage: `Input table`, + }), + sortText: 'A', + })); + +export const buildConstantsDefinitions = ( + userConstants: string[], + detail?: string +): AutocompleteCommandDefinition[] => + userConstants.map((label) => ({ + label, + insertText: label, + kind: 14, + detail: + detail ?? + i18n.translate('monaco.esql.autocomplete.constantDefinition', { + defaultMessage: `User defined variable`, + }), + sortText: 'A', + })); + +export const buildNewVarDefinition = (label: string): AutocompleteCommandDefinition => { + return { + label, + insertText: `${label} =`, + kind: 21, + detail: i18n.translate('monaco.esql.autocomplete.newVarDoc', { + defaultMessage: 'Define a new variable', + }), + sortText: '1', + }; +}; + +export const buildPoliciesDefinitions = ( + policies: Array<{ name: string; sourceIndices: string[] }> +): AutocompleteCommandDefinition[] => + policies.map(({ name: label, sourceIndices }) => ({ + label, + insertText: label, + kind: 5, + detail: i18n.translate('monaco.esql.autocomplete.policyDefinition', { + defaultMessage: `Policy defined on {count, plural, one {index} other {indices}}: {indices}`, + values: { + count: sourceIndices.length, + indices: sourceIndices.join(', '), + }, + }), + sortText: 'D', + })); + +export const buildMatchingFieldsDefinition = ( + matchingField: string, + fields: string[] +): AutocompleteCommandDefinition[] => + fields.map((label) => ({ + label, + insertText: label, + kind: 4, + detail: i18n.translate('monaco.esql.autocomplete.matchingFieldDefinition', { + defaultMessage: `Use to match on {matchingField} on the policy`, + values: { + matchingField, + }, + }), + sortText: 'D', + })); + +export const buildOptionDefinition = (option: CommandOptionsDefinition) => { + const completeItem: AutocompleteCommandDefinition = { + label: option.name, + insertText: option.name, + kind: 21, + detail: option.description, + sortText: 'D', + }; + if (option.wrapped) { + completeItem.insertText = `${option.wrapped[0]}${option.name} $0 ${option.wrapped[1]}`; + completeItem.insertTextRules = 4; // monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet; + } + return completeItem; +}; + +export const buildNoPoliciesAvailableDefinition = (): AutocompleteCommandDefinition => ({ + label: i18n.translate('monaco.esql.autocomplete.noPoliciesLabel', { + defaultMessage: 'No available policy', + }), + insertText: '', + kind: 26, + detail: i18n.translate('monaco.esql.autocomplete.noPoliciesLabelsFound', { + defaultMessage: 'Click to create', + }), + sortText: 'D', + command: { + id: 'esql.policies.create', + title: i18n.translate('monaco.esql.autocomplete.createNewPolicy', { + defaultMessage: 'Click to create', + }), + }, +}); + +function getUnitDuration(unit: number = 1) { + const filteredTimeLiteral = timeLiterals.filter(({ name }) => { + const result = /s$/.test(name); + return unit > 1 ? result : !result; + }); + return filteredTimeLiteral.map(({ name }) => `${unit} ${name}`); +} + +export function getCompatibleLiterals(commandName: string, types: string[], names?: string[]) { + const suggestions: AutocompleteCommandDefinition[] = []; + if (types.includes('number') && commandName === 'limit') { + // suggest 10/50/100 + suggestions.push(...buildConstantsDefinitions(['10', '100', '1000'], '')); + } + if (types.includes('time_literal')) { + // filter plural for now and suggest only unit + singular + suggestions.push(...buildConstantsDefinitions(getUnitDuration(1))); // i.e. 1 year + } + // this is a special type built from the suggestion system, not inherited from the AST + if (types.includes('time_literal_unit')) { + suggestions.push(...buildConstantsDefinitions(timeLiterals.map(({ name }) => name))); // i.e. year, month, ... + } + if (types.includes('chrono_literal')) { + suggestions.push(...buildConstantsDefinitions(chronoLiterals.map(({ name }) => name))); // i.e. EPOC_DAY, ... + } + if (types.includes('string')) { + if (names) { + const index = types.indexOf('string'); + if (/pattern/.test(names[index])) { + suggestions.push(...buildConstantsDefinitions(['"a-pattern"'], 'A pattern string')); + } else { + suggestions.push(...buildConstantsDefinitions(['string'], '')); + } + } + } + return suggestions; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.ts new file mode 100644 index 0000000000000..ad6428fcbc771 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/autocomplete/types.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 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 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../../..'; + +/** @internal **/ +export interface UserDefinedVariables { + userDefined: string[]; + policies: string[]; +} + +/** @internal **/ +export type AutocompleteCommandDefinition = Pick< + monaco.languages.CompletionItem, + | 'label' + | 'insertText' + | 'kind' + | 'detail' + | 'documentation' + | 'sortText' + | 'insertTextRules' + | 'command' +>; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts new file mode 100644 index 0000000000000..91011a87a26a1 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/aggs.ts @@ -0,0 +1,127 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { FunctionDefinition } from './types'; + +function createNumericAggDefinition({ + name, + description, + args = [], +}: { + name: string; + description: string; + args?: Array<{ name: string; type: string; value: string }>; +}): FunctionDefinition { + const extraParamsExample = args.length ? `, ${args.map(({ value }) => value).join(',')}` : ''; + return { + name, + description, + supportedCommands: ['stats'], + signatures: [ + { + params: [ + { name: 'column', type: 'number', noNestingFunctions: true }, + ...args.map(({ name: paramName, type }) => ({ + name: paramName, + type, + noNestingFunctions: true, + })), + ], + returnType: 'number', + examples: [ + `from index | stats result = ${name}(field${extraParamsExample})`, + `from index | stats ${name}(field${extraParamsExample})`, + ], + }, + ], + }; +} + +export const statsAggregationFunctionDefinitions: FunctionDefinition[] = [ + { + name: 'avg', + description: i18n.translate('monaco.esql.definitions.avgDoc', { + defaultMessage: 'Returns the average of the values in a field', + }), + }, + { + name: 'max', + description: i18n.translate('monaco.esql.definitions.maxDoc', { + defaultMessage: 'Returns the maximum value in a field.', + }), + }, + { + name: 'min', + description: i18n.translate('monaco.esql.definitions.minDoc', { + defaultMessage: 'Returns the minimum value in a field.', + }), + }, + { + name: 'sum', + description: i18n.translate('monaco.esql.definitions.sumDoc', { + defaultMessage: 'Returns the sum of the values in a field.', + }), + }, + { + name: 'median', + description: i18n.translate('monaco.esql.definitions.medianDoc', { + defaultMessage: 'Returns the 50% percentile.', + }), + }, + { + name: 'median_absolute_deviation', + description: i18n.translate('monaco.esql.definitions.medianDeviationDoc', { + defaultMessage: + 'Returns the median of each data point’s deviation from the median of the entire sample.', + }), + }, + { + name: 'percentile', + description: i18n.translate('monaco.esql.definitions.percentiletDoc', { + defaultMessage: 'Returns the n percentile of a field.', + }), + args: [{ name: 'percentile', type: 'number', value: '90' }], + }, +] + .map(createNumericAggDefinition) + .concat([ + { + name: 'count', + description: i18n.translate('monaco.esql.definitions.countDoc', { + defaultMessage: 'Returns the count of the values in a field.', + }), + supportedCommands: ['stats'], + signatures: [ + { + params: [ + { name: 'column', type: 'any', noNestingFunctions: true, supportsWildcard: true }, + ], + returnType: 'number', + examples: [`from index | stats result = count(field)`, `from index | stats count(field)`], + }, + ], + }, + { + name: 'count_distinct', + description: i18n.translate('monaco.esql.definitions.countDistinctDoc', { + defaultMessage: 'Returns the count of distinct values in a field.', + }), + supportedCommands: ['stats'], + signatures: [ + { + params: [{ name: 'column', type: 'any', noNestingFunctions: true }], + returnType: 'number', + examples: [ + `from index | stats result = count_distinct(field)`, + `from index | stats count_distinct(field)`, + ], + }, + ], + }, + ]); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts new file mode 100644 index 0000000000000..eed2fcc5d65b4 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/builtin.ts @@ -0,0 +1,348 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { FunctionDefinition } from './types'; + +function createMathDefinition( + name: string, + types: Array, + description: string, + warning?: FunctionDefinition['warning'] +) { + return { + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: types.map((type) => { + if (Array.isArray(type)) { + return { + params: [ + { name: 'left', type: type[0] }, + { name: 'right', type: type[1] }, + ], + returnType: /literal/.test(type[0]) ? type[1] : type[0], + }; + } + return { + params: [ + { name: 'left', type }, + { name: 'right', type }, + ], + returnType: type, + }; + }), + warning, + }; +} + +function createComparisonDefinition( + { + name, + description, + }: { + name: string; + description: string; + }, + warning?: FunctionDefinition['warning'] +) { + return { + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'number' }, + { name: 'right', type: 'number' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'date' }, + { name: 'right', type: 'date' }, + ], + returnType: 'boolean', + }, + ], + }; +} + +export const builtinFunctions: FunctionDefinition[] = [ + createMathDefinition( + '+', + ['number', 'date', ['date', 'time_literal'], ['time_literal', 'date']], + i18n.translate('monaco.esql.definition.addDoc', { + defaultMessage: 'Add (+)', + }) + ), + createMathDefinition( + '-', + ['number', 'date', ['date', 'time_literal'], ['time_literal', 'date']], + i18n.translate('monaco.esql.definition.subtractDoc', { + defaultMessage: 'Subtract (-)', + }) + ), + createMathDefinition( + '*', + ['number'], + i18n.translate('monaco.esql.definition.multiplyDoc', { + defaultMessage: 'Multiply (*)', + }) + ), + createMathDefinition( + '/', + ['number'], + i18n.translate('monaco.esql.definition.divideDoc', { + defaultMessage: 'Divide (/)', + }), + (left, right) => { + if (right.type === 'literal' && right.literalType === 'number') { + return right.value === 0 + ? i18n.translate('monaco.esql.divide.warning.divideByZero', { + defaultMessage: 'Cannot divide by zero: {left}/{right}', + values: { + left: left.text, + right: right.value, + }, + }) + : undefined; + } + } + ), + createMathDefinition( + '%', + ['number'], + i18n.translate('monaco.esql.definition.moduleDoc', { + defaultMessage: 'Module (%)', + }), + (left, right) => { + if (right.type === 'literal' && right.literalType === 'number') { + return right.value === 0 + ? i18n.translate('monaco.esql.divide.warning.zeroModule', { + defaultMessage: 'Module by zero can return null value: {left}/{right}', + values: { + left: left.text, + right: right.value, + }, + }) + : undefined; + } + } + ), + ...[ + { + name: '==', + description: i18n.translate('monaco.esql.definition.equalToDoc', { + defaultMessage: 'Equal to', + }), + }, + { + name: '!=', + description: i18n.translate('monaco.esql.definition.notEqualToDoc', { + defaultMessage: 'Not equal to', + }), + }, + { + name: '<', + description: i18n.translate('monaco.esql.definition.lessThanDoc', { + defaultMessage: 'Less than', + }), + }, + { + name: '>', + description: i18n.translate('monaco.esql.definition.greaterThanDoc', { + defaultMessage: 'Greater than', + }), + }, + { + name: '<=', + description: i18n.translate('monaco.esql.definition.lessThanOrEqualToDoc', { + defaultMessage: 'Less than or equal to', + }), + }, + { + name: '>=', + description: i18n.translate('monaco.esql.definition.greaterThanOrEqualToDoc', { + defaultMessage: 'Greater than or equal to', + }), + }, + ].map((op) => createComparisonDefinition(op)), + ...[ + { + name: 'like', + description: i18n.translate('monaco.esql.definition.likeDoc', { + defaultMessage: 'Filter data based on string patterns', + }), + }, + { name: 'not_like', description: '' }, + { + name: 'rlike', + description: i18n.translate('monaco.esql.definition.rlikeDoc', { + defaultMessage: 'Filter data based on string regular expressions', + }), + }, + { name: 'not_rlike', description: '' }, + ].map(({ name, description }) => ({ + builtin: true, + ignoreAsSuggestion: /not/.test(name), + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string' }, + ], + returnType: 'boolean', + }, + ], + })), + ...[ + { + name: 'in', + description: i18n.translate('monaco.esql.definition.inDoc', { + defaultMessage: + 'Tests if the value an expression takes is contained in a list of other expressions', + }), + }, + { name: 'not_in', description: '' }, + ].map(({ name, description }) => ({ + builtin: true, + ignoreAsSuggestion: /not/.test(name), + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'number' }, + { name: 'right', type: 'number[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'string' }, + { name: 'right', type: 'string[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'boolean' }, + { name: 'right', type: 'boolean[]' }, + ], + returnType: 'boolean', + }, + { + params: [ + { name: 'left', type: 'date' }, + { name: 'right', type: 'date[]' }, + ], + returnType: 'boolean', + }, + ], + })), + ...[ + { + name: 'and', + description: i18n.translate('monaco.esql.definition.andDoc', { + defaultMessage: 'and', + }), + }, + { + name: 'or', + description: i18n.translate('monaco.esql.definition.orDoc', { + defaultMessage: 'or', + }), + }, + ].map(({ name, description }) => ({ + builtin: true, + name, + description, + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [ + { name: 'left', type: 'boolean' }, + { name: 'right', type: 'boolean' }, + ], + returnType: 'boolean', + }, + ], + })), + { + builtin: true, + name: 'not', + description: i18n.translate('monaco.esql.definition.notDoc', { + defaultMessage: 'Not', + }), + supportedCommands: ['eval', 'where', 'row'], + signatures: [ + { + params: [{ name: 'expression', type: 'boolean' }], + returnType: 'boolean', + }, + ], + }, + { + builtin: true, + name: '=', + description: i18n.translate('monaco.esql.definition.assignDoc', { + defaultMessage: 'Assign (=)', + }), + supportedCommands: ['eval', 'stats', 'row', 'dissect', 'where', 'enrich'], + signatures: [ + { + params: [ + { name: 'left', type: 'any' }, + { name: 'right', type: 'any' }, + ], + returnType: 'void', + }, + ], + }, + { + name: 'functions', + description: i18n.translate('monaco.esql.definition.functionsDoc', { + defaultMessage: 'Show ES|QL avaialble functions with signatures', + }), + supportedCommands: ['show'], + signatures: [ + { + params: [], + returnType: 'void', + }, + ], + }, + { + name: 'info', + description: i18n.translate('monaco.esql.definition.infoDoc', { + defaultMessage: 'Show information about the current ES node', + }), + supportedCommands: ['show'], + signatures: [ + { + params: [], + returnType: 'void', + }, + ], + }, +]; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts new file mode 100644 index 0000000000000..4404bf00b5fad --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/commands.ts @@ -0,0 +1,280 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { isColumnItem } from '../shared/helpers'; +import { ESQLColumn, ESQLCommand, ESQLMessage } from '../types'; +import { + appendSeparatorOption, + asOption, + byOption, + metadataOption, + onOption, + withOption, +} from './options'; +import type { CommandDefinition } from './types'; + +export const commandDefinitions: CommandDefinition[] = [ + { + name: 'row', + description: i18n.translate('monaco.esql.definitions.rowDoc', { + defaultMessage: + 'Produces a row with one or more columns with values that you specify. This can be useful for testing.', + }), + examples: ['row a=1', 'row a=1, b=2'], + signature: { + multipleParams: true, + // syntax check already validates part of this + params: [{ name: 'assignment', type: 'any' }], + }, + options: [], + }, + { + name: 'from', + description: i18n.translate('monaco.esql.definitions.fromDoc', { + defaultMessage: + 'Retrieves data from one or more data streams, indices, or aliases. In a query or subquery, you must use the from command first and it does not need a leading pipe. For example, to retrieve data from an index:', + }), + examples: ['from logs', 'from logs-*', 'from logs_*, events-*'], + options: [metadataOption], + signature: { + multipleParams: true, + params: [{ name: 'index', type: 'source', wildcards: true }], + }, + }, + { + name: 'show', + description: i18n.translate('monaco.esql.definitions.showDoc', { + defaultMessage: 'Returns information about the deployment and its capabilities', + }), + examples: ['show functions', 'show info'], + options: [], + signature: { + multipleParams: false, + params: [{ name: 'functions', type: 'string', values: ['functions', 'info'] }], + }, + }, + { + name: 'stats', + description: i18n.translate('monaco.esql.definitions.statsDoc', { + defaultMessage: + 'Calculates aggregate statistics, such as average, count, and sum, over the incoming search results set. Similar to SQL aggregation, if the stats command is used without a BY clause, only one row is returned, which is the aggregation over the entire incoming search results set. When you use a BY clause, one row is returned for each distinct value in the field specified in the BY clause. The stats command returns only the fields in the aggregation, and you can use a wide range of statistical functions with the stats command. When you perform more than one aggregation, separate each aggregation with a comma.', + }), + examples: ['… | stats avg = avg(a)', '… | stats sum(b) by b'], + signature: { + multipleParams: true, + params: [{ name: 'expression', type: 'function' }], + }, + options: [byOption], + }, + { + name: 'eval', + description: i18n.translate('monaco.esql.definitions.evalDoc', { + defaultMessage: + 'Calculates an expression and puts the resulting value into a search results field.', + }), + examples: [ + '… | eval b * c', + '… | eval a = b * c', + '… | eval then = now() + 1 year + 2 weeks', + '… | eval a = b * c, d = e * f', + ], + signature: { + multipleParams: true, + params: [{ name: 'expression', type: 'any' }], + }, + options: [], + }, + { + name: 'rename', + description: i18n.translate('monaco.esql.definitions.renameDoc', { + defaultMessage: 'Renames an old column to a new one', + }), + examples: ['… | rename old as new', '… | rename old as new, a as b'], + signature: { + multipleParams: true, + params: [{ name: 'renameClause', type: 'column' }], + }, + options: [asOption], + }, + { + name: 'limit', + description: i18n.translate('monaco.esql.definitions.limitDoc', { + defaultMessage: + 'Returns the first search results, in search order, based on the "limit" specified.', + }), + examples: ['… | limit 100', '… | limit 0'], + signature: { + multipleParams: false, + params: [{ name: 'size', type: 'number', literalOnly: true }], + }, + options: [], + }, + { + name: 'keep', + description: i18n.translate('monaco.esql.definitions.keepDoc', { + defaultMessage: 'Rearranges fields in the input table by applying the keep clauses in fields', + }), + examples: ['… | keep a', '… | keep a,b'], + options: [], + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column', wildcards: true }], + }, + validate: (command: ESQLCommand) => { + // the command name is automatically converted into KEEP by the ast_walker + // so validate the actual text + const messages: ESQLMessage[] = []; + if (/^project/.test(command.text.toLowerCase())) { + messages.push({ + location: command.location, + text: i18n.translate('monaco.esql.validation.projectCommandDeprecated', { + defaultMessage: 'PROJECT command is no longer supported, please use KEEP instead', + }), + type: 'warning', + }); + } + return messages; + }, + }, + { + name: 'drop', + description: i18n.translate('monaco.esql.definitions.dropDoc', { + defaultMessage: 'Drops columns', + }), + examples: ['… | drop a', '… | drop a,b'], + options: [], + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column', wildcards: true }], + }, + validate: (command: ESQLCommand) => { + const messages: ESQLMessage[] = []; + const wildcardItems = command.args.filter((arg) => isColumnItem(arg) && arg.name === '*'); + if (wildcardItems.length) { + messages.push( + ...wildcardItems.map((column) => ({ + location: (column as ESQLColumn).location, + text: i18n.translate('monaco.esql.validation.dropAllColumnsError', { + defaultMessage: 'Removing all fields is not allowed [*]', + }), + type: 'error' as const, + })) + ); + } + const droppingTimestamp = command.args.find( + (arg) => isColumnItem(arg) && arg.name === '@timestamp' + ); + if (droppingTimestamp) { + messages.push({ + location: (droppingTimestamp as ESQLColumn).location, + text: i18n.translate('monaco.esql.validation.dropTimestampWarning', { + defaultMessage: 'Drop [@timestamp] will remove all time filters to the search results', + }), + type: 'warning', + }); + } + return messages; + }, + }, + { + name: 'sort', + description: i18n.translate('monaco.esql.definitions.sortDoc', { + defaultMessage: + 'Sorts all results by the specified fields. By default, null values are treated as being larger than any other value. With an ascending sort order, null values are sorted last, and with a descending sort order, null values are sorted first. You can change that by providing NULLS FIRST or NULLS LAST', + }), + examples: [ + '… | sort a desc, b nulls last, c asc nulls first', + '… | sort b nulls last', + '… | sort c asc nulls first', + ], + options: [], + signature: { + multipleParams: true, + params: [ + { name: 'column', type: 'column' }, + { name: 'direction', type: 'string', optional: true, values: ['asc', 'desc'] }, + { name: 'nulls', type: 'string', optional: true, values: ['nulls first', 'nulls last'] }, + ], + }, + }, + { + name: 'where', + description: i18n.translate('monaco.esql.definitions.whereDoc', { + defaultMessage: + 'Uses "predicate-expressions" to filter search results. A predicate expression, when evaluated, returns TRUE or FALSE. The where command only returns the results that evaluate to TRUE. For example, to filter results for a specific field value', + }), + examples: ['… | where status_code == 200'], + signature: { + multipleParams: false, + params: [{ name: 'expression', type: 'boolean' }], + }, + options: [], + }, + { + name: 'dissect', + description: i18n.translate('monaco.esql.definitions.dissectDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + examples: ['… | dissect a "%{b} %{c}"'], + options: [appendSeparatorOption], + signature: { + multipleParams: false, + params: [ + { name: 'column', type: 'column', innerType: 'string' }, + { name: 'pattern', type: 'string', literalOnly: true }, + ], + }, + }, + { + name: 'grok', + description: i18n.translate('monaco.esql.definitions.grokDoc', { + defaultMessage: + 'Extracts multiple string values from a single string input, based on a pattern', + }), + examples: ['… | grok a "%{IP:b} %{NUMBER:c}"'], + options: [], + signature: { + multipleParams: false, + params: [ + { name: 'column', type: 'column', innerType: 'string' }, + { name: 'pattern', type: 'string', literalOnly: true }, + ], + }, + }, + { + name: 'mv_expand', + description: i18n.translate('monaco.esql.definitions.mvExpandDoc', { + defaultMessage: 'Expands multivalued fields into one row per value, duplicating other fields', + }), + examples: ['row a=[1,2,3] | mv_expand a'], + options: [], + signature: { + multipleParams: false, + params: [{ name: 'column', type: 'column', innerType: 'list' }], + }, + }, + { + name: 'enrich', + description: i18n.translate('monaco.esql.definitions.enrichDoc', { + defaultMessage: + 'Enrich table with another table. Before you can use enrich, you need to create and execute an enrich policy.', + }), + examples: [ + '… | enrich my-policy', + '… | enrich my-policy on pivotField', + '… | enrich my-policy on pivotField with a = enrichFieldA, b = enrichFieldB', + ], + options: [onOption, withOption], + signature: { + multipleParams: false, + params: [{ name: 'policyName', type: 'source', innerType: 'policy' }], + }, + }, +]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts similarity index 52% rename from packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts rename to packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts index 12056ee784695..135987c4b30b6 100644 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/functions_commands.ts +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/functions.ts @@ -7,47 +7,12 @@ */ import { i18n } from '@kbn/i18n'; -import { buildDocumentation, buildFunctionDocumentation } from './utils'; +import { FunctionDefinition } from './types'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const whereCommandDefinition: AutocompleteCommandDefinition[] = [ - { - label: 'cidr_match', - insertText: 'cidr_match', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.cidrMatchDoc', { - defaultMessage: - 'The function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specificatione.', - }), - documentation: { - value: buildDocumentation('cidr_match(grouped[T]): aggregated[T]', [ - 'from index | eval cidr="10.0.0.0/8" | where cidr_match(ip_field, "127.0.0.1/30", cidr)', - ]), - }, - sortText: 'C', - }, -]; - -interface FunctionDefinition { - name: string; - description: string; - signatures: Array<{ - params: Array<{ - name: string; - type: string | string[]; - optional?: boolean; - }>; - infiniteParams?: boolean; - returnType: string; - examples?: string[]; - }>; -} - -const mathCommandFullDefinitions: FunctionDefinition[] = [ +export const evalFunctionsDefinitions: FunctionDefinition[] = [ { name: 'round', - description: i18n.translate('monaco.esql.autocomplete.roundDoc', { + description: i18n.translate('monaco.esql.definitions.roundDoc', { defaultMessage: 'Returns a number rounded to the decimal, specified by he closest integer value. The default is to round to an integer.', }), @@ -55,39 +20,39 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval round_value = round(field)`], + examples: [`from index | eval round_value = round(field)`], }, ], }, { name: 'abs', - description: i18n.translate('monaco.esql.autocomplete.absDoc', { + description: i18n.translate('monaco.esql.definitions.absDoc', { defaultMessage: 'Returns the absolute value.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval abs_value = abs(field)`], + examples: [`from index | eval abs_value = abs(field)`], }, ], }, { name: 'log10', - description: i18n.translate('monaco.esql.autocomplete.log10Doc', { + description: i18n.translate('monaco.esql.definitions.log10Doc', { defaultMessage: 'Returns the log base 10.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval log10_value = log10(field)`], + examples: [`from index | eval log10_value = log10(field)`], }, ], }, { name: 'pow', - description: i18n.translate('monaco.esql.autocomplete.powDoc', { + description: i18n.translate('monaco.esql.definitions.powDoc', { defaultMessage: 'Returns the the value of a base (first argument) raised to a power (second argument).', }), @@ -98,31 +63,48 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'exponent', type: 'number' }, ], returnType: 'number', - examples: ['from index where field="value" | eval s = POW(field, exponent)'], + examples: ['from index | eval s = POW(field, exponent)'], }, ], }, { name: 'concat', - description: i18n.translate('monaco.esql.autocomplete.concatDoc', { + description: i18n.translate('monaco.esql.definitions.concatDoc', { defaultMessage: 'Concatenates two or more strings.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], infiniteParams: true, + minParams: 1, returnType: 'string', - examples: [ - 'from index where field="value" | eval concatenated = concat(field1, "-", field2)', + examples: ['from index | eval concatenated = concat(field1, "-", field2)'], + }, + ], + }, + { + name: 'replace', + description: i18n.translate('monaco.esql.definitions.replaceDoc', { + defaultMessage: + 'The function substitutes in the string (1st argument) any match of the regular expression (2nd argument) with the replacement string (3rd argument). If any of the arguments are NULL, the result is NULL.', + }), + signatures: [ + { + params: [ + { name: 'field', type: 'string' }, + { name: 'regexp', type: 'string' }, + { name: 'replacement', type: 'string' }, ], + returnType: 'string', + examples: ['from index | eval newStr = replace(field, "Hello", "World")'], }, ], }, { name: 'substring', - description: i18n.translate('monaco.esql.autocomplete.substringDoc', { + description: i18n.translate('monaco.esql.definitions.substringDoc', { defaultMessage: - 'Returns a substring of a string, specified by a start position and an optional length. This example returns the first three characters of every last name.', + 'Returns a substring of a string, specified by a start position and an optional length.', }), signatures: [ { @@ -132,26 +114,26 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'endIndex', type: 'number' }, ], returnType: 'string', - examples: ['from index where field="value" | eval new_string = substring(field, 1, 3)'], + examples: ['from index | eval new_string = substring(field, 1, 3)'], }, ], }, { name: 'trim', - description: i18n.translate('monaco.esql.autocomplete.trimDoc', { + description: i18n.translate('monaco.esql.definitions.trimDoc', { defaultMessage: 'Removes leading and trailing whitespaces from strings.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], returnType: 'string', - examples: ['from index where field="value" | eval new_string = trim(field)'], + examples: ['from index | eval new_string = trim(field)'], }, ], }, { name: 'starts_with', - description: i18n.translate('monaco.esql.autocomplete.startsWithDoc', { + description: i18n.translate('monaco.esql.definitions.startsWithDoc', { defaultMessage: 'Returns a boolean that indicates whether a keyword string starts with another string.', }), @@ -162,13 +144,30 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'prefix', type: 'string' }, ], returnType: 'boolean', - examples: ['from index where field="value" | eval new_string = starts_with(field, "a")'], + examples: ['from index | eval starts_with_a = starts_with(field, "a")'], + }, + ], + }, + { + name: 'ends_with', + description: i18n.translate('monaco.esql.definitions.endsWithDoc', { + defaultMessage: + 'Returns a boolean that indicates whether a keyword string ends with another string:', + }), + signatures: [ + { + params: [ + { name: 'field', type: 'string' }, + { name: 'prefix', type: 'string' }, + ], + returnType: 'boolean', + examples: ['from index | eval ends_with_a = ends_with(field, "a")'], }, ], }, { name: 'split', - description: i18n.translate('monaco.esql.autocomplete.splitDoc', { + description: i18n.translate('monaco.esql.definitions.splitDoc', { defaultMessage: 'Splits a single valued string into multiple strings.', }), signatures: [ @@ -184,173 +183,183 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'to_string', - description: i18n.translate('monaco.esql.autocomplete.toStringDoc', { + alias: ['to_str'], + description: i18n.translate('monaco.esql.definitions.toStringDoc', { defaultMessage: 'Converts to string.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'string', - examples: [`from index where field="value"" | EVAL string = to_string(field)`], + examples: [`from index" | EVAL string = to_string(field)`], }, ], }, { name: 'to_boolean', - description: i18n.translate('monaco.esql.autocomplete.toBooleanDoc', { + alias: ['to_bool'], + description: i18n.translate('monaco.esql.definitions.toBooleanDoc', { defaultMessage: 'Converts to boolean.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'boolean', - examples: [`from index where field="value"" | EVAL bool = to_boolean(field)`], + examples: [`from index" | EVAL bool = to_boolean(field)`], }, ], }, { name: 'to_datetime', - description: i18n.translate('monaco.esql.autocomplete.toDateTimeDoc', { + alias: ['to_dt'], + description: i18n.translate('monaco.esql.definitions.toDateTimeDoc', { defaultMessage: 'Converts to date.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'date', - examples: [`from index where field="value"" | EVAL datetime = to_datetime(field)`], + examples: [`from index" | EVAL datetime = to_datetime(field)`], }, ], }, { name: 'to_degrees', - description: i18n.translate('monaco.esql.autocomplete.toDegreesDoc', { + description: i18n.translate('monaco.esql.definitions.toDegreesDoc', { defaultMessage: 'Coverts to degrees', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval degrees = to_degrees(field)`], + examples: [`from index | eval degrees = to_degrees(field)`], }, ], }, { name: 'to_double', - description: i18n.translate('monaco.esql.autocomplete.toDoubleDoc', { + alias: ['to_dbl'], + description: i18n.translate('monaco.esql.definitions.toDoubleDoc', { defaultMessage: 'Converts to double.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL double = to_double(field)`], + examples: [`from index | EVAL double = to_double(field)`], }, ], }, { name: 'to_integer', - description: i18n.translate('monaco.esql.autocomplete.toIntegerDoc', { + alias: ['to_int'], + description: i18n.translate('monaco.esql.definitions.toIntegerDoc', { defaultMessage: 'Converts to integer.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL integer = to_integer(field)`], + examples: [`from index | EVAL integer = to_integer(field)`], }, ], }, { name: 'to_long', - description: i18n.translate('monaco.esql.autocomplete.toLongDoc', { + description: i18n.translate('monaco.esql.definitions.toLongDoc', { defaultMessage: 'Converts to long.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [`from index where field="value"" | EVAL long = to_long(field)`], + examples: [`from index | EVAL long = to_long(field)`], }, ], }, { name: 'to_radians', - description: i18n.translate('monaco.esql.autocomplete.toRadiansDoc', { + description: i18n.translate('monaco.esql.definitions.toRadiansDoc', { defaultMessage: 'Converts to radians', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval radians = to_radians(field)`], + examples: [`from index | eval radians = to_radians(field)`], }, ], }, { name: 'to_unsigned_long', - description: i18n.translate('monaco.esql.autocomplete.toUnsignedLongDoc', { + alias: ['to_ul', 'to_ulong'], + description: i18n.translate('monaco.esql.definitions.toUnsignedLongDoc', { defaultMessage: 'Converts to unsigned long.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], returnType: 'number', - examples: [ - `from index where field="value"" | EVAL unsigned_long = to_unsigned_long(field)`, - ], + examples: [`from index | EVAL unsigned_long = to_unsigned_long(field)`], }, ], }, { name: 'to_ip', - description: i18n.translate('monaco.esql.autocomplete.toIpDoc', { + description: i18n.translate('monaco.esql.definitions.toIpDoc', { defaultMessage: 'Converts to ip.', }), signatures: [ { params: [{ name: 'field', type: 'any' }], - returnType: 'string[]', - examples: [`from index where field="value"" | EVAL ip = to_ip(field)`], + returnType: 'ip', + examples: [`from index | EVAL ip = to_ip(field)`], }, ], }, { name: 'to_version', - description: i18n.translate('monaco.esql.autocomplete.toVersionDoc', { + alias: ['to_ver'], + description: i18n.translate('monaco.esql.definitions.toVersionDoc', { defaultMessage: 'Converts to version.', }), signatures: [ { - params: [{ name: 'field', type: ['string', 'version'] }], + params: [{ name: 'field', type: 'string' }], returnType: 'version', - examples: [`from index where field="value"" | EVAL version = to_version(field)`], + examples: [`from index | EVAL version = to_version(stringField)`], + }, + { + params: [{ name: 'field', type: 'version' }], + returnType: 'version', + examples: [`from index | EVAL version = to_version(versionField)`], }, ], }, { name: 'date_extract', - description: i18n.translate('monaco.esql.autocomplete.dateExtractDoc', { + description: i18n.translate('monaco.esql.definitions.dateExtractDoc', { defaultMessage: `Extracts parts of a date, like year, month, day, hour. The supported field types are those provided by java.time.temporal.ChronoField`, }), signatures: [ { params: [ - { name: 'field', type: 'date' }, { name: 'date_part', - type: 'string', + type: 'chrono_literal', }, + { name: 'field', type: 'date' }, ], returnType: 'number', examples: [ - `ROW date = DATE_PARSE("2022-05-06", "yyyy-MM-dd") | EVAL year = DATE_EXTRACT(date, "year")`, + `ROW date = DATE_PARSE("yyyy-MM-dd", "2022-05-06") | EVAL year = DATE_EXTRACT("year", date)`, ], }, ], }, { name: 'date_format', - description: i18n.translate('monaco.esql.autocomplete.dateFormatDoc', { + description: i18n.translate('monaco.esql.definitions.dateFormatDoc', { defaultMessage: `Returns a string representation of a date in the provided format. If no format is specified, the "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format is used.`, }), signatures: [ @@ -360,15 +369,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'format_string', type: 'string', optional: true }, ], returnType: 'string', - examples: [ - 'from index where field="value" | eval hired = date_format(hire_date, "YYYY-MM-dd")', - ], + examples: ['from index | eval hired = date_format("YYYY-MM-dd", hire_date)'], }, ], }, { name: 'date_trunc', - description: i18n.translate('monaco.esql.autocomplete.dateTruncDoc', { + description: i18n.translate('monaco.esql.definitions.dateTruncDoc', { defaultMessage: `Rounds down a date to the closest interval. Intervals can be expressed using the timespan literal syntax.`, }), signatures: [ @@ -378,15 +385,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'field', type: 'date' }, ], returnType: 'date', - examples: [ - `from index where field="value" | eval year_hired = DATE_TRUNC(1 year, hire_date)`, - ], + examples: [`from index | eval year_hired = DATE_TRUNC(1 year, hire_date)`], }, ], }, { name: 'date_parse', - description: i18n.translate('monaco.esql.autocomplete.dateParseDoc', { + description: i18n.translate('monaco.esql.definitions.dateParseDoc', { defaultMessage: `Parse dates from strings.`, }), signatures: [ @@ -397,14 +402,14 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ ], returnType: 'date', examples: [ - `from index where field="value" | eval year_hired = date_parse(hire_date, yyyy-MM-dd'T'HH:mm:ss.SSS'Z')`, + `from index | eval year_hired = date_parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", hire_date)`, ], }, ], }, { name: 'auto_bucket', - description: i18n.translate('monaco.esql.autocomplete.autoBucketDoc', { + description: i18n.translate('monaco.esql.definitions.autoBucketDoc', { defaultMessage: `Automatically bucket dates based on a given range and bucket target.`, }), signatures: [ @@ -417,7 +422,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ ], returnType: 'date', examples: [ - 'from index where field="value" | eval hd = auto_bucket(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")', + 'from index | eval hd = auto_bucket(hire_date, 20, "1985-01-01T00:00:00Z", "1986-01-01T00:00:00Z")', ], }, { @@ -428,113 +433,124 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'endValue', type: 'number' }, ], returnType: 'number', - examples: [ - 'from index where field="value" | eval bs = auto_bucket(salary, 20, 25324, 74999)', - ], + examples: ['from index | eval bs = auto_bucket(salary, 20, 25324, 74999)'], }, ], }, { name: 'is_finite', - description: i18n.translate('monaco.esql.autocomplete.isFiniteDoc', { + description: i18n.translate('monaco.esql.definitions.isFiniteDoc', { defaultMessage: 'Returns a boolean that indicates whether its input is a finite number.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'boolean', - examples: ['from index where field="value" | eval s = is_finite(field/0)'], + examples: ['from index | eval s = is_finite(field/0)'], }, ], }, { name: 'is_infinite', - description: i18n.translate('monaco.esql.autocomplete.isInfiniteDoc', { + description: i18n.translate('monaco.esql.definitions.isInfiniteDoc', { defaultMessage: 'Returns a boolean that indicates whether its input is infinite.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'boolean', - examples: ['from index where field="value" | eval s = is_infinite(field/0)'], + examples: ['from index | eval s = is_infinite(field/0)'], + }, + ], + }, + { + name: 'is_nan', + description: i18n.translate('monaco.esql.definitions.isNanDoc', { + defaultMessage: 'Returns a boolean that indicates whether its input is not a number.', + }), + signatures: [ + { + params: [{ name: 'field', type: 'number' }], + returnType: 'boolean', + examples: ['row a = 1 | eval is_nan(a)'], }, ], }, { name: 'case', - description: i18n.translate('monaco.esql.autocomplete.caseDoc', { + description: i18n.translate('monaco.esql.definitions.caseDoc', { defaultMessage: 'Accepts pairs of conditions and values. The function returns the value that belongs to the first condition that evaluates to `true`. If the number of arguments is odd, the last argument is the default value which is returned when no condition matches.', }), signatures: [ { params: [ - { name: 'condition', type: 'booleanExpression' }, + { name: 'condition', type: 'boolean' }, { name: 'value', type: 'any' }, ], - infiniteParams: true, + minParams: 3, returnType: 'any', examples: [ - `from index where field="value" | eval type = case(languages <= 1, "monolingual", languages <= 2, "bilingual", "polyglot")`, + `from index | eval type = case(languages <= 1, "monolingual", languages <= 2, "bilingual", "polyglot")`, ], }, ], }, { name: 'length', - description: i18n.translate('monaco.esql.autocomplete.lengthDoc', { + description: i18n.translate('monaco.esql.definitions.lengthDoc', { defaultMessage: 'Returns the character length of a string.', }), signatures: [ { params: [{ name: 'field', type: 'string' }], returnType: 'number', - examples: [`from index where field="value" | eval fn_length = length(field)`], + examples: [`from index | eval fn_length = length(field)`], }, ], }, { name: 'acos', - description: i18n.translate('monaco.esql.autocomplete.acosDoc', { + description: i18n.translate('monaco.esql.definitions.acosDoc', { defaultMessage: 'Inverse cosine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval acos = acos(field)`], + examples: [`from index | eval acos = acos(field)`], }, ], }, { name: 'asin', - description: i18n.translate('monaco.esql.autocomplete.asinDoc', { + description: i18n.translate('monaco.esql.definitions.asinDoc', { defaultMessage: 'Inverse sine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval asin = asin(field)`], + examples: [`from index | eval asin = asin(field)`], }, ], }, { name: 'atan', - description: i18n.translate('monaco.esql.autocomplete.atanDoc', { + description: i18n.translate('monaco.esql.definitions.atanDoc', { defaultMessage: 'Inverse tangent trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval atan = atan(field)`], + examples: [`from index | eval atan = atan(field)`], }, ], }, { name: 'atan2', - description: i18n.translate('monaco.esql.autocomplete.atan2Doc', { + description: i18n.translate('monaco.esql.definitions.atan2Doc', { defaultMessage: 'The angle between the positive x-axis and the ray from the origin to the point (x , y) in the Cartesian plane', }), @@ -545,13 +561,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'y', type: 'number' }, ], returnType: 'number', - examples: [`from index where field="value" | eval atan2 = atan2(x, y)`], + examples: [`from index | eval atan2 = atan2(x, y)`], }, ], }, { name: 'coalesce', - description: i18n.translate('monaco.esql.autocomplete.coalesceDoc', { + description: i18n.translate('monaco.esql.definitions.coalesceDoc', { defaultMessage: 'Returns the first non-null value.', }), signatures: [ @@ -565,46 +581,46 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'cos', - description: i18n.translate('monaco.esql.autocomplete.cosDoc', { + description: i18n.translate('monaco.esql.definitions.cosDoc', { defaultMessage: 'Cosine trigonometric function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval cos = cos(field)`], + examples: [`from index | eval cos = cos(field)`], }, ], }, { name: 'cosh', - description: i18n.translate('monaco.esql.autocomplete.coshDoc', { + description: i18n.translate('monaco.esql.definitions.coshDoc', { defaultMessage: 'Cosine hyperbolic function', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval cosh = cosh(field)`], + examples: [`from index | eval cosh = cosh(field)`], }, ], }, { name: 'floor', - description: i18n.translate('monaco.esql.autocomplete.floorDoc', { + description: i18n.translate('monaco.esql.definitions.floorDoc', { defaultMessage: 'Round a number down to the nearest integer.', }), signatures: [ { params: [{ name: 'field', type: 'number' }], returnType: 'number', - examples: [`from index where field="value" | eval a = floor(field)`], + examples: [`from index | eval a = floor(field)`], }, ], }, { name: 'greatest', - description: i18n.translate('monaco.esql.autocomplete.greatestDoc', { + description: i18n.translate('monaco.esql.definitions.greatestDoc', { defaultMessage: 'Returns the maximum value from many columns.', }), signatures: [ @@ -618,7 +634,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'left', - description: i18n.translate('monaco.esql.autocomplete.leftDoc', { + description: i18n.translate('monaco.esql.definitions.leftDoc', { defaultMessage: 'Return the substring that extracts length chars from the string starting from the left.', }), @@ -629,13 +645,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'length', type: 'number' }, ], returnType: 'string', - examples: [`from index where field="value" | eval substr = left(field, 3)`], + examples: [`from index | eval substr = left(field, 3)`], }, ], }, { name: 'ltrim', - description: i18n.translate('monaco.esql.autocomplete.ltrimDoc', { + description: i18n.translate('monaco.esql.definitions.ltrimDoc', { defaultMessage: 'Removes leading whitespaces from strings.', }), signatures: [ @@ -648,7 +664,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'now', - description: i18n.translate('monaco.esql.autocomplete.nowDoc', { + description: i18n.translate('monaco.esql.definitions.nowDoc', { defaultMessage: 'Returns current date and time.', }), signatures: [ @@ -661,7 +677,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'right', - description: i18n.translate('monaco.esql.autocomplete.rightDoc', { + description: i18n.translate('monaco.esql.definitions.rightDoc', { defaultMessage: 'Return the substring that extracts length chars from the string starting from the right.', }), @@ -672,13 +688,13 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ { name: 'length', type: 'number' }, ], returnType: 'string', - examples: [`from index where field="value" | eval string = right(field, 3)`], + examples: [`from index | eval string = right(field, 3)`], }, ], }, { name: 'rtrim', - description: i18n.translate('monaco.esql.autocomplete.rtrimDoc', { + description: i18n.translate('monaco.esql.definitions.rtrimDoc', { defaultMessage: 'Removes trailing whitespaces from strings.', }), signatures: [ @@ -691,7 +707,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sin', - description: i18n.translate('monaco.esql.autocomplete.sinDoc', { + description: i18n.translate('monaco.esql.definitions.sinDoc', { defaultMessage: 'Sine trigonometric function.', }), signatures: [ @@ -704,7 +720,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sinh', - description: i18n.translate('monaco.esql.autocomplete.sinhDoc', { + description: i18n.translate('monaco.esql.definitions.sinhDoc', { defaultMessage: 'Sine hyperbolic function.', }), signatures: [ @@ -717,7 +733,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'sqrt', - description: i18n.translate('monaco.esql.autocomplete.sqrtDoc', { + description: i18n.translate('monaco.esql.definitions.sqrtDoc', { defaultMessage: 'Returns the square root of a number. ', }), signatures: [ @@ -730,7 +746,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'tan', - description: i18n.translate('monaco.esql.autocomplete.tanDoc', { + description: i18n.translate('monaco.esql.definitions.tanDoc', { defaultMessage: 'Tangent trigonometric function.', }), signatures: [ @@ -743,7 +759,7 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, { name: 'tanh', - description: i18n.translate('monaco.esql.autocomplete.tanhDoc', { + description: i18n.translate('monaco.esql.definitions.tanhDoc', { defaultMessage: 'Tangent hyperbolic function.', }), signatures: [ @@ -754,167 +770,180 @@ const mathCommandFullDefinitions: FunctionDefinition[] = [ }, ], }, -].sort(({ name: a }, { name: b }) => a.localeCompare(b)); - -function printArguments({ - name, - type, - optional, - reference, -}: { - name: string; - type: string | string[]; - optional?: boolean; - reference?: string; -}): string { - return `${name}${optional ? ':?' : ':'} ${Array.isArray(type) ? type.join(' | ') : type}`; -} - -export const mathCommandDefinition: AutocompleteCommandDefinition[] = - mathCommandFullDefinitions.map(({ name, description, signatures }) => ({ - label: name, - insertText: name, - kind: 1, - detail: description, - documentation: { - value: buildFunctionDocumentation( - signatures.map(({ params, returnType, infiniteParams, examples }) => ({ - declaration: `${name}(${params.map(printArguments).join(', ')}${ - infiniteParams ? ` ,[... ${params.map(printArguments)}]` : '' - }): ${returnType}`, - examples, - })) - ), - }, - sortText: 'C', - })); - -export const aggregationFunctionsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'avg', - insertText: 'avg', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.avgDoc', { - defaultMessage: 'Returns the average of the values in a field', - }), - documentation: { - value: buildDocumentation('avg(grouped[T]): aggregated[T]', [ - 'from index | stats average = avg(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'max', - insertText: 'max', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.maxDoc', { - defaultMessage: 'Returns the maximum value in a field.', - }), - documentation: { - value: buildDocumentation('max(grouped[T]): aggregated[T]', [ - 'from index | stats max = max(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'min', - insertText: 'min', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.minDoc', { - defaultMessage: 'Returns the minimum value in a field.', - }), - documentation: { - value: buildDocumentation('min(grouped[T]): aggregated[T]', [ - 'from index | stats min = min(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'sum', - insertText: 'sum', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.sumDoc', { - defaultMessage: 'Returns the sum of the values in a field.', - }), - documentation: { - value: buildDocumentation('sum(grouped[T]): aggregated[T]', [ - 'from index | stats sum = sum(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'count', - insertText: 'count', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.countDoc', { - defaultMessage: 'Returns the count of the values in a field.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = count(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'count_distinct', - insertText: 'count_distinct', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.countDistinctDoc', { - defaultMessage: 'Returns the count of distinct values in a field.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = count_distinct(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'median', - insertText: 'median', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.medianDoc', { - defaultMessage: 'Returns the 50% percentile.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = median(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'median_absolute_deviation', - insertText: 'median_absolute_deviation', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.medianDeviationDoc', { + { + name: 'cidr_match', + description: i18n.translate('monaco.esql.definitions.cidrMatchDoc', { defaultMessage: - 'Returns the median of each data point’s deviation from the median of the entire sample.', - }), - documentation: { - value: buildDocumentation('count(grouped[T]): aggregated[T]', [ - 'from index | stats count = median_absolute_deviation(field)', - ]), - }, - sortText: 'C', - }, - { - label: 'percentile', - insertText: 'percentile', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.percentiletDoc', { - defaultMessage: 'Returns the n percentile of a field.', - }), - documentation: { - value: buildDocumentation('percentile(grouped[T]): aggregated[T]', [ - 'from index | stats pct = percentile(field, 90)', - ]), - }, - sortText: 'C', - }, -]; + 'The function takes a first parameter of type IP, followed by one or more parameters evaluated to a CIDR specificatione.', + }), + signatures: [ + { + minParams: 2, + params: [ + { name: 'ip', type: 'ip' }, + { name: 'cidr_block', type: 'string' }, + ], + returnType: 'boolean', + examples: [ + 'from index | where cidr_match(ip_field, "127.0.0.1/30")', + 'from index | eval cidr="10.0.0.0/8" | where cidr_match(ip_field, "127.0.0.1/30", cidr)', + ], + }, + ], + }, + { + name: 'mv_avg', + description: i18n.translate('monaco.esql.definitions.mvAvgDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the average of all of the values.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | mv_avg(a)'], + }, + ], + }, + { + name: 'mv_concat', + description: i18n.translate('monaco.esql.definitions.mvConcatDoc', { + defaultMessage: + 'Converts a multivalued string field into a single valued field containing the concatenation of all values separated by a delimiter', + }), + signatures: [ + { + params: [ + { name: 'multivalue', type: 'string[]' }, + { name: 'delimeter', type: 'string' }, + ], + returnType: 'string', + examples: ['row a = ["1", "2", "3"] | mv_concat(a, ", ")'], + }, + ], + }, + { + name: 'mv_count', + description: i18n.translate('monaco.esql.definitions.mvCountDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing a count of the number of values', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'any[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_count(a)'], + }, + ], + }, + { + name: 'mv_dedupe', + description: i18n.translate('monaco.esql.definitions.mvDedupeDoc', { + defaultMessage: 'Removes duplicates from a multivalued field', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'any[]' }], + returnType: 'any[]', + examples: ['row a = [2, 2, 3] | eval mv_dedupe(a)'], + }, + ], + }, + { + name: 'mv_max', + description: i18n.translate('monaco.esql.definitions.mvMaxDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the maximum value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_max(a)'], + }, + ], + }, + { + name: 'mv_min', + description: i18n.translate('monaco.esql.definitions.mvMinDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the minimum value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_min(a)'], + }, + ], + }, + { + name: 'mv_median', + description: i18n.translate('monaco.esql.definitions.mvMedianDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the median value.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_median(a)'], + }, + ], + }, + { + name: 'mv_sum', + description: i18n.translate('monaco.esql.definitions.mvSumDoc', { + defaultMessage: + 'Converts a multivalued field into a single valued field containing the sum of all of the values.', + }), + signatures: [ + { + params: [{ name: 'multivalue', type: 'number[]' }], + returnType: 'number', + examples: ['row a = [1, 2, 3] | eval mv_sum(a)'], + }, + ], + }, + { + name: 'pi', + description: i18n.translate('monaco.esql.definitions.piDoc', { + defaultMessage: 'The ratio of a circle’s circumference to its diameter.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval pi()'], + }, + ], + }, + { + name: 'e', + description: i18n.translate('monaco.esql.definitions.eDoc', { + defaultMessage: 'Euler’s number.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval e()'], + }, + ], + }, + { + name: 'tau', + description: i18n.translate('monaco.esql.definitions.tauDoc', { + defaultMessage: 'The ratio of a circle’s circumference to its radius.', + }), + signatures: [ + { + params: [], + returnType: 'number', + examples: ['row a = 1 | eval tau()'], + }, + ], + }, +] + .sort(({ name: a }, { name: b }) => a.localeCompare(b)) + .map((def) => ({ ...def, supportedCommands: ['eval', 'where', 'row'] })); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts new file mode 100644 index 0000000000000..409aaf762475e --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/helpers.ts @@ -0,0 +1,101 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { CommandDefinition, CommandOptionsDefinition, FunctionDefinition } from './types'; + +export function getCommandOrOptionsSignature({ + name, + signature, + ...rest +}: CommandDefinition | CommandOptionsDefinition): string { + const args = signature.params + .map(({ name: argName, type }) => { + return `<${argName}>`; + }) + .join(' '); + const optionArgs = + 'options' in rest ? rest.options.map(getCommandOrOptionsSignature).join(' ') : ''; + const signatureString = `${name.toUpperCase()} ${args}${ + signature.multipleParams ? `[, ${args}]` : '' + }${optionArgs ? ' ' + optionArgs : ''}`; + if ('wrapped' in rest && rest.wrapped) { + return `${rest.wrapped[0]}${signatureString}${rest.wrapped[1]}${rest.optional ? '?' : ''}`; + } + return signatureString; +} + +export function getFunctionSignatures( + { name, signatures }: FunctionDefinition, + { withTypes }: { withTypes: boolean } = { withTypes: true } +) { + return signatures.map(({ params, returnType, infiniteParams, examples }) => ({ + declaration: `${name}(${params.map((arg) => printArguments(arg, withTypes)).join(', ')}${ + infiniteParams ? ` ,[... ${params.map((arg) => printArguments(arg, withTypes))}]` : '' + })${withTypes ? `: ${returnType}` : ''}`, + examples, + })); +} + +export function getCommandSignature( + { name, signature, options, examples }: CommandDefinition, + { withTypes }: { withTypes: boolean } = { withTypes: true } +) { + return { + declaration: `${name} ${printCommandArguments(signature, withTypes)} ${options.map( + (option) => + `${option.wrapped ? option.wrapped[0] : ''}${option.name} ${printCommandArguments( + option.signature, + withTypes + )}${option.wrapped ? option.wrapped[1] : ''}` + )}`, + examples, + }; +} + +function printCommandArguments( + { multipleParams, params }: CommandDefinition['signature'], + withTypes: boolean +): string { + return `${params.map((arg) => printCommandArgument(arg, withTypes)).join(', `')}${ + multipleParams + ? ` ,[...${params.map((arg) => printCommandArgument(arg, withTypes)).join(', `')}]` + : '' + }`; +} + +function printCommandArgument( + param: CommandDefinition['signature']['params'][number], + withTypes: boolean +): string { + if (!withTypes) { + return param.name || ''; + } + return `${param.name}${param.optional ? ':?' : ':'} ${param.type}${ + param.innerType ? `{${param.innerType}}` : '' + }`; +} + +export function printArguments( + { + name, + type, + optional, + reference, + }: { + name: string; + type: string | string[]; + optional?: boolean; + reference?: string; + }, + withTypes: boolean +): string { + if (!withTypes) { + return name; + } + return `${name}${optional ? ':?' : ':'} ${Array.isArray(type) ? type.join(' | ') : type}`; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts new file mode 100644 index 0000000000000..3cc61683372a7 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/literals.ts @@ -0,0 +1,142 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { Literals } from './types'; + +export const timeLiterals: Literals[] = [ + { + name: 'year', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.year', { + defaultMessage: 'Year', + }), + }, + { + name: 'years', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.years', { + defaultMessage: 'Years (Plural)', + }), + }, + { + name: 'month', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.month', { + defaultMessage: 'Month', + }), + }, + { + name: 'months', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.months', { + defaultMessage: 'Months (Plural)', + }), + }, + { + name: 'week', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.week', { + defaultMessage: 'Week', + }), + }, + { + name: 'weeks', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.weeks', { + defaultMessage: 'Weeks (Plural)', + }), + }, + { + name: 'day', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.day', { + defaultMessage: 'Day', + }), + }, + { + name: 'days', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.days', { + defaultMessage: 'Days (Plural)', + }), + }, + { + name: 'hour', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.hour', { + defaultMessage: 'Hour', + }), + }, + { + name: 'hours', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.hours', { + defaultMessage: 'Hours (Plural)', + }), + }, + { + name: 'minute', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.minute', { + defaultMessage: 'Minute', + }), + }, + { + name: 'minutes', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.minutes', { + defaultMessage: 'Minutes (Plural)', + }), + }, + { + name: 'second', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.second', { + defaultMessage: 'Second', + }), + }, + { + name: 'seconds', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.seconds', { + defaultMessage: 'Seconds (Plural)', + }), + }, + { + name: 'millisecond', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.millisecond', { + defaultMessage: 'Millisecond', + }), + }, + { + name: 'milliseconds', + description: i18n.translate('monaco.esql.definitions.dateDurationDefinition.milliseconds', { + defaultMessage: 'Milliseconds (Plural)', + }), + }, +]; + +export const chronoLiterals: Literals[] = [ + 'ALIGNED_DAY_OF_WEEK_IN_MONTH', + 'ALIGNED_DAY_OF_WEEK_IN_YEAR', + 'ALIGNED_WEEK_OF_MONTH', + 'ALIGNED_WEEK_OF_YEAR', + 'AMPM_OF_DAY', + 'CLOCK_HOUR_OF_AMPM', + 'CLOCK_HOUR_OF_DAY', + 'DAY_OF_MONTH', + 'DAY_OF_WEEK', + 'DAY_OF_YEAR', + 'EPOCH_DAY', + 'ERA', + 'HOUR_OF_AMPM', + 'HOUR_OF_DAY', + 'INSTANT_SECONDS', + 'MICRO_OF_DAY', + 'MICRO_OF_SECOND', + 'MILLI_OF_DAY', + 'MILLI_OF_SECOND', + 'MINUTE_OF_DAY', + 'MINUTE_OF_HOUR', + 'MONTH_OF_YEAR', + 'NANO_OF_DAY', + 'NANO_OF_SECOND', + 'OFFSET_SECONDS', + 'PROLEPTIC_MONTH', + 'SECOND_OF_DAY', + 'SECOND_OF_MINUTE', + 'YEAR', + 'YEAR_OF_ERA', +].map((name) => ({ name: `"${name}"`, description: '' })); diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts new file mode 100644 index 0000000000000..465d6d25dc32e --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/options.ts @@ -0,0 +1,106 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import { isLiteralItem } from '../shared/helpers'; +import { ESQLCommandOption, ESQLMessage } from '../types'; +import { CommandOptionsDefinition } from './types'; + +export const byOption: CommandOptionsDefinition = { + name: 'by', + description: i18n.translate('monaco.esql.definitions.byDoc', { + defaultMessage: 'By', + }), + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column' }], + }, + optional: true, +}; + +export const metadataOption: CommandOptionsDefinition = { + name: 'metadata', + description: i18n.translate('monaco.esql.definitions.metadataDoc', { + defaultMessage: 'Metadata', + }), + signature: { + multipleParams: true, + params: [{ name: 'column', type: 'column' }], + }, + optional: true, + wrapped: ['[', ']'], +}; + +export const asOption: CommandOptionsDefinition = { + name: 'as', + description: i18n.translate('monaco.esql.definitions.asDoc', { defaultMessage: 'As' }), + signature: { + multipleParams: false, + params: [ + { name: 'oldName', type: 'column' }, + { name: 'newName', type: 'column' }, + ], + }, + optional: false, +}; + +export const onOption: CommandOptionsDefinition = { + name: 'on', + description: i18n.translate('monaco.esql.definitions.onDoc', { defaultMessage: 'On' }), + signature: { + multipleParams: false, + params: [{ name: 'matchingColumn', type: 'column' }], + }, + optional: true, +}; + +export const withOption: CommandOptionsDefinition = { + name: 'with', + description: i18n.translate('monaco.esql.definitions.withDoc', { defaultMessage: 'With' }), + signature: { + multipleParams: true, + params: [{ name: 'assignment', type: 'any' }], + }, + optional: true, +}; + +export const appendSeparatorOption: CommandOptionsDefinition = { + name: 'append_separator', + description: i18n.translate('monaco.esql.definitions.appendSeparatorDoc', { + defaultMessage: + 'The character(s) that separate the appended fields. Default to empty string ("").', + }), + signature: { + multipleParams: false, + params: [{ name: 'separator', type: 'string' }], + }, + optional: true, + skipCommonValidation: true, // tell the validation engine to use only the validate function here + validate: (option: ESQLCommandOption) => { + const messages: ESQLMessage[] = []; + const [firstArg] = option.args; + if ( + !Array.isArray(firstArg) && + (!isLiteralItem(firstArg) || firstArg.literalType !== 'string') + ) { + const value = 'value' in firstArg ? firstArg.value : firstArg.name; + messages.push({ + location: firstArg.location, + text: i18n.translate('monaco.esql.validation.wrongDissectOptionArgumentType', { + defaultMessage: + 'Invalid value for dissect append_separator: expected a string, but was [{value}]', + values: { + value, + }, + }), + type: 'error', + }); + } + return messages; + }, +}; diff --git a/packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts b/packages/kbn-monaco/src/esql/lib/ast/definitions/types.ts new file mode 100644 index 0000000000000..c52f332f3f2eb --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/definitions/types.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 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 or the Server + * Side Public License, v 1. + */ + +import type { ESQLCommand, ESQLCommandOption, ESQLMessage, ESQLSingleAstItem } from '../types'; + +export interface FunctionDefinition { + builtin?: boolean; + ignoreAsSuggestion?: boolean; + name: string; + alias?: string[]; + description: string; + supportedCommands: string[]; + signatures: Array<{ + params: Array<{ + name: string; + type: string; + optional?: boolean; + noNestingFunctions?: boolean; + supportsWildcard?: boolean; + }>; + infiniteParams?: boolean; + minParams?: number; + returnType: string; + examples?: string[]; + }>; + warning?: (...args: ESQLSingleAstItem[]) => string | undefined; +} + +export interface CommandBaseDefinition { + name: string; + alias?: string; + description: string; + signature: { + multipleParams: boolean; + // innerType here is useful to drill down the type in case of "column" + // i.e. column of type string + params: Array<{ + name: string; + type: string; + optional?: boolean; + innerType?: string; + values?: string[]; + literalOnly?: boolean; + wildcards?: boolean; + }>; + }; +} + +export interface CommandOptionsDefinition extends CommandBaseDefinition { + wrapped?: string[]; + optional: boolean; + skipCommonValidation?: boolean; + validate?: (option: ESQLCommandOption) => ESQLMessage[]; +} + +export interface CommandDefinition extends CommandBaseDefinition { + options: CommandOptionsDefinition[]; + examples: string[]; + validate?: (option: ESQLCommand) => ESQLMessage[]; +} + +export interface Literals { + name: string; + description: string; +} + +export type SignatureType = + | FunctionDefinition['signatures'][number] + | CommandOptionsDefinition['signature']; +export type SignatureArgType = SignatureType['params'][number]; diff --git a/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts b/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts new file mode 100644 index 0000000000000..b118a7dec5489 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/hover/index.ts @@ -0,0 +1,81 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { monaco } from '../../../../monaco_imports'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { getAstContext } from '../shared/context'; +import { monacoPositionToOffset, getFunctionDefinition, isSourceItem } from '../shared/helpers'; +import { getPolicyHelper } from '../shared/resources_helpers'; +import { ESQLCallbacks } from '../shared/types'; +import type { AstProviderFn } from '../types'; + +export async function getHoverItem( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken, + astProvider: AstProviderFn, + resourceRetriever?: ESQLCallbacks +) { + const innerText = model.getValue(); + const offset = monacoPositionToOffset(innerText, position); + + const { ast } = await astProvider(innerText); + const astContext = getAstContext(innerText, ast, offset); + const { getPolicyMetadata } = getPolicyHelper(resourceRetriever); + + if (['newCommand', 'list'].includes(astContext.type)) { + return { contents: [] }; + } + + if (astContext.type === 'function') { + const fnDefinition = getFunctionDefinition(astContext.node.name); + + if (fnDefinition) { + return { + contents: [ + { value: getFunctionSignatures(fnDefinition)[0].declaration }, + { value: fnDefinition.description }, + ], + }; + } + } + + if (astContext.type === 'expression') { + if ( + astContext.node && + isSourceItem(astContext.node) && + astContext.node.sourceType === 'policy' + ) { + const policyMetadata = await getPolicyMetadata(astContext.node.name); + if (policyMetadata) { + return { + contents: [ + { + value: `${i18n.translate('monaco.esql.hover.policyIndexes', { + defaultMessage: '**Indexes**', + })}: ${policyMetadata.sourceIndices}`, + }, + { + value: `${i18n.translate('monaco.esql.hover.policyMatchingField', { + defaultMessage: '**Matching field**', + })}: ${policyMetadata.matchField}`, + }, + { + value: `${i18n.translate('monaco.esql.hover.policyEnrichedFields', { + defaultMessage: '**Fields**', + })}: ${policyMetadata.enrichFields}`, + }, + ], + }; + } + } + } + + return { contents: [] }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts new file mode 100644 index 0000000000000..618928f36bcfb --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/constants.ts @@ -0,0 +1,9 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +export const EDITOR_MARKER = 'marker_esql_editor'; diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts new file mode 100644 index 0000000000000..3a51038ec4e92 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/context.ts @@ -0,0 +1,158 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { + ESQLAstItem, + ESQLSingleAstItem, + ESQLAst, + ESQLFunction, + ESQLCommand, + ESQLCommandOption, +} from '../types'; +import { EDITOR_MARKER } from './constants'; +import { + isOptionItem, + isColumnItem, + getLastCharFromTrimmed, + getFunctionDefinition, +} from './helpers'; + +function findNode(nodes: ESQLAstItem[], offset: number): ESQLSingleAstItem | undefined { + for (const node of nodes) { + if (Array.isArray(node)) { + const ret = findNode(node, offset); + if (ret) { + return ret; + } + } else { + if (node.location.min <= offset && node.location.max >= offset) { + if ('args' in node) { + const ret = findNode(node.args, offset); + // if the found node is the marker, then return its parent + if (ret?.text === EDITOR_MARKER) { + return node; + } + if (ret) { + return ret; + } + } + return node; + } + } + } +} + +function findCommand(ast: ESQLAst, offset: number) { + const commandIndex = ast.findIndex( + ({ location }) => location.min <= offset && location.max >= offset + ); + return ast[commandIndex] || ast[ast.length - 1]; +} + +function findOption(nodes: ESQLAstItem[], offset: number): ESQLCommandOption | undefined { + // this is a similar logic to the findNode, but it check if the command is in root or option scope + for (const node of nodes) { + if (!Array.isArray(node) && isOptionItem(node)) { + if ( + (node.location.min <= offset && node.location.max >= offset) || + (nodes[nodes.length - 1] === node && node.location.max < offset) + ) { + return node; + } + } + } +} + +function isMarkerNode(node: ESQLSingleAstItem | undefined): boolean { + return Boolean(node && isColumnItem(node) && node.name === EDITOR_MARKER); +} + +function cleanMarkerNode(node: ESQLSingleAstItem | undefined): ESQLSingleAstItem | undefined { + return isMarkerNode(node) ? undefined : node; +} + +function isNotMarkerNodeOrArray(arg: ESQLAstItem) { + return Array.isArray(arg) || !isMarkerNode(arg); +} + +function mapToNonMarkerNode(arg: ESQLAstItem): ESQLAstItem { + return Array.isArray(arg) ? arg.filter(isNotMarkerNodeOrArray).map(mapToNonMarkerNode) : arg; +} + +export function removeMarkerArgFromArgsList( + node: T | undefined +) { + if (!node) { + return; + } + if (node.type === 'command' || node.type === 'option' || node.type === 'function') { + return { + ...node, + args: node.args.filter(isNotMarkerNodeOrArray).map(mapToNonMarkerNode), + }; + } + return node; +} + +function findAstPosition(ast: ESQLAst, offset: number) { + const command = findCommand(ast, offset); + if (!command) { + return { command: undefined, node: undefined, option: undefined }; + } + return { + command: removeMarkerArgFromArgsList(command)!, + option: removeMarkerArgFromArgsList(findOption(command.args, offset)), + node: removeMarkerArgFromArgsList(cleanMarkerNode(findNode(command.args, offset))), + }; +} + +function isNotEnrichClauseAssigment(node: ESQLFunction, command: ESQLCommand) { + return node.name !== '=' && command.name !== 'enrich'; +} +function isBuiltinFunction(node: ESQLFunction) { + return Boolean(getFunctionDefinition(node.name)?.builtin); +} + +export function getAstContext(innerText: string, ast: ESQLAst, offset: number) { + const { command, option, node } = findAstPosition(ast, offset); + if (node) { + if (node.type === 'function') { + if (['in', 'not_in'].includes(node.name)) { + // command ... a in ( ) + return { type: 'list' as const, command, node, option }; + } + if (isNotEnrichClauseAssigment(node, command) && !isBuiltinFunction(node)) { + // command ... fn( ) + return { type: 'function' as const, command, node, option }; + } + } + if (node.type === 'option' || option) { + // command ... by + return { type: 'option' as const, command, node, option }; + } + } + + if (!command || (innerText.length <= offset && getLastCharFromTrimmed(innerText) === '|')) { + // // ... | + return { type: 'newCommand' as const, command: undefined, node, option }; + } + + if (command && command.args.length) { + if (option) { + return { type: 'option' as const, command, node, option }; + } + } + + // command a ... OR command a = ... + return { + type: 'expression' as const, + command, + option, + node, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts new file mode 100644 index 0000000000000..f54849b7e81cf --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/helpers.ts @@ -0,0 +1,451 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { monaco } from '../../../../monaco_imports'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import { builtinFunctions } from '../definitions/builtin'; +import { commandDefinitions } from '../definitions/commands'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { byOption, metadataOption, asOption, onOption, withOption } from '../definitions/options'; +import { + CommandDefinition, + CommandOptionsDefinition, + FunctionDefinition, + SignatureArgType, +} from '../definitions/types'; +import { + ESQLAstItem, + ESQLColumn, + ESQLCommandOption, + ESQLFunction, + ESQLLiteral, + ESQLSingleAstItem, + ESQLSource, + ESQLTimeInterval, +} from '../types'; +import { ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; +import { removeMarkerArgFromArgsList } from './context'; + +export function isFunctionItem(arg: ESQLAstItem): arg is ESQLFunction { + return arg && !Array.isArray(arg) && arg.type === 'function'; +} + +export function isOptionItem(arg: ESQLAstItem): arg is ESQLCommandOption { + return !Array.isArray(arg) && arg.type === 'option'; +} + +export function isSourceItem(arg: ESQLAstItem): arg is ESQLSource { + return arg && !Array.isArray(arg) && arg.type === 'source'; +} + +export function isColumnItem(arg: ESQLAstItem): arg is ESQLColumn { + return arg && !Array.isArray(arg) && arg.type === 'column'; +} + +export function isLiteralItem(arg: ESQLAstItem): arg is ESQLLiteral { + return arg && !Array.isArray(arg) && arg.type === 'literal'; +} + +export function isTimeIntervalItem(arg: ESQLAstItem): arg is ESQLTimeInterval { + return arg && !Array.isArray(arg) && arg.type === 'timeInterval'; +} + +export function isAssignment(arg: ESQLAstItem): arg is ESQLFunction { + return isFunctionItem(arg) && arg.name === '='; +} + +export function isAssignmentComplete(node: ESQLFunction | undefined) { + const assignExpression = removeMarkerArgFromArgsList(node)?.args?.[1]; + return Boolean(assignExpression && Array.isArray(assignExpression) && assignExpression.length); +} + +export function isExpression(arg: ESQLAstItem): arg is ESQLFunction { + return isFunctionItem(arg) && arg.name !== '='; +} + +export function isIncompleteItem(arg: ESQLAstItem): boolean { + return !arg || (!Array.isArray(arg) && arg.incomplete); +} + +// From Monaco position to linear offset +export function monacoPositionToOffset(expression: string, position: monaco.Position): number { + const lines = expression.split(/\n/); + return lines + .slice(0, position.lineNumber) + .reduce( + (prev, current, index) => + prev + (index === position.lineNumber - 1 ? position.column - 1 : current.length + 1), + 0 + ); +} + +let fnLookups: Map | undefined; +let commandLookups: Map | undefined; + +function buildFunctionLookup() { + if (!fnLookups) { + fnLookups = builtinFunctions + .concat(evalFunctionsDefinitions, statsAggregationFunctionDefinitions) + .reduce((memo, def) => { + memo.set(def.name, def); + if (def.alias) { + for (const alias of def.alias) { + memo.set(alias, def); + } + } + return memo; + }, new Map()); + } + return fnLookups; +} + +type ReasonTypes = 'missingCommand' | 'unsupportedFunction' | 'unknownFunction'; + +export function isSupportedFunction( + name: string, + parentCommand?: string +): { supported: boolean; reason: ReasonTypes | undefined } { + if (!parentCommand) { + return { + supported: false, + reason: 'missingCommand', + }; + } + const fn = buildFunctionLookup().get(name); + const isSupported = Boolean(fn?.supportedCommands.includes(parentCommand)); + return { + supported: isSupported, + reason: isSupported ? undefined : fn ? 'unsupportedFunction' : 'unknownFunction', + }; +} + +export function getFunctionDefinition(name: string) { + return buildFunctionLookup().get(name.toLowerCase()); +} + +function buildCommandLookup() { + if (!commandLookups) { + commandLookups = commandDefinitions.reduce((memo, def) => { + memo.set(def.name, def); + if (def.alias) { + memo.set(def.alias, def); + } + return memo; + }, new Map()); + } + return commandLookups; +} + +export function getCommandDefinition(name: string): CommandDefinition { + return buildCommandLookup().get(name.toLowerCase())!; +} + +export function getAllCommands() { + return Array.from(buildCommandLookup().values()); +} + +export function getCommandOption(name: CommandOptionsDefinition['name']) { + switch (name) { + case 'by': + return byOption; + case 'metadata': + return metadataOption; + case 'as': + return asOption; + case 'on': + return onOption; + case 'with': + return withOption; + default: + return; + } +} + +function compareLiteralType(argTypes: string, item: ESQLLiteral) { + if (item.literalType !== 'string') { + return argTypes === item.literalType; + } + if (argTypes === 'chrono_literal') { + return chronoLiterals.some(({ name }) => name === item.text); + } + return argTypes === item.literalType; +} + +export function getColumnHit( + columnName: string, + { fields, variables }: Pick, + position?: number +): ESQLRealField | ESQLVariable | undefined { + return fields.get(columnName) || variables.get(columnName)?.[0]; +} + +const ARRAY_REGEXP = /\[\]$/; + +export function isArrayType(type: string) { + return ARRAY_REGEXP.test(type); +} + +export function extractSingleType(type: string) { + return type.replace(ARRAY_REGEXP, ''); +} + +export function createMapFromList(arr: T[]): Map { + const arrMap = new Map(); + for (const item of arr) { + arrMap.set(item.name, item); + } + return arrMap; +} + +export function areFieldAndVariableTypesCompatible( + fieldType: string | string[] | undefined, + variableType: string | string[] +) { + if (fieldType == null) { + return false; + } + return fieldType === variableType; +} + +export function printFunctionSignature(arg: ESQLFunction): string { + const fnDef = getFunctionDefinition(arg.name); + if (fnDef) { + const signature = getFunctionSignatures( + { + ...fnDef, + signatures: [ + { + ...fnDef?.signatures[0], + params: arg.args.map((innerArg) => + Array.isArray(innerArg) + ? { name: `InnerArgument[]`, type: '' } + : { name: innerArg.text, type: innerArg.type } + ), + returnType: '', + }, + ], + }, + { withTypes: false } + ); + return signature[0].declaration; + } + return ''; +} + +export function getAllArrayValues(arg: ESQLAstItem) { + const values: string[] = []; + if (Array.isArray(arg)) { + for (const subArg of arg) { + if (Array.isArray(subArg)) { + break; + } + if (subArg.type === 'literal') { + values.push(String(subArg.value)); + } + if (subArg.type === 'column') { + values.push(subArg.name); + } + if (subArg.type === 'timeInterval') { + values.push(subArg.name); + } + if (subArg.type === 'function') { + const signature = printFunctionSignature(subArg); + if (signature) { + values.push(signature); + } + } + } + } + return values; +} + +export function getAllArrayTypes( + arg: ESQLAstItem, + parentCommand: string, + references: ReferenceMaps +) { + const types = []; + if (Array.isArray(arg)) { + for (const subArg of arg) { + if (Array.isArray(subArg)) { + break; + } + if (subArg.type === 'literal') { + types.push(subArg.literalType); + } + if (subArg.type === 'column') { + const hit = getColumnHit(subArg.name, references); + types.push(hit?.type || 'unsupported'); + } + if (subArg.type === 'timeInterval') { + types.push('time_literal'); + } + if (subArg.type === 'function') { + if (isSupportedFunction(subArg.name, parentCommand).supported) { + const fnDef = buildFunctionLookup().get(subArg.name)!; + types.push(fnDef.signatures[0].returnType); + } + } + } + } + return types; +} + +export function inKnownTimeInterval(item: ESQLTimeInterval): boolean { + return timeLiterals.some(({ name }) => name === item.unit.toLowerCase()); +} + +export function isEqualType( + item: ESQLSingleAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand?: string +) { + const argType = 'innerType' in argDef && argDef.innerType ? argDef.innerType : argDef.type; + if (argType === 'any') { + return true; + } + if (item.type === 'literal') { + return compareLiteralType(argType, item); + } + if (item.type === 'list') { + const listType = `${item.values[0].literalType}[]`; + // argType = 'list' means any list value is ok + return argType === item.type || argType === listType; + } + if (item.type === 'function') { + if (isSupportedFunction(item.name, parentCommand).supported) { + const fnDef = buildFunctionLookup().get(item.name)!; + return fnDef.signatures.some((signature) => argType === signature.returnType); + } + } + if (item.type === 'timeInterval') { + return argType === 'time_literal' && inKnownTimeInterval(item); + } + if (item.type === 'column') { + if (argType === 'column') { + // anything goes, so avoid any effort here + return true; + } + const hit = getColumnHit(item.name, references); + if (!hit) { + return false; + } + const wrappedTypes = Array.isArray(hit.type) ? hit.type : [hit.type]; + return wrappedTypes.some((ct) => argType === ct); + } + if (item.type === 'source') { + return item.sourceType === argType; + } +} + +export function endsWithOpenBracket(text: string) { + return /\($/.test(text); +} + +export function isDateFunction(fnName: string) { + // TODO: improve this and rely in signature in the future + return ['to_datetime', 'date_trunc', 'date_parse'].includes(fnName.toLowerCase()); +} + +export function getDateMathOperation() { + return builtinFunctions.filter(({ name }) => ['+', '-'].includes(name)); +} + +export function getDurationItemsWithQuantifier(quantifier: number = 1) { + return timeLiterals + .filter(({ name }) => !/s$/.test(name)) + .map(({ name, ...rest }) => ({ + label: `${quantifier} ${name}`, + insertText: `${quantifier} ${name}`, + ...rest, + })); +} + +function fuzzySearch(fuzzyName: string, resources: IterableIterator) { + const wildCardPosition = getWildcardPosition(fuzzyName); + if (wildCardPosition !== 'none') { + const matcher = getMatcher(fuzzyName, wildCardPosition); + for (const resourceName of resources) { + if (matcher(resourceName)) { + return true; + } + } + } +} + +function getMatcher(name: string, position: 'start' | 'end' | 'middle') { + if (position === 'start') { + const prefix = name.substring(1); + return (resource: string) => resource.endsWith(prefix); + } + if (position === 'end') { + const prefix = name.substring(0, name.length - 1); + return (resource: string) => resource.startsWith(prefix); + } + const [prefix, postFix] = name.split('*'); + return (resource: string) => resource.startsWith(prefix) && resource.endsWith(postFix); +} + +function getWildcardPosition(name: string) { + if (!hasWildcard(name)) { + return 'none'; + } + if (name.startsWith('*')) { + return 'start'; + } + if (name.endsWith('*')) { + return 'end'; + } + return 'middle'; +} + +export function hasWildcard(name: string) { + return name.includes('*'); +} +export function hasCCSSource(name: string) { + return name.includes(':'); +} + +export function columnExists( + column: ESQLColumn, + { fields, variables }: Pick +) { + if (fields.has(column.name) || variables.has(column.name)) { + return { hit: true, nameHit: column.name }; + } + if (column.quoted) { + const trimmedName = column.name.replace(/\s/g, ''); + if (variables.has(trimmedName)) { + return { hit: true, nameHit: trimmedName }; + } + } + if ( + Boolean(fuzzySearch(column.name, fields.keys()) || fuzzySearch(column.name, variables.keys())) + ) { + return { hit: true, nameHit: column.name }; + } + return { hit: false }; +} + +export function sourceExists(index: string, sources: Set) { + if (sources.has(index)) { + return true; + } + return Boolean(fuzzySearch(index, sources.keys())); +} + +export function getLastCharFromTrimmed(text: string) { + return text[text.trimEnd().length - 1]; +} + +export function isRestartingExpression(text: string) { + return getLastCharFromTrimmed(text) === ','; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts new file mode 100644 index 0000000000000..fcd4cbb0737ff --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/resources_helpers.ts @@ -0,0 +1,66 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { ESQLCallbacks } from './types'; +import type { ESQLRealField } from '../validation/types'; + +export function getFieldsByTypeHelper(queryText: string, resourceRetriever?: ESQLCallbacks) { + const cacheFields = new Map(); + const getFields = async () => { + if (!cacheFields.size) { + const fieldsOfType = await resourceRetriever?.getFieldsFor?.({ query: queryText }); + for (const field of fieldsOfType || []) { + cacheFields.set(field.name, field); + } + } + }; + return { + getFieldsByType: async (expectedType: string | string[] = 'any', ignored: string[] = []) => { + const types = Array.isArray(expectedType) ? expectedType : [expectedType]; + await getFields(); + return ( + Array.from(cacheFields.values()) + ?.filter(({ name, type }) => { + const ts = Array.isArray(type) ? type : [type]; + return ( + !ignored.includes(name) && ts.some((t) => types[0] === 'any' || types.includes(t)) + ); + }) + .map(({ name }) => name) || [] + ); + }, + getFieldsMap: async () => { + await getFields(); + const cacheCopy = new Map(); + cacheFields.forEach((value, key) => cacheCopy.set(key, value)); + return cacheCopy; + }, + }; +} + +export function getPolicyHelper(resourceRetriever?: ESQLCallbacks) { + const getPolicies = async () => { + return (await resourceRetriever?.getPolicies?.()) || []; + }; + return { + getPolicies: async () => { + const policies = await getPolicies(); + return policies; + }, + getPolicyMetadata: async (policyName: string) => { + const policies = await getPolicies(); + return policies.find(({ name }) => name === policyName); + }, + }; +} + +export function getSourcesHelper(resourceRetriever?: ESQLCallbacks) { + return async () => { + return (await resourceRetriever?.getSources?.()) || []; + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts new file mode 100644 index 0000000000000..ceb507f59784a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/types.ts @@ -0,0 +1,22 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +/** @internal **/ +type CallbackFn = (ctx?: Options) => Result[] | Promise; + +/** @public **/ +export interface ESQLCallbacks { + getSources?: CallbackFn<{}, { name: string; hidden: boolean }>; + getFieldsFor?: CallbackFn<{ query: string }, { name: string; type: string }>; + getPolicies?: CallbackFn< + {}, + { name: string; sourceIndices: string[]; matchField: string; enrichFields: string[] } + >; + getPolicyFields?: CallbackFn; + getPolicyMatchingField?: CallbackFn; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts b/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts new file mode 100644 index 0000000000000..3f93ce50b71c3 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/shared/variables.ts @@ -0,0 +1,172 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { ESQLColumn, ESQLAstItem, ESQLCommand, ESQLCommandOption } from '../types'; +import type { ESQLVariable, ESQLRealField } from '../validation/types'; +import { EDITOR_MARKER } from './constants'; +import { + isColumnItem, + isAssignment, + isExpression, + isOptionItem, + isFunctionItem, + getFunctionDefinition, +} from './helpers'; + +function addToVariableOccurrencies(variables: Map, instance: ESQLVariable) { + if (!variables.has(instance.name)) { + variables.set(instance.name, []); + } + const variablesOccurrencies = variables.get(instance.name)!; + variablesOccurrencies.push(instance); +} + +function replaceTrimmedVariable( + variables: Map, + newRef: ESQLColumn, + oldRef: ESQLVariable[] +) { + // now replace the existing trimmed version with this original one + addToVariableOccurrencies(variables, { + name: newRef.name, + type: oldRef[0].type, + location: newRef.location, + }); + // remove the trimmed one + variables.delete(oldRef[0].name); +} + +function addToVariables( + oldArg: ESQLAstItem, + newArg: ESQLAstItem, + fields: Map, + variables: Map +) { + if (isColumnItem(oldArg) && isColumnItem(newArg)) { + const newVariable: ESQLVariable = { + name: newArg.name, + type: 'number' /* fallback to number */, + location: newArg.location, + }; + // Now workout the exact type + // it can be a rename of another variable as well + let oldRef = fields.get(oldArg.name) || variables.get(oldArg.name); + if (oldRef) { + addToVariableOccurrencies(variables, newVariable); + newVariable.type = Array.isArray(oldRef) ? oldRef[0].type : oldRef.type; + } else if (oldArg.quoted) { + // a last attempt in case the user tried to rename an expression: + // trim every space and try a new hit + const expressionTrimmedRef = oldArg.name.replace(/\s/g, ''); + oldRef = variables.get(expressionTrimmedRef); + if (oldRef) { + addToVariableOccurrencies(variables, newVariable); + newVariable.type = oldRef[0].type; + replaceTrimmedVariable(variables, oldArg, oldRef); + } + } + } +} + +function getAssignRightHandSideType(item: ESQLAstItem, fields: Map) { + if (Array.isArray(item)) { + const firstArg = item[0]; + if (Array.isArray(firstArg) || !firstArg) { + return; + } + if (firstArg.type === 'literal') { + return firstArg.literalType; + } + if (isColumnItem(firstArg)) { + const field = fields.get(firstArg.name); + if (field) { + return field.type; + } + } + if (isFunctionItem(firstArg)) { + const fnDefinition = getFunctionDefinition(firstArg.name); + return fnDefinition?.signatures[0].returnType; + } + return firstArg.type; + } +} + +export function excludeVariablesFromCurrentCommand( + commands: ESQLCommand[], + currentCommand: ESQLCommand, + fieldsMap: Map +) { + const anyVariables = collectVariables(commands, fieldsMap); + const currentCommandVariables = collectVariables([currentCommand], fieldsMap); + const resultVariables = new Map(); + anyVariables.forEach((value, key) => { + if (!currentCommandVariables.has(key)) { + resultVariables.set(key, value); + } + }); + return resultVariables; +} + +export function collectVariables( + commands: ESQLCommand[], + fields: Map +): Map { + const variables = new Map(); + for (const command of commands) { + if (['row', 'eval', 'stats'].includes(command.name)) { + const assignOperations = command.args.filter(isAssignment); + for (const assignOperation of assignOperations) { + if (isColumnItem(assignOperation.args[0])) { + const rightHandSideArgType = getAssignRightHandSideType(assignOperation.args[1], fields); + addToVariableOccurrencies(variables, { + name: assignOperation.args[0].name, + type: rightHandSideArgType || 'number' /* fallback to number */, + location: assignOperation.args[0].location, + }); + } + } + const expressionOperations = command.args.filter(isExpression); + for (const expressionOperation of expressionOperations) { + if (!expressionOperation.text.includes(EDITOR_MARKER)) { + // just save the entire expression as variable string + const expressionType = 'number'; + addToVariableOccurrencies(variables, { + name: expressionOperation.text, + type: expressionType, + location: expressionOperation.location, + }); + } + } + } + if (command.name === 'enrich') { + const commandOptionsWithAssignment = command.args.filter( + (arg) => isOptionItem(arg) && arg.name === 'with' + ) as ESQLCommandOption[]; + for (const commandOption of commandOptionsWithAssignment) { + for (const assignFn of commandOption.args) { + if (isFunctionItem(assignFn)) { + const [newArg, oldArg] = assignFn?.args || []; + if (Array.isArray(oldArg)) { + addToVariables(oldArg[0], newArg, fields, variables); + } + } + } + } + } + if (command.name === 'rename') { + const commandOptionsWithAssignment = command.args.filter( + (arg) => isOptionItem(arg) && arg.name === 'as' + ) as ESQLCommandOption[]; + for (const commandOption of commandOptionsWithAssignment) { + const [oldArg, newArg] = commandOption.args; + addToVariables(oldArg, newArg, fields, variables); + } + } + } + return variables; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts b/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts new file mode 100644 index 0000000000000..a3202591a9c7a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/signature/index.ts @@ -0,0 +1,22 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { monaco } from '../../../../monaco_imports'; +import type { AstProviderFn } from '../types'; + +export function getSignatureHelp( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.SignatureHelpContext, + astProvider: AstProviderFn +): monaco.languages.SignatureHelpResult { + return { + value: { signatures: [], activeParameter: 0, activeSignature: 0 }, + dispose: () => {}, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/types.ts b/packages/kbn-monaco/src/esql/lib/ast/types.ts new file mode 100644 index 0000000000000..6c241270de457 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/types.ts @@ -0,0 +1,86 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { EditorError } from '../../../types'; + +export type ESQLAst = ESQLCommand[]; + +export type ESQLSingleAstItem = + | ESQLFunction + | ESQLCommandOption + | ESQLSource + | ESQLColumn + | ESQLTimeInterval + | ESQLList + | ESQLLiteral; + +export type ESQLAstItem = ESQLSingleAstItem | ESQLAstItem[]; + +export interface ESQLLocation { + min: number; + max: number; +} + +interface ESQLAstBaseItem { + name: string; + text: string; + location: ESQLLocation; + incomplete: boolean; +} + +export interface ESQLCommand extends ESQLAstBaseItem { + type: 'command'; + args: ESQLAstItem[]; +} + +export interface ESQLCommandOption extends ESQLAstBaseItem { + type: 'option'; + args: ESQLAstItem[]; +} + +export interface ESQLFunction extends ESQLAstBaseItem { + type: 'function'; + args: ESQLAstItem[]; +} + +export interface ESQLTimeInterval extends ESQLAstBaseItem { + type: 'timeInterval'; + unit: string; + quantity: number; +} + +export interface ESQLSource extends ESQLAstBaseItem { + type: 'source'; + sourceType: 'index' | 'policy'; +} + +export interface ESQLColumn extends ESQLAstBaseItem { + type: 'column'; + quoted: boolean; +} + +export interface ESQLList extends ESQLAstBaseItem { + type: 'list'; + values: ESQLLiteral[]; +} + +export interface ESQLLiteral extends ESQLAstBaseItem { + type: 'literal'; + literalType: 'string' | 'number' | 'boolean' | 'null'; + value: string | number; +} + +export interface ESQLMessage { + type: 'error' | 'warning'; + text: string; + location: ESQLLocation; +} + +export type AstProviderFn = ( + text: string | undefined +) => Promise<{ ast: ESQLAst; errors: EditorError[] }>; diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts new file mode 100644 index 0000000000000..16913677c4890 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/errors.ts @@ -0,0 +1,217 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { ESQLLocation, ESQLMessage } from '../types'; +import type { ErrorTypes, ErrorValues } from './types'; + +function getMessageAndTypeFromId({ + messageId, + values, +}: { + messageId: K; + values: ErrorValues; +}): { message: string; type?: 'error' | 'warning' } { + // Use a less strict type instead of doing a typecast on each message type + const out = values as unknown as Record; + // i18n validation wants to the values prop to be declared inline, so need to unpack and redeclare again all props + switch (messageId) { + case 'wrongArgumentType': + return { + message: i18n.translate('monaco.esql.validation.wrongArgumentType', { + defaultMessage: + 'Argument of [{name}] must be [{argType}], found value [{value}] type [{givenType}]', + values: { + name: out.name, + argType: out.argType, + value: out.value, + givenType: out.givenType, + }, + }), + }; + case 'unknownColumn': + return { + message: i18n.translate('monaco.esql.validation.unknownColumn', { + defaultMessage: 'Unknown column [{name}]', + values: { name: out.name }, + }), + }; + case 'unknownIndex': + return { + message: i18n.translate('monaco.esql.validation.unknownIndex', { + defaultMessage: 'Unknown index [{name}]', + values: { name: out.name }, + }), + }; + case 'unknownFunction': + return { + message: i18n.translate('monaco.esql.validation.missingFunction', { + defaultMessage: 'Unknown function [{name}]', + values: { name: out.name }, + }), + }; + case 'wrongArgumentNumber': + return { + message: i18n.translate('monaco.esql.validation.wrongArgumentNumber', { + defaultMessage: + 'Error building [{fn}]: expects exactly {numArgs, plural, one {one argument} other {{numArgs} arguments}}, passed {passedArgs} instead.', + values: { fn: out.fn, numArgs: out.numArgs, passedArgs: out.passedArgs }, + }), + }; + case 'noNestedArgumentSupport': + return { + message: i18n.translate('monaco.esql.validation.noNestedArgumentSupport', { + defaultMessage: + "Aggregate function's parameters must be an attribute or literal; found [{name}] of type [{argType}]", + values: { name: out.name, argType: out.argType }, + }), + }; + case 'shadowFieldType': + return { + message: i18n.translate('monaco.esql.validation.typeOverwrite', { + defaultMessage: + 'Column [{field}] of type {fieldType} has been overwritten as new type: {newType}', + values: { field: out.field, fieldType: out.fieldType, newType: out.newType }, + }), + type: 'warning', + }; + case 'unsupportedColumnTypeForCommand': + return { + message: i18n.translate('monaco.esql.validation.unsupportedColumnTypeForCommand', { + defaultMessage: + '{command} only supports {type} {typeCount, plural, one {type} other {types}} values, found [{column}] of type {givenType}', + values: { + command: out.command, + type: out.type, + typeCount: out.typeCount, + column: out.column, + givenType: out.givenType, + }, + }), + }; + case 'unknownOption': + return { + message: i18n.translate('monaco.esql.validation.unknownOption', { + defaultMessage: 'Invalid option for {command}: [{option}]', + values: { + command: out.command, + option: out.option, + }, + }), + }; + case 'unsupportedFunction': + return { + message: i18n.translate('monaco.esql.validation.unsupportedFunction', { + defaultMessage: '{command} does not support function {name}', + values: { + command: out.command, + name: out.name, + }, + }), + }; + case 'unknownInterval': + return { + message: i18n.translate('monaco.esql.validation.unknownInterval', { + defaultMessage: `Unexpected time interval qualifier: '{value}'`, + values: { + value: out.value, + }, + }), + }; + case 'unsupportedTypeForCommand': + return { + message: i18n.translate('monaco.esql.validation.unsupportedTypeForCommand', { + defaultMessage: '{command} does not support [{type}] in expression [{value}]', + values: { + command: out.command, + type: out.type, + value: out.value, + }, + }), + }; + case 'unknownPolicy': + return { + message: i18n.translate('monaco.esql.validation.unknownPolicy', { + defaultMessage: 'Unknown policy [{name}]', + values: { + name: out.name, + }, + }), + }; + case 'unknownAggregateFunction': + return { + message: i18n.translate('monaco.esql.validation.unknowAggregateFunction', { + defaultMessage: '{command} expects an aggregate function, found [{value}]', + values: { + command: out.command, + value: out.value, + }, + }), + }; + case 'wildcardNotSupportedForCommand': + return { + message: i18n.translate('monaco.esql.validation.wildcardNotSupportedForCommand', { + defaultMessage: 'Using wildcards (*) in {command} is not allowed [{value}]', + values: { + command: out.command, + value: out.value, + }, + }), + }; + case 'noWildcardSupportAsArg': + return { + message: i18n.translate('monaco.esql.validation.wildcardNotSupportedForFunction', { + defaultMessage: 'Using wildcards (*) in {name} is not allowed', + values: { + name: out.name, + }, + }), + }; + case 'ccsNotSupportedForCommand': + return { + message: i18n.translate('monaco.esql.validation.ccsNotSupportedForCommand', { + defaultMessage: 'ES|QL does not yet support querying remote indices [{value}]', + values: { + value: out.value, + }, + }), + }; + case 'unsupportedFieldType': + return { + message: i18n.translate('monaco.esql.validation.unsupportedFieldType', { + defaultMessage: + 'Field [{field}] cannot be retrieved, it is unsupported or not indexed; returning null', + values: { + field: out.field, + }, + }), + type: 'warning', + }; + } + return { message: '' }; +} + +export function getMessageFromId({ + locations, + ...payload +}: { + messageId: K; + values: ErrorValues; + locations: ESQLLocation; +}): ESQLMessage { + const { message, type = 'error' } = getMessageAndTypeFromId(payload); + return createMessage(type, message, locations); +} + +export function createMessage(type: 'error' | 'warning', message: string, location: ESQLLocation) { + return { + type, + text: message, + location, + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts new file mode 100644 index 0000000000000..51015e0d8d09d --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/helpers.ts @@ -0,0 +1,21 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { ESQLAst } from '../types'; +import type { ESQLPolicy } from './types'; + +export function buildQueryForFieldsFromSource(queryString: string, ast: ESQLAst) { + const firstCommand = ast[0]; + return queryString.substring(0, firstCommand.location.max + 1); +} + +export function buildQueryForFieldsInPolicies(policies: ESQLPolicy[]) { + return `from ${policies + .flatMap(({ sourceIndices }) => sourceIndices) + .join(', ')} | keep ${policies.flatMap(({ enrichFields }) => enrichFields).join(', ')}`; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts new file mode 100644 index 0000000000000..24c6de0f7db6f --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/resources.ts @@ -0,0 +1,85 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { nonNullable } from '../ast_helpers'; +import { createMapFromList, isSourceItem } from '../shared/helpers'; +import { + getFieldsByTypeHelper, + getPolicyHelper, + getSourcesHelper, +} from '../shared/resources_helpers'; +import type { ESQLCallbacks } from '../shared/types'; +import type { ESQLCommand } from '../types'; +import { buildQueryForFieldsFromSource, buildQueryForFieldsInPolicies } from './helpers'; +import type { ESQLRealField, ESQLPolicy } from './types'; + +export async function retrieveFields( + queryString: string, + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.length < 1) { + return new Map(); + } + if (commands[0].name === 'row') { + return new Map(); + } + const customQuery = buildQueryForFieldsFromSource(queryString, commands); + return await getFieldsByTypeHelper(customQuery, callbacks).getFieldsMap(); +} + +export async function retrievePolicies( + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.every(({ name }) => name !== 'enrich')) { + return new Map(); + } + + const policies = await getPolicyHelper(callbacks).getPolicies(); + return createMapFromList(policies); +} + +export async function retrieveSources( + commands: ESQLCommand[], + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks || commands.length < 1) { + return new Set(); + } + if (['row', 'show'].includes(commands[0].name)) { + return new Set(); + } + const sources = await getSourcesHelper(callbacks)(); + return new Set(sources.map(({ name }) => name)); +} + +export async function retrievePoliciesFields( + commands: ESQLCommand[], + policies: Map, + callbacks?: ESQLCallbacks +): Promise> { + if (!callbacks) { + return new Map(); + } + const enrichCommands = commands.filter(({ name }) => name === 'enrich'); + if (!enrichCommands.length) { + return new Map(); + } + const policyNames = enrichCommands + .map(({ args }) => (isSourceItem(args[0]) ? args[0].name : undefined)) + .filter(nonNullable); + if (!policyNames.every((name) => policies.has(name))) { + return new Map(); + } + + const customQuery = buildQueryForFieldsInPolicies( + policyNames.map((name) => policies.get(name)) as ESQLPolicy[] + ); + return await getFieldsByTypeHelper(customQuery, callbacks).getFieldsMap(); +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts new file mode 100644 index 0000000000000..07b7e504ab1be --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/types.ts @@ -0,0 +1,127 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { EditorError } from '../../../../types'; +import { ESQLMessage, ESQLLocation } from '../types'; + +export interface ESQLVariable { + name: string; + type: string; + location: ESQLLocation; +} + +export interface ESQLRealField { + name: string; + type: string; +} + +export interface ESQLPolicy { + name: string; + sourceIndices: string[]; + matchField: string; + enrichFields: string[]; +} + +export interface ReferenceMaps { + sources: Set; + variables: Map; + fields: Map; + policies: Map; +} + +export interface ValidationErrors { + wrongArgumentType: { + message: string; + type: { + name: string; + argType: string; + value: string | number | Date; + givenType: string; + }; + }; + wrongArgumentNumber: { + message: string; + type: { fn: string; numArgs: number; passedArgs: number }; + }; + unknownColumn: { + message: string; + type: { name: string | number }; + }; + unknownFunction: { + message: string; + type: { name: string }; + }; + unknownIndex: { + message: string; + type: { name: string }; + }; + noNestedArgumentSupport: { + message: string; + type: { name: string; argType: string }; + }; + unsupportedFunction: { + message: string; + type: { name: string; command: string }; + }; + shadowFieldType: { + message: string; + type: { field: string; fieldType: string; newType: string }; + }; + unsupportedColumnTypeForCommand: { + message: string; + type: { command: string; type: string; typeCount: number; givenType: string; column: string }; + }; + unknownOption: { + message: string; + type: { command: string; option: string }; + }; + wrongOptionArgumentType: { + message: string; + type: { command: string; option: string; type: string; givenValue: string }; + }; + unknownInterval: { + message: string; + type: { value: string }; + }; + unsupportedTypeForCommand: { + message: string; + type: { command: string; value: string; type: string }; + }; + unknownPolicy: { + message: string; + type: { name: string }; + }; + unknownAggregateFunction: { + message: string; + type: { command: string; value: string }; + }; + wildcardNotSupportedForCommand: { + message: string; + type: { command: string; value: string }; + }; + noWildcardSupportAsArg: { + message: string; + type: { name: string }; + }; + ccsNotSupportedForCommand: { + message: string; + type: { value: string }; + }; + unsupportedFieldType: { + message: string; + type: { field: string }; + }; +} + +export type ErrorTypes = keyof ValidationErrors; +export type ErrorValues = ValidationErrors[K]['type']; + +export interface ValidationResult { + errors: Array; + warnings: ESQLMessage[]; +} diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts new file mode 100644 index 0000000000000..8da25c2b46b8a --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.test.ts @@ -0,0 +1,1440 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { CharStreams } from 'antlr4ts'; +import { getParser, ROOT_STATEMENT } from '../../antlr_facade'; +// import { mathCommandDefinition } from '../../autocomplete/autocomplete_definitions'; +// import { getDurationItemsWithQuantifier } from '../../autocomplete/helpers'; +import { AstListener } from '../ast_factory'; +import { validateAst } from './validation'; +import { ESQLAst } from '../types'; +import { ESQLErrorListener } from '../../monaco/esql_error_listener'; +import { evalFunctionsDefinitions } from '../definitions/functions'; +import { getFunctionSignatures } from '../definitions/helpers'; +import { FunctionDefinition } from '../definitions/types'; +import { chronoLiterals, timeLiterals } from '../definitions/literals'; +import { statsAggregationFunctionDefinitions } from '../definitions/aggs'; +import capitalize from 'lodash/capitalize'; +import { EditorError } from '../../../../types'; + +function getCallbackMocks() { + return { + getFieldsFor: jest.fn(async ({ query }) => + /enrich/.test(query) + ? [ + { name: 'otherField', type: 'string' }, + { name: 'yetAnotherField', type: 'number' }, + ] + : /unsupported_index/.test(query) + ? [{ name: 'unsupported_field', type: 'unsupported' }] + : [ + ...['string', 'number', 'date', 'boolean', 'ip'].map((type) => ({ + name: `${type}Field`, + type, + })), + { name: 'any#Char$ field', type: 'number' }, + { name: 'kubernetes.something.something', type: 'number' }, + { + name: `listField`, + type: `list`, + }, + { name: '@timestamp', type: 'date' }, + ] + ), + getSources: jest.fn(async () => + ['a', 'index', 'otherIndex', '.secretIndex', 'my-index', 'unsupported_index'].map((name) => ({ + name, + hidden: name.startsWith('.'), + })) + ), + getPolicies: jest.fn(async () => [ + { + name: 'policy', + sourceIndices: ['enrichIndex1'], + matchField: 'otherStringField', + enrichFields: ['otherField', 'yetAnotherField'], + }, + ]), + }; +} + +const toDoubleSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_double')!; +const toStringSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_string')!; +const toDateSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_datetime')!; +const toBooleanSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_boolean')!; +const toIpSignature = evalFunctionsDefinitions.find(({ name }) => name === 'to_ip')!; + +const toAvgSignature = statsAggregationFunctionDefinitions.find(({ name }) => name === 'avg')!; + +const nestedFunctions = { + number: prepareNestedFunction(toDoubleSignature), + string: prepareNestedFunction(toStringSignature), + date: prepareNestedFunction(toDateSignature), + boolean: prepareNestedFunction(toBooleanSignature), + ip: prepareNestedFunction(toIpSignature), +}; + +const literals = { + chrono_literal: chronoLiterals[0].name, + time_literal: timeLiterals[0].name, +}; +function getLiteralType(typeString: 'chrono_literal' | 'time_literal') { + if (typeString === 'chrono_literal') { + return literals[typeString]; + } + return `1 ${literals[typeString]}`; +} +function getFieldName( + typeString: 'string' | 'number' | 'date' | 'boolean' | 'ip', + { useNestedFunction, isStats }: { useNestedFunction: boolean; isStats: boolean } +) { + if (useNestedFunction && isStats) { + return prepareNestedFunction(toAvgSignature); + } + return useNestedFunction ? nestedFunctions[typeString] : `${typeString}Field`; +} + +function getMultiValue(type: 'string[]' | 'number[]' | 'boolean[]' | 'any[]') { + if (/string|any/.test(type)) { + return `["a", "b", "c"]`; + } + if (/number/.test(type)) { + return `[1, 2, 3]`; + } + return `[true, false]`; +} + +function prepareNestedFunction(fnSignature: FunctionDefinition): string { + return getFunctionSignatures( + { + ...fnSignature, + signatures: [ + { + ...fnSignature?.signatures[0]!, + params: getFieldMapping(fnSignature?.signatures[0]!.params), + }, + ], + }, + { withTypes: false } + )[0].declaration; +} +function getFieldMapping( + params: FunctionDefinition['signatures'][number]['params'], + { useNestedFunction, useLiterals }: { useNestedFunction: boolean; useLiterals: boolean } = { + useNestedFunction: false, + useLiterals: true, + } +) { + return params.map(({ name: _name, type, ...rest }) => { + const typeString: string = type; + if (['string', 'number', 'date', 'boolean', 'ip'].includes(typeString)) { + return { + name: getFieldName(typeString as 'string' | 'number' | 'date' | 'boolean' | 'ip', { + useNestedFunction, + isStats: !useLiterals, + }), + type, + ...rest, + }; + } + if (/literal$/.test(typeString) && useLiterals) { + return { + name: getLiteralType(typeString as 'chrono_literal' | 'time_literal'), + type, + ...rest, + }; + } + if (['string[]', 'number[]', 'boolean[]', 'any[]'].includes(typeString)) { + return { + name: getMultiValue(typeString as 'string[]' | 'number[]' | 'boolean[]' | 'any[]'), + type, + ...rest, + }; + } + return { name: 'stringField', type, ...rest }; + }); +} + +describe('validation logic', () => { + const getAstAndErrors = async ( + text: string | undefined + ): Promise<{ + errors: EditorError[]; + ast: ESQLAst; + }> => { + if (text == null) { + return { ast: [], errors: [] }; + } + const errorListener = new ESQLErrorListener(); + const parseListener = new AstListener(); + const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); + + parser[ROOT_STATEMENT](); + + return { ...parseListener.getAst(), errors: errorListener.getErrors() }; + }; + + function testErrorsAndWarningsFn( + statement: string, + expectedErrors: string[] = [], + expectedWarnings: string[] = [], + { only, skip }: { only?: boolean; skip?: boolean } = {} + ) { + const testFn = only ? it.only : skip ? it.skip : it; + testFn( + `${statement} => ${expectedErrors.length} errors, ${expectedWarnings.length} warnings`, + async () => { + const callbackMocks = getCallbackMocks(); + const { warnings, errors } = await validateAst(statement, getAstAndErrors, callbackMocks); + expect(errors.map((e) => ('message' in e ? e.message : e.text))).toEqual(expectedErrors); + expect(warnings.map((w) => w.text)).toEqual(expectedWarnings); + } + ); + } + + type TestArgs = [string, string[], string[]?]; + + // Make only and skip work with our custom wrapper + const testErrorsAndWarnings = Object.assign(testErrorsAndWarningsFn, { + skip: (...args: TestArgs) => { + const warningArgs = [[]].slice(args.length - 2); + return testErrorsAndWarningsFn( + ...((args.length > 1 ? [...args, ...warningArgs] : args) as TestArgs), + { + skip: true, + } + ); + }, + only: (...args: TestArgs) => { + const warningArgs = [[]].slice(args.length - 2); + return testErrorsAndWarningsFn( + ...((args.length > 1 ? [...args, ...warningArgs] : args) as TestArgs), + { + only: true, + } + ); + }, + }); + + describe('ESQL query should start with a source command', () => { + ['eval', 'stats', 'rename', 'limit', 'keep', 'drop', 'mv_expand', 'dissect', 'grok'].map( + (command) => + testErrorsAndWarnings(command, [ + `SyntaxError: expected {FROM, ROW, SHOW} but found "${command}"`, + ]) + ); + }); + + describe('from', () => { + testErrorsAndWarnings('f', ['SyntaxError: expected {FROM, ROW, SHOW} but found "f"']); + testErrorsAndWarnings(`from `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from index,`, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from assignment = 1`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "="', + 'Unknown index [assignment]', + ]); + testErrorsAndWarnings(`from index`, []); + testErrorsAndWarnings(`FROM index`, []); + testErrorsAndWarnings(`FrOm index`, []); + testErrorsAndWarnings('from `index`', []); + + testErrorsAndWarnings(`from index, otherIndex`, []); + testErrorsAndWarnings(`from index, missingIndex`, ['Unknown index [missingIndex]']); + testErrorsAndWarnings(`from fn()`, ['Unknown index [fn()]']); + testErrorsAndWarnings(`from average()`, ['Unknown index [average()]']); + testErrorsAndWarnings(`from index [METADATA _id]`, []); + testErrorsAndWarnings(`from index [metadata _id]`, []); + + testErrorsAndWarnings(`from index [METADATA _id, _source]`, []); + testErrorsAndWarnings(`from index [metadata _id, _source] [METADATA _id2]`, [ + 'SyntaxError: expected {, PIPE} but found "["', + ]); + testErrorsAndWarnings(`from index metadata _id`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "metadata"', + ]); + testErrorsAndWarnings(`from index (metadata _id)`, [ + 'SyntaxError: expected {, PIPE, COMMA, OPENING_BRACKET} but found "(metadata"', + ]); + testErrorsAndWarnings(`from ind*, other*`, []); + testErrorsAndWarnings(`from index*`, []); + testErrorsAndWarnings(`from *ex`, []); + testErrorsAndWarnings(`from in*ex`, []); + testErrorsAndWarnings(`from ind*ex`, []); + testErrorsAndWarnings(`from indexes*`, ['Unknown index [indexes*]']); + + testErrorsAndWarnings(`from remote-*:indexes*`, [ + 'ES|QL does not yet support querying remote indices [remote-*:indexes*]', + ]); + testErrorsAndWarnings(`from remote-*:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-*:indexes]', + ]); + testErrorsAndWarnings(`from remote-ccs:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from a, remote-ccs:indexes`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from remote-ccs:indexes [METADATA _id]`, [ + 'ES|QL does not yet support querying remote indices [remote-ccs:indexes]', + ]); + testErrorsAndWarnings(`from *:indexes [METADATA _id]`, [ + 'ES|QL does not yet support querying remote indices [*:indexes]', + ]); + testErrorsAndWarnings('from .secretIndex', []); + testErrorsAndWarnings('from my-index', []); + }); + + describe('row', () => { + testErrorsAndWarnings('row', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('row missing_column', ['Unknown column [missing_column]']); + testErrorsAndWarnings('row fn()', ['Unknown function [fn]']); + testErrorsAndWarnings('row missing_column, missing_column2', [ + 'Unknown column [missing_column]', + 'Unknown column [missing_column2]', + ]); + testErrorsAndWarnings('row a=1', []); + testErrorsAndWarnings('row a=1, missing_column', ['Unknown column [missing_column]']); + testErrorsAndWarnings('row a=1, b = average()', ['Unknown function [average]']); + testErrorsAndWarnings('row a = [1, 2, 3]', []); + testErrorsAndWarnings('row a = (1)', []); + testErrorsAndWarnings('row a = (1, 2, 3)', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ","', + "SyntaxError: extraneous input ')' expecting ", + ]); + + testErrorsAndWarnings('row var = 1 in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 5 in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 5 not in (1, 2, 3)', []); + testErrorsAndWarnings('row var = 1 in (1, 2, 3, round(5))', []); + testErrorsAndWarnings('row var = "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = "a" not in ("a", "b", "c")', []); + testErrorsAndWarnings('row var = 1 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 not in ("a", "b", "c")', [ + 'Argument of [not_in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('row var = 5 not in (1, 2, 3, "a")', [ + 'Argument of [not_in] must be [number[]], found value [(1, 2, 3, "a")] type [(number, number, number, string)]', + ]); + + function tweakSignatureForRowCommand(signature: string) { + /** + * row has no access to any field, so replace it with literal + * or functions (for dates) + */ + return signature + .replace(/numberField/g, '5') + .replace(/stringField/g, '"a"') + .replace(/dateField/g, 'now()') + .replace(/booleanField/g, 'true') + .replace(/ipField/g, 'to_ip("127.0.0.1")'); + } + + for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + const signatureStringCorrect = tweakSignatureForRowCommand( + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureStringCorrect}`, []); + testErrorsAndWarnings(`row ${signatureStringCorrect}`); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = tweakSignatureForRowCommand( + getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: true, + }); + const signatureString = tweakSignatureForRowCommand( + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + ); + + testErrorsAndWarnings(`row var = ${signatureString}`); + + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = canBeFieldButNotString || isLiteralType ? '"a"' : '5'; + return { name: nameValue, type, ...rest }; + }); + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name === '5' ? 'number' : 'string'}]` + ); + const wrongSignatureString = tweakSignatureForRowCommand( + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + ); + testErrorsAndWarnings(`row var = ${wrongSignatureString}`, expectedErrors); + } + } + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`row var = 5 ${op} 0`, []); + testErrorsAndWarnings(`row var = NOT 5 ${op} 0`, []); + testErrorsAndWarnings(`row var = (numberField ${op} 0)`, []); + testErrorsAndWarnings(`row var = (NOT (5 ${op} 0))`, []); + testErrorsAndWarnings(`row var = "a" ${op} 0`, [ + `Argument of [${op}] must be [number], found value ["a"] type [string]`, + ]); + } + for (const op of ['+', '-', '*', '/', '%']) { + testErrorsAndWarnings(`row var = 1 ${op} 1`, []); + testErrorsAndWarnings(`row var = (5 ${op} 1)`, []); + } + + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`row var = "a" ${op} "?a"`, []); + testErrorsAndWarnings(`row var = "a" NOT ${op} "?a"`, []); + testErrorsAndWarnings(`row var = NOT "a" ${op} "?a"`, []); + testErrorsAndWarnings(`row var = NOT "a" NOT ${op} "?a"`, []); + testErrorsAndWarnings(`row var = 5 ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = 5 NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = NOT 5 ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [5] type [number]`, + ]); + testErrorsAndWarnings(`row var = NOT 5 NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [5] type [number]`, + ]); + } + + describe('date math', () => { + testErrorsAndWarnings('row 1 anno', [ + 'Row does not support [date_period] in expression [1 anno]', + ]); + testErrorsAndWarnings('row var = 1 anno', ["Unexpected time interval qualifier: 'anno'"]); + testErrorsAndWarnings('row now() + 1 anno', ["Unexpected time interval qualifier: 'anno'"]); + for (const timeLiteral of timeLiterals) { + testErrorsAndWarnings(`row 1 ${timeLiteral.name}`, [ + `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + testErrorsAndWarnings(`row 1 ${timeLiteral.name}`, [ + `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + + // this is not possible for now + // testErrorsAndWarnings(`row var = 1 ${timeLiteral.name}`, [ + // `Row does not support [date_period] in expression [1 ${timeLiteral.name}]`, + // ]); + testErrorsAndWarnings(`row var = now() - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`row var = now() - 1 ${timeLiteral.name.toUpperCase()}`, []); + testErrorsAndWarnings(`row var = now() - 1 ${capitalize(timeLiteral.name)}`, []); + testErrorsAndWarnings(`row var = now() + 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`row 1 ${timeLiteral.name} + 1 year`, [ + `Argument of [+] must be [date], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + for (const op of ['*', '/', '%']) { + testErrorsAndWarnings(`row var = now() ${op} 1 ${timeLiteral.name}`, [ + `Argument of [${op}] must be [number], found value [now()] type [date]`, + `Argument of [${op}] must be [number], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + } + } + }); + }); + + describe('show', () => { + testErrorsAndWarnings('show', ['SyntaxError: expected {SHOW} but found ""']); + testErrorsAndWarnings('show functions', []); + testErrorsAndWarnings('show info', []); + testErrorsAndWarnings('show functions blah', [ + "SyntaxError: extraneous input 'blah' expecting ", + ]); + }); + + describe('limit', () => { + testErrorsAndWarnings('from index | limit ', [ + `SyntaxError: missing INTEGER_LITERAL at ''`, + ]); + testErrorsAndWarnings('from index | limit 4 ', []); + testErrorsAndWarnings('from index | limit 4.5', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "4.5"', + ]); + testErrorsAndWarnings('from index | limit a', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "a"', + ]); + testErrorsAndWarnings('from index | limit numberField', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "numberField"', + ]); + testErrorsAndWarnings('from index | limit stringField', [ + 'SyntaxError: expected {INTEGER_LITERAL} but found "stringField"', + ]); + testErrorsAndWarnings('from index | limit 4', []); + }); + + describe('keep', () => { + testErrorsAndWarnings('from index | keep ', [ + `SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`, + ]); + testErrorsAndWarnings('from index | keep stringField, numberField, dateField', []); + testErrorsAndWarnings('from index | keep `stringField`, `numberField`, `dateField`', []); + testErrorsAndWarnings('from index | keep 4.5', ['Unknown column [4.5]']); + testErrorsAndWarnings('from index | keep missingField, numberField, dateField', [ + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from index | keep `any#Char$ field`', []); + testErrorsAndWarnings( + 'from index | project ', + [`SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | project stringField, numberField, dateField', + [], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | PROJECT stringField, numberField, dateField', + [], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings( + 'from index | project missingField, numberField, dateField', + ['Unknown column [missingField]'], + ['PROJECT command is no longer supported, please use KEEP instead'] + ); + testErrorsAndWarnings('from index | keep s*', []); + testErrorsAndWarnings('from index | keep *Field', []); + testErrorsAndWarnings('from index | keep s*Field', []); + testErrorsAndWarnings('from index | keep string*Field', []); + testErrorsAndWarnings('from index | keep s*, n*', []); + testErrorsAndWarnings('from index | keep m*', ['Unknown column [m*]']); + testErrorsAndWarnings('from index | keep *m', ['Unknown column [*m]']); + testErrorsAndWarnings('from index | keep d*m', ['Unknown column [d*m]']); + testErrorsAndWarnings( + 'from unsupported_index | keep unsupported_field', + [], + [ + 'Field [unsupported_field] cannot be retrieved, it is unsupported or not indexed; returning null', + ] + ); + }); + + describe('drop', () => { + testErrorsAndWarnings('from index | drop ', [ + `SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''`, + ]); + testErrorsAndWarnings('from index | drop stringField, numberField, dateField', []); + testErrorsAndWarnings('from index | drop 4.5', ['Unknown column [4.5]']); + testErrorsAndWarnings('from index | drop missingField, numberField, dateField', [ + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from index | drop `any#Char$ field`', []); + testErrorsAndWarnings('from index | drop s*', []); + testErrorsAndWarnings('from index | drop *Field', []); + testErrorsAndWarnings('from index | drop s*Field', []); + testErrorsAndWarnings('from index | drop string*Field', []); + testErrorsAndWarnings('from index | drop s*, n*', []); + testErrorsAndWarnings('from index | drop m*', ['Unknown column [m*]']); + testErrorsAndWarnings('from index | drop *m', ['Unknown column [*m]']); + testErrorsAndWarnings('from index | drop d*m', ['Unknown column [d*m]']); + testErrorsAndWarnings('from index | drop *', ['Removing all fields is not allowed [*]']); + testErrorsAndWarnings('from index | drop stringField, *', [ + 'Removing all fields is not allowed [*]', + ]); + testErrorsAndWarnings( + 'from index | drop @timestamp', + [], + ['Drop [@timestamp] will remove all time filters to the search results'] + ); + testErrorsAndWarnings( + 'from index | drop stringField, @timestamp', + [], + ['Drop [@timestamp] will remove all time filters to the search results'] + ); + }); + + describe('mv_expand', () => { + testErrorsAndWarnings('from a | mv_expand ', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | mv_expand stringField', [ + 'Mv_expand only supports list type values, found [stringField] of type string', + ]); + + testErrorsAndWarnings(`from a | mv_expand listField`, []); + + testErrorsAndWarnings('from a | mv_expand listField, b', [ + 'SyntaxError: expected {, PIPE} but found ","', + ]); + + testErrorsAndWarnings('row a = "a" | mv_expand a', [ + 'Mv_expand only supports list type values, found [a] of type string', + ]); + testErrorsAndWarnings('row a = [1, 2, 3] | mv_expand a', []); + }); + + describe('rename', () => { + testErrorsAndWarnings('from a | rename', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename stringField', [ + 'SyntaxError: expected {AS} but found ""', + ]); + testErrorsAndWarnings('from a | rename a', [ + 'SyntaxError: expected {AS} but found ""', + 'Unknown column [a]', + ]); + testErrorsAndWarnings('from a | rename stringField as', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename missingField as', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [missingField]', + ]); + testErrorsAndWarnings('from a | rename stringField as b', []); + testErrorsAndWarnings('from a | rename stringField AS b', []); + testErrorsAndWarnings('from a | rename stringField As b', []); + testErrorsAndWarnings('from a | rename stringField As b, b AS c', []); + testErrorsAndWarnings('from a | rename fn() as a', [ + 'Unknown column [fn()]', + 'Unknown column [a]', + ]); + testErrorsAndWarnings('from a | eval numberField + 1 | rename `numberField + 1` as a', []); + testErrorsAndWarnings( + 'from a | stats avg(numberField) | rename `avg(numberField)` as avg0', + [] + ); + testErrorsAndWarnings('from a | eval numberField + 1 | rename `numberField + 1` as ', [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | rename s* as strings', [ + 'Using wildcards (*) in rename is not allowed [s*]', + 'Unknown column [strings]', + ]); + }); + + describe('dissect', () => { + testErrorsAndWarnings('from a | dissect', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | dissect stringField', [ + "SyntaxError: missing STRING at ''", + ]); + testErrorsAndWarnings('from a | dissect stringField 2', [ + 'SyntaxError: expected {STRING, DOT} but found "2"', + ]); + testErrorsAndWarnings('from a | dissect stringField .', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + 'Unknown column [stringField.]', + ]); + testErrorsAndWarnings('from a | dissect stringField %a', [ + "SyntaxError: missing STRING at '%'", + ]); + // Do not try to validate the dissect pattern string + testErrorsAndWarnings('from a | dissect stringField "%{a}"', []); + testErrorsAndWarnings('from a | dissect numberField "%{a}"', [ + 'Dissect only supports string type values, found [numberField] of type number', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option ', [ + 'SyntaxError: expected {ASSIGN} but found ""', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option = ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET} but found ""', + 'Invalid option for dissect: [option]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" option = 1', [ + 'Invalid option for dissect: [option]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" append_separator = "-"', []); + testErrorsAndWarnings('from a | dissect stringField "%{a}" ignore_missing = true', [ + 'Invalid option for dissect: [ignore_missing]', + ]); + testErrorsAndWarnings('from a | dissect stringField "%{a}" append_separator = true', [ + 'Invalid value for dissect append_separator: expected a string, but was [true]', + ]); + // testErrorsAndWarnings('from a | dissect s* "%{a}"', [ + // 'Using wildcards (*) in dissect is not allowed [s*]', + // ]); + }); + + describe('grok', () => { + testErrorsAndWarnings('from a | grok', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | grok stringField', ["SyntaxError: missing STRING at ''"]); + testErrorsAndWarnings('from a | grok stringField 2', [ + 'SyntaxError: expected {STRING, DOT} but found "2"', + ]); + testErrorsAndWarnings('from a | grok stringField .', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + 'Unknown column [stringField.]', + ]); + testErrorsAndWarnings('from a | grok stringField %a', ["SyntaxError: missing STRING at '%'"]); + // Do not try to validate the grok pattern string + testErrorsAndWarnings('from a | grok stringField "%{a}"', []); + testErrorsAndWarnings('from a | grok numberField "%{a}"', [ + 'Grok only supports string type values, found [numberField] of type number', + ]); + // testErrorsAndWarnings('from a | grok s* "%{a}"', [ + // 'Using wildcards (*) in grok is not allowed [s*]', + // ]); + }); + + describe('where', () => { + testErrorsAndWarnings('from a | where b', ['Unknown column [b]']); + for (const cond of ['true', 'false']) { + testErrorsAndWarnings(`from a | where ${cond}`, []); + testErrorsAndWarnings(`from a | where NOT ${cond}`, []); + } + for (const nValue of ['1', '+1', '1 * 1', '-1', '1 / 1']) { + testErrorsAndWarnings(`from a | where ${nValue} > 0`, []); + testErrorsAndWarnings(`from a | where NOT ${nValue} > 0`, []); + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`from a | where numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | where NOT numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | where (numberField ${op} 0)`, []); + testErrorsAndWarnings(`from a | where (NOT (numberField ${op} 0))`, []); + testErrorsAndWarnings(`from a | where 1 ${op} 0`, []); + testErrorsAndWarnings(`from a | eval stringField ${op} 0`, [ + `Argument of [${op}] must be [number], found value [stringField] type [string]`, + ]); + } + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`from a | where stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where NOT stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where NOT stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | where numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where NOT numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | where NOT numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + } + + testErrorsAndWarnings(`from a | where cidr_match(ipField)`, [ + `Error building [cidr_match]: expects exactly 2 arguments, passed 1 instead.`, + ]); + testErrorsAndWarnings( + `from a | eval cidr = "172.0.0.1/30" | where cidr_match(ipField, "172.0.0.1/30", cidr)`, + [] + ); + + // Test that all functions work in where + const numericOrStringFunctions = evalFunctionsDefinitions.filter(({ name, signatures }) => { + return signatures.some( + ({ returnType, params }) => + ['number', 'string'].includes(returnType) && + params.every(({ type }) => ['number', 'string'].includes(type)) + ); + }); + for (const { name, signatures, ...rest } of numericOrStringFunctions) { + const supportedSignatures = signatures.filter(({ returnType }) => + ['number', 'string'].includes(returnType) + ); + for (const { params, returnType } of supportedSignatures) { + const correctMapping = params + .filter(({ optional }) => !optional) + .map(({ type }) => + ['number', 'string'].includes(Array.isArray(type) ? type.join(', ') : type) + ? { name: `${type}Field`, type } + : { name: `numberField`, type } + ); + testErrorsAndWarnings( + `from a | where ${returnType !== 'number' ? 'length(' : ''}${ + // hijacking a bit this function to produce a function call + getFunctionSignatures( + { name, ...rest, signatures: [{ params: correctMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }${returnType !== 'number' ? ')' : ''} > 0`, + [] + ); + + // now test that validation is working also inside each function + // put a number field where a string is expected and viceversa + // then test an error is returned + const incorrectMapping = params + .filter(({ optional }) => !optional) + .map(({ type }) => + type === 'string' ? { name: `numberField`, type } : { name: 'stringField', type } + ); + + const expectedErrors = params + .filter(({ optional }) => !optional) + .map(({ name: argName, type }) => { + const actualValue = + type === 'string' + ? { name: `numberField`, type: 'number' } + : { name: 'stringField', type: 'string' }; + return `Argument of [${name}] must be [${type}], found value [${actualValue.name}] type [${actualValue.type}]`; + }); + testErrorsAndWarnings( + `from a | where ${returnType !== 'number' ? 'length(' : ''}${ + // hijacking a bit this function to produce a function call + getFunctionSignatures( + { name, ...rest, signatures: [{ params: incorrectMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }${returnType !== 'number' ? ')' : ''} > 0`, + expectedErrors + ); + } + } + }); + + describe('eval', () => { + testErrorsAndWarnings('from a | eval ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval stringField ', []); + testErrorsAndWarnings('from a | eval b = stringField', []); + testErrorsAndWarnings('from a | eval numberField + 1', []); + testErrorsAndWarnings('from a | eval numberField + ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval stringField + 1', [ + 'Argument of [+] must be [number], found value [stringField] type [string]', + ]); + testErrorsAndWarnings('from a | eval a=b', ['Unknown column [b]']); + testErrorsAndWarnings('from a | eval a=b, ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + 'Unknown column [b]', + ]); + testErrorsAndWarnings('from a | eval a=round', ['Unknown column [round]']); + testErrorsAndWarnings('from a | eval a=round(', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval a=round(numberField) ', []); + testErrorsAndWarnings('from a | eval a=round(numberField), ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | eval a=round(numberField) + round(numberField) ', []); + testErrorsAndWarnings('from a | eval a=round(numberField) + round(stringField) ', [ + 'Argument of [round] must be [number], found value [stringField] type [string]', + ]); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(stringField), numberField ', + ['Argument of [round] must be [number], found value [stringField] type [string]'] + ); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(numberField), numberField ', + [] + ); + testErrorsAndWarnings( + 'from a | eval a=round(numberField) + round(numberField), b = numberField ', + [] + ); + + for (const { name, alias, signatures, ...defRest } of evalFunctionsDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + testErrorsAndWarnings( + `from a | eval ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration; + + testErrorsAndWarnings(`from a | eval var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: true, + }); + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + }` + ); + + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = + canBeFieldButNotString || isLiteralType ? 'stringField' : 'numberField'; + return { name: nameValue, type, ...rest }; + }); + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name.replace('Field', '')}]` + ); + testErrorsAndWarnings( + `from a | eval ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }`, + expectedErrors + ); + } + + // test that wildcard won't work as arg + if (fieldMapping.length === 1) { + const fieldMappingWithWildcard = [...fieldMapping]; + fieldMappingWithWildcard[0].name = '*'; + + testErrorsAndWarnings( + `from a | eval var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithWildcard, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + [`Using wildcards (*) in ${name} is not allowed`] + ); + } + } + } + for (const op of ['>', '>=', '<', '<=', '==']) { + testErrorsAndWarnings(`from a | eval numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | eval NOT numberField ${op} 0`, []); + testErrorsAndWarnings(`from a | eval (numberField ${op} 0)`, []); + testErrorsAndWarnings(`from a | eval (NOT (numberField ${op} 0))`, []); + testErrorsAndWarnings(`from a | eval 1 ${op} 0`, []); + testErrorsAndWarnings(`from a | eval stringField ${op} 0`, [ + `Argument of [${op}] must be [number], found value [stringField] type [string]`, + ]); + } + for (const op of ['+', '-', '*', '/', '%']) { + testErrorsAndWarnings(`from a | eval numberField ${op} 1`, []); + testErrorsAndWarnings(`from a | eval (numberField ${op} 1)`, []); + testErrorsAndWarnings(`from a | eval 1 ${op} 1`, []); + } + for (const divideByZeroExpr of ['1/0', 'var = 1/0', '1 + 1/0']) { + testErrorsAndWarnings( + `from a | eval ${divideByZeroExpr}`, + [], + ['Cannot divide by zero: 1/0'] + ); + } + for (const divideByZeroExpr of ['1%0', 'var = 1%0', '1 + 1%0']) { + testErrorsAndWarnings( + `from a | eval ${divideByZeroExpr}`, + [], + ['Module by zero can return null value: 1/0'] + ); + } + for (const op of ['like', 'rlike']) { + testErrorsAndWarnings(`from a | eval stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval NOT stringField ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval NOT stringField NOT ${op} "?a"`, []); + testErrorsAndWarnings(`from a | eval numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval NOT numberField ${op} "?a"`, [ + `Argument of [${op}] must be [string], found value [numberField] type [number]`, + ]); + testErrorsAndWarnings(`from a | eval NOT numberField NOT ${op} "?a"`, [ + `Argument of [not_${op}] must be [string], found value [numberField] type [number]`, + ]); + } + // test lists + testErrorsAndWarnings('from a | eval 1 in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3)', []); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3, numberField)', []); + testErrorsAndWarnings('from a | eval 1 in (1, 2, 3, round(numberField))', []); + testErrorsAndWarnings('from a | eval "a" in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField not in ("a", "b", "c")', []); + testErrorsAndWarnings('from a | eval stringField not in ("a", "b", "c", stringField)', []); + testErrorsAndWarnings('from a | eval 1 in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField in ("a", "b", "c")', [ + 'Argument of [in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField not in ("a", "b", "c")', [ + 'Argument of [not_in] must be [number[]], found value [("a", "b", "c")] type [(string, string, string)]', + ]); + testErrorsAndWarnings('from a | eval numberField not in (1, 2, 3, stringField)', [ + 'Argument of [not_in] must be [number[]], found value [(1, 2, 3, stringField)] type [(number, number, number, string)]', + ]); + + testErrorsAndWarnings('from a | eval avg(numberField)', ['Eval does not support function avg']); + testErrorsAndWarnings('from a | stats avg(numberField) | eval `avg(numberField)` + 1', []); + + describe('date math', () => { + testErrorsAndWarnings('from a | eval 1 anno', [ + 'Eval does not support [date_period] in expression [1 anno]', + ]); + testErrorsAndWarnings('from a | eval var = 1 anno', [ + "Unexpected time interval qualifier: 'anno'", + ]); + testErrorsAndWarnings('from a | eval now() + 1 anno', [ + "Unexpected time interval qualifier: 'anno'", + ]); + for (const timeLiteral of timeLiterals) { + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name}`, [ + `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name}`, [ + `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + ]); + + // this is not possible for now + // testErrorsAndWarnings(`from a | eval var = 1 ${timeLiteral.name}`, [ + // `Eval does not support [date_period] in expression [1 ${timeLiteral.name}]`, + // ]); + testErrorsAndWarnings(`from a | eval var = now() - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`from a | eval var = dateField - 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings( + `from a | eval var = dateField - 1 ${timeLiteral.name.toUpperCase()}`, + [] + ); + testErrorsAndWarnings( + `from a | eval var = dateField - 1 ${capitalize(timeLiteral.name)}`, + [] + ); + testErrorsAndWarnings(`from a | eval var = dateField + 1 ${timeLiteral.name}`, []); + testErrorsAndWarnings(`from a | eval 1 ${timeLiteral.name} + 1 year`, [ + `Argument of [+] must be [date], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + for (const op of ['*', '/', '%']) { + testErrorsAndWarnings(`from a | eval var = now() ${op} 1 ${timeLiteral.name}`, [ + `Argument of [${op}] must be [number], found value [now()] type [date]`, + `Argument of [${op}] must be [number], found value [1 ${timeLiteral.name}] type [duration]`, + ]); + } + } + }); + }); + + describe('stats', () => { + testErrorsAndWarnings('from a | stats ', []); + testErrorsAndWarnings('from a | stats numberField ', [ + 'Stats expects an aggregate function, found [numberField]', + ]); + testErrorsAndWarnings('from a | stats numberField=', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | stats numberField=5 by ', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings('from a | stats numberField=5 by ', [ + "SyntaxError: missing {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} at ''", + ]); + + testErrorsAndWarnings('from a | stats avg(numberField) by wrongField', [ + 'Unknown column [wrongField]', + ]); + testErrorsAndWarnings('from a | stats avg(numberField) by 1', [ + 'SyntaxError: expected {UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found "1"', + 'Unknown column [1]', + ]); + testErrorsAndWarnings('from a | stats avg(numberField) by percentile(numberField)', [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [percentile]', + ]); + + testErrorsAndWarnings( + 'from a | stats avg(numberField) by stringField, percentile(numberField) by ipField', + [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [percentile]', + ] + ); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) by ipField', + [] + ); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) BY ipField', + [] + ); + + testErrorsAndWarnings('from a | stats numberField + 1', ['Stats does not support function +']); + + testErrorsAndWarnings('from a | stats numberField + 1 by ipField', [ + 'Stats does not support function +', + ]); + + testErrorsAndWarnings( + 'from a | stats avg(numberField), percentile(numberField, 50) + 1 by ipField', + ['Stats does not support function +'] + ); + + testErrorsAndWarnings('from a | stats avg(numberField) by avg(numberField)', [ + 'SyntaxError: expected {, PIPE, COMMA, DOT} but found "("', + 'Unknown column [avg]', + ]); + + testErrorsAndWarnings('from a | stats count(*)', []); + testErrorsAndWarnings('from a | stats var0 = count(*)', []); + testErrorsAndWarnings('from a | stats var0 = avg(numberField), count(*)', []); + + for (const { name, alias, signatures, ...defRest } of statsAggregationFunctionDefinitions) { + for (const { params, returnType } of signatures) { + const fieldMapping = getFieldMapping(params); + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + testErrorsAndWarnings( + `from a | stats ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }` + ); + + if (alias) { + for (const otherName of alias) { + const signatureStringWithAlias = getFunctionSignatures( + { name: otherName, ...defRest, signatures: [{ params: fieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration; + + testErrorsAndWarnings(`from a | stats var = ${signatureStringWithAlias}`, []); + } + } + + // Skip functions that have only arguments of type "any", as it is not possible to pass "the wrong type". + // auto_bucket and to_version functions are a bit harder to test exactly a combination of argument and predict the + // the right error message + if ( + params.every(({ type }) => type !== 'any') && + !['auto_bucket', 'to_version'].includes(name) + ) { + // now test nested functions + const fieldMappingWithNestedFunctions = getFieldMapping(params, { + useNestedFunction: true, + useLiterals: false, + }); + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithNestedFunctions, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + params.map( + (_) => + `Aggregate function's parameters must be an attribute or literal; found [avg(numberField)] of type [number]` + ) + ); + // and the message is case of wrong argument type is passed + const wrongFieldMapping = params.map(({ name: _name, type, ...rest }) => { + const typeString = type; + const canBeFieldButNotString = ['number', 'date', 'boolean', 'ip'].includes(typeString); + const isLiteralType = /literal$/.test(typeString); + // pick a field name purposely wrong + const nameValue = + canBeFieldButNotString || isLiteralType ? 'stringField' : 'numberField'; + return { name: nameValue, type, ...rest }; + }); + + const expectedErrors = params.map( + ({ type }, i) => + `Argument of [${name}] must be [${type}], found value [${ + wrongFieldMapping[i].name + }] type [${wrongFieldMapping[i].name.replace('Field', '')}]` + ); + testErrorsAndWarnings( + `from a | stats ${ + getFunctionSignatures( + { name, ...defRest, signatures: [{ params: wrongFieldMapping, returnType }] }, + { withTypes: false } + )[0].declaration + }`, + expectedErrors + ); + + // test that only count() accepts wildcard as arg + // just check that the function accepts only 1 arg as the parser cannot handle multiple args with * as start arg + if (fieldMapping.length === 1) { + const fieldMappingWithWildcard = [...fieldMapping]; + fieldMappingWithWildcard[0].name = '*'; + + testErrorsAndWarnings( + `from a | stats var = ${ + getFunctionSignatures( + { + name, + ...defRest, + signatures: [{ params: fieldMappingWithWildcard, returnType }], + }, + { withTypes: false } + )[0].declaration + }`, + name === 'count' ? [] : [`Using wildcards (*) in ${name} is not allowed`] + ); + } + } + } + } + }); + + describe('sort', () => { + testErrorsAndWarnings('from a | sort ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | sort "field" ', []); + testErrorsAndWarnings('from a | sort wrongField ', ['Unknown column [wrongField]']); + testErrorsAndWarnings('from a | sort numberField, ', [ + 'SyntaxError: expected {STRING, INTEGER_LITERAL, DECIMAL_LITERAL, FALSE, LP, NOT, NULL, PARAM, TRUE, PLUS, MINUS, OPENING_BRACKET, UNQUOTED_IDENTIFIER, QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings('from a | sort numberField, stringField', []); + for (const dir of ['desc', 'asc']) { + testErrorsAndWarnings(`from a | sort "field" ${dir} `, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} `, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} nulls `, [ + "SyntaxError: missing {FIRST, LAST} at ''", + ]); + for (const nullDir of ['first', 'last']) { + testErrorsAndWarnings(`from a | sort numberField ${dir} nulls ${nullDir}`, []); + testErrorsAndWarnings(`from a | sort numberField ${dir} ${nullDir}`, [ + `SyntaxError: extraneous input '${nullDir}' expecting `, + ]); + } + } + for (const nullDir of ['first', 'last']) { + testErrorsAndWarnings(`from a | sort numberField nulls ${nullDir}`, []); + testErrorsAndWarnings(`from a | sort numberField ${nullDir}`, [ + `SyntaxError: extraneous input '${nullDir}' expecting `, + ]); + } + }); + + describe('enrich', () => { + testErrorsAndWarnings(`from a | enrich`, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from a | enrich policy `, []); + testErrorsAndWarnings(`from a | enrich missing-policy `, ['Unknown policy [missing-policy]']); + testErrorsAndWarnings(`from a | enrich policy on `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + ]); + testErrorsAndWarnings(`from a | enrich policy on b `, ['Unknown column [b]']); + testErrorsAndWarnings(`from a | enrich policy on numberField with `, [ + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 `, [ + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = c `, [ + 'Unknown column [var0]', + `Unknown column [c]`, + ]); + // need to re-enable once the fields/variables become location aware + // testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = stringField `, [ + // `Unknown column [stringField]`, + // ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = , `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ','", + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + 'Unknown column [var0]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField, var1 `, [ + 'Unknown column [var1]', + ]); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField `, []); + testErrorsAndWarnings( + `from a | enrich policy on numberField with var0 = otherField, yetAnotherField `, + [] + ); + testErrorsAndWarnings(`from a | enrich policy on numberField with var0 = otherField, var1 = `, [ + "SyntaxError: missing {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} at ''", + 'Unknown column [var1]', + ]); + + testErrorsAndWarnings( + `from a | enrich policy on numberField with var0 = otherField, var1 = yetAnotherField`, + [] + ); + testErrorsAndWarnings(`from a | enrich policy with `, [ + 'SyntaxError: expected {SRC_UNQUOTED_IDENTIFIER, SRC_QUOTED_IDENTIFIER} but found ""', + ]); + testErrorsAndWarnings(`from a | enrich policy with otherField`, []); + testErrorsAndWarnings(`from a | enrich policy | eval otherField`, []); + testErrorsAndWarnings(`from a | enrich policy with var0 = otherField | eval var0`, []); + testErrorsAndWarnings('from a | enrich my-pol*', [ + 'Using wildcards (*) in enrich is not allowed [my-pol*]', + ]); + }); + + describe('shadowing', () => { + testErrorsAndWarnings( + 'from a | eval stringField = 5', + [], + ['Column [stringField] of type string has been overwritten as new type: number'] + ); + testErrorsAndWarnings( + 'from a | eval numberField = "5"', + [], + ['Column [numberField] of type number has been overwritten as new type: string'] + ); + }); + + describe('callbacks', () => { + it(`should not fetch source and fields list when a row command is set`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval a`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getFieldsFor).not.toHaveBeenCalled(); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + }); + + it(`should fetch policies if no enrich command is found`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval a`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getPolicies).not.toHaveBeenCalled(); + }); + + it(`should not fetch source and fields for empty command`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(` `, getAstAndErrors, callbackMocks); + expect(callbackMocks.getFieldsFor).not.toHaveBeenCalled(); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + }); + + it(`should skip initial source and fields call but still call fields for enriched policy`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`row a = 1 | eval b = a | enrich policy`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + expect(callbackMocks.getPolicies).toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(1); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: `from enrichIndex1 | keep otherField, yetAnotherField`, + }); + }); + + it('should call fields callbacks also for show command', async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`show functions | keep name`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).not.toHaveBeenCalled(); + expect(callbackMocks.getPolicies).not.toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(1); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: 'show functions', + }); + }); + + it(`should fetch additional fields if an enrich command is found`, async () => { + const callbackMocks = getCallbackMocks(); + await validateAst(`from a | eval b = a | enrich policy`, getAstAndErrors, callbackMocks); + expect(callbackMocks.getSources).toHaveBeenCalled(); + expect(callbackMocks.getPolicies).toHaveBeenCalled(); + expect(callbackMocks.getFieldsFor).toHaveBeenCalledTimes(2); + expect(callbackMocks.getFieldsFor).toHaveBeenLastCalledWith({ + query: `from enrichIndex1 | keep otherField, yetAnotherField`, + }); + }); + }); +}); diff --git a/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts new file mode 100644 index 0000000000000..b1a2a53be7acf --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/ast/validation/validation.ts @@ -0,0 +1,780 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import uniqBy from 'lodash/uniqBy'; +import capitalize from 'lodash/capitalize'; +import { CommandOptionsDefinition, SignatureArgType } from '../definitions/types'; +import { + areFieldAndVariableTypesCompatible, + extractSingleType, + getAllArrayTypes, + getAllArrayValues, + getColumnHit, + getCommandDefinition, + getFunctionDefinition, + isArrayType, + isAssignment, + isColumnItem, + isEqualType, + isFunctionItem, + isLiteralItem, + isOptionItem, + isSourceItem, + isSupportedFunction, + isTimeIntervalItem, + inKnownTimeInterval, + printFunctionSignature, + sourceExists, + columnExists, + hasWildcard, + hasCCSSource, +} from '../shared/helpers'; +import { collectVariables } from '../shared/variables'; +import type { + AstProviderFn, + ESQLAstItem, + ESQLColumn, + ESQLCommand, + ESQLCommandOption, + ESQLFunction, + ESQLMessage, + ESQLSingleAstItem, + ESQLSource, +} from '../types'; +import { getMessageFromId, createMessage } from './errors'; +import type { ESQLRealField, ESQLVariable, ReferenceMaps, ValidationResult } from './types'; +import type { ESQLCallbacks } from '../shared/types'; +import { + retrieveSources, + retrieveFields, + retrievePolicies, + retrievePoliciesFields, +} from './resources'; + +function validateFunctionLiteralArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if (isLiteralItem(actualArg)) { + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.value, + givenType: actualArg.literalType, + }, + locations: actualArg.location, + }) + ); + } + } + if (isTimeIntervalItem(actualArg)) { + // check first if it's a valid interval string + if (!inKnownTimeInterval(actualArg)) { + messages.push( + getMessageFromId({ + messageId: 'unknownInterval', + values: { + value: actualArg.unit, + }, + locations: actualArg.location, + }) + ); + } else { + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.name, + givenType: 'duration', + }, + locations: actualArg.location, + }) + ); + } + } + } + return messages; +} + +function validateNestedFunctionArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if ( + isFunctionItem(actualArg) && + // no need to check the reason here, it is checked already above + isSupportedFunction(actualArg.name, parentCommand).supported + ) { + const argFn = getFunctionDefinition(actualArg.name)!; + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: printFunctionSignature(actualArg) || actualArg.name, + givenType: argFn.signatures[0].returnType, + }, + locations: actualArg.location, + }) + ); + } else { + if ('noNestingFunctions' in argDef && argDef.noNestingFunctions) { + messages.push( + getMessageFromId({ + messageId: 'noNestedArgumentSupport', + values: { name: actualArg.text, argType: argFn.signatures[0].returnType }, + locations: actualArg.location, + }) + ); + } + } + } + return messages; +} + +function validateFunctionColumnArg( + astFunction: ESQLFunction, + actualArg: ESQLAstItem, + argDef: SignatureArgType, + references: ReferenceMaps, + parentCommand: string +) { + const messages: ESQLMessage[] = []; + if (isColumnItem(actualArg) && actualArg.name) { + const { hit: columnCheck, nameHit } = columnExists(actualArg, references); + if (!columnCheck) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: actualArg.name, + }, + locations: actualArg.location, + }) + ); + } else { + if (actualArg.name === '*') { + // if function does not support wildcards return a specific error + if (!('supportsWildcard' in argDef) || !argDef.supportsWildcard) { + messages.push( + getMessageFromId({ + messageId: 'noWildcardSupportAsArg', + values: { + name: astFunction.name, + }, + locations: actualArg.location, + }) + ); + } + // do not validate any further for now, only count() accepts wildcard as args... + } else { + // guaranteed by the check above + const columnHit = getColumnHit(nameHit!, references); + // check the type of the column hit + const typeHit = columnHit!.type; + if (!isEqualType(actualArg, argDef, references, parentCommand)) { + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: actualArg.name, + givenType: typeHit, + }, + locations: actualArg.location, + }) + ); + } + } + } + } + return messages; +} + +function validateFunction( + astFunction: ESQLFunction, + parentCommand: string, + references: ReferenceMaps +): ESQLMessage[] { + const messages: ESQLMessage[] = []; + + if (astFunction.incomplete) { + return messages; + } + + const isFnSupported = isSupportedFunction(astFunction.name, parentCommand); + + if (!isFnSupported.supported) { + if (isFnSupported.reason === 'unknownFunction') { + messages.push( + getMessageFromId({ + messageId: 'unknownFunction', + values: { + name: astFunction.name, + }, + locations: astFunction.location, + }) + ); + } + if (isFnSupported.reason === 'unsupportedFunction') { + messages.push( + getMessageFromId({ + messageId: 'unsupportedFunction', + values: { name: astFunction.name, command: capitalize(parentCommand) }, + locations: astFunction.location, + }) + ); + } + return messages; + } + const fnDefinition = getFunctionDefinition(astFunction.name)!; + const matchingSignatures = fnDefinition.signatures.filter((def) => { + if (def.infiniteParams && astFunction.args.length > 0) { + return true; + } + if (def.minParams && astFunction.args.length >= def.minParams) { + return true; + } + if (astFunction.args.length === def.params.length) { + return true; + } + return astFunction.args.length >= def.params.filter(({ optional }) => !optional).length; + }); + if (!matchingSignatures.length) { + const numArgs = fnDefinition.signatures[0].params.filter(({ optional }) => !optional).length; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentNumber', + values: { + fn: astFunction.name, + numArgs, + passedArgs: astFunction.args.length, + }, + locations: astFunction.location, + }) + ); + } + // now perform the same check on all functions args + for (const arg of astFunction.args) { + const wrappedArray = Array.isArray(arg) ? arg : [arg]; + for (const subArg of wrappedArray) { + if (isFunctionItem(subArg)) { + messages.push(...validateFunction(subArg, parentCommand, references)); + } + } + } + // check if the definition has some warning to show: + if (fnDefinition.warning) { + const message = fnDefinition.warning( + ...(astFunction.args.filter((arg) => !Array.isArray(arg)) as ESQLSingleAstItem[]) + ); + if (message) { + messages.push(createMessage('warning', message, astFunction.location)); + } + } + // at this point we're sure that at least one signature is matching + const failingSignatures: ESQLMessage[][] = []; + for (const signature of matchingSignatures) { + const failingSignature: ESQLMessage[] = []; + signature.params.forEach((argDef, index) => { + const outerArg = astFunction.args[index]!; + if (!outerArg && argDef.optional) { + // that's ok, just skip it + // the else case is already catched with the argument counts check + // few lines above + return; + } + if (Array.isArray(outerArg) && isArrayType(argDef.type)) { + const extractedType = extractSingleType(argDef.type); + const everyArgInListMessages = outerArg + .map((arg) => { + return [ + validateFunctionLiteralArg, + validateNestedFunctionArg, + validateFunctionColumnArg, + ].flatMap((validateFn) => { + return validateFn( + astFunction, + arg, + { ...argDef, type: extractedType }, + references, + parentCommand + ); + }); + }) + .filter((ms) => ms.length); + if (everyArgInListMessages.length) { + failingSignature.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: astFunction.name, + argType: argDef.type, + value: `(${getAllArrayValues(outerArg).join(', ')})`, + givenType: `(${getAllArrayTypes(outerArg, parentCommand, references).join(', ')})`, + }, + locations: { + min: (outerArg[0] as ESQLSingleAstItem).location.min, + max: (outerArg[outerArg.length - 1] as ESQLSingleAstItem).location.max, + }, + }) + ); + } + return; + } + const wrappedArg = Array.isArray(outerArg) ? outerArg : [outerArg]; + for (const actualArg of wrappedArg) { + const argValidationMessages = [ + validateFunctionLiteralArg, + validateNestedFunctionArg, + validateFunctionColumnArg, + ].flatMap((validateFn) => { + return validateFn(astFunction, actualArg, argDef, references, parentCommand); + }); + failingSignature.push(...argValidationMessages); + + if (isSourceItem(actualArg)) { + // something went wrong with the AST translation + throw new Error('Source should not allowed as function argument'); + } + } + }); + if (failingSignature.length) { + failingSignatures.push(failingSignature); + } + } + if (failingSignatures.length && failingSignatures.length === matchingSignatures.length) { + const failingSignatureOrderedByErrorCount = failingSignatures + .map((arr, index) => ({ index, count: arr.length })) + .sort((a, b) => a.count - b.count); + const indexForShortestFailingsignature = failingSignatureOrderedByErrorCount[0].index; + messages.push(...failingSignatures[indexForShortestFailingsignature]); + } + // This is due to a special case in enrich where an implicit assignment is possible + // so the AST needs to store an explicit "columnX = columnX" which duplicates the message + return uniqBy(messages, ({ location }) => `${location.min}-${location.max}`); +} + +function validateOption( + option: ESQLCommandOption, + optionDef: CommandOptionsDefinition | undefined, + command: ESQLCommand, + referenceMaps: ReferenceMaps +): ESQLMessage[] { + // check if the arguments of the option are of the correct type + const messages: ESQLMessage[] = []; + if (option.incomplete || command.incomplete) { + return messages; + } + if (!optionDef) { + messages.push( + getMessageFromId({ + messageId: 'unknownOption', + values: { command: command.name, option: option.name }, + locations: option.location, + }) + ); + return messages; + } + // use dedicate validate fn if provided + if (optionDef.validate) { + messages.push(...optionDef.validate(option)); + } + if (!optionDef.skipCommonValidation) { + option.args.forEach((arg, index) => { + if (!Array.isArray(arg)) { + if (!optionDef.signature.multipleParams) { + const argDef = optionDef.signature.params[index]; + if (!isEqualType(arg, argDef, referenceMaps, command.name)) { + const value = 'value' in arg ? arg.value : arg.name; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: option.name, + argType: argDef.type, + value, + givenType: arg.type, + }, + locations: arg.location, + }) + ); + } + if (isColumnItem(arg)) { + messages.push(...validateColumnForCommand(arg, command.name, referenceMaps)); + } + } else { + const argDef = optionDef.signature.params[0]; + if (!isEqualType(arg, argDef, referenceMaps, command.name)) { + const value = 'value' in arg ? arg.value : arg.name; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: argDef.name, + argType: argDef.type, + value, + givenType: arg.type, + }, + locations: arg.location, + }) + ); + } + if (isColumnItem(arg)) { + messages.push(...validateColumnForCommand(arg, command.name, referenceMaps)); + } + if (isFunctionItem(arg) && isAssignment(arg)) { + messages.push(...validateFunction(arg, command.name, referenceMaps)); + } + } + } + }); + } + + return messages; +} + +function validateSource( + source: ESQLSource, + commandName: string, + { sources, policies }: ReferenceMaps +) { + const messages: ESQLMessage[] = []; + if (source.incomplete) { + return messages; + } + const commandDef = getCommandDefinition(commandName); + if (commandDef.signature.params.every(({ type }) => type !== source.type)) { + const firstArg = commandDef.signature.params[0]; + messages.push( + getMessageFromId({ + messageId: 'wrongArgumentType', + values: { + name: firstArg.name, + argType: firstArg.type, + value: source.name, + givenType: source.type, + }, + locations: source.location, + }) + ); + } else { + const hasCCS = hasCCSSource(source.name); + if (hasCCS) { + messages.push( + getMessageFromId({ + messageId: 'ccsNotSupportedForCommand', + values: { value: source.name }, + locations: source.location, + }) + ); + } else { + const isWildcardAndNotSupported = + hasWildcard(source.name) && !commandDef.signature.params.some(({ wildcards }) => wildcards); + if (isWildcardAndNotSupported) { + messages.push( + getMessageFromId({ + messageId: 'wildcardNotSupportedForCommand', + values: { command: commandName, value: source.name }, + locations: source.location, + }) + ); + } else { + if (source.sourceType === 'index' && !sourceExists(source.name, sources)) { + messages.push( + getMessageFromId({ + messageId: 'unknownIndex', + values: { name: source.name }, + locations: source.location, + }) + ); + } else if (source.sourceType === 'policy' && !policies.has(source.name)) { + messages.push( + getMessageFromId({ + messageId: 'unknownPolicy', + values: { name: source.name }, + locations: source.location, + }) + ); + } + } + } + } + return messages; +} + +function validateColumnForCommand( + column: ESQLColumn, + commandName: string, + references: ReferenceMaps +): ESQLMessage[] { + const messages: ESQLMessage[] = []; + + if (['from', 'show', 'limit'].includes(commandName)) { + return messages; + } + if (commandName === 'row') { + if (!references.variables.has(column.name)) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: column.name, + }, + locations: column.location, + }) + ); + } + } else { + const { hit: columnCheck, nameHit } = columnExists(column, references); + if (columnCheck && nameHit) { + const commandDef = getCommandDefinition(commandName); + const columnParamsWithInnerTypes = commandDef.signature.params.filter( + ({ type, innerType }) => type === 'column' && innerType + ); + + if (columnParamsWithInnerTypes.length) { + // this should be guaranteed by the columnCheck above + const columnRef = getColumnHit(nameHit, references)!; + if ( + columnParamsWithInnerTypes.every(({ innerType }) => { + return innerType !== columnRef.type; + }) + ) { + const supportedTypes = columnParamsWithInnerTypes.map(({ innerType }) => innerType); + + messages.push( + getMessageFromId({ + messageId: 'unsupportedColumnTypeForCommand', + values: { + command: capitalize(commandName), + type: supportedTypes.join(', '), + typeCount: supportedTypes.length, + givenType: columnRef.type, + column: nameHit, + }, + locations: column.location, + }) + ); + } + } + if ( + hasWildcard(nameHit) && + !commandDef.signature.params.some(({ type, wildcards }) => type === 'column' && wildcards) + ) { + messages.push( + getMessageFromId({ + messageId: 'wildcardNotSupportedForCommand', + values: { + command: commandName, + value: nameHit, + }, + locations: column.location, + }) + ); + } + } else { + if (column.name) { + messages.push( + getMessageFromId({ + messageId: 'unknownColumn', + values: { + name: column.name, + }, + locations: column.location, + }) + ); + } + } + } + return messages; +} + +function validateCommand(command: ESQLCommand, references: ReferenceMaps): ESQLMessage[] { + const messages: ESQLMessage[] = []; + if (command.incomplete) { + return messages; + } + // do not check the command exists, the grammar is already picking that up + const commandDef = getCommandDefinition(command.name); + + if (commandDef.validate) { + messages.push(...commandDef.validate(command)); + } + + // Now validate arguments + for (const commandArg of command.args) { + const wrappedArg = Array.isArray(commandArg) ? commandArg : [commandArg]; + for (const arg of wrappedArg) { + if (isFunctionItem(arg)) { + messages.push(...validateFunction(arg, command.name, references)); + } + + if (isOptionItem(arg)) { + messages.push( + ...validateOption( + arg, + commandDef.options.find(({ name }) => name === arg.name), + command, + references + ) + ); + } + if (isColumnItem(arg)) { + if (command.name === 'stats') { + messages.push( + getMessageFromId({ + messageId: 'unknownAggregateFunction', + values: { + command: capitalize(command.name), + value: (arg as ESQLSingleAstItem).name, + }, + locations: (arg as ESQLSingleAstItem).location, + }) + ); + } else { + messages.push(...validateColumnForCommand(arg, command.name, references)); + } + } + if (isTimeIntervalItem(arg)) { + messages.push( + getMessageFromId({ + messageId: 'unsupportedTypeForCommand', + values: { + command: capitalize(command.name), + type: 'date_period', + value: arg.name, + }, + locations: arg.location, + }) + ); + } + if (isSourceItem(arg)) { + messages.push(...validateSource(arg, command.name, references)); + } + } + } + // no need to check for mandatory options passed + // as they are already validated at syntax level + return messages; +} + +function validateFieldsShadowing( + fields: Map, + variables: Map +) { + const messages: ESQLMessage[] = []; + for (const variable of variables.keys()) { + if (fields.has(variable)) { + const variableHits = variables.get(variable)!; + if (!areFieldAndVariableTypesCompatible(fields.get(variable)?.type, variableHits[0].type)) { + const fieldType = fields.get(variable)!.type; + const variableType = variableHits[0].type; + const flatFieldType = fieldType; + const flatVariableType = variableType; + messages.push( + getMessageFromId({ + messageId: 'shadowFieldType', + values: { + field: variable, + fieldType: flatFieldType, + newType: flatVariableType, + }, + locations: variableHits[0].location, + }) + ); + } + } + } + return messages; +} + +function validateUnsupportedTypeFields(fields: Map) { + const messages: ESQLMessage[] = []; + for (const field of fields.values()) { + if (field.type === 'unsupported') { + messages.push( + getMessageFromId({ + messageId: 'unsupportedFieldType', + values: { + field: field.name, + }, + locations: { min: 1, max: 1 }, + }) + ); + } + } + return messages; +} + +/** + * This function will perform an high level validation of the + * query AST. An initial syntax validation is already performed by the parser + * while here it can detect things like function names, types correctness and potential warnings + * @param ast A valid AST data structure + */ +export async function validateAst( + queryString: string, + astProvider: AstProviderFn, + callbacks?: ESQLCallbacks +): Promise { + const messages: ESQLMessage[] = []; + + const { ast, errors } = await astProvider(queryString); + + const [sources, availableFields, availablePolicies] = await Promise.all([ + // retrieve the list of available sources + retrieveSources(ast, callbacks), + // retrieve available fields (if a source command has been defined) + retrieveFields(queryString, ast, callbacks), + // retrieve available policies (if an enrich command has been defined) + retrievePolicies(ast, callbacks), + ]); + + if (availablePolicies.size && ast.filter(({ name }) => name === 'enrich')) { + const fieldsFromPoliciesMap = await retrievePoliciesFields(ast, availablePolicies, callbacks); + fieldsFromPoliciesMap.forEach((value, key) => availableFields.set(key, value)); + } + + const variables = collectVariables(ast, availableFields); + // notify if the user is rewriting a column as variable with another type + messages.push(...validateFieldsShadowing(availableFields, variables)); + messages.push(...validateUnsupportedTypeFields(availableFields)); + + for (const command of ast) { + const commandMessages = validateCommand(command, { + sources, + fields: availableFields, + policies: availablePolicies, + variables, + }); + messages.push(...commandMessages); + } + return { + errors: [...errors, ...messages.filter(({ type }) => type === 'error')], + warnings: messages.filter(({ type }) => type === 'warning'), + }; +} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts deleted file mode 100644 index 92b2e8f7c31d1..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/comparison_commands.ts +++ /dev/null @@ -1,116 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const comparisonOperatorsCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'or', - insertText: 'or', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.orDoc', { - defaultMessage: 'or', - }), - sortText: 'D', - }, - { - label: 'and', - insertText: 'and', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.andDoc', { - defaultMessage: 'and', - }), - sortText: 'D', - }, -]; - -export const comparisonCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: '==', - insertText: '==', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.equalToDoc', { - defaultMessage: 'Equal to', - }), - sortText: 'D', - }, - { - label: '!=', - insertText: '!=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.notEqualToDoc', { - defaultMessage: 'Not equal to', - }), - sortText: 'D', - }, - { - label: '<', - insertText: '<', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.lessThanDoc', { - defaultMessage: 'Less than', - }), - sortText: 'D', - }, - { - label: '>', - insertText: '>', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.greaterThanDoc', { - defaultMessage: 'Greater than', - }), - sortText: 'D', - }, - { - label: '<=', - insertText: '<=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.lessThanOrEqualToDoc', { - defaultMessage: 'Less than or equal to', - }), - sortText: 'D', - }, - { - label: '>=', - insertText: '>=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.greaterThanOrEqualToDoc', { - defaultMessage: 'Greater than or equal to', - }), - sortText: 'D', - }, - { - label: 'like', - insertText: 'like', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.likeDoc', { - defaultMessage: 'Filter data based on string patterns', - }), - sortText: 'D', - }, - { - label: 'rlike', - insertText: 'rlike', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.rlikeDoc', { - defaultMessage: 'Filter data based on string regular expressions', - }), - sortText: 'D', - }, - { - label: 'in', - insertText: 'in', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.inDoc', { - defaultMessage: - 'Tests if the value an expression takes is contained in a list of other expressions', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts deleted file mode 100644 index 2eb0226914ee9..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/date_math_expressions.ts +++ /dev/null @@ -1,157 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const dateExpressionDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'year', - insertText: 'year', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.year', { - defaultMessage: 'Year', - }), - sortText: 'D', - }, - { - label: 'years', - insertText: 'years', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.years', { - defaultMessage: 'Years (Plural)', - }), - sortText: 'D', - }, - { - label: 'month', - insertText: 'month', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.month', { - defaultMessage: 'Month', - }), - sortText: 'D', - }, - { - label: 'months', - insertText: 'months', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.months', { - defaultMessage: 'Months (Plural)', - }), - sortText: 'D', - }, - { - label: 'week', - insertText: 'week', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.week', { - defaultMessage: 'Week', - }), - sortText: 'D', - }, - { - label: 'weeks', - insertText: 'weeks', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.weeks', { - defaultMessage: 'Weeks (Plural)', - }), - sortText: 'D', - }, - { - label: 'day', - insertText: 'day', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.day', { - defaultMessage: 'Day', - }), - sortText: 'D', - }, - { - label: 'days', - insertText: 'days', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.days', { - defaultMessage: 'Days (Plural)', - }), - sortText: 'D', - }, - { - label: 'hour', - insertText: 'hour', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.hour', { - defaultMessage: 'Hour', - }), - sortText: 'D', - }, - { - label: 'hours', - insertText: 'hours', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.hours', { - defaultMessage: 'Hours (Plural)', - }), - sortText: 'D', - }, - { - label: 'minute', - insertText: 'minute', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.minute', { - defaultMessage: 'Minute', - }), - sortText: 'D', - }, - { - label: 'minutes', - insertText: 'minutes', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.minutes', { - defaultMessage: 'Minutes (Plural)', - }), - sortText: 'D', - }, - { - label: 'second', - insertText: 'second', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.second', { - defaultMessage: 'Second', - }), - sortText: 'D', - }, - { - label: 'seconds', - insertText: 'seconds', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.seconds', { - defaultMessage: 'Seconds (Plural)', - }), - sortText: 'D', - }, - { - label: 'millisecond', - insertText: 'millisecond', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.millisecond', { - defaultMessage: 'Millisecond', - }), - sortText: 'D', - }, - { - label: 'milliseconds', - insertText: 'milliseconds', - kind: 12, - detail: i18n.translate('monaco.esql.autocomplete.dateDurationDefinition.milliseconds', { - defaultMessage: 'Milliseconds (Plural)', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts deleted file mode 100644 index f6348fe2c11e2..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/dynamic_commands.ts +++ /dev/null @@ -1,114 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const buildPoliciesDefinitions = ( - policies: Array<{ name: string; indices: string[] }> -): AutocompleteCommandDefinition[] => - policies.map(({ name: label, indices }) => ({ - label, - insertText: label, - kind: 5, - detail: i18n.translate('monaco.esql.autocomplete.policyDefinition', { - defaultMessage: `Policy defined on {count, plural, one {index} other {indices}}: {indices}`, - values: { - count: indices.length, - indices: indices.join(', '), - }, - }), - sortText: 'D', - })); - -export const buildFieldsDefinitions = (fields: string[]): AutocompleteCommandDefinition[] => - fields.map((label) => ({ - label, - insertText: label, - kind: 4, - detail: i18n.translate('monaco.esql.autocomplete.fieldDefinition', { - defaultMessage: `Field specified by the input table`, - }), - sortText: 'D', - })); - -export const buildNoPoliciesAvailableDefinition = (): AutocompleteCommandDefinition[] => [ - { - label: i18n.translate('monaco.esql.autocomplete.noPoliciesLabel', { - defaultMessage: 'No available policy', - }), - insertText: '', - kind: 26, - detail: i18n.translate('monaco.esql.autocomplete.noPoliciesLabelsFound', { - defaultMessage: 'Click to create', - }), - sortText: 'D', - command: { - id: 'esql.policies.create', - title: i18n.translate('monaco.esql.autocomplete.createNewPolicy', { - defaultMessage: 'Click to create', - }), - }, - }, -]; - -export const buildMatchingFieldsDefinition = ( - matchingField: string, - fields: string[] -): AutocompleteCommandDefinition[] => - fields.map((label) => ({ - label, - insertText: label, - kind: 4, - detail: i18n.translate('monaco.esql.autocomplete.matchingFieldDefinition', { - defaultMessage: `Use to match on {matchingField} on the policy`, - values: { - matchingField, - }, - }), - sortText: 'D', - })); - -export const buildNewVarDefinition = (label: string): AutocompleteCommandDefinition => { - return { - label, - insertText: label, - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.newVarDoc', { - defaultMessage: 'Define a new variable', - }), - sortText: 'D', - }; -}; - -export const buildSourcesDefinitions = (sources: string[]): AutocompleteCommandDefinition[] => - sources.map((label) => ({ - label, - insertText: label, - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.sourceDefinition', { - defaultMessage: `Input table`, - }), - sortText: 'A', - })); - -export const buildConstantsDefinitions = ( - userConstants: string[], - detail?: string -): AutocompleteCommandDefinition[] => - userConstants.map((label) => ({ - label, - insertText: label, - kind: 14, - detail: - detail ?? - i18n.translate('monaco.esql.autocomplete.constantDefinition', { - defaultMessage: `User defined variable`, - }), - sortText: 'A', - })); diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts deleted file mode 100644 index e1fb514cfa4de..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/index.ts +++ /dev/null @@ -1,41 +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 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 or the Server - * Side Public License, v 1. - */ - -export { - aggregationFunctionsDefinitions, - mathCommandDefinition, - whereCommandDefinition, -} from './functions_commands'; -export { sourceCommandsDefinitions } from './source_commands'; -export { processingCommandsDefinitions, pipeDefinition } from './processing_commands'; - -export { - comparisonCommandsDefinitions, - comparisonOperatorsCommandsDefinitions, -} from './comparison_commands'; -export { - mathOperatorsCommandsDefinitions, - assignOperatorDefinition, - asOperatorDefinition, - byOperatorDefinition, - openBracketDefinition, - closeBracketDefinition, -} from './operators_commands'; - -export { - orderingCommandsDefinitions, - nullsCommandsDefinition, - nullsOrderingCommandsDefinitions, -} from './ordering_commands'; - -export { - buildNewVarDefinition, - buildSourcesDefinitions, - buildFieldsDefinitions, - buildConstantsDefinitions, -} from './dynamic_commands'; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts deleted file mode 100644 index 91ccb74cb9501..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/operators_commands.ts +++ /dev/null @@ -1,119 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import type { AutocompleteCommandDefinition } from '../types'; - -export const byOperatorDefinition: AutocompleteCommandDefinition = { - label: 'by', - insertText: 'by', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.byDoc', { - defaultMessage: 'By', - }), - sortText: 'D', -}; - -export const onOperatorDefinition: AutocompleteCommandDefinition = { - label: 'on', - insertText: 'on', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.onDoc', { - defaultMessage: 'On', - }), - sortText: 'D', -}; - -export const withOperatorDefinition: AutocompleteCommandDefinition = { - label: 'with', - insertText: 'with', - kind: 21, - detail: i18n.translate('monaco.esql.autocomplete.withDoc', { - defaultMessage: 'With', - }), - sortText: 'D', -}; - -export const asOperatorDefinition: AutocompleteCommandDefinition = { - label: 'as', - insertText: 'as', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.asDoc', { - defaultMessage: 'As', - }), - sortText: 'D', -}; - -export const assignOperatorDefinition: AutocompleteCommandDefinition = { - label: '=', - insertText: '=', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.assignDoc', { - defaultMessage: 'Assign (=)', - }), - sortText: 'D', -}; - -export const openBracketDefinition: AutocompleteCommandDefinition = { - label: '(', - insertText: '(', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.openBracketDoc', { - defaultMessage: 'Open Bracket (', - }), - sortText: 'A', -}; - -export const closeBracketDefinition: AutocompleteCommandDefinition = { - label: ')', - insertText: ')', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.closeBracketDoc', { - defaultMessage: 'Close Bracket )', - }), - sortText: 'A', -}; - -export const mathOperatorsCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: '+', - insertText: '+', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.addDoc', { - defaultMessage: 'Add (+)', - }), - sortText: 'D', - }, - { - label: '-', - insertText: '-', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.subtractDoc', { - defaultMessage: 'Subtract (-)', - }), - sortText: 'D', - }, - { - label: '/', - insertText: '/', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.divideDoc', { - defaultMessage: 'Divide (/)', - }), - sortText: 'D', - }, - { - label: '*', - insertText: '*', - kind: 11, - detail: i18n.translate('monaco.esql.autocomplete.multiplyDoc', { - defaultMessage: 'Multiply (*)', - }), - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts deleted file mode 100644 index 6e932e742a69b..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/ordering_commands.ts +++ /dev/null @@ -1,54 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const orderingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'asc', - insertText: 'asc', - kind: 17, - detail: i18n.translate('monaco.esql.autocomplete.ascDoc', { - defaultMessage: 'Ascending Order', - }), - sortText: 'D', - }, - { - label: 'desc', - insertText: 'desc', - kind: 17, - detail: i18n.translate('monaco.esql.autocomplete.descDoc', { - defaultMessage: 'Descending Order', - }), - sortText: 'D', - }, -]; - -export const nullsCommandsDefinition: AutocompleteCommandDefinition = { - label: 'nulls', - insertText: 'nulls', - kind: 13, - sortText: 'D', -}; - -export const nullsOrderingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'first', - insertText: 'first', - kind: 13, - sortText: 'D', - }, - { - label: 'last', - insertText: 'last', - kind: 13, - sortText: 'D', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts deleted file mode 100644 index 5fe6969f3eddb..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/processing_commands.ts +++ /dev/null @@ -1,197 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { buildDocumentation } from './utils'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const pipeDefinition: AutocompleteCommandDefinition = { - label: '|', - insertText: '|', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.pipeDoc', { - defaultMessage: 'Pipe (|)', - }), - sortText: 'B', -}; - -export const processingCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'stats', - insertText: 'stats', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.statsDoc', { - defaultMessage: - 'Calculates aggregate statistics, such as average, count, and sum, over the incoming search results set. Similar to SQL aggregation, if the stats command is used without a BY clause, only one row is returned, which is the aggregation over the entire incoming search results set. When you use a BY clause, one row is returned for each distinct value in the field specified in the BY clause. The stats command returns only the fields in the aggregation, and you can use a wide range of statistical functions with the stats command. When you perform more than one aggregation, separate each aggregation with a comma.', - }), - documentation: { - value: buildDocumentation( - 'stats aggs = fieldSpecification ( `,` fieldSpecification )* ( `by` groups = identifier ( `,` identifier )* )?', - ['… | stats sum(b) by b)', '… | stats avg = avg(a)'] - ), - }, - sortText: 'B', - }, - { - label: 'limit', - insertText: 'limit', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.limitDoc', { - defaultMessage: - 'Returns the first search results, in search order, based on the "limit" specified.', - }), - documentation: { - value: buildDocumentation('limit size = integerLiteral', ['… | limit 100', '… | limit 0']), - }, - sortText: 'B', - }, - { - label: 'eval', - insertText: 'eval', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.evalDoc', { - defaultMessage: - 'Calculates an expression and puts the resulting value into a search results field.', - }), - documentation: { - value: buildDocumentation('eval columns = fieldSpecification ( `,` fieldSpecification )*', [ - '… | eval a = b * c', - '… | eval then = 1 year + 2 weeks', - ]), - }, - sortText: 'B', - }, - { - label: 'keep', - insertText: 'keep', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.keepDoc', { - defaultMessage: 'Rearranges fields in the input table by applying the keep clauses in fields', - }), - documentation: { - value: buildDocumentation('keep fieldSpecification `,` fieldSpecification *', [ - '… | keep a,b', - ]), - }, - sortText: 'B', - }, - { - label: 'rename', - insertText: 'rename', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.renameDoc', { - defaultMessage: 'Renames an old column to a new one', - }), - documentation: { - value: buildDocumentation('rename new as old', ['… | rename a as b']), - }, - sortText: 'B', - }, - { - label: 'drop', - insertText: 'drop', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.dropDoc', { - defaultMessage: 'Drops columns', - }), - documentation: { - value: buildDocumentation('drop fieldSpecification `,` fieldSpecification *', [ - '… | drop a,b', - ]), - }, - sortText: 'B', - }, - { - label: 'sort', - insertText: 'sort', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.sortDoc', { - defaultMessage: - 'Sorts all results by the specified fields. When in descending order, the results missing a field are considered the smallest possible value of the field, or the largest possible value of the field when in ascending order.', - }), - documentation: { - value: buildDocumentation('sort orders = orderExpression ( `,` orderExpression )*', [ - '… | sort a desc, b nulls last, c asc nulls first', - '… | sort b nulls last`', - '… | sort c asc nulls first`', - ]), - }, - sortText: 'B', - }, - { - label: 'where', - insertText: 'where', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.whereDoc', { - defaultMessage: - 'Uses "predicate-expressions" to filter search results. A predicate expression, when evaluated, returns TRUE or FALSE. The where command only returns the results that evaluate to TRUE. For example, to filter results for a specific field value', - }), - documentation: { - value: buildDocumentation('where condition = expression', ['… | where status_code == 200']), - }, - sortText: 'B', - }, - { - label: 'dissect', - insertText: 'dissect', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.dissectDoc', { - defaultMessage: - 'Extracts multiple string values from a single string input, based on a pattern', - }), - documentation: { - value: buildDocumentation( - 'dissect (append_separator=)?', - ['… | dissect a "%{b} %{c}";'] - ), - }, - sortText: 'B', - }, - { - label: 'grok', - insertText: 'grok', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.grokDoc', { - defaultMessage: - 'Extracts multiple string values from a single string input, based on a pattern', - }), - documentation: { - value: buildDocumentation('grok ', [ - '… | grok a "%{b} %{c}";', - ]), - }, - sortText: 'B', - }, - { - label: 'mv_expand', - insertText: 'mv_expand', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.mvExpandDoc', { - defaultMessage: 'Expands multivalued fields into one row per value, duplicating other fields', - }), - documentation: { - value: buildDocumentation('mv_expand field', [ - 'ROW a=[1,2,3], b="b", j=["a","b"] | MV_EXPAND a', - ]), - }, - sortText: 'B', - }, - { - label: 'enrich', - insertText: 'enrich', - kind: 1, - detail: i18n.translate('monaco.esql.autocomplete.enrichDoc', { - defaultMessage: 'Enrich table with another table', - }), - documentation: { - value: buildDocumentation('enrich policy', ['... | ENRICH a']), - }, - sortText: 'B', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts deleted file mode 100644 index a14f776de1bbf..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_definitions/source_commands.ts +++ /dev/null @@ -1,31 +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 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 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { buildDocumentation } from './utils'; - -import type { AutocompleteCommandDefinition } from '../types'; - -export const sourceCommandsDefinitions: AutocompleteCommandDefinition[] = [ - { - label: 'from', - insertText: 'from', - kind: 0, - detail: i18n.translate('monaco.esql.autocomplete.fromDoc', { - defaultMessage: - 'Retrieves data from one or more datasets. A dataset is a collection of data that you want to search. The only supported dataset is an index. In a query or subquery, you must use the from command first and it does not need a leading pipe. For example, to retrieve data from an index:', - }), - documentation: { - value: buildDocumentation( - 'from` indexPatterns = wildcardIdentifier (`,` wildcardIdentifier)*', - ['from logs', 'from logs-*', 'from logs_*, events-*', 'from from remote*:logs*'] - ), - }, - sortText: 'A', - }, -]; diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts deleted file mode 100644 index a33c9f99f6f9e..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.test.ts +++ /dev/null @@ -1,226 +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 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 or the Server - * Side Public License, v 1. - */ - -import { CharStreams } from 'antlr4ts'; -import { AutocompleteListener } from './autocomplete_listener'; -import { ANTLREErrorListener } from '../../../common/error_listener'; - -import { getParser, ROOT_STATEMENT } from '../antlr_facade'; - -import { isDynamicAutocompleteItem } from './dymanic_item'; -import { getDurationItemsWithQuantifier } from './helpers'; -import { mathCommandDefinition } from './autocomplete_definitions/functions_commands'; - -describe('autocomplete_listener', () => { - const getAutocompleteSuggestions = (text: string) => { - const errorListener = new ANTLREErrorListener(); - const parseListener = new AutocompleteListener(); - const parser = getParser(CharStreams.fromString(text), errorListener, parseListener); - - parser[ROOT_STATEMENT](); - - return parseListener.getAutocompleteSuggestions(); - }; - - const testSuggestions = (text: string, expected: string[]) => { - test(`${text} => [${expected.join(',')}]`, () => { - const { suggestions } = getAutocompleteSuggestions(text); - expect(suggestions.map((i) => (isDynamicAutocompleteItem(i) ? i : i.label))).toEqual( - expected - ); - }); - }; - - describe('from', () => { - testSuggestions('f', ['from']); - testSuggestions('from ', ['SourceIdentifier']); - testSuggestions('from a,', ['SourceIdentifier']); - testSuggestions('from a, b ', ['SourceIdentifier']); - }); - - describe('where', () => { - testSuggestions('from a | where ', ['cidr_match', 'FieldIdentifier']); - testSuggestions('from a | where "field" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | where "field" >= ', ['FieldIdentifier']); - testSuggestions('from a | where "field" >= "field1" ', ['or', 'and', '|']); - testSuggestions('from a | where "field" >= "field1" and ', ['FieldIdentifier']); - testSuggestions('from a | where "field" >= "field1" and "field2" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | stats a=avg("field") | where a ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | stats a=avg("b") | where "c" ', [ - '==', - '!=', - '<', - '>', - '<=', - '>=', - 'like', - 'rlike', - 'in', - ]); - testSuggestions('from a | where "field" >= "field1" and "field2 == ', ['FieldIdentifier']); - }); - - describe('sort', () => { - testSuggestions('from a | sort ', ['FieldIdentifier']); - testSuggestions('from a | sort "field" ', ['asc', 'desc']); - testSuggestions('from a | sort "field" desc ', ['nulls']); - testSuggestions('from a | sort "field" desc nulls ', ['first', 'last']); - }); - - describe('limit', () => { - testSuggestions('from a | limit ', ['1000']); - testSuggestions('from a | limit 4 ', ['|']); - }); - - describe('mv_expand', () => { - testSuggestions('from a | mv_expand ', ['FieldIdentifier']); - testSuggestions('from a | mv_expand a ', ['|']); - }); - - describe('stats', () => { - testSuggestions('from a | stats ', ['var0']); - testSuggestions('from a | stats a ', ['=']); - testSuggestions('from a | stats a=', [ - 'avg', - 'max', - 'min', - 'sum', - 'count', - 'count_distinct', - 'median', - 'median_absolute_deviation', - 'percentile', - ]); - testSuggestions('from a | stats a=b by ', ['FieldIdentifier']); - testSuggestions('from a | stats a=c by d', ['|']); - testSuggestions('from a | stats a=b, ', ['var0']); - testSuggestions('from a | stats a=max', ['(']); - testSuggestions('from a | stats a=min(', ['FieldIdentifier']); - testSuggestions('from a | stats a=min(b', [')', 'FieldIdentifier']); - testSuggestions('from a | stats a=min(b) ', ['|', 'by']); - testSuggestions('from a | stats a=min(b) by ', ['FieldIdentifier']); - testSuggestions('from a | stats a=min(b),', ['var0']); - testSuggestions('from a | stats var0=min(b),var1=c,', ['var2']); - testSuggestions('from a | stats a=min(b), b=max(', ['FieldIdentifier']); - }); - - describe('enrich', () => { - for (const prevCommand of [ - '', - '| enrich other-policy ', - '| enrich other-policy on b ', - '| enrich other-policy with c ', - ]) { - testSuggestions(`from a ${prevCommand}| enrich`, ['PolicyIdentifier']); - testSuggestions(`from a ${prevCommand}| enrich policy `, ['|', 'on', 'with']); - testSuggestions(`from a ${prevCommand}| enrich policy on `, [ - 'PolicyMatchingFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b `, ['|', 'with']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with `, [ - 'var0', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 `, ['=', '|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = `, [ - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c `, ['|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, `, [ - 'var1', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 `, ['=', '|']); - testSuggestions(`from a ${prevCommand}| enrich policy on b with var0 = c, var1 = `, [ - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy with `, [ - 'var0', - 'PolicyFieldIdentifier', - ]); - testSuggestions(`from a ${prevCommand}| enrich policy with c`, ['=', '|']); - } - }); - - describe('eval', () => { - const functionSuggestions = mathCommandDefinition.map(({ label }) => String(label)); - - testSuggestions('from a | eval ', ['var0']); - testSuggestions('from a | eval a ', ['=']); - testSuggestions('from a | eval a=', functionSuggestions); - testSuggestions('from a | eval a=b, ', ['var0']); - testSuggestions('from a | eval a=round', ['(']); - testSuggestions('from a | eval a=round(', ['FieldIdentifier']); - testSuggestions('from a | eval a=round(b) ', ['|', '+', '-', '/', '*']); - testSuggestions('from a | eval a=round(b),', ['var0']); - testSuggestions('from a | eval a=round(b) + ', ['FieldIdentifier', ...functionSuggestions]); - // NOTE: this is handled also partially in the suggestion wrapper with auto-injection of closing brackets - testSuggestions('from a | eval a=round(b', [')', 'FieldIdentifier']); - testSuggestions('from a | eval a=round(b), b=round(', ['FieldIdentifier']); - testSuggestions('from a | stats a=round(b), b=round(', ['FieldIdentifier']); - testSuggestions('from a | eval var0=round(b), var1=round(c) | stats ', ['var2']); - - describe('date math', () => { - const dateSuggestions = [ - 'year', - 'month', - 'week', - 'day', - 'hour', - 'minute', - 'second', - 'millisecond', - ].flatMap((v) => [v, `${v}s`]); - const dateMathSymbols = ['+', '-']; - testSuggestions('from a | eval a = 1 ', dateMathSymbols.concat(dateSuggestions, ['|'])); - testSuggestions('from a | eval a = 1 year ', dateMathSymbols.concat(dateSuggestions, ['|'])); - testSuggestions( - 'from a | eval a = 1 day + 2 ', - dateMathSymbols.concat(dateSuggestions, ['|']) - ); - testSuggestions( - 'from a | eval var0=date_trunc(', - ['FieldIdentifier'].concat(...getDurationItemsWithQuantifier().map(({ label }) => label)) - ); - testSuggestions( - 'from a | eval var0=date_trunc(2 ', - [')', 'FieldIdentifier'].concat(dateSuggestions) - ); - }); - }); -}); diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts deleted file mode 100644 index 35c75e6ce6021..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/autocomplete_listener.ts +++ /dev/null @@ -1,641 +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 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 or the Server - * Side Public License, v 1. - */ -import type { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import type { AutocompleteCommandDefinition, UserDefinedVariables } from './types'; -import { DynamicAutocompleteItem } from './dymanic_item'; - -import { esql_parserListener as ESQLParserListener } from '../../antlr/esql_parser_listener'; -import { - esql_parser, - esql_parser as ESQLParser, - EnrichCommandContext, - EnrichWithClauseContext, - OperatorExpressionContext, -} from '../../antlr/esql_parser'; - -import { - processingCommandsDefinitions, - sourceCommandsDefinitions, - orderingCommandsDefinitions, - nullsCommandsDefinition, - nullsOrderingCommandsDefinitions, - comparisonCommandsDefinitions, - comparisonOperatorsCommandsDefinitions, - byOperatorDefinition, - pipeDefinition, - openBracketDefinition, - closeBracketDefinition, - mathOperatorsCommandsDefinitions, - aggregationFunctionsDefinitions, - mathCommandDefinition, - whereCommandDefinition, - assignOperatorDefinition, - buildConstantsDefinitions, - buildNewVarDefinition, - asOperatorDefinition, -} from './autocomplete_definitions'; - -import { - EvalCommandContext, - StatsCommandContext, - ComparisonContext, - WhereCommandContext, - SourceCommandContext, - OrderExpressionContext, - FieldContext, - QualifiedNameContext, - ProcessingCommandContext, - SourceIdentifierContext, - UserVariableContext, - BooleanExpressionContext, - RegexBooleanExpressionContext, - WhereBooleanExpressionContext, - LimitCommandContext, - ValueExpressionContext, - KeepCommandContext, - DropCommandContext, - RenameCommandContext, - DissectCommandContext, - GrokCommandContext, - MvExpandCommandContext, -} from '../../antlr/esql_parser'; -import { - onOperatorDefinition, - withOperatorDefinition, -} from './autocomplete_definitions/operators_commands'; -import { dateExpressionDefinitions } from './autocomplete_definitions/date_math_expressions'; -import { - endsWithOpenBracket, - getDateMathOperation, - getDurationItemsWithQuantifier, - isDateFunction, -} from './helpers'; - -export function nonNullable(v: T): v is NonNullable { - return v != null; -} - -export class AutocompleteListener implements ESQLParserListener { - private suggestions: Array = []; - private readonly userDefinedVariables: UserDefinedVariables = { - sourceIdentifiers: [], - policyIdentifiers: [], - }; - private readonly tables: string[][] = []; - private parentContext: number | undefined; - - private get fields(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.FieldIdentifier]; - } - - private get policies(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyIdentifier]; - } - - private get policyFields(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyFieldIdentifier]; - } - - private get policyMatchingField(): [DynamicAutocompleteItem] { - return [DynamicAutocompleteItem.PolicyMatchingFieldIdentifier]; - } - - private get hasSuggestions() { - return Boolean(this.suggestions.length); - } - - private isTerminalNodeExists(node: TerminalNode | undefined) { - return node && node.payload?.startIndex >= 0; - } - - private inspectOperatorExpressionContext( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined, - innerScope: 'constant' | 'dateExpression' | 'booleanExpression' - ): boolean { - if (!context) { - return false; - } - if (Array.isArray(context)) { - return context.some((c) => this.inspectOperatorExpressionContext(c, innerScope)); - } - if (context.operatorExpression()?.length) { - return this.inspectOperatorExpressionContext(context.operatorExpression(), innerScope); - } - if (context.primaryExpression()) { - return Boolean(context.primaryExpression()?.[innerScope]()); - } - return false; - } - - private hasDateExpressionTerminalNode( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined - ): boolean { - return this.inspectOperatorExpressionContext(context, 'dateExpression'); - } - - private hasOnlyConstantDefined( - context: OperatorExpressionContext | OperatorExpressionContext[] | undefined - ): boolean { - return this.inspectOperatorExpressionContext(context, 'constant'); - } - - private applyConditionalSuggestion( - skipDefinitions: AutocompleteCommandDefinition[], - targetDefinition: AutocompleteCommandDefinition, - context: number - ) { - if (!skipDefinitions.find((i) => i === targetDefinition) && this.parentContext === context) { - return targetDefinition; - } - } - - private getEndCommandSuggestions(skipDefinitions: AutocompleteCommandDefinition[] = []) { - return [ - pipeDefinition, - this.applyConditionalSuggestion(skipDefinitions, byOperatorDefinition, ESQLParser.STATS), - this.applyConditionalSuggestion(skipDefinitions, onOperatorDefinition, ESQLParser.ENRICH), - this.applyConditionalSuggestion(skipDefinitions, withOperatorDefinition, ESQLParser.ENRICH), - ].filter(nonNullable); - } - - private getNewVarName() { - const vars = this.tables.flat(); - let index = 0; - - while (true) { - const value = `var${index}`; - if (!vars.includes(value)) { - return value; - } - index++; - } - } - - getAutocompleteSuggestions() { - return { - suggestions: this.suggestions, - userDefinedVariables: this.userDefinedVariables, - }; - } - - /** ESQLParserListener fields **/ - - enterSourceCommand(ctx: SourceCommandContext) { - this.suggestions = []; - } - - exitSourceCommand(ctx: SourceCommandContext) { - if (ctx.exception) { - this.suggestions = sourceCommandsDefinitions; - } - } - - enterSourceIdentifier(ctx: SourceIdentifierContext) { - this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; - } - - exitSourceIdentifier(ctx: SourceIdentifierContext) { - if (!ctx.childCount) { - this.suggestions = [DynamicAutocompleteItem.SourceIdentifier]; - } else if (!ctx.exception && ctx.text) { - this.userDefinedVariables.sourceIdentifiers.push(ctx.text); - } - } - - enterProcessingCommand(ctx: ProcessingCommandContext) { - this.tables.push([]); - this.suggestions = []; - this.parentContext = undefined; - } - - exitProcessingCommand(ctx: ProcessingCommandContext) { - if (ctx.exception) { - this.suggestions = processingCommandsDefinitions; - } - this.parentContext = undefined; - } - - enterStatsCommand(ctx: StatsCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.STATS; - const fn = ctx.fields(); - if (!fn) { - this.suggestions = [buildNewVarDefinition(this.getNewVarName())]; - return; - } - } - - enterEvalCommand(ctx: EvalCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.EVAL; - } - - exitStatsCommand(ctx: StatsCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - this.suggestions = this.getEndCommandSuggestions([byOperatorDefinition]); - } - } - - exitKeepCommand?(ctx: KeepCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - if (qn.text.slice(-1) !== ',') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - - exitDropCommand?(ctx: DropCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - if (qn.text.slice(-1) !== ',') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - - enterRenameCommand(ctx: RenameCommandContext) { - this.parentContext = ESQLParser.RENAME; - } - - exitRenameCommand?(ctx: RenameCommandContext) { - const rc = ctx.renameClause(); - const commaExists = ctx.COMMA(); - if (!rc[0].exception) { - const qn = rc[0].renameVariable(); - const asExists = this.isTerminalNodeExists(rc[0].AS()); - if (asExists && qn && !qn.text) { - this.suggestions = []; - } - if (qn && qn.text) { - if (!commaExists.length) { - this.suggestions = this.getEndCommandSuggestions(); - } - } - } - } - - exitDissectCommand?(ctx: DissectCommandContext) { - const qn = ctx.qualifiedNames(); - const pattern = ctx.string(); - if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitGrokCommand?(ctx: GrokCommandContext) { - const qn = ctx.qualifiedNames(); - const pattern = ctx.string(); - if (qn && qn.text && pattern && pattern.text && pattern.text !== '') { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitMvExpandCommand?(ctx: MvExpandCommandContext) { - const qn = ctx.qualifiedNames(); - if (qn && qn.text) { - this.suggestions = this.getEndCommandSuggestions(); - } - } - - exitQualifiedName(ctx: QualifiedNameContext) { - const isInEval = this.parentContext === ESQLParser.EVAL; - const isInStats = this.parentContext === ESQLParser.STATS; - const isInRename = this.parentContext === ESQLParser.RENAME; - if (this.parentContext && isInRename) { - if (!ctx.exception && ctx.text) { - this.suggestions = [asOperatorDefinition]; - } - } - if (this.parentContext && (isInStats || isInEval)) { - this.suggestions = [ - ...this.getEndCommandSuggestions(), - ...(isInEval ? mathOperatorsCommandsDefinitions : []), - ]; - } - - if ( - ctx - .identifier() - .some( - (i) => - !( - this.isTerminalNodeExists(i.QUOTED_IDENTIFIER()) || - this.isTerminalNodeExists(i.UNQUOTED_IDENTIFIER()) - ) - ) - ) { - this.suggestions = this.fields; - } - } - - enterField(ctx: FieldContext) { - this.suggestions = []; - } - - exitField(ctx: FieldContext) { - const hasAssign = this.isTerminalNodeExists(ctx.ASSIGN()); - - if (ctx.exception) { - if (!hasAssign) { - this.suggestions = [buildNewVarDefinition(this.getNewVarName())]; - return; - } - } else { - if (!hasAssign) { - this.suggestions = [assignOperatorDefinition]; - } - } - } - - exitUserVariable(ctx: UserVariableContext) { - if (!ctx.exception && ctx.text) { - this.tables.at(-1)?.push(ctx.text); - } - } - - enterBooleanExpression(ctx: BooleanExpressionContext) { - this.suggestions = []; - } - - exitBooleanExpression(ctx: BooleanExpressionContext) { - if (ctx.exception) { - const ve = ctx.valueExpression(); - if (!ve) { - if (this.parentContext === ESQLParser.STATS) { - this.suggestions = [...aggregationFunctionsDefinitions]; - return; - } - - if (this.parentContext === ESQLParser.EVAL) { - this.suggestions = [...mathCommandDefinition]; - return; - } - } - } - } - - exitValueExpression(ctx: ValueExpressionContext) { - const isInStats = this.parentContext === ESQLParser.STATS; - const isInEval = this.parentContext === ESQLParser.EVAL; - - if (isInStats || isInEval) { - const hasFN = - ctx.tryGetToken(esql_parser.UNARY_FUNCTION, 0) || - ctx.tryGetToken(esql_parser.MATH_FUNCTION, 0); - const hasLP = ctx.tryGetToken(esql_parser.LP, 0); - const hasRP = ctx.tryGetToken(esql_parser.RP, 0); - // TODO: handle also other math signs later on - const hasPlusOrMinus = - ctx.tryGetToken(esql_parser.PLUS, 0) || ctx.tryGetToken(esql_parser.MINUS, 0); - - const hasDateLiteral = ctx.tryGetToken(esql_parser.DATE_LITERAL, 0); - - const isInDurationMode = hasDateLiteral || (hasFN && isDateFunction(hasFN.text)); - if (hasPlusOrMinus && this.isTerminalNodeExists(hasPlusOrMinus)) { - if (isInEval) { - this.suggestions = isInDurationMode - ? // eval a = 1 year + || eval a = date_trunc(1 year, date) - - [ - ...mathCommandDefinition.filter(({ label }) => isDateFunction(String(label))), - ...getDurationItemsWithQuantifier(), - ] - : // eval a = 1 + || eval a = abs(b) - - [...this.fields, ...mathCommandDefinition]; - } else { - this.suggestions = [...this.fields, ...aggregationFunctionsDefinitions]; - } - return; - } - - // Monaco will auto close the brackets but the language listener will not pick up yet this auto-change. - // We try to inject it outside but it won't cover all scenarios - if (hasFN) { - if (!hasLP) { - this.suggestions = [openBracketDefinition]; - return; - } - - this.suggestions = []; - - if (!hasRP) { - if (ctx.childCount === 3) { - // TODO: improve here to suggest comma if signature has multiple args - this.suggestions.push(closeBracketDefinition); - } - } - this.suggestions.push(...this.fields); - // Need to get the function name from the previous node (current is "(" ) - const fnName = hasFN.text; - const fnsToCheck = isInEval ? mathCommandDefinition : aggregationFunctionsDefinitions; - if (fnName && fnsToCheck.some(({ label }) => label === fnName)) { - // push date suggestions only for date functions - // TODO: improve this checks - if (isInEval && isDateFunction(fnName)) { - if (!ctx.tryGetToken(esql_parser.DATE_LITERAL, 0)) { - this.suggestions.push( - // if it's just after the open bracket, suggest also a number together with a date period, - // otherwise just the date period unit - ...(endsWithOpenBracket(ctx.text) - ? getDurationItemsWithQuantifier() - : dateExpressionDefinitions) - ); - } - } - } - - return; - } else { - if (ctx.childCount === 1) { - if (ctx.text && ctx.text.indexOf('(') === -1) { - this.suggestions = [...mathOperatorsCommandsDefinitions]; - if (isInEval) { - // eval a = 1 || eval a = 1 year + 1 - if ( - this.hasDateExpressionTerminalNode(ctx.operatorExpression()) || - this.hasOnlyConstantDefined(ctx.operatorExpression()) - ) { - this.suggestions = [...getDateMathOperation(), ...dateExpressionDefinitions]; - } - } - - if (isInStats) { - this.suggestions.push(...aggregationFunctionsDefinitions); - } - - this.suggestions.push(...this.getEndCommandSuggestions()); - } - return; - } - } - this.suggestions = [...this.fields]; - if (ctx.exception && isInEval) { - // case: eval a = x * or / - this.suggestions.push(...mathCommandDefinition); - } - this.suggestions.push(...this.getEndCommandSuggestions()); - } - } - - enterWhereBooleanExpression(ctx: WhereBooleanExpressionContext) { - this.suggestions = []; - } - - enterWhereCommand(ctx: WhereCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.WHERE; - } - - enterEnrichCommand(ctx: EnrichCommandContext) { - this.suggestions = []; - this.parentContext = ESQLParser.ENRICH; - } - - exitEnrichCommand(ctx: EnrichCommandContext) { - const policyName = ctx.enrichIdentifier().text; - if (policyName && !this.userDefinedVariables.policyIdentifiers.includes(policyName)) { - this.userDefinedVariables.policyIdentifiers.push(policyName); - } - - if (this.parentContext === ESQLParser.WITH) { - return; - } - if (!policyName) { - this.suggestions = this.policies; - } - - if (policyName) - if (this.parentContext === ESQLParser.ENRICH) { - const hasOn = this.isTerminalNodeExists(ctx.ON()); - if (hasOn && !ctx._matchField.text) { - this.suggestions = this.policyMatchingField; - } else { - this.suggestions = this.getEndCommandSuggestions( - hasOn ? [onOperatorDefinition] : undefined - ); - } - } - } - - enterEnrichWithClause(ctx: EnrichWithClauseContext) { - this.suggestions = []; - this.parentContext = ESQLParser.WITH; - } - - exitEnrichWithClause(ctx: EnrichWithClauseContext) { - const hasAssign = this.isTerminalNodeExists(ctx.ASSIGN()); - // Note: this gets filled only after the assign operation :( - if (ctx._newName?.text) { - this.tables.at(-1)?.push(ctx._newName.text); - } - - if (!ctx.exception && ctx.enrichFieldIdentifier().length === 1) { - // if it's after the assign operator, then suggest the fields from the policy - // TODO: need to check if the enrichFieldIdentifier given is a policyField or not and decide whether append the assignOperator - this.suggestions = !hasAssign - ? [assignOperatorDefinition, ...this.getEndCommandSuggestions()] - : this.policyFields; - } else { - this.suggestions = []; - if (!hasAssign) { - this.suggestions.push(buildNewVarDefinition(this.getNewVarName())); - } - if (!ctx._enrichField?.text) { - this.suggestions.push(...this.policyFields); - } - if (this.suggestions.length === 0) { - this.suggestions = this.getEndCommandSuggestions([ - onOperatorDefinition, - withOperatorDefinition, - ]); - } - } - } - - exitWhereCommand(ctx: WhereCommandContext) { - const booleanExpression = ctx.whereBooleanExpression(); - - if (booleanExpression.exception) { - if (!booleanExpression.text) { - this.suggestions = [...whereCommandDefinition, ...this.fields]; - return; - } - this.suggestions = this.fields; - return; - } else { - const innerBooleanExpressions = booleanExpression.getRuleContexts( - WhereBooleanExpressionContext - ); - const regexBooleanExpression = booleanExpression.getRuleContexts( - RegexBooleanExpressionContext - ); - - if (booleanExpression.WHERE_FUNCTIONS()) { - if (booleanExpression.COMMA().length) { - this.suggestions = []; - return; - } - } - - if (regexBooleanExpression.length) { - this.suggestions = []; - return; - } - - if (innerBooleanExpressions.some((be) => be.exception)) { - this.suggestions = this.fields; - return; - } - } - if (!this.hasSuggestions && !booleanExpression.WHERE_FUNCTIONS()) { - this.suggestions = comparisonCommandsDefinitions; - } - } - - exitComparison(ctx: ComparisonContext) { - const operatorExpression = ctx.operatorExpression(); - if (operatorExpression.some((o) => o.exception)) { - this.suggestions = this.fields; - return; - } - this.suggestions = [ - ...comparisonOperatorsCommandsDefinitions, - ...this.getEndCommandSuggestions(), - ]; - } - - exitOrderExpression(ctx: OrderExpressionContext) { - if (ctx.booleanExpression().exception) { - this.suggestions = this.fields; - return; - } - if (!this.isTerminalNodeExists(ctx.ORDERING())) { - this.suggestions = orderingCommandsDefinitions; - return; - } - if (!this.isTerminalNodeExists(ctx.NULLS_ORDERING())) { - this.suggestions = [nullsCommandsDefinition]; - return; - } - if (!this.isTerminalNodeExists(ctx.NULLS_ORDERING_DIRECTION())) { - this.suggestions = nullsOrderingCommandsDefinitions; - return; - } - } - - exitLimitCommand(ctx: LimitCommandContext) { - const DEFAULT_LIMIT_SIZE = 1000; - - if (!this.isTerminalNodeExists(ctx.INTEGER_LITERAL())) { - this.suggestions = buildConstantsDefinitions([DEFAULT_LIMIT_SIZE.toString()], ''); - } else { - this.suggestions = this.getEndCommandSuggestions(); - } - } -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.ts deleted file mode 100644 index 621c8900447a0..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/dymanic_item.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 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 or the Server - * Side Public License, v 1. - */ - -export enum DynamicAutocompleteItem { - SourceIdentifier = 'SourceIdentifier', - FieldIdentifier = 'FieldIdentifier', - PolicyIdentifier = 'PolicyIdentifier', - PolicyFieldIdentifier = 'PolicyFieldIdentifier', - PolicyMatchingFieldIdentifier = 'PolicyMatchingFieldIdentifier', -} - -const DynamicAutocompleteItems = Object.values(DynamicAutocompleteItem); - -export function isDynamicAutocompleteItem(v: unknown): v is DynamicAutocompleteItem { - return DynamicAutocompleteItems.some((dai) => dai === v); -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts deleted file mode 100644 index be1392cb11e72..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/helpers.ts +++ /dev/null @@ -1,33 +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 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 or the Server - * Side Public License, v 1. - */ - -import { mathOperatorsCommandsDefinitions } from './autocomplete_definitions'; -import { dateExpressionDefinitions } from './autocomplete_definitions/date_math_expressions'; - -export function endsWithOpenBracket(text: string) { - return /\($/.test(text); -} - -export function isDateFunction(fnName: string) { - // TODO: improve this and rely in signature in the future - return ['to_datetime', 'date_trunc', 'date_parse'].includes(fnName.toLowerCase()); -} - -export function getDateMathOperation() { - return mathOperatorsCommandsDefinitions.filter(({ label }) => ['+', '-'].includes(String(label))); -} - -export function getDurationItemsWithQuantifier(quantifier: number = 1) { - return dateExpressionDefinitions - .filter(({ label }) => !/s$/.test(label.toString())) - .map(({ label, insertText, ...rest }) => ({ - label: `${quantifier} ${label}`, - insertText: `${quantifier} ${insertText}`, - ...rest, - })); -} diff --git a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts b/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts deleted file mode 100644 index fc22bae7bbdb9..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/autocomplete/types.ts +++ /dev/null @@ -1,36 +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 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 or the Server - * Side Public License, v 1. - */ - -import { monaco } from '../../../..'; - -/** @public **/ -export interface ESQLCustomAutocompleteCallbacks { - getSourceIdentifiers?: CallbackFn; - getFieldsIdentifiers?: CallbackFn; - getPoliciesIdentifiers?: CallbackFn<{ name: string; indices: string[] }>; - getPolicyFieldsIdentifiers?: CallbackFn; - getPolicyMatchingFieldIdentifiers?: CallbackFn; -} - -/** @internal **/ -type CallbackFn = (ctx: { - word: string; - userDefinedVariables: UserDefinedVariables; -}) => T[] | Promise; - -/** @internal **/ -export interface UserDefinedVariables { - sourceIdentifiers: string[]; - policyIdentifiers: string[]; -} - -/** @internal **/ -export type AutocompleteCommandDefinition = Pick< - monaco.languages.CompletionItem, - 'label' | 'insertText' | 'kind' | 'detail' | 'documentation' | 'sortText' | 'command' ->; diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts new file mode 100644 index 0000000000000..39bd193d5611c --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_ast_provider.ts @@ -0,0 +1,121 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import type { EditorError } from '../../../types'; +import type { ESQLCallbacks } from '../ast/shared/types'; +import { monaco } from '../../../monaco_imports'; +import type { ESQLWorker } from '../../worker/esql_worker'; +import { suggest } from '../ast/autocomplete/autocomplete'; +import { getHoverItem } from '../ast/hover'; +import { getSignatureHelp } from '../ast/signature'; +import type { ESQLMessage } from '../ast/types'; +import { validateAst } from '../ast/validation/validation'; + +// from linear offset to Monaco position +export function offsetToRowColumn(expression: string, offset: number): monaco.Position { + const lines = expression.split(/\n/); + let remainingChars = offset; + let lineNumber = 1; + for (const line of lines) { + if (line.length >= remainingChars) { + return new monaco.Position(lineNumber, remainingChars + 1); + } + remainingChars -= line.length + 1; + lineNumber++; + } + + throw new Error('Algorithm failure'); +} + +function wrapAsMonacoMessage( + type: 'error' | 'warning', + code: string, + messages: Array +): EditorError[] { + const fallbackPosition = { column: 0, lineNumber: 0 }; + return messages.map((e) => { + if ('severity' in e) { + return e; + } + const startPosition = e.location ? offsetToRowColumn(code, e.location.min) : fallbackPosition; + const endPosition = e.location + ? offsetToRowColumn(code, e.location.max || 0) + : fallbackPosition; + return { + message: e.text, + startColumn: startPosition.column, + startLineNumber: startPosition.lineNumber, + endColumn: endPosition.column + 1, + endLineNumber: endPosition.lineNumber, + severity: type === 'error' ? monaco.MarkerSeverity.Error : monaco.MarkerSeverity.Warning, + _source: 'client' as const, + }; + }); +} + +export class ESQLAstAdapter { + constructor( + private worker: (...uris: monaco.Uri[]) => Promise, + private callbacks?: ESQLCallbacks + ) {} + + private async getAstWorker(model: monaco.editor.ITextModel) { + const worker = await this.worker(model.uri); + return worker.getAst; + } + + async getAst(model: monaco.editor.ITextModel, code?: string) { + const getAstFn = await this.getAstWorker(model); + return getAstFn(code ?? model.getValue()); + } + + async validate(model: monaco.editor.ITextModel, code: string) { + const getAstFn = await this.getAstWorker(model); + const { errors, warnings } = await validateAst( + code ?? model.getValue(), + getAstFn, + this.callbacks + ); + const monacoErrors = wrapAsMonacoMessage('error', code, errors); + const monacoWarnings = wrapAsMonacoMessage('warning', code, warnings); + return { errors: monacoErrors, warnings: monacoWarnings }; + } + + async suggestSignature( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.SignatureHelpContext + ) { + const getAstFn = await this.getAstWorker(model); + return getSignatureHelp(model, position, context, getAstFn); + } + + async getHover( + model: monaco.editor.ITextModel, + position: monaco.Position, + token: monaco.CancellationToken + ) { + const getAstFn = await this.getAstWorker(model); + return getHoverItem(model, position, token, getAstFn, this.callbacks); + } + + async autocomplete( + model: monaco.editor.ITextModel, + position: monaco.Position, + context: monaco.languages.CompletionContext + ) { + const getAstFn = await this.getAstWorker(model); + const suggestionEntries = await suggest(model, position, context, getAstFn, this.callbacks); + return { + suggestions: suggestionEntries.map((suggestion) => ({ + ...suggestion, + range: undefined as unknown as monaco.IRange, + })), + }; + } +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts deleted file mode 100644 index 4a407c3519769..0000000000000 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_completion_provider.ts +++ /dev/null @@ -1,136 +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 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 or the Server - * Side Public License, v 1. - */ - -import { monaco } from '../../../monaco_imports'; -import { DynamicAutocompleteItem, isDynamicAutocompleteItem } from '../autocomplete/dymanic_item'; -import { - buildFieldsDefinitions, - buildSourcesDefinitions, - buildPoliciesDefinitions, - buildNoPoliciesAvailableDefinition, - buildMatchingFieldsDefinition, -} from '../autocomplete/autocomplete_definitions/dynamic_commands'; -import { pipeDefinition } from '../autocomplete/autocomplete_definitions'; - -import type { - AutocompleteCommandDefinition, - ESQLCustomAutocompleteCallbacks, - UserDefinedVariables, -} from '../autocomplete/types'; -import type { ESQLWorker } from '../../worker/esql_worker'; - -export class ESQLCompletionAdapter implements monaco.languages.CompletionItemProvider { - constructor( - private worker: (...uris: monaco.Uri[]) => Promise, - private callbacks?: ESQLCustomAutocompleteCallbacks - ) {} - - public triggerCharacters = ['(', ' ', '']; - - private async injectDynamicAutocompleteItems( - suggestions: Array, - ctx: { - word: string; - userDefinedVariables: UserDefinedVariables; - } - ): Promise { - const allSuggestions: AutocompleteCommandDefinition[][] = await Promise.all( - suggestions.map(async (suggestion) => { - if (!isDynamicAutocompleteItem(suggestion)) { - return [suggestion]; - } - let dynamicItems: AutocompleteCommandDefinition[] = []; - - if (suggestion === DynamicAutocompleteItem.SourceIdentifier) { - dynamicItems = buildSourcesDefinitions( - (await this.callbacks?.getSourceIdentifiers?.(ctx)) ?? [] - ); - if (!ctx.word && ctx.userDefinedVariables.sourceIdentifiers.length) { - dynamicItems = [pipeDefinition]; - } - } - - if (suggestion === DynamicAutocompleteItem.FieldIdentifier) { - dynamicItems = buildFieldsDefinitions( - (await this.callbacks?.getFieldsIdentifiers?.(ctx)) ?? [] - ); - } - - if (suggestion === DynamicAutocompleteItem.PolicyIdentifier) { - const results = await this.callbacks?.getPoliciesIdentifiers?.(ctx); - dynamicItems = results?.length - ? buildPoliciesDefinitions(results) - : buildNoPoliciesAvailableDefinition(); - } - - if (suggestion === DynamicAutocompleteItem.PolicyFieldIdentifier) { - dynamicItems = buildFieldsDefinitions( - (await this.callbacks?.getPolicyFieldsIdentifiers?.(ctx)) || [] - ); - } - - if (suggestion === DynamicAutocompleteItem.PolicyMatchingFieldIdentifier) { - const [fields = [], matchingField] = await Promise.all([ - this.callbacks?.getFieldsIdentifiers?.(ctx), - this.callbacks?.getPolicyMatchingFieldIdentifiers?.(ctx), - ]); - dynamicItems = matchingField?.length - ? buildMatchingFieldsDefinition(matchingField[0], fields) - : buildFieldsDefinitions(fields); - } - return dynamicItems; - }) - ); - - return allSuggestions.flat(); - } - - async provideCompletionItems( - model: monaco.editor.IReadOnlyModel, - position: monaco.Position - ): Promise { - const lines = model.getLineCount(); - - const currentLineChars = model.getValueInRange({ - startLineNumber: 0, - startColumn: 0, - endLineNumber: position.lineNumber, - endColumn: position.column, - }); - const wordInfo = model.getWordUntilPosition(position); - const worker = await this.worker(model.uri); - const providedSuggestions = - lines !== position.lineNumber || - model.getLineContent(position.lineNumber).trimEnd().length >= position.column - ? await worker.provideAutocompleteSuggestionsFromString(currentLineChars) - : await worker.provideAutocompleteSuggestions(model.uri.toString(), { - word: wordInfo.word, - line: position.lineNumber, - index: position.column, - }); - - const withDynamicItems = providedSuggestions - ? await this.injectDynamicAutocompleteItems(providedSuggestions.suggestions, { - word: wordInfo.word, - userDefinedVariables: providedSuggestions.userDefinedVariables, - }) - : []; - - return { - suggestions: withDynamicItems.map((i) => ({ - ...i, - range: { - startLineNumber: position.lineNumber, - endLineNumber: position.lineNumber, - startColumn: wordInfo.startColumn, - endColumn: wordInfo.endColumn, - }, - })), - }; - } -} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts new file mode 100644 index 0000000000000..8881c9b458cc0 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_error_listener.ts @@ -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 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 or the Server + * Side Public License, v 1. + */ + +import type { ANTLRErrorListener, Recognizer, RecognitionException } from 'antlr4ts'; +import type { EditorError } from '../../../types'; +import { createError } from '../ast/ast_errors'; + +export class ESQLErrorListener implements ANTLRErrorListener { + private errors: EditorError[] = []; + + syntaxError( + recognizer: Recognizer, + offendingSymbol: any, + line: number, + column: number, + message: string, + error: RecognitionException | undefined + ): void { + const higherLevelError = error ? createError(error) : undefined; + const textMessage = + higherLevelError?.text && higherLevelError.text !== error?.message + ? higherLevelError.text + : `SyntaxError: ${message}`; + + let endColumn = column + 1; + let startColumn = column; + + if (higherLevelError) { + startColumn = higherLevelError.location.min + 1; + endColumn = higherLevelError.location.max + 1; + } else if (offendingSymbol?._text) { + endColumn = column + offendingSymbol._text.length; + } + + this.errors.push({ + startLineNumber: line, + endLineNumber: line, + startColumn, + endColumn, + message: textMessage, + severity: 8, // monaco.MarkerSeverity.Error, + }); + } + + getErrors(): EditorError[] { + return this.errors; + } +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts index c4817aac586d4..0148884f9bf8b 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_line_tokens.ts @@ -11,11 +11,12 @@ import { ESQLState } from './esql_state'; /** @internal **/ export class ESQLLineTokens implements monaco.languages.ILineTokens { - endState: monaco.languages.IState; + endState: ESQLState; tokens: monaco.languages.IToken[]; - constructor(tokens: monaco.languages.IToken[]) { + constructor(tokens: monaco.languages.IToken[], line: number) { this.endState = new ESQLState(); + this.endState.setLineNumber(line); this.tokens = tokens; } } diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts index a7cfd10f79276..d69702ff926f4 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_state.ts @@ -10,8 +10,20 @@ import { monaco } from '../../../monaco_imports'; /** @internal **/ export class ESQLState implements monaco.languages.IState { + private lastLine: number = 0; + + setLineNumber(n: number) { + this.lastLine = n; + } + + getLineNumber() { + return this.lastLine; + } + clone(): monaco.languages.IState { - return new ESQLState(); + const newState = new ESQLState(); + newState.setLineNumber(this.lastLine); + return newState; } equals(other: monaco.languages.IState): boolean { diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts index 6fc6caee2886f..1647b954ada7d 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_theme.ts @@ -77,12 +77,9 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ 'row', 'show', 'limit', - 'cidr_match', 'nulls_ordering_direction', 'nulls_ordering', 'null', - 'boolean_value', - 'comparison_operator', 'enrich', 'on', 'with', @@ -90,12 +87,8 @@ export const buildESQlTheme = (): monaco.editor.IStandaloneThemeData => ({ euiThemeVars.euiColorPrimaryText ), - // aggregation functions - ...buildRuleGroup(['unary_function'], euiThemeVars.euiColorPrimaryText), - // is null functions - ...buildRuleGroup(['where_functions'], euiThemeVars.euiColorPrimaryText), - // math functions - ...buildRuleGroup(['math_function'], euiThemeVars.euiColorPrimaryText), + // functions + ...buildRuleGroup(['functions'], euiThemeVars.euiColorPrimaryText), // operators ...buildRuleGroup( diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts new file mode 100644 index 0000000000000..497344dd606c4 --- /dev/null +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_token_helpers.ts @@ -0,0 +1,33 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { monaco } from '../../../monaco_imports'; +import { nonNullable } from '../ast/ast_helpers'; +import { ESQL_TOKEN_POSTFIX } from '../constants'; + +export function enrichTokensWithFunctionsMetadata( + tokens: monaco.languages.IToken[] +): monaco.languages.IToken[] { + // need to trim spaces as "abs (arg)" is still valid as function + const myTokensWithoutSpaces = tokens.filter( + ({ scopes }) => scopes !== 'expr_ws' + ESQL_TOKEN_POSTFIX + ); + // find out all unquoted_identifiers index + const possiblyFunctions = myTokensWithoutSpaces + .map((t, i) => (t.scopes === 'unquoted_identifier' + ESQL_TOKEN_POSTFIX ? i : undefined)) + .filter(nonNullable); + + // then check if the token next is an opening bracket + for (const index of possiblyFunctions) { + if (myTokensWithoutSpaces[index + 1]?.scopes === 'lp' + ESQL_TOKEN_POSTFIX) { + // set the custom "functions" token (only used in theming) + myTokensWithoutSpaces[index].scopes = 'functions' + ESQL_TOKEN_POSTFIX; + } + } + return [...tokens]; +} diff --git a/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts b/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts index 2166a5e6f68ea..aa0234c155c33 100644 --- a/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts +++ b/packages/kbn-monaco/src/esql/lib/monaco/esql_tokens_provider.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { CharStreams, Token } from 'antlr4ts'; +import { CharStreams, type Token } from 'antlr4ts'; import { monaco } from '../../../monaco_imports'; import { ANTLREErrorListener } from '../../../common/error_listener'; @@ -16,6 +16,7 @@ import { ESQLState } from './esql_state'; import { getLexer } from '../antlr_facade'; import { ESQL_TOKEN_POSTFIX } from '../constants'; +import { enrichTokensWithFunctionsMetadata } from './esql_token_helpers'; const EOF = -1; @@ -24,10 +25,16 @@ export class ESQLTokensProvider implements monaco.languages.TokensProvider { return new ESQLState(); } - tokenize(line: string, state: monaco.languages.IState): monaco.languages.ILineTokens { + tokenize(line: string, prevState: ESQLState): monaco.languages.ILineTokens { const errorStartingPoints: number[] = []; const errorListener = new ANTLREErrorListener(); - const inputStream = CharStreams.fromString(line); + // This has the drawback of not styling any ESQL wrong query as + // | from ... + const cleanedLine = + prevState.getLineNumber() && line.trimStart()[0] === '|' + ? line.trimStart().substring(1) + : line; + const inputStream = CharStreams.fromString(cleanedLine); const lexer = getLexer(inputStream, errorListener); let done = false; @@ -63,6 +70,11 @@ export class ESQLTokensProvider implements monaco.languages.TokensProvider { myTokens.sort((a, b) => a.startIndex - b.startIndex); - return new ESQLLineTokens(myTokens); + // special tratement for functions + // the previous custom Kibana grammar baked functions directly as tokens, so highlight was easier + // The ES grammar doesn't have the token concept of "function" + const tokensWithFunctions = enrichTokensWithFunctionsMetadata(myTokens); + + return new ESQLLineTokens(tokensWithFunctions, prevState.getLineNumber() + 1); } } diff --git a/packages/kbn-monaco/src/esql/worker/esql_worker.ts b/packages/kbn-monaco/src/esql/worker/esql_worker.ts index 4656ac9e9db7c..db3e01ae220e5 100644 --- a/packages/kbn-monaco/src/esql/worker/esql_worker.ts +++ b/packages/kbn-monaco/src/esql/worker/esql_worker.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import { CharStreams, type CodePointCharStream } from 'antlr4ts'; -import { monaco } from '../../monaco_imports'; -import { AutocompleteListener } from '../lib/autocomplete/autocomplete_listener'; +import { CharStreams } from 'antlr4ts'; +import type { monaco } from '../../monaco_imports'; import type { BaseWorkerDefinition } from '../../types'; import { getParser, ROOT_STATEMENT } from '../lib/antlr_facade'; -import { ANTLREErrorListener } from '../../common/error_listener'; +import { AstListener } from '../lib/ast/ast_factory'; +import { ESQLErrorListener } from '../lib/monaco/esql_error_listener'; export class ESQLWorker implements BaseWorkerDefinition { private readonly _ctx: monaco.worker.IWorkerContext; @@ -33,7 +33,7 @@ export class ESQLWorker implements BaseWorkerDefinition { const inputStream = this.getModelCharStream(modelUri); if (inputStream) { - const errorListener = new ANTLREErrorListener(); + const errorListener = new ESQLErrorListener(); const parser = getParser(inputStream, errorListener); parser[ROOT_STATEMENT](); @@ -43,32 +43,21 @@ export class ESQLWorker implements BaseWorkerDefinition { return []; } - private async provideAutocompleteSuggestionFromRawString( - inputStream: CodePointCharStream | undefined - ) { - if (inputStream) { - const errorListener = new ANTLREErrorListener(); - const parseListener = new AutocompleteListener(); - const parser = getParser(inputStream, errorListener, parseListener); - - parser[ROOT_STATEMENT](); - - return parseListener.getAutocompleteSuggestions(); + async getAst(text: string | undefined) { + if (!text) { + return { ast: [], errors: [] }; } - } - - public async provideAutocompleteSuggestions( - modelUri: string, - meta: { - word: string; - line: number; - index: number; - } - ) { - return this.provideAutocompleteSuggestionFromRawString(this.getModelCharStream(modelUri)); - } - - public async provideAutocompleteSuggestionsFromString(text: string) { - return this.provideAutocompleteSuggestionFromRawString(CharStreams.fromString(text)); + const inputStream = CharStreams.fromString(text); + const errorListener = new ESQLErrorListener(); + const parserListener = new AstListener(); + const parser = getParser(inputStream, errorListener, parserListener); + + parser[ROOT_STATEMENT](); + + const { ast } = parserListener.getAst(); + return { + ast, + errors: errorListener.getErrors(), + }; } } diff --git a/packages/kbn-monaco/src/types.ts b/packages/kbn-monaco/src/types.ts index 0e5952db8344c..b2559fd919d16 100644 --- a/packages/kbn-monaco/src/types.ts +++ b/packages/kbn-monaco/src/types.ts @@ -23,11 +23,25 @@ export interface CompleteLangModuleType extends LangModuleType { validation$: () => Observable; } -export interface CustomLangModuleType extends LangModuleType { +export interface LanguageProvidersModule { + validate: ( + model: monaco.editor.ITextModel, + code: string, + callbacks?: Deps + ) => Promise<{ errors: monaco.editor.IMarkerData[]; warnings: monaco.editor.IMarkerData[] }>; + getSuggestionProvider: (callbacks?: Deps) => monaco.languages.CompletionItemProvider; + getSignatureProvider?: (callbacks?: Deps) => monaco.languages.SignatureHelpProvider; + getHoverProvider?: (callbacks?: Deps) => monaco.languages.HoverProvider; +} + +export interface CustomLangModuleType + extends Omit, + LanguageProvidersModule { onLanguage: () => void; } export interface EditorError { + severity: monaco.MarkerSeverity; startLineNumber: number; startColumn: number; endLineNumber: number; diff --git a/packages/kbn-profiling-utils/common/__fixtures__/base_flamegraph.ts b/packages/kbn-profiling-utils/common/__fixtures__/base_flamegraph.ts index ce4aa885d3543..625a32959494c 100644 --- a/packages/kbn-profiling-utils/common/__fixtures__/base_flamegraph.ts +++ b/packages/kbn-profiling-utils/common/__fixtures__/base_flamegraph.ts @@ -288,10 +288,6 @@ export const baseFlamegraph: BaseFlameGraph = { Size: 35, SamplingRate: 1, SelfCPU: 7, - SelfAnnualCO2Tons: 0.0013627551116480942, - TotalAnnualCO2Tons: 0.04769642890768329, - SelfAnnualCostsUSD: 61.30240940376492, - TotalAnnualCostsUSD: 2145.5843291317715, TotalCPU: 245, TotalSamples: 7, TotalSeconds: 4.980000019073486, diff --git a/packages/kbn-profiling-utils/common/flamegraph.ts b/packages/kbn-profiling-utils/common/flamegraph.ts index 407a83b4d3504..fc19de530d58d 100644 --- a/packages/kbn-profiling-utils/common/flamegraph.ts +++ b/packages/kbn-profiling-utils/common/flamegraph.ts @@ -52,10 +52,6 @@ export interface BaseFlameGraph { AnnualCO2TonsInclusive: number[]; AnnualCostsUSDInclusive: number[]; AnnualCostsUSDExclusive: number[]; - SelfAnnualCO2Tons: number; - TotalAnnualCO2Tons: number; - SelfAnnualCostsUSD: number; - TotalAnnualCostsUSD: number; } /** Elasticsearch flamegraph */ @@ -77,8 +73,6 @@ export interface ElasticFlameGraph TotalAnnualCO2KgsItems: number[]; SelfAnnualCostsUSDItems: number[]; TotalAnnualCostsUSDItems: number[]; - SelfAnnualCO2Kgs: number; - TotalAnnualCO2Kgs: number; } /** @@ -119,10 +113,6 @@ export function createFlameGraph(base: BaseFlameGraph): ElasticFlameGraph { TotalAnnualCO2KgsItems: base.AnnualCO2TonsInclusive.map(convertTonsToKgs), SelfAnnualCostsUSDItems: base.AnnualCostsUSDExclusive, TotalAnnualCostsUSDItems: base.AnnualCostsUSDInclusive, - SelfAnnualCO2Kgs: convertTonsToKgs(base.SelfAnnualCO2Tons), - TotalAnnualCO2Kgs: convertTonsToKgs(base.TotalAnnualCO2Tons), - SelfAnnualCostsUSD: base.SelfAnnualCostsUSD, - TotalAnnualCostsUSD: base.TotalAnnualCostsUSD, }; const rootFrameGroupID = createFrameGroupID( diff --git a/packages/kbn-profiling-utils/common/functions.ts b/packages/kbn-profiling-utils/common/functions.ts index 5d1a225693caf..72dd41899f861 100644 --- a/packages/kbn-profiling-utils/common/functions.ts +++ b/packages/kbn-profiling-utils/common/functions.ts @@ -205,8 +205,8 @@ export function createTopNFunctions({ const sumSelfCPU = sumBy(framesAndCountsAndIds, 'CountExclusive'); const sumTotalCPU = sumBy(framesAndCountsAndIds, 'CountInclusive'); - const totalAnnualCO2Kgs = sumBy(framesAndCountsAndIds, 'totalAnnualCO2kgs'); - const totalAnnualCostUSD = sumBy(framesAndCountsAndIds, 'totalAnnualCostUSD'); + const totalAnnualCO2Kgs = sumBy(framesAndCountsAndIds, 'selfAnnualCO2kgs'); + const totalAnnualCostUSD = sumBy(framesAndCountsAndIds, 'selfAnnualCostUSD'); return { TotalCount: totalCount, diff --git a/packages/kbn-search-connectors/types/native_connectors.ts b/packages/kbn-search-connectors/types/native_connectors.ts index e29f1ebbf8a8a..232484011a1c1 100644 --- a/packages/kbn-search-connectors/types/native_connectors.ts +++ b/packages/kbn-search-connectors/types/native_connectors.ts @@ -1378,6 +1378,84 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record/packages/kbn-search-errors'], +}; diff --git a/packages/kbn-search-errors/kibana.jsonc b/packages/kbn-search-errors/kibana.jsonc new file mode 100644 index 0000000000000..9d4e7e2472b9d --- /dev/null +++ b/packages/kbn-search-errors/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/search-errors", + "owner": "@elastic/kibana-data-discovery" +} diff --git a/packages/kbn-search-errors/package.json b/packages/kbn-search-errors/package.json new file mode 100644 index 0000000000000..7b7dfe1bf0290 --- /dev/null +++ b/packages/kbn-search-errors/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/search-errors", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/src/plugins/data/public/search/errors/es_error.test.tsx b/packages/kbn-search-errors/src/es_error.test.tsx similarity index 100% rename from src/plugins/data/public/search/errors/es_error.test.tsx rename to packages/kbn-search-errors/src/es_error.test.tsx diff --git a/src/plugins/data/public/search/errors/es_error.tsx b/packages/kbn-search-errors/src/es_error.tsx similarity index 66% rename from src/plugins/data/public/search/errors/es_error.tsx rename to packages/kbn-search-errors/src/es_error.tsx index f5b978b38bc1e..8a5ab1ad3c503 100644 --- a/src/plugins/data/public/search/errors/es_error.tsx +++ b/packages/kbn-search-errors/src/es_error.tsx @@ -9,22 +9,32 @@ import React from 'react'; import { EuiButton, EuiCodeBlock, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ApplicationStart } from '@kbn/core/public'; -import { KbnError } from '@kbn/kibana-utils-plugin/common'; +import type { ApplicationStart } from '@kbn/core/public'; import { IEsError } from './types'; import { getRootCause } from './utils'; -export class EsError extends KbnError { +/** + * Checks if a given errors originated from Elasticsearch. + * Those params are assigned to the attributes property of an error. + * + * @param e + */ +export function isEsError(e: any): e is IEsError { + return !!e.attributes; +} + +export class EsError extends Error { readonly attributes: IEsError['attributes']; constructor(protected readonly err: IEsError, private readonly openInInspector: () => void) { super( `EsError: ${ getRootCause(err?.attributes?.error)?.reason || - i18n.translate('data.esError.unknownRootCause', { defaultMessage: 'unknown' }) + i18n.translate('searchErrors.esError.unknownRootCause', { defaultMessage: 'unknown' }) }` ); this.attributes = err.attributes; + Object.setPrototypeOf(this, new.target.prototype); } public getErrorMessage() { @@ -48,8 +58,14 @@ export class EsError extends KbnError { public getActions(application: ApplicationStart) { return [ - - {i18n.translate('data.esError.viewDetailsButtonLabel', { + + {i18n.translate('searchErrors.esError.viewDetailsButtonLabel', { defaultMessage: 'View details', })} , diff --git a/src/plugins/data/public/search/errors/painless_error.test.tsx b/packages/kbn-search-errors/src/painless_error.test.tsx similarity index 60% rename from src/plugins/data/public/search/errors/painless_error.test.tsx rename to packages/kbn-search-errors/src/painless_error.test.tsx index 03d4180b2aaac..25787eb650bd9 100644 --- a/src/plugins/data/public/search/errors/painless_error.test.tsx +++ b/packages/kbn-search-errors/src/painless_error.test.tsx @@ -12,7 +12,53 @@ const startMock = coreMock.createStart(); import { mount } from 'enzyme'; import { PainlessError } from './painless_error'; import { findTestSubject } from '@elastic/eui/lib/test'; -import * as searchPhaseException from '../../../common/search/test_data/search_phase_execution_exception.json'; + +const searchPhaseException = { + error: { + root_cause: [ + { + type: 'script_exception', + reason: 'compile error', + script_stack: ['invalid', '^---- HERE'], + script: 'invalid', + lang: 'painless', + position: { + offset: 0, + start: 0, + end: 7, + }, + }, + ], + type: 'search_phase_execution_exception', + reason: 'all shards failed', + phase: 'query', + grouped: true, + failed_shards: [ + { + shard: 0, + index: '.kibana_11', + node: 'b3HX8C96Q7q1zgfVLxEsPA', + reason: { + type: 'script_exception', + reason: 'compile error', + script_stack: ['invalid', '^---- HERE'], + script: 'invalid', + lang: 'painless', + position: { + offset: 0, + start: 0, + end: 7, + }, + caused_by: { + type: 'illegal_argument_exception', + reason: 'cannot resolve symbol [invalid]', + }, + }, + }, + ], + }, + status: 400, +}; describe('PainlessError', () => { beforeEach(() => { diff --git a/src/plugins/data/public/search/errors/painless_error.tsx b/packages/kbn-search-errors/src/painless_error.tsx similarity index 91% rename from src/plugins/data/public/search/errors/painless_error.tsx rename to packages/kbn-search-errors/src/painless_error.tsx index e76adddfb0815..08657ea134ab6 100644 --- a/src/plugins/data/public/search/errors/painless_error.tsx +++ b/packages/kbn-search-errors/src/painless_error.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiSpacer, EuiText, EuiCodeBlock } from '@elastic/eui'; -import { ApplicationStart } from '@kbn/core/public'; +import type { ApplicationStart } from '@kbn/core/public'; import type { DataView } from '@kbn/data-views-plugin/common'; -import { IEsError, isEsError } from './types'; -import { EsError } from './es_error'; +import type { IEsError } from './types'; +import { EsError, isEsError } from './es_error'; import { getRootCause } from './utils'; export class PainlessError extends EsError { @@ -37,7 +37,7 @@ export class PainlessError extends EsError { return ( <> - {i18n.translate('data.painlessError.painlessScriptedFieldErrorMessage', { + {i18n.translate('searchErrors.painlessError.painlessScriptedFieldErrorMessage', { defaultMessage: 'Error executing runtime field or scripted field on index pattern {indexPatternName}', values: { @@ -73,7 +73,7 @@ export class PainlessError extends EsError { onClick={() => onClick(this?.indexPattern?.id)} size="s" > - {i18n.translate('data.painlessError.buttonTxt', { + {i18n.translate('searchErrors.painlessError.buttonTxt', { defaultMessage: 'Edit script', })} diff --git a/src/plugins/data/public/search/search_interceptor/utils.ts b/packages/kbn-search-errors/src/render_search_error.ts similarity index 63% rename from src/plugins/data/public/search/search_interceptor/utils.ts rename to packages/kbn-search-errors/src/render_search_error.ts index f31e816de5267..73dd298877cca 100644 --- a/src/plugins/data/public/search/search_interceptor/utils.ts +++ b/packages/kbn-search-errors/src/render_search_error.ts @@ -6,19 +6,13 @@ * Side Public License, v 1. */ -import stringify from 'json-stable-stringify'; -import { Sha256 } from '@kbn/crypto-browser'; import { i18n } from '@kbn/i18n'; import { ReactNode } from 'react'; -import { BfetchRequestError } from '@kbn/bfetch-plugin/public'; -import { ApplicationStart } from '@kbn/core-application-browser'; -import { EsError } from '../errors'; +import { BfetchRequestError } from '@kbn/bfetch-error'; +import type { ApplicationStart } from '@kbn/core-application-browser'; +import { EsError } from './es_error'; -export async function createRequestHash(keys: Record) { - return new Sha256().update(stringify(keys), 'utf8').digest('hex'); -} - -export function getSearchErrorOverrideDisplay({ +export function renderSearchError({ error, application, }: { @@ -27,7 +21,7 @@ export function getSearchErrorOverrideDisplay({ }): { title: string; body: ReactNode; actions?: ReactNode[] } | undefined { if (error instanceof EsError) { return { - title: i18n.translate('data.search.esErrorTitle', { + title: i18n.translate('searchErrors.search.esErrorTitle', { defaultMessage: 'Cannot retrieve search results', }), body: error.getErrorMessage(), @@ -36,12 +30,12 @@ export function getSearchErrorOverrideDisplay({ } if (error.constructor.name === 'HttpFetchError' || error instanceof BfetchRequestError) { - const defaultMsg = i18n.translate('data.errors.fetchError', { + const defaultMsg = i18n.translate('searchErrors.errors.fetchError', { defaultMessage: 'Check your network connection and try again.', }); return { - title: i18n.translate('data.search.httpErrorTitle', { + title: i18n.translate('searchErrors.search.httpErrorTitle', { defaultMessage: 'Unable to connect to the Kibana server', }), body: error.message || defaultMsg, diff --git a/packages/kbn-search-errors/src/types.ts b/packages/kbn-search-errors/src/types.ts new file mode 100644 index 0000000000000..085d5961a2984 --- /dev/null +++ b/packages/kbn-search-errors/src/types.ts @@ -0,0 +1,24 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { estypes } from '@elastic/elasticsearch'; +import type { ConnectionRequestParams } from '@elastic/transport'; +import type { KibanaServerError } from '@kbn/kibana-utils-plugin/common'; + +type SanitizedConnectionRequestParams = Pick< + ConnectionRequestParams, + 'method' | 'path' | 'querystring' +>; + +interface IEsErrorAttributes { + error?: estypes.ErrorCause; + rawResponse?: estypes.SearchResponseBody; + requestParams?: SanitizedConnectionRequestParams; +} + +export type IEsError = KibanaServerError; diff --git a/src/plugins/data/public/search/errors/utils.ts b/packages/kbn-search-errors/src/utils.ts similarity index 100% rename from src/plugins/data/public/search/errors/utils.ts rename to packages/kbn-search-errors/src/utils.ts diff --git a/packages/kbn-search-errors/tsconfig.json b/packages/kbn-search-errors/tsconfig.json new file mode 100644 index 0000000000000..7c50a64bd11ee --- /dev/null +++ b/packages/kbn-search-errors/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n", + "@kbn/core", + "@kbn/kibana-utils-plugin", + "@kbn/data-views-plugin", + "@kbn/core-application-browser", + "@kbn/bfetch-error", + ] +} diff --git a/packages/kbn-text-based-editor/src/editor_footer.tsx b/packages/kbn-text-based-editor/src/editor_footer.tsx index 6bc663713a8d0..b9b183424c77a 100644 --- a/packages/kbn-text-based-editor/src/editor_footer.tsx +++ b/packages/kbn-text-based-editor/src/editor_footer.tsx @@ -26,7 +26,7 @@ import { import { Interpolation, Theme, css } from '@emotion/react'; import { css as classNameCss } from '@emotion/css'; -import type { MonacoError } from './helpers'; +import type { MonacoMessage } from './helpers'; const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0; const COMMAND_KEY = isMac ? '⌘' : '^'; @@ -98,10 +98,10 @@ export function ErrorsWarningsPopover({ isSpaceReduced, }: { isPopoverOpen: boolean; - items: MonacoError[]; + items: MonacoMessage[]; type: 'error' | 'warning'; setIsPopoverOpen: (flag: boolean) => void; - onErrorClick: (error: MonacoError) => void; + onErrorClick: (error: MonacoMessage) => void; isSpaceReduced?: boolean; }) { const strings = getConstsByType(type, items.length); @@ -109,7 +109,14 @@ export function ErrorsWarningsPopover({ - + { + setIsPopoverOpen(!isPopoverOpen); + }} + /> ; - errors?: MonacoError[]; - warning?: MonacoError[]; + errors?: MonacoMessage[]; + warnings?: MonacoMessage[]; detectTimestamp: boolean; - onErrorClick: (error: MonacoError) => void; + onErrorClick: (error: MonacoMessage) => void; runQuery: () => void; hideRunQueryText?: boolean; disableSubmitAction?: boolean; @@ -199,7 +206,7 @@ export const EditorFooter = memo(function EditorFooter({ lines, containerCSS, errors, - warning, + warnings, detectTimestamp, onErrorClick, runQuery, @@ -209,8 +216,8 @@ export const EditorFooter = memo(function EditorFooter({ isSpaceReduced, }: EditorFooterProps) { const { euiTheme } = useEuiTheme(); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - + const [isErrorPopoverOpen, setIsErrorPopoverOpen] = useState(false); + const [isWarningPopoverOpen, setIsWarningPopoverOpen] = useState(false); return ( 0 && ( { + if (isOpen) { + setIsWarningPopoverOpen(false); + } + setIsErrorPopoverOpen(isOpen); + }} onErrorClick={onErrorClick} - isSpaceReduced={isSpaceReduced} /> )} - {warning && warning.length > 0 && ( + {warnings && warnings.length > 0 && ( { + if (isOpen) { + setIsErrorPopoverOpen(false); + } + setIsWarningPopoverOpen(isOpen); + }} onErrorClick={onErrorClick} - isSpaceReduced={isSpaceReduced} /> )} diff --git a/packages/kbn-text-based-editor/src/helpers.test.ts b/packages/kbn-text-based-editor/src/helpers.test.ts index f0a4268f857bc..8ba691bb4e3ee 100644 --- a/packages/kbn-text-based-editor/src/helpers.test.ts +++ b/packages/kbn-text-based-editor/src/helpers.test.ts @@ -11,7 +11,7 @@ import { parseWarning, getInlineEditorText, getWrappedInPipesCode, - getIndicesForAutocomplete, + getIndicesList, } from './helpers'; describe('helpers', function () { @@ -23,7 +23,7 @@ describe('helpers', function () { const errors = [error]; expect(parseErrors(errors, 'SELECT miaou from test')).toEqual([ { - endColumn: 13, + endColumn: 14, endLineNumber: 1, message: ' Unknown column [miaou]', severity: 8, @@ -47,7 +47,7 @@ describe('helpers', function () { ) ).toEqual([ { - endColumn: 11, + endColumn: 12, endLineNumber: 3, message: ' Condition expression needs to be boolean, found [TEXT]', severity: 8, @@ -83,7 +83,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -99,7 +99,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -108,7 +108,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.src)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 84, startLineNumber: 1, }, @@ -124,7 +124,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -133,7 +133,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -142,7 +142,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -157,7 +157,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -166,7 +166,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', - severity: 8, + severity: 4, startColumn: 1, startLineNumber: 1, }, @@ -175,7 +175,7 @@ describe('helpers', function () { endLineNumber: 1, message: 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', - severity: 8, + severity: 4, startColumn: 52, startLineNumber: 1, }, @@ -233,8 +233,8 @@ describe('helpers', function () { }); }); - describe('getIndicesForAutocomplete', function () { - it('should not return system indices', async function () { + describe('getIndicesList', function () { + it('should return also system indices with hidden flag on', async function () { const dataViewsMock = dataViewPluginMocks.createStartContract(); const updatedDataViewsMock = { ...dataViewsMock, @@ -249,8 +249,11 @@ describe('helpers', function () { }, ]), }; - const indices = await getIndicesForAutocomplete(updatedDataViewsMock); - expect(indices).toStrictEqual(['logs']); + const indices = await getIndicesList(updatedDataViewsMock); + expect(indices).toStrictEqual([ + { name: '.system1', hidden: true }, + { name: 'logs', hidden: false }, + ]); }); }); }); diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index 234a5ae0089ab..88df8ef6a75e4 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -11,15 +11,9 @@ import useDebounce from 'react-use/lib/useDebounce'; import { monaco } from '@kbn/monaco'; import { i18n } from '@kbn/i18n'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { MapCache } from 'lodash'; -export interface MonacoError { - message: string; - startColumn: number; - startLineNumber: number; - endColumn: number; - endLineNumber: number; - severity: monaco.MarkerSeverity; -} +export type MonacoMessage = monaco.editor.IMarkerData; export const useDebounceWithOptions = ( fn: Function, @@ -45,7 +39,7 @@ export const useDebounceWithOptions = ( const quotedWarningMessageRegexp = /"(.*?)"/g; -export const parseWarning = (warning: string): MonacoError[] => { +export const parseWarning = (warning: string): MonacoMessage[] => { if (quotedWarningMessageRegexp.test(warning)) { const matches = warning.match(quotedWarningMessageRegexp); if (matches) { @@ -81,7 +75,7 @@ export const parseWarning = (warning: string): MonacoError[] => { startLineNumber, endColumn: startColumn + errorLength - 1, endLineNumber: startLineNumber, - severity: monaco.MarkerSeverity.Error, + severity: monaco.MarkerSeverity.Warning, }; }); } @@ -94,14 +88,18 @@ export const parseWarning = (warning: string): MonacoError[] => { startLineNumber: 1, endColumn: 10, endLineNumber: 1, - severity: monaco.MarkerSeverity.Error, + severity: monaco.MarkerSeverity.Warning, }, ]; }; -export const parseErrors = (errors: Error[], code: string): MonacoError[] => { +export const parseErrors = (errors: Error[], code: string): MonacoMessage[] => { return errors.map((error) => { - if (error.message.includes('line')) { + if ( + // Found while testing random commands (as inlinestats) + !error.message.includes('esql_illegal_argument_exception') && + error.message.includes('line') + ) { const text = error.message.split('line')[1]; const [lineNumber, startPosition, errorMessage] = text.split(':'); // initialize the length to 10 in case no error word found @@ -114,7 +112,7 @@ export const parseErrors = (errors: Error[], code: string): MonacoError[] => { message: errorMessage, startColumn: Number(startPosition), startLineNumber: Number(lineNumber), - endColumn: Number(startPosition) + errorLength, + endColumn: Number(startPosition) + errorLength + 1, endLineNumber: Number(lineNumber), severity: monaco.MarkerSeverity.Error, }; @@ -193,11 +191,23 @@ export const getWrappedInPipesCode = (code: string, isWrapped: boolean): string return codeNoLines.join(isWrapped ? ' | ' : '\n| '); }; -export const getIndicesForAutocomplete = async (dataViews: DataViewsPublicPluginStart) => { +export const getIndicesList = async (dataViews: DataViewsPublicPluginStart) => { const indices = await dataViews.getIndices({ showAllIndices: false, pattern: '*', isRollupIndex: () => false, }); - return indices.filter((index) => !index.name.startsWith('.')).map((i) => i.name); + return indices.map((index) => ({ name: index.name, hidden: index.name.startsWith('.') })); +}; + +// refresh the esql cache entry after 10 minutes +const CACHE_INVALIDATE_DELAY = 10 * 60 * 1000; + +export const clearCacheWhenOld = (cache: MapCache, esqlQuery: string) => { + if (cache.has(esqlQuery)) { + const cacheEntry = cache.get(esqlQuery); + if (Date.now() - cacheEntry.timestamp > CACHE_INVALIDATE_DELAY) { + cache.delete(esqlQuery); + } + } }; diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 9d175ef86ecf0..adcff950575e3 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -6,22 +6,22 @@ * Side Public License, v 1. */ -import React, { useRef, memo, useEffect, useState, useCallback } from 'react'; +import React, { useRef, memo, useEffect, useState, useCallback, useMemo } from 'react'; import classNames from 'classnames'; +import memoize from 'lodash/memoize'; import { SQLLang, monaco, ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang, - ESQLCustomAutocompleteCallbacks, + type ESQLCallbacks, } from '@kbn/monaco'; import type { AggregateQuery } from '@kbn/es-query'; import { getAggregateQueryMode, getLanguageDisplayName } from '@kbn/es-query'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; import type { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; -import type { SerializedEnrichPolicy } from '@kbn/index-management-plugin/common'; import { type LanguageDocumentationSections, LanguageDocumentationPopover, @@ -50,13 +50,14 @@ import { } from './text_based_languages_editor.styles'; import { useDebounceWithOptions, - parseErrors, parseWarning, getInlineEditorText, getDocumentationSections, - MonacoError, + type MonacoMessage, getWrappedInPipesCode, - getIndicesForAutocomplete, + parseErrors, + getIndicesList, + clearCacheWhenOld, } from './helpers'; import { EditorFooter } from './editor_footer'; import { ResizableButton } from './resizable_button'; @@ -136,7 +137,6 @@ const languageId = (language: string) => { let clickedOutside = false; let initialRender = true; let updateLinesFromModel = false; -let currentCursorContent = ''; let lines = 1; export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ @@ -146,8 +146,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ expandCodeEditor, isCodeEditorExpanded, detectTimestamp = false, - errors, - warning, + errors: serverErrors, + warning: serverWarning, isDisabled, isDarkMode, hideMinimizeButton, @@ -163,6 +163,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const { dataViews, expressions, indexManagementApiService, application } = kibana.services; const [code, setCode] = useState(queryString ?? ''); const [codeOneLiner, setCodeOneLiner] = useState(''); + // To make server side errors less "sticky", register the state of the code when submitting + const [codeWhenSubmitted, setCodeStateOnSubmission] = useState(code); const [editorHeight, setEditorHeight] = useState( isCodeEditorExpanded ? EDITOR_INITIAL_HEIGHT_EXPANDED : EDITOR_INITIAL_HEIGHT ); @@ -171,13 +173,27 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const [isCompactFocused, setIsCompactFocused] = useState(isCodeEditorExpanded); const [isCodeEditorExpandedFocused, setIsCodeEditorExpandedFocused] = useState(false); const [isWordWrapped, setIsWordWrapped] = useState(false); - const [editorErrors, setEditorErrors] = useState([]); - const [editorWarning, setEditorWarning] = useState([]); + + const [editorMessages, setEditorMessages] = useState<{ + errors: MonacoMessage[]; + warnings: MonacoMessage[]; + }>({ + errors: serverErrors ? parseErrors(serverErrors, code) : [], + warnings: serverWarning ? parseWarning(serverWarning) : [], + }); + + const onQuerySubmit = useCallback(() => { + const currentValue = editor1.current?.getValue(); + if (currentValue != null) { + setCodeStateOnSubmission(currentValue); + } + onTextLangQuerySubmit({ [language]: currentValue } as AggregateQuery); + }, [language, onTextLangQuerySubmit]); const [documentationSections, setDocumentationSections] = useState(); - const policiesRef = useRef([]); + const codeRef = useRef(code); // Registers a command to redirect users to the index management page // to create a new policy. The command is called by the buildNoPoliciesAvailableDefinition @@ -193,8 +209,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ isCompactFocused, editorHeight, isCodeEditorExpanded, - Boolean(errors?.length), - Boolean(warning), + Boolean(editorMessages.errors.length), + Boolean(editorMessages.warnings.length), isCodeEditorExpandedFocused, Boolean(documentationSections), Boolean(editorIsInline) @@ -247,11 +263,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ [editorHeight] ); - const onQuerySubmit = useCallback(() => { - const currentValue = editor1.current?.getValue(); - onTextLangQuerySubmit({ [language]: currentValue } as AggregateQuery); - }, [language, onTextLangQuerySubmit]); - const restoreInitialMode = () => { setIsCodeEditorExpandedFocused(false); if (isCodeEditorExpanded) return; @@ -294,30 +305,117 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ updateLinesFromModel = true; }, []); + const { cache: esqlFieldsCache, memoizedFieldsFromESQL } = useMemo(() => { + // need to store the timing of the first request so we can atomically clear the cache per query + const fn = memoize( + (...args: [{ esql: string }, ExpressionsStart]) => ({ + timestamp: Date.now(), + result: fetchFieldsFromESQL(...args), + }), + ({ esql }) => esql + ); + return { cache: fn.cache, memoizedFieldsFromESQL: fn }; + }, []); + + const esqlCallbacks: ESQLCallbacks = useMemo( + () => ({ + getSources: async () => { + return await getIndicesList(dataViews); + }, + getFieldsFor: async ({ query: queryToExecute }: { query?: string } | undefined = {}) => { + if (queryToExecute) { + // ES|QL with limit 0 returns only the columns and is more performant + const esqlQuery = { + esql: `${queryToExecute} | limit 0`, + }; + // Check if there's a stale entry and clear it + clearCacheWhenOld(esqlFieldsCache, esqlQuery.esql); + try { + const table = await memoizedFieldsFromESQL(esqlQuery, expressions).result; + return table?.columns.map((c) => ({ name: c.name, type: c.meta.type })) || []; + } catch (e) { + // no action yet + } + } + return []; + }, + getPolicies: async () => { + const { data: policies, error } = + (await indexManagementApiService?.getAllEnrichPolicies()) || {}; + if (error || !policies) { + return []; + } + return policies.map(({ type, query: policyQuery, ...rest }) => rest); + }, + }), + [dataViews, expressions, indexManagementApiService, esqlFieldsCache, memoizedFieldsFromESQL] + ); + + const queryValidation = useCallback( + async ({ active }: { active: boolean }) => { + if (!editorModel.current || language !== 'esql' || editorModel.current.isDisposed()) return; + monaco.editor.setModelMarkers(editorModel.current, 'Unified search', []); + const { warnings: parserWarnings, errors: parserErrors } = await ESQLLang.validate( + editorModel.current, + code, + esqlCallbacks + ); + const markers = []; + + if (parserErrors.length) { + markers.push(...parserErrors); + } + if (active) { + setEditorMessages({ errors: parserErrors, warnings: parserWarnings }); + monaco.editor.setModelMarkers(editorModel.current, 'Unified search', markers); + return; + } + }, + [esqlCallbacks, language, code] + ); + useDebounceWithOptions( () => { if (!editorModel.current) return; - if (warning && (!errors || !errors.length)) { - const parsedWarning = parseWarning(warning); - setEditorWarning(parsedWarning); - } else { - setEditorWarning([]); - } - if (errors && errors.length) { - const parsedErrors = parseErrors(errors, code); - setEditorErrors(parsedErrors); - monaco.editor.setModelMarkers(editorModel.current, 'Unified search', parsedErrors); + const subscription = { active: true }; + if (code === codeWhenSubmitted) { + if (serverErrors || serverWarning) { + const parsedErrors = parseErrors(serverErrors || [], code); + const parsedWarning = serverWarning ? parseWarning(serverWarning) : []; + setEditorMessages({ + errors: parsedErrors, + warnings: parsedErrors.length ? [] : parsedWarning, + }); + monaco.editor.setModelMarkers( + editorModel.current, + 'Unified search', + parsedErrors.length ? parsedErrors : [] + ); + return; + } } else { - monaco.editor.setModelMarkers(editorModel.current, 'Unified search', []); - setEditorErrors([]); + queryValidation(subscription).catch((error) => { + // console.log({ error }); + }); } + return () => (subscription.active = false); }, { skipFirstRender: false }, 256, - [errors, warning] + [serverErrors, serverWarning, code] + ); + + const suggestionProvider = useMemo( + () => (language === 'esql' ? ESQLLang.getSuggestionProvider?.(esqlCallbacks) : undefined), + [language, esqlCallbacks] ); - const onErrorClick = useCallback(({ startLineNumber, startColumn }: MonacoError) => { + const hoverProvider = useMemo( + () => (language === 'esql' ? ESQLLang.getHoverProvider?.(esqlCallbacks) : undefined), + [language, esqlCallbacks] + ); + + const onErrorClick = useCallback(({ startLineNumber, startColumn }: MonacoMessage) => { if (!editor1.current) { return; } @@ -351,7 +449,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ const text = getInlineEditorText(queryString, Boolean(hasLines)); const queryLength = text.length; const unusedSpace = - (errors && errors.length) || warning + editorMessages.errors.length || editorMessages.warnings.length ? EDITOR_ONE_LINER_UNUSED_SPACE_WITH_ERRORS : EDITOR_ONE_LINER_UNUSED_SPACE; const charactersAlowed = Math.floor((width - unusedSpace) / FONT_WIDTH); @@ -364,7 +462,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } } }, - [isCompactFocused, queryString, errors, warning] + [isCompactFocused, queryString, editorMessages] ); useEffect(() => { @@ -417,73 +515,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } }, [language, documentationSections]); - const getSourceIdentifiers: ESQLCustomAutocompleteCallbacks['getSourceIdentifiers'] = - useCallback(async () => { - return await getIndicesForAutocomplete(dataViews); - }, [dataViews]); - - const getFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getFieldsIdentifiers'] = useCallback( - async (ctx) => { - const pipes = currentCursorContent?.split('|'); - pipes?.pop(); - const validContent = pipes?.join('|'); - if (validContent) { - // ES|QL with limit 0 returns only the columns and is more performant - const esqlQuery = { - esql: `${validContent} | limit 0`, - }; - try { - const table = await fetchFieldsFromESQL(esqlQuery, expressions); - return table?.columns.map((c) => c.name) || []; - } catch (e) { - // no action yet - } - } - return []; - }, - [expressions] - ); - - const getPoliciesIdentifiers: ESQLCustomAutocompleteCallbacks['getPoliciesIdentifiers'] = - useCallback( - async (ctx) => { - const { data: policies, error } = - (await indexManagementApiService?.getAllEnrichPolicies()) || {}; - policiesRef.current = policies || []; - if (error || !policies) { - return []; - } - return policies.map(({ name, sourceIndices }) => ({ name, indices: sourceIndices })); - }, - [indexManagementApiService] - ); - - const getPolicyFieldsIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyFieldsIdentifiers'] = - useCallback( - async (ctx) => - policiesRef.current - .filter(({ name }) => ctx.userDefinedVariables.policyIdentifiers.includes(name)) - .flatMap(({ enrichFields }) => enrichFields), - [] - ); - - const getPolicyMatchingFieldIdentifiers: ESQLCustomAutocompleteCallbacks['getPolicyMatchingFieldIdentifiers'] = - useCallback( - async (ctx) => { - // try to load the list if none is present yet but - // at least one policy is declared in the userDefinedVariables - // (this happens if the user pastes an ESQL statement with the policy name in it) - if (!policiesRef.current.length && ctx.userDefinedVariables.policyIdentifiers.length) { - await getPoliciesIdentifiers(ctx); - } - const matchingField = policiesRef.current.find(({ name }) => - ctx.userDefinedVariables.policyIdentifiers.includes(name) - )?.matchField; - return matchingField ? [matchingField] : []; - }, - [getPoliciesIdentifiers] - ); - const codeEditorOptions: CodeEditorProps['options'] = { automaticLayout: false, accessibilitySupport: 'off', @@ -675,44 +706,60 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ )} )} - {!isCompactFocused && errors && errors.length > 0 && ( + {!isCompactFocused && editorMessages.errors.length > 0 && ( - {errors.length} - - )} - {!isCompactFocused && warning && (!errors || errors.length === 0) && ( - - {editorWarning.length} + {editorMessages.errors.length} )} + {!isCompactFocused && + editorMessages.warnings.length > 0 && + editorMessages.errors.length === 0 && ( + + {editorMessages.warnings.length} + + )} { + if (isCompactFocused || !hoverProvider?.provideHover) { + return { contents: [] }; + } + return hoverProvider?.provideHover(model, position, token); + }, + }} onChange={onQueryUpdate} editorDidMount={(editor) => { editor1.current = editor; @@ -736,7 +783,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ endColumn: currentPosition?.column ?? 1, }); if (content) { - currentCursorContent = content || editor.getValue(); + codeRef.current = content || editor.getValue(); } }); @@ -752,9 +799,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ editor.addCommand( // eslint-disable-next-line no-bitwise monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, - function () { - onQuerySubmit(); - } + onQuerySubmit ); if (!isCodeEditorExpanded) { editor.onDidContentSizeChange((e) => { @@ -767,10 +812,13 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ { + if (editorMessages.errors.some((e) => e.source !== 'client')) { + onQuerySubmit(); + } + }} detectTimestamp={detectTimestamp} editorIsInline={editorIsInline} disableSubmitAction={disableSubmitAction} @@ -858,8 +906,6 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ )} {isCodeEditorExpanded && ( diff --git a/packages/kbn-ui-shared-deps-src/BUILD.bazel b/packages/kbn-ui-shared-deps-src/BUILD.bazel index 95b9c7ac51e27..cd97c193f9f86 100644 --- a/packages/kbn-ui-shared-deps-src/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-src/BUILD.bazel @@ -28,6 +28,7 @@ webpack_cli( "//packages/kbn-datemath", "//packages/kbn-analytics", "//packages/kbn-es-query", + "//packages/kbn-search-errors", "//packages/kbn-std", "//packages/kbn-safer-lodash-set", "//packages/kbn-peggy", diff --git a/packages/kbn-ui-shared-deps-src/src/definitions.js b/packages/kbn-ui-shared-deps-src/src/definitions.js index e95ff4ac0a732..9ae258dca6bc8 100644 --- a/packages/kbn-ui-shared-deps-src/src/definitions.js +++ b/packages/kbn-ui-shared-deps-src/src/definitions.js @@ -89,6 +89,7 @@ const externals = { uuid: '__kbnSharedDeps__.Uuid', '@kbn/analytics': '__kbnSharedDeps__.KbnAnalytics', '@kbn/es-query': '__kbnSharedDeps__.KbnEsQuery', + '@kbn/search-errors': '__kbnSharedDeps__.KbnSearchErrors', '@kbn/std': '__kbnSharedDeps__.KbnStd', '@kbn/safer-lodash-set': '__kbnSharedDeps__.SaferLodashSet', '@kbn/shared-ux-error-boundary': '__kbnSharedDeps__.KbnSharedUxErrorBoundary', diff --git a/packages/kbn-ui-shared-deps-src/src/entry.js b/packages/kbn-ui-shared-deps-src/src/entry.js index 6e30acf963ab2..6ba856cbbc2d1 100644 --- a/packages/kbn-ui-shared-deps-src/src/entry.js +++ b/packages/kbn-ui-shared-deps-src/src/entry.js @@ -64,6 +64,7 @@ export const TsLib = require('tslib'); export const Uuid = require('uuid'); export const KbnAnalytics = require('@kbn/analytics'); export const KbnEsQuery = require('@kbn/es-query'); +export const KbnSearchErrors = require('@kbn/search-errors'); export const KbnStd = require('@kbn/std'); export const SaferLodashSet = require('@kbn/safer-lodash-set'); diff --git a/packages/kbn-ui-shared-deps-src/tsconfig.json b/packages/kbn-ui-shared-deps-src/tsconfig.json index 6b89a4adff0df..33f7503df2416 100644 --- a/packages/kbn-ui-shared-deps-src/tsconfig.json +++ b/packages/kbn-ui-shared-deps-src/tsconfig.json @@ -11,22 +11,11 @@ "**/*.js", ], "exclude": [ + "src/entry.js", "**/*.config.js", "target/**/*", ], "kbn_references": [ - "@kbn/ui-theme", - "@kbn/i18n", - "@kbn/i18n-react", - "@kbn/monaco", - "@kbn/datemath", - "@kbn/flot-charts", - "@kbn/analytics", - "@kbn/es-query", - "@kbn/rison", - "@kbn/std", - "@kbn/safer-lodash-set", "@kbn/repo-info", - "@kbn/shared-ux-error-boundary" ] } diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts index 8ce37bd473a8a..6a389b5485e3b 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts @@ -42,7 +42,7 @@ describe('migration v2', () => { }); it('clean ups if migration fails', async () => { - const { runMigrations, client } = await setupNextMinor(); + const { runMigrations /* , client */ } = await setupNextMinor(); await expect(runMigrations()).rejects.toThrowErrorMatchingInlineSnapshot(` "Unable to complete saved object migrations for the [${defaultKibanaIndex}] index: Migrations failed. Reason: 1 corrupt saved object documents were found: corrupt:2baf4de0-a6d4-11ed-ba5a-39196fc76e60 @@ -63,7 +63,7 @@ describe('migration v2', () => { ); expect(logRecordWithPit).toBeTruthy(); - + /* TEMPORARILY DISABLE const pitId = logRecordWithPit.right.pitId; expect(pitId).toBeTruthy(); @@ -75,6 +75,7 @@ describe('migration v2', () => { }) // throws an exception that cannot search with closed PIT ).rejects.toThrow(/search_phase_execution_exception/); + */ }); afterEach(async () => { diff --git a/src/plugins/bfetch/common/index.ts b/src/plugins/bfetch/common/index.ts index caa3219541cc5..8f4b28c48e25f 100644 --- a/src/plugins/bfetch/common/index.ts +++ b/src/plugins/bfetch/common/index.ts @@ -16,4 +16,3 @@ export { DISABLE_BFETCH, BFETCH_ROUTE_VERSION_LATEST, } from './constants'; -export { BfetchRequestError } from './bfetch_error'; diff --git a/src/plugins/bfetch/common/util/normalize_error.ts b/src/plugins/bfetch/common/util/normalize_error.ts index ab34f89a9feed..0bbec5eb86e01 100644 --- a/src/plugins/bfetch/common/util/normalize_error.ts +++ b/src/plugins/bfetch/common/util/normalize_error.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { BfetchRequestError } from '@kbn/bfetch-error'; import { ErrorLike } from '../batch'; -import { BfetchRequestError } from '..'; export const normalizeError = (err: any): E => { if (!err) { diff --git a/src/plugins/bfetch/public/index.ts b/src/plugins/bfetch/public/index.ts index aba764781f78e..a4c60cdf127d7 100644 --- a/src/plugins/bfetch/public/index.ts +++ b/src/plugins/bfetch/public/index.ts @@ -15,7 +15,6 @@ export { split } from './streaming'; export type { BatchedFunc } from './batching/types'; export { DISABLE_BFETCH } from '../common/constants'; -export { BfetchRequestError } from '../common/bfetch_error'; export function plugin(initializerContext: PluginInitializerContext) { return new BfetchPublicPlugin(initializerContext); diff --git a/src/plugins/bfetch/public/streaming/from_streaming_xhr.ts b/src/plugins/bfetch/public/streaming/from_streaming_xhr.ts index 6e65e556f53c4..a2778f181f516 100644 --- a/src/plugins/bfetch/public/streaming/from_streaming_xhr.ts +++ b/src/plugins/bfetch/public/streaming/from_streaming_xhr.ts @@ -7,7 +7,7 @@ */ import { Observable, Subject } from 'rxjs'; -import { BfetchRequestError } from '../../common'; +import { BfetchRequestError } from '@kbn/bfetch-error'; /** * Creates observable from streaming XMLHttpRequest, where each event diff --git a/src/plugins/bfetch/tsconfig.json b/src/plugins/bfetch/tsconfig.json index 48e56a689b447..49e273f958e0a 100644 --- a/src/plugins/bfetch/tsconfig.json +++ b/src/plugins/bfetch/tsconfig.json @@ -11,6 +11,7 @@ "@kbn/config-schema", "@kbn/std", "@kbn/core-http-common", + "@kbn/bfetch-error", ], "exclude": [ "target/**/*", diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index a851e28f60829..221a4f7ce9517 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -165,8 +165,6 @@ export type { SearchRequest, SearchSourceFields, SerializedSearchSourceFields, - // errors - IEsError, WaitUntilNextSessionCompletesOptions, } from './search'; @@ -178,8 +176,6 @@ export { noSearchSessionStorageCapabilityMessage, SEARCH_SESSIONS_MANAGEMENT_ID, waitUntilNextSessionCompletes$, - isEsError, - getSearchErrorOverrideDisplay, SearchSource, SearchSessionState, SortDirection, diff --git a/src/plugins/data/public/search/errors/types.ts b/src/plugins/data/public/search/errors/types.ts deleted file mode 100644 index 14477327e83bb..0000000000000 --- a/src/plugins/data/public/search/errors/types.ts +++ /dev/null @@ -1,22 +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 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 or the Server - * Side Public License, v 1. - */ - -import { KibanaServerError } from '@kbn/kibana-utils-plugin/common'; -import { IEsErrorAttributes } from '../../../common'; - -export type IEsError = KibanaServerError; - -/** - * Checks if a given errors originated from Elasticsearch. - * Those params are assigned to the attributes property of an error. - * - * @param e - */ -export function isEsError(e: any): e is IEsError { - return !!e.attributes; -} diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index 0921b0bc7bb74..54ac47680a2b6 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -56,7 +56,5 @@ export { getEsPreference } from './es_search'; export type { SearchInterceptorDeps } from './search_interceptor'; export { SearchInterceptor } from './search_interceptor'; -export { getSearchErrorOverrideDisplay } from './search_interceptor/utils'; -export * from './errors'; export { SearchService } from './search_service'; diff --git a/src/plugins/data/public/search/search_interceptor/create_request_hash.ts b/src/plugins/data/public/search/search_interceptor/create_request_hash.ts new file mode 100644 index 0000000000000..99927d7f84d80 --- /dev/null +++ b/src/plugins/data/public/search/search_interceptor/create_request_hash.ts @@ -0,0 +1,14 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { Sha256 } from '@kbn/crypto-browser'; +import stringify from 'json-stable-stringify'; + +export async function createRequestHash(keys: Record) { + return new Sha256().update(stringify(keys), 'utf8').digest('hex'); +} diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts index 09db89ee74a0e..1c6bc41e33216 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts @@ -12,7 +12,7 @@ import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; import { IEsSearchRequest } from '../../../common/search'; import { SearchInterceptor } from './search_interceptor'; import { AbortError } from '@kbn/kibana-utils-plugin/public'; -import { SearchTimeoutError, PainlessError, TimeoutErrorMode, EsError } from '../errors'; +import { PainlessError, EsError, type IEsError } from '@kbn/search-errors'; import { ISessionService, SearchSessionState } from '..'; import { bfetchPluginMock } from '@kbn/bfetch-plugin/public/mocks'; import { BfetchPublicSetup } from '@kbn/bfetch-plugin/public'; @@ -22,12 +22,12 @@ import * as resourceNotFoundException from '../../../common/search/test_data/res import { BehaviorSubject } from 'rxjs'; import { dataPluginMock } from '../../mocks'; import { UI_SETTINGS } from '../../../common'; -import type { IEsError } from '../errors'; import type { SearchServiceStartDependencies } from '../search_service'; import type { Start as InspectorStart } from '@kbn/inspector-plugin/public'; +import { SearchTimeoutError, TimeoutErrorMode } from './timeout_error'; -jest.mock('./utils', () => { - const originalModule = jest.requireActual('./utils'); +jest.mock('./create_request_hash', () => { + const originalModule = jest.requireActual('./create_request_hash'); return { ...originalModule, createRequestHash: jest.fn().mockImplementation((input) => { @@ -36,11 +36,11 @@ jest.mock('./utils', () => { }; }); -jest.mock('../errors/search_session_incomplete_warning', () => ({ +jest.mock('./search_session_incomplete_warning', () => ({ SearchSessionIncompleteWarning: jest.fn(), })); -import { SearchSessionIncompleteWarning } from '../errors/search_session_incomplete_warning'; +import { SearchSessionIncompleteWarning } from './search_session_incomplete_warning'; import { getMockSearchConfig } from '../../../config.mock'; let searchInterceptor: SearchInterceptor; diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts index 68dca8f4d0304..8bae4b3fc7c12 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts @@ -34,7 +34,6 @@ import { estypes } from '@elastic/elasticsearch'; import { i18n } from '@kbn/i18n'; import { PublicMethodsOf } from '@kbn/utility-types'; import type { HttpSetup, IHttpFetchError } from '@kbn/core-http-browser'; -import { BfetchRequestError } from '@kbn/bfetch-plugin/public'; import { type Start as InspectorStart, RequestAdapter } from '@kbn/inspector-plugin/public'; import { @@ -50,6 +49,14 @@ import { import { BatchedFunc, BfetchPublicSetup, DISABLE_BFETCH } from '@kbn/bfetch-plugin/public'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { AbortError, KibanaServerError } from '@kbn/kibana-utils-plugin/public'; +import { BfetchRequestError } from '@kbn/bfetch-error'; +import { + EsError, + isEsError, + isPainlessError, + PainlessError, + renderSearchError, +} from '@kbn/search-errors'; import { ENHANCED_ES_SEARCH_STRATEGY, IAsyncSearchOptions, @@ -63,21 +70,14 @@ import { type SanitizedConnectionRequestParams, } from '../../../common'; import { SearchUsageCollector } from '../collectors'; -import { - EsError, - isEsError, - isPainlessError, - PainlessError, - SearchTimeoutError, - TimeoutErrorMode, - SearchSessionIncompleteWarning, -} from '../errors'; +import { SearchTimeoutError, TimeoutErrorMode } from './timeout_error'; +import { SearchSessionIncompleteWarning } from './search_session_incomplete_warning'; import { ISessionService, SearchSessionState } from '../session'; import { SearchResponseCache } from './search_response_cache'; -import { createRequestHash, getSearchErrorOverrideDisplay } from './utils'; import { SearchAbortController } from './search_abort_controller'; import { SearchConfigSchema } from '../../../config'; import type { SearchServiceStartDependencies } from '../search_service'; +import { createRequestHash } from './create_request_hash'; export interface SearchInterceptorDeps { bfetch: BfetchPublicSetup; @@ -585,15 +585,15 @@ export class SearchInterceptor { return; } - const overrideDisplay = getSearchErrorOverrideDisplay({ + const searchErrorDisplay = renderSearchError({ error: e, application: this.application, }); - if (overrideDisplay) { + if (searchErrorDisplay) { this.deps.toasts.addDanger({ - title: overrideDisplay.title, - text: toMountPoint(overrideDisplay.body, { theme$: this.deps.theme.theme$ }), + title: searchErrorDisplay.title, + text: toMountPoint(searchErrorDisplay.body, { theme$: this.deps.theme.theme$ }), }); } else { this.deps.toasts.addError(e, { diff --git a/src/plugins/data/public/search/errors/search_session_incomplete_warning.tsx b/src/plugins/data/public/search/search_interceptor/search_session_incomplete_warning.tsx similarity index 100% rename from src/plugins/data/public/search/errors/search_session_incomplete_warning.tsx rename to src/plugins/data/public/search/search_interceptor/search_session_incomplete_warning.tsx diff --git a/src/plugins/data/public/search/errors/timeout_error.test.tsx b/src/plugins/data/public/search/search_interceptor/timeout_error.test.tsx similarity index 100% rename from src/plugins/data/public/search/errors/timeout_error.test.tsx rename to src/plugins/data/public/search/search_interceptor/timeout_error.test.tsx diff --git a/src/plugins/data/public/search/errors/timeout_error.tsx b/src/plugins/data/public/search/search_interceptor/timeout_error.tsx similarity index 100% rename from src/plugins/data/public/search/errors/timeout_error.tsx rename to src/plugins/data/public/search/search_interceptor/timeout_error.tsx diff --git a/src/plugins/data/tsconfig.json b/src/plugins/data/tsconfig.json index 7619be78a82dc..77cc9b6aa5b54 100644 --- a/src/plugins/data/tsconfig.json +++ b/src/plugins/data/tsconfig.json @@ -43,13 +43,14 @@ "@kbn/crypto-browser", "@kbn/config", "@kbn/config-schema", - "@kbn/core-application-browser", "@kbn/core-saved-objects-server", "@kbn/core-saved-objects-utils-server", "@kbn/data-service", "@kbn/react-kibana-context-render", + "@kbn/search-errors", "@kbn/search-response-warnings", - "@kbn/shared-ux-link-redirect-app" + "@kbn/shared-ux-link-redirect-app", + "@kbn/bfetch-error" ], "exclude": [ "target/**/*", diff --git a/src/plugins/data_views/docs/openapi/bundled.json b/src/plugins/data_views/docs/openapi/bundled.json index e4f7e9856e2bd..52912da70f307 100644 --- a/src/plugins/data_views/docs/openapi/bundled.json +++ b/src/plugins/data_views/docs/openapi/bundled.json @@ -198,6 +198,9 @@ "data views" ], "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, { "$ref": "#/components/parameters/view_id" } @@ -449,7 +452,10 @@ "type": "object" }, "fields": { - "type": "array" + "type": "array", + "items": { + "type": "object" + } } } }, @@ -2687,7 +2693,18 @@ }, "sourcefilters": { "type": "array", - "description": "The array of field names you want to filter out in Discover." + "description": "The array of field names you want to filter out in Discover.", + "items": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "string" + } + } + } }, "timefieldname": { "type": "string", diff --git a/src/plugins/data_views/docs/openapi/bundled.yaml b/src/plugins/data_views/docs/openapi/bundled.yaml index 65ffd986ade7d..a0afe1e93a8ef 100644 --- a/src/plugins/data_views/docs/openapi/bundled.yaml +++ b/src/plugins/data_views/docs/openapi/bundled.yaml @@ -125,6 +125,7 @@ paths: tags: - data views parameters: + - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/view_id' responses: '204': @@ -290,6 +291,8 @@ paths: type: object fields: type: array + items: + type: object examples: createRuntimeFieldResponse: $ref: '#/components/examples/create_runtime_field_response' @@ -2017,6 +2020,13 @@ components: sourcefilters: type: array description: The array of field names you want to filter out in Discover. + items: + type: object + required: + - value + properties: + value: + type: string timefieldname: type: string description: The timestamp field name, which you use for time-based data views. diff --git a/src/plugins/data_views/docs/openapi/components/schemas/sourcefilters.yaml b/src/plugins/data_views/docs/openapi/components/schemas/sourcefilters.yaml index 4ba0980e43730..b2dda2e2e8579 100644 --- a/src/plugins/data_views/docs/openapi/components/schemas/sourcefilters.yaml +++ b/src/plugins/data_views/docs/openapi/components/schemas/sourcefilters.yaml @@ -1,2 +1,9 @@ type: array -description: The array of field names you want to filter out in Discover. \ No newline at end of file +description: The array of field names you want to filter out in Discover. +items: + type: object + required: + - value + properties: + value: + type: string diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml index 73d206a6991f3..e239978f39f87 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml @@ -33,6 +33,7 @@ delete: tags: - data views parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' - $ref: '../components/parameters/view_id.yaml' responses: '204': diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml index bf8613992f411..04f836cae94fe 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}@runtime_field.yaml @@ -79,6 +79,8 @@ put: type: object fields: type: array + items: + type: object examples: createRuntimeFieldResponse: $ref: '../components/examples/create_runtime_field_response.yaml' diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index 0bb6947dc7674..bba3e23d3e70f 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -20,6 +20,8 @@ import { import type { SavedSearch } from '@kbn/saved-search-plugin/public'; import { EuiFlexItem } from '@elastic/eui'; import { css } from '@emotion/react'; +import useObservable from 'react-use/lib/useObservable'; +import { of } from 'rxjs'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { FIELD_STATISTICS_LOADED } from './constants'; import type { DiscoverStateContainer } from '../../services/discover_state'; @@ -120,7 +122,9 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { trackUiMetric, searchSessionId, } = props; - const totalHits$ = stateContainer?.dataState.data$.totalHits$; + const totalHits = useObservable(stateContainer?.dataState.data$.totalHits$ ?? of(undefined)); + const totalDocuments = useMemo(() => totalHits?.result, [totalHits]); + const services = useDiscoverServices(); const [embeddable, setEmbeddable] = useState< | ErrorEmbeddable @@ -173,7 +177,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { onAddFilter, sessionId: searchSessionId, fieldsToFetch: stateContainer?.dataState.data$.availableFields$?.getValue().fields, - totalDocuments: totalHits$ ? totalHits$.getValue()?.result : undefined, + totalDocuments, samplingOption: { mode: 'normal_sampling', shardSize: 5000, @@ -191,7 +195,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { filters, onAddFilter, searchSessionId, - totalHits$, + totalDocuments, stateContainer, ]); diff --git a/src/plugins/discover/public/components/common/error_callout.test.tsx b/src/plugins/discover/public/components/common/error_callout.test.tsx index fd07af1bd548d..3094dbc8846aa 100644 --- a/src/plugins/discover/public/components/common/error_callout.test.tsx +++ b/src/plugins/discover/public/components/common/error_callout.test.tsx @@ -14,13 +14,13 @@ import React, { ReactNode } from 'react'; import { discoverServiceMock } from '../../__mocks__/services'; import { ErrorCallout } from './error_callout'; -const mockGetSearchErrorOverrideDisplay = jest.fn(); +const mockRenderSearchError = jest.fn(); -jest.mock('@kbn/data-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/data-plugin/public'); +jest.mock('@kbn/search-errors', () => { + const originalModule = jest.requireActual('@kbn/search-errors'); return { ...originalModule, - getSearchErrorOverrideDisplay: () => mockGetSearchErrorOverrideDisplay(), + renderSearchError: () => mockRenderSearchError(), }; }); @@ -31,7 +31,7 @@ describe('ErrorCallout', () => { ); afterEach(() => { - mockGetSearchErrorOverrideDisplay.mockReset(); + mockRenderSearchError.mockReset(); }); it('should render', () => { @@ -54,7 +54,7 @@ describe('ErrorCallout', () => { const title = 'Override title'; const error = new Error('My error'); const overrideDisplay =
Override display
; - mockGetSearchErrorOverrideDisplay.mockReturnValue({ title, body: overrideDisplay }); + mockRenderSearchError.mockReturnValue({ title, body: overrideDisplay }); const wrapper = mountWithServices(); const prompt = wrapper.find(EuiEmptyPrompt); expect(prompt).toHaveLength(1); diff --git a/src/plugins/discover/public/components/common/error_callout.tsx b/src/plugins/discover/public/components/common/error_callout.tsx index 9b6aa341d5fdc..a2aa2b478a3dc 100644 --- a/src/plugins/discover/public/components/common/error_callout.tsx +++ b/src/plugins/discover/public/components/common/error_callout.tsx @@ -8,7 +8,7 @@ import { EuiButton, EuiEmptyPrompt, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; -import { getSearchErrorOverrideDisplay } from '@kbn/data-plugin/public'; +import { renderSearchError } from '@kbn/search-errors'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useDiscoverServices } from '../../hooks/use_discover_services'; @@ -22,7 +22,7 @@ export const ErrorCallout = ({ title, error }: Props) => { const { core } = useDiscoverServices(); const { euiTheme } = useEuiTheme(); - const overrideDisplay = getSearchErrorOverrideDisplay({ + const searchErrorDisplay = renderSearchError({ error, application: core.application, }); @@ -31,15 +31,17 @@ export const ErrorCallout = ({ title, error }: Props) => { {overrideDisplay?.title ?? title}} - actions={overrideDisplay?.actions ?? []} + title={ +

{searchErrorDisplay?.title ?? title}

+ } + actions={searchErrorDisplay?.actions ?? []} body={
- {overrideDisplay?.body ?? ( + {searchErrorDisplay?.body ?? ( <>

@@ -81,7 +81,7 @@ export function EmbeddablePanelError({ return ( https://github.com/elastic/eui/issues/4108 - const sortedRows = useMemo( - () => - sort.columnIndex !== null && sort.direction - ? orderBy(rows, columns[sort.columnIndex]?.id, sort.direction) - : rows, - [columns, rows, sort] - ); + const sortedRows = useMemo(() => { + if (sort.columnIndex !== null && sort.direction) { + const id = columns[sort.columnIndex]?.id; + return sortNullsLast(rows, sort.direction, id); + } + + return rows; + }, [columns, rows, sort.columnIndex, sort.direction]); // renderCellValue is a component which renders a cell based on column and row indexes const renderCellValue = useMemo( diff --git a/src/plugins/vis_types/table/public/components/utils.test.ts b/src/plugins/vis_types/table/public/components/utils.test.ts new file mode 100644 index 0000000000000..0b81f70a5fe41 --- /dev/null +++ b/src/plugins/vis_types/table/public/components/utils.test.ts @@ -0,0 +1,52 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +import { sortNullsLast } from './utils'; + +describe('sortNullsLast', () => { + const rows = [ + { + col1: null, + }, + { + col1: 'meow', + }, + { + col1: 'woof', + }, + ]; + test('should sort correctly in ascending order', async () => { + const sortedRows = sortNullsLast(rows, 'asc', 'col1'); + expect(sortedRows).toStrictEqual([ + { + col1: 'meow', + }, + { + col1: 'woof', + }, + { + col1: null, + }, + ]); + }); + + test('should sort correctly in descending order', async () => { + const sortedRows = sortNullsLast(rows, 'desc', 'col1'); + expect(sortedRows).toStrictEqual([ + { + col1: 'woof', + }, + { + col1: 'meow', + }, + { + col1: null, + }, + ]); + }); +}); diff --git a/src/plugins/vis_types/table/public/components/utils.ts b/src/plugins/vis_types/table/public/components/utils.ts index 4bba926099626..6dc89d483d2d4 100644 --- a/src/plugins/vis_types/table/public/components/utils.ts +++ b/src/plugins/vis_types/table/public/components/utils.ts @@ -7,6 +7,7 @@ */ import { i18n } from '@kbn/i18n'; +import type { DatatableRow } from '@kbn/expressions-plugin/common'; import { AggTypes } from '../../common'; const totalAggregations = [ @@ -42,4 +43,31 @@ const totalAggregations = [ }, ]; -export { totalAggregations }; +const sortNullsLast = ( + rows: DatatableRow[], + direction: 'asc' | 'desc', + id: string +): DatatableRow[] => { + return rows.sort((row1, row2) => { + const rowA = row1[id]; + const rowB = row2[id]; + + if (rowA === null) { + return 1; + } + if (rowB === null) { + return -1; + } + if (rowA === rowB) { + return 0; + } + + if (direction === 'desc') { + return rowA < rowB ? 1 : -1; + } else { + return rowA < rowB ? -1 : 1; + } + }); +}; + +export { totalAggregations, sortNullsLast }; diff --git a/test/functional/apps/discover/group2/_data_grid_field_tokens.ts b/test/functional/apps/discover/group2/_data_grid_field_tokens.ts index 3731c1e15f446..af4943a13e62a 100644 --- a/test/functional/apps/discover/group2/_data_grid_field_tokens.ts +++ b/test/functional/apps/discover/group2/_data_grid_field_tokens.ts @@ -130,7 +130,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.unifiedFieldList.clickFieldListItemAdd('ip'); await PageObjects.unifiedFieldList.clickFieldListItemAdd('geo.coordinates'); - expect(await findFirstColumnTokens()).to.eql(['Number', 'String', 'String']); + expect(await findFirstColumnTokens()).to.eql(['Number', 'String', 'String', 'String']); expect(await findFirstDocViewerTokens()).to.eql([ 'String', @@ -140,7 +140,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'Number', 'String', 'String', - 'Unknown field', + 'String', 'String', 'String', ]); diff --git a/tsconfig.base.json b/tsconfig.base.json index 5f25914be2352..cf06d8343691f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -106,6 +106,8 @@ "@kbn/banners-plugin/*": ["x-pack/plugins/banners/*"], "@kbn/bazel-runner": ["packages/kbn-bazel-runner"], "@kbn/bazel-runner/*": ["packages/kbn-bazel-runner/*"], + "@kbn/bfetch-error": ["packages/kbn-bfetch-error"], + "@kbn/bfetch-error/*": ["packages/kbn-bfetch-error/*"], "@kbn/bfetch-explorer-plugin": ["examples/bfetch_explorer"], "@kbn/bfetch-explorer-plugin/*": ["examples/bfetch_explorer/*"], "@kbn/bfetch-plugin": ["src/plugins/bfetch"], @@ -1294,6 +1296,8 @@ "@kbn/search-api-panels/*": ["packages/kbn-search-api-panels/*"], "@kbn/search-connectors": ["packages/kbn-search-connectors"], "@kbn/search-connectors/*": ["packages/kbn-search-connectors/*"], + "@kbn/search-errors": ["packages/kbn-search-errors"], + "@kbn/search-errors/*": ["packages/kbn-search-errors/*"], "@kbn/search-examples-plugin": ["examples/search_examples"], "@kbn/search-examples-plugin/*": ["examples/search_examples/*"], "@kbn/search-index-documents": ["packages/kbn-search-index-documents"], diff --git a/versions.json b/versions.json index a8ff665dcbd05..26fee0ef485b3 100644 --- a/versions.json +++ b/versions.json @@ -2,14 +2,14 @@ "notice": "This file is not maintained outside of the main branch and should only be used for tooling.", "versions": [ { - "version": "8.12.0", + "version": "8.13.0", "branch": "main", "currentMajor": true, "currentMinor": true }, { - "version": "8.11.2", - "branch": "8.11", + "version": "8.12.0", + "branch": "8.12", "currentMajor": true, "previousMinor": true }, diff --git a/x-pack/README.md b/x-pack/README.md index ea8777f46b143..255a4d3e2b6e8 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -14,12 +14,6 @@ xpack.observability.unsafe.alertDetails.metrics.enabled: true **[For Infrastructure rule types]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table -```yaml -xpack.observability.unsafe.alertDetails.logs.enabled: true -``` - -**[For Logs threshold rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table - ```yaml xpack.observability.unsafe.alertDetails.uptime.enabled: true ``` diff --git a/x-pack/package.json b/x-pack/package.json index 66a2b81da7dd2..47de19fb67a3c 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -1,6 +1,6 @@ { "name": "x-pack", - "version": "8.12.0", + "version": "8.13.0", "author": "Elastic", "private": true, "license": "Elastic-License", diff --git a/x-pack/performance/journeys/apm_service_inventory.ts b/x-pack/performance/journeys/apm_service_inventory.ts index cbef53858eea6..84f2518575df8 100644 --- a/x-pack/performance/journeys/apm_service_inventory.ts +++ b/x-pack/performance/journeys/apm_service_inventory.ts @@ -11,6 +11,8 @@ import { SynthtraceClient } from '../services/synthtrace'; import { generateData } from '../synthtrace_data/apm_data'; export const journey = new Journey({ + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172757 + skipped: true, beforeSteps: async ({ kbnUrl, log, auth, es }) => { // Install APM Package const synthClient = new SynthtraceClient({ diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts b/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts deleted file mode 100644 index 9047f768449e5..0000000000000 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_services_list.ts +++ /dev/null @@ -1,77 +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 { i18n } from '@kbn/i18n'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; -import { ServiceHealthStatus } from '../../common/service_health_status'; -import { callApmApi } from '../services/rest/create_call_apm_api'; -import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; - -export function registerGetApmServicesListFunction({ - registerFunction, -}: { - registerFunction: RegisterFunctionDefinition; -}) { - registerFunction( - { - name: 'get_apm_services_list', - contexts: ['apm'], - description: `Gets a list of services`, - descriptionForUser: i18n.translate( - 'xpack.apm.observabilityAiAssistant.functions.registerGetApmServicesList.descriptionForUser', - { - defaultMessage: `Gets the list of monitored services, their health status, and alerts.`, - } - ), - parameters: { - type: 'object', - additionalProperties: false, - properties: { - 'service.environment': { - ...NON_EMPTY_STRING, - description: - 'Optionally filter the services by the environments that they are running in', - }, - start: { - ...NON_EMPTY_STRING, - description: - 'The start of the time range, in Elasticsearch date math, like `now`.', - }, - end: { - ...NON_EMPTY_STRING, - description: - 'The end of the time range, in Elasticsearch date math, like `now-24h`.', - }, - healthStatus: { - type: 'array', - description: 'Filter service list by health status', - additionalProperties: false, - additionalItems: false, - items: { - type: 'string', - enum: [ - ServiceHealthStatus.unknown, - ServiceHealthStatus.healthy, - ServiceHealthStatus.warning, - ServiceHealthStatus.critical, - ], - }, - }, - }, - required: ['start', 'end'], - } as const, - }, - async ({ arguments: args }, signal) => { - return callApmApi('POST /internal/apm/assistant/get_services_list', { - signal, - params: { - body: args, - }, - }); - } - ); -} diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx index 56269d884ad84..445610321cbb8 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx +++ b/x-pack/plugins/apm/public/assistant_functions/get_apm_timeseries.tsx @@ -5,294 +5,164 @@ * 2.0. */ import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { + RegisterRenderFunctionDefinition, + RenderFunction, +} from '@kbn/observability-ai-assistant-plugin/public/types'; + import { groupBy } from 'lodash'; import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { FETCH_STATUS } from '../hooks/use_fetcher'; -import { callApmApi } from '../services/rest/create_call_apm_api'; -import { getTimeZone } from '../components/shared/charts/helper/timezone'; -import { TimeseriesChart } from '../components/shared/charts/timeseries_chart'; -import { ChartPointerEventContextProvider } from '../context/chart_pointer_event/chart_pointer_event_context'; -import { ApmThemeProvider } from '../components/routing/app_root'; -import { Coordinate, TimeSeries } from '../../typings/timeseries'; -import { - ChartType, - getTimeSeriesColor, -} from '../components/shared/charts/helper/get_timeseries_color'; import { LatencyAggregationType } from '../../common/latency_aggregation_types'; import { asPercent, asTransactionRate, getDurationFormatter, } from '../../common/utils/formatters'; +import type { + GetApmTimeseriesFunctionArguments, + GetApmTimeseriesFunctionResponse, +} from '../../server/assistant_functions/get_apm_timeseries'; +import { Coordinate, TimeSeries } from '../../typings/timeseries'; +import { ApmThemeProvider } from '../components/routing/app_root'; +import { + ChartType, + getTimeSeriesColor, +} from '../components/shared/charts/helper/get_timeseries_color'; +import { getTimeZone } from '../components/shared/charts/helper/timezone'; +import { TimeseriesChart } from '../components/shared/charts/timeseries_chart'; import { getMaxY, getResponseTimeTickFormatter, } from '../components/shared/charts/transaction_charts/helper'; -import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; +import { ChartPointerEventContextProvider } from '../context/chart_pointer_event/chart_pointer_event_context'; +import { FETCH_STATUS } from '../hooks/use_fetcher'; export function registerGetApmTimeseriesFunction({ - registerFunction, + registerRenderFunction, }: { - registerFunction: RegisterFunctionDefinition; + registerRenderFunction: RegisterRenderFunctionDefinition; }) { - registerFunction( - { - contexts: ['apm'], - name: 'get_apm_timeseries', - descriptionForUser: i18n.translate( - 'xpack.apm.observabilityAiAssistant.functions.registerGetApmTimeseries.descriptionForUser', - { - defaultMessage: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions`, - } - ), - description: `Visualise and analyse different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. A visualisation will be displayed above your reply - DO NOT attempt to display or generate an image yourself, or any other placeholder. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions.`, - parameters: { - type: 'object', - properties: { - start: { - type: 'string', - description: - 'The start of the time range, in Elasticsearch date math, like `now`.', - }, - end: { - type: 'string', - description: - 'The end of the time range, in Elasticsearch date math, like `now-24h`.', - }, - stats: { - type: 'array', - items: { - type: 'object', - properties: { - timeseries: { - description: 'The metric to be displayed', - oneOf: [ - { - type: 'object', - properties: { - name: { - type: 'string', - enum: [ - 'transaction_throughput', - 'transaction_failure_rate', - ], - }, - 'transaction.type': { - type: 'string', - description: 'The transaction type', - }, - }, - required: ['name'], - }, - { - type: 'object', - properties: { - name: { - type: 'string', - enum: [ - 'exit_span_throughput', - 'exit_span_failure_rate', - 'exit_span_latency', - ], - }, - 'span.destination.service.resource': { - type: 'string', - description: - 'The name of the downstream dependency for the service', - }, - }, - required: ['name'], - }, - { - type: 'object', - properties: { - name: { - type: 'string', - const: 'error_event_rate', - }, - }, - required: ['name'], - }, - { - type: 'object', - properties: { - name: { - type: 'string', - const: 'transaction_latency', - }, - 'transaction.type': { - type: 'string', - }, - function: { - type: 'string', - enum: ['avg', 'p95', 'p99'], - }, - }, - required: ['name', 'function'], - }, - ], - }, - 'service.name': { - ...NON_EMPTY_STRING, - description: 'The name of the service', - }, - 'service.environment': { - description: - 'The environment that the service is running in. If undefined, all environments will be included. Only use this if you have confirmed the environment that the service is running in.', - }, - filter: { - type: 'string', - description: - 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', - }, - title: { - type: 'string', - description: - 'A unique, human readable, concise title for this specific group series.', - }, - offset: { - type: 'string', - description: - 'The offset. Right: 15m. 8h. 1d. Wrong: -15m. -8h. -1d.', - }, - }, - required: ['service.name', 'timeseries', 'title'], - }, - }, - }, - required: ['stats', 'start', 'end'], - } as const, - }, - async ({ arguments: { stats, start, end } }, signal) => { - const response = await callApmApi( - 'POST /internal/apm/assistant/get_apm_timeseries', - { - signal, - params: { - body: { stats: stats as any, start, end }, - }, - } - ); - - return response; - }, - ({ arguments: args, response }) => { - const groupedSeries = groupBy(response.data, (series) => series.group); - - const { - services: { uiSettings }, - } = useKibana(); - - const timeZone = getTimeZone(uiSettings); - - return ( - - - - {Object.values(groupedSeries).map((groupSeries) => { - const groupId = groupSeries[0].group; - - const maxY = getMaxY(groupSeries); - const latencyFormatter = getDurationFormatter(maxY, 10, 1000); - - let yLabelFormat: (value: number) => string; - - const firstStat = groupSeries[0].stat; - - switch (firstStat.timeseries.name) { - case 'transaction_throughput': - case 'exit_span_throughput': - case 'error_event_rate': - yLabelFormat = asTransactionRate; - break; - - case 'transaction_latency': - case 'exit_span_latency': - yLabelFormat = - getResponseTimeTickFormatter(latencyFormatter); - break; - - case 'transaction_failure_rate': - case 'exit_span_failure_rate': - yLabelFormat = (y) => asPercent(y || 0, 100); - break; - } - - const timeseries: Array> = - groupSeries.map((series): TimeSeries => { - let chartType: ChartType; - - const data = series.data; - - switch (series.stat.timeseries.name) { - case 'transaction_throughput': - case 'exit_span_throughput': - chartType = ChartType.THROUGHPUT; - break; - - case 'transaction_failure_rate': - case 'exit_span_failure_rate': - chartType = ChartType.FAILED_TRANSACTION_RATE; - break; - - case 'transaction_latency': - if ( - series.stat.timeseries.function === - LatencyAggregationType.p99 - ) { - chartType = ChartType.LATENCY_P99; - } else if ( - series.stat.timeseries.function === - LatencyAggregationType.p95 - ) { - chartType = ChartType.LATENCY_P95; - } else { - chartType = ChartType.LATENCY_AVG; - } - break; - - case 'exit_span_latency': + registerRenderFunction('get_apm_timeseries', (parameters) => { + const { response } = parameters as Parameters< + RenderFunction< + GetApmTimeseriesFunctionArguments, + GetApmTimeseriesFunctionResponse + > + >[0]; + + const groupedSeries = groupBy(response.data, (series) => series.group); + + const { + services: { uiSettings }, + } = useKibana(); + + const timeZone = getTimeZone(uiSettings); + + return ( + + + + {Object.values(groupedSeries).map((groupSeries) => { + const groupId = groupSeries[0].group; + + const maxY = getMaxY(groupSeries); + const latencyFormatter = getDurationFormatter(maxY, 10, 1000); + + let yLabelFormat: (value: number) => string; + + const firstStat = groupSeries[0].stat; + + switch (firstStat.timeseries.name) { + case 'transaction_throughput': + case 'exit_span_throughput': + case 'error_event_rate': + yLabelFormat = asTransactionRate; + break; + + case 'transaction_latency': + case 'exit_span_latency': + yLabelFormat = getResponseTimeTickFormatter(latencyFormatter); + break; + + case 'transaction_failure_rate': + case 'exit_span_failure_rate': + yLabelFormat = (y) => asPercent(y || 0, 100); + break; + } + + const timeseries: Array> = groupSeries.map( + (series): TimeSeries => { + let chartType: ChartType; + + const data = series.data; + + switch (series.stat.timeseries.name) { + case 'transaction_throughput': + case 'exit_span_throughput': + chartType = ChartType.THROUGHPUT; + break; + + case 'transaction_failure_rate': + case 'exit_span_failure_rate': + chartType = ChartType.FAILED_TRANSACTION_RATE; + break; + + case 'transaction_latency': + if ( + series.stat.timeseries.function === + LatencyAggregationType.p99 + ) { + chartType = ChartType.LATENCY_P99; + } else if ( + series.stat.timeseries.function === + LatencyAggregationType.p95 + ) { + chartType = ChartType.LATENCY_P95; + } else { chartType = ChartType.LATENCY_AVG; - break; - - case 'error_event_rate': - chartType = ChartType.ERROR_OCCURRENCES; - break; - } - - return { - title: series.id, - type: 'line', - color: getTimeSeriesColor(chartType!).currentPeriodColor, - data, - }; - }); - - return ( - - - - {groupId} - - - - - ); - })} - - - - ); - } - ); + } + break; + + case 'exit_span_latency': + chartType = ChartType.LATENCY_AVG; + break; + + case 'error_event_rate': + chartType = ChartType.ERROR_OCCURRENCES; + break; + } + + return { + title: series.id, + type: 'line', + color: getTimeSeriesColor(chartType!).currentPeriodColor, + data, + }; + } + ); + + return ( + + + + {groupId} + + + + + ); + })} + + + + ); + }); } diff --git a/x-pack/plugins/apm/public/assistant_functions/index.ts b/x-pack/plugins/apm/public/assistant_functions/index.ts index 128091cf2472d..773d2fbfba27f 100644 --- a/x-pack/plugins/apm/public/assistant_functions/index.ts +++ b/x-pack/plugins/apm/public/assistant_functions/index.ts @@ -5,152 +5,15 @@ * 2.0. */ -import type { CoreStart } from '@kbn/core/public'; -import type { - RegisterContextDefinition, - RegisterFunctionDefinition, -} from '@kbn/observability-ai-assistant-plugin/common/types'; -import type { ApmPluginStartDeps } from '../plugin'; -import { - createCallApmApi, - callApmApi, -} from '../services/rest/create_call_apm_api'; -import { registerGetApmCorrelationsFunction } from './get_apm_correlations'; -import { registerGetApmDownstreamDependenciesFunction } from './get_apm_downstream_dependencies'; -import { registerGetApmErrorDocumentFunction } from './get_apm_error_document'; -import { registerGetApmServicesListFunction } from './get_apm_services_list'; -import { registerGetApmServiceSummaryFunction } from './get_apm_service_summary'; +import { RegisterRenderFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/public/types'; import { registerGetApmTimeseriesFunction } from './get_apm_timeseries'; export async function registerAssistantFunctions({ - pluginsStart, - coreStart, - registerContext, - registerFunction, - signal, + registerRenderFunction, }: { - pluginsStart: ApmPluginStartDeps; - coreStart: CoreStart; - registerContext: RegisterContextDefinition; - registerFunction: RegisterFunctionDefinition; - signal: AbortSignal; + registerRenderFunction: RegisterRenderFunctionDefinition; }) { - createCallApmApi(coreStart); - - const response = await callApmApi('GET /internal/apm/has_data', { - signal, - }); - - if (!response.hasData) { - return; - } - registerGetApmTimeseriesFunction({ - registerFunction, - }); - - registerGetApmErrorDocumentFunction({ - registerFunction, - }); - - registerGetApmCorrelationsFunction({ - registerFunction, - }); - - registerGetApmDownstreamDependenciesFunction({ - registerFunction, - }); - - registerGetApmServiceSummaryFunction({ - registerFunction, - }); - - registerGetApmServicesListFunction({ - registerFunction, - }); - - registerContext({ - name: 'apm', - description: ` - When analyzing APM data, prefer the APM specific functions over the generic Lens, - Elasticsearch or Kibana ones, unless those are explicitly requested by the user. - - When requesting metrics for a service, make sure you also know what environment - it is running in. Metrics aggregated over multiple environments are useless. - - There are four important data types in Elastic APM. Each of them have the - following fields: - - service.name: the name of the service - - service.node.name: the id of the service instance (often the hostname) - - service.environment: the environment (often production, development) - - agent.name: the name of the agent (go, java, etc) - - The four data types are transactions, exit spans, error events, and application - metrics. - - Transactions have three metrics: throughput, failure rate, and latency. The - fields are: - - - transaction.type: often request or page-load (the main transaction types), - but can also be worker, or route-change. - - transaction.name: The name of the transaction group, often something like - 'GET /api/product/:productId' - - transaction.result: The result. Used to capture HTTP response codes - (2xx,3xx,4xx,5xx) for request transactions. - - event.outcome: whether the transaction was succesful or not. success, - failure, or unknown. - - Exit spans have three metrics: throughput, failure rate and latency. The fields - are: - - span.type: db, external - - span.subtype: the type of database (redis, postgres) or protocol (http, grpc) - - span.destination.service.resource: the address of the destination of the call - - event.outcome: whether the transaction was succesful or not. success, - failure, or unknown. - - Error events have one metric, error event rate. The fields are: - - error.grouping_name: a human readable keyword that identifies the error group - - For transaction metrics we also collect anomalies. These are scored 0 (low) to - 100 (critical). - - For root cause analysis, locate a change point in the relevant metrics for a - service or downstream dependency. You can locate a change point by using a - sliding window, e.g. start with a small time range, like 30m, and make it - bigger until you identify a change point. It's very important to identify a - change point. If you don't have a change point, ask the user for next steps. - You can also use an anomaly or a deployment as a change point. Then, compare - data before the change with data after the change. You can either use the - groupBy parameter in get_apm_chart to get the most occuring values in a certain - data set, or you can use correlations to see for which field and value the - frequency has changed when comparing the foreground set to the background set. - This is useful when comparing data from before the change point with after the - change point. For instance, you might see a specific error pop up more often - after the change point. - - When comparing anomalies and changes in timeseries, first, zoom in to a smaller - time window, at least 30 minutes before and 30 minutes after the change - occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a - time window that starts at 2023-07-05T07:45:00.000Z and ends at - 2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and - anomalies to determine a correlation, make sure to compare the timestamps. If - in doubt, rate the likelihood of them being related, given the time difference, - between 1 and 10. If below 5, assume it's not related. Mention this likelihood - (and the time difference) to the user. - - Your goal is to help the user determine the root cause of an issue quickly and - transparently. If you see a change or - anomaly in a metric for a service, try to find similar changes in the metrics - for the traffic to its downstream dependencies, by comparing transaction - metrics to span metrics. To inspect the traffic from one service to a - downstream dependency, first get the downstream dependencies for a service, - then get the span metrics from that service (\`service.name\`) to its - downstream dependency (\`span.destination.service.resource\`). For instance, - for an anomaly in throughput, first inspect \`transaction_throughput\` for - \`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream - dependencies, by grouping by \`span.destination.service.resource\`. Repeat this - process over the next service its downstream dependencies until you identify a - root cause. If you can not find any similar changes, use correlations or - grouping to find attributes that could be causes for the change.`, + registerRenderFunction, }); } diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index 51a5587452261..173e52e5955cd 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -428,15 +428,11 @@ export class ApmPlugin implements Plugin { const { fleet } = plugins; plugins.observabilityAIAssistant.service.register( - async ({ signal, registerContext, registerFunction }) => { + async ({ registerRenderFunction }) => { const mod = await import('./assistant_functions'); mod.registerAssistantFunctions({ - coreStart: core, - pluginsStart: plugins, - registerContext, - registerFunction, - signal, + registerRenderFunction, }); } ); diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_correlations.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_correlations.ts similarity index 91% rename from x-pack/plugins/apm/public/assistant_functions/get_apm_correlations.ts rename to x-pack/plugins/apm/server/assistant_functions/get_apm_correlations.ts index 2d600e41e4860..f3f61f7d16937 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_correlations.ts +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_correlations.ts @@ -6,15 +6,14 @@ */ import { i18n } from '@kbn/i18n'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; +import { FunctionRegistrationParameters } from '.'; import { CorrelationsEventType } from '../../common/assistant/constants'; -import { callApmApi } from '../services/rest/create_call_apm_api'; +import { getApmCorrelationValues } from '../routes/assistant_functions/get_apm_correlation_values'; export function registerGetApmCorrelationsFunction({ + apmEventClient, registerFunction, -}: { - registerFunction: RegisterFunctionDefinition; -}) { +}: FunctionRegistrationParameters) { registerFunction( { name: 'get_apm_correlations', @@ -113,12 +112,12 @@ export function registerGetApmCorrelationsFunction({ } as const, }, async ({ arguments: args }, signal) => { - return callApmApi('POST /internal/apm/assistant/get_correlation_values', { - signal, - params: { - body: args, - }, - }); + return { + content: await getApmCorrelationValues({ + arguments: args as any, + apmEventClient, + }), + }; } ); } diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_downstream_dependencies.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_downstream_dependencies.ts similarity index 83% rename from x-pack/plugins/apm/public/assistant_functions/get_apm_downstream_dependencies.ts rename to x-pack/plugins/apm/server/assistant_functions/get_apm_downstream_dependencies.ts index fea837dd76c31..0440f684eeedd 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_downstream_dependencies.ts +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_downstream_dependencies.ts @@ -6,14 +6,13 @@ */ import { i18n } from '@kbn/i18n'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; -import { callApmApi } from '../services/rest/create_call_apm_api'; +import type { FunctionRegistrationParameters } from '.'; +import { getAssistantDownstreamDependencies } from '../routes/assistant_functions/get_apm_downstream_dependencies'; export function registerGetApmDownstreamDependenciesFunction({ + apmEventClient, registerFunction, -}: { - registerFunction: RegisterFunctionDefinition; -}) { +}: FunctionRegistrationParameters) { registerFunction( { name: 'get_apm_downstream_dependencies', @@ -57,15 +56,12 @@ export function registerGetApmDownstreamDependenciesFunction({ } as const, }, async ({ arguments: args }, signal) => { - return callApmApi( - 'GET /internal/apm/assistant/get_downstream_dependencies', - { - signal, - params: { - query: args, - }, - } - ); + return { + content: await getAssistantDownstreamDependencies({ + arguments: args, + apmEventClient, + }), + }; } ); } diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_error_document.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_error_document.ts similarity index 83% rename from x-pack/plugins/apm/public/assistant_functions/get_apm_error_document.ts rename to x-pack/plugins/apm/server/assistant_functions/get_apm_error_document.ts index a5c66478e3fd7..e5082f47ad8eb 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_error_document.ts +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_error_document.ts @@ -6,14 +6,13 @@ */ import { i18n } from '@kbn/i18n'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; -import { callApmApi } from '../services/rest/create_call_apm_api'; +import type { FunctionRegistrationParameters } from '.'; +import { getApmErrorDocument } from '../routes/assistant_functions/get_apm_error_document'; export function registerGetApmErrorDocumentFunction({ + apmEventClient, registerFunction, -}: { - registerFunction: RegisterFunctionDefinition; -}) { +}: FunctionRegistrationParameters) { registerFunction( { name: 'get_apm_error_document', @@ -55,12 +54,12 @@ export function registerGetApmErrorDocumentFunction({ } as const, }, async ({ arguments: args }, signal) => { - return callApmApi('GET /internal/apm/assistant/get_error_document', { - signal, - params: { - query: args, - }, - }); + return { + content: await getApmErrorDocument({ + apmEventClient, + arguments: args, + }), + }; } ); } diff --git a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_service_summary.ts similarity index 64% rename from x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts rename to x-pack/plugins/apm/server/assistant_functions/get_apm_service_summary.ts index 189633ec95975..291e4fdae33b0 100644 --- a/x-pack/plugins/apm/public/assistant_functions/get_apm_service_summary.ts +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_service_summary.ts @@ -5,16 +5,19 @@ * 2.0. */ +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { i18n } from '@kbn/i18n'; -import type { RegisterFunctionDefinition } from '@kbn/observability-ai-assistant-plugin/common/types'; -import { callApmApi } from '../services/rest/create_call_apm_api'; +import type { FunctionRegistrationParameters } from '.'; +import { getApmAlertsClient } from '../lib/helpers/get_apm_alerts_client'; +import { getMlClient } from '../lib/helpers/get_ml_client'; +import { getApmServiceSummary } from '../routes/assistant_functions/get_apm_service_summary'; import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; export function registerGetApmServiceSummaryFunction({ + resources, + apmEventClient, registerFunction, -}: { - registerFunction: RegisterFunctionDefinition; -}) { +}: FunctionRegistrationParameters) { registerFunction( { name: 'get_apm_service_summary', @@ -58,12 +61,33 @@ alerts and anomalies.`, } as const, }, async ({ arguments: args }, signal) => { - return callApmApi('GET /internal/apm/assistant/get_service_summary', { - signal, - params: { - query: args, - }, - }); + const { context, request, plugins, logger } = resources; + + const [annotationsClient, esClient, apmAlertsClient, mlClient] = + await Promise.all([ + plugins.observability.setup.getScopedAnnotationsClient( + context, + request + ), + context.core.then( + (coreContext): ElasticsearchClient => + coreContext.elasticsearch.client.asCurrentUser + ), + getApmAlertsClient(resources), + getMlClient(resources), + ]); + + return { + content: await getApmServiceSummary({ + apmEventClient, + annotationsClient, + esClient, + apmAlertsClient, + mlClient, + logger, + arguments: args, + }), + }; } ); } diff --git a/x-pack/plugins/apm/server/assistant_functions/get_apm_services_list.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_services_list.ts new file mode 100644 index 0000000000000..178d47f8d33ed --- /dev/null +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_services_list.ts @@ -0,0 +1,137 @@ +/* + * 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 datemath from '@elastic/datemath'; +import { i18n } from '@kbn/i18n'; +import { FunctionRegistrationParameters } from '.'; +import { ApmDocumentType } from '../../common/document_type'; +import { ENVIRONMENT_ALL } from '../../common/environment_filter_values'; +import { RollupInterval } from '../../common/rollup'; +import { ServiceHealthStatus } from '../../common/service_health_status'; +import { getApmAlertsClient } from '../lib/helpers/get_apm_alerts_client'; +import { getMlClient } from '../lib/helpers/get_ml_client'; +import { getRandomSampler } from '../lib/helpers/get_random_sampler'; +import { getServicesItems } from '../routes/services/get_services/get_services_items'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; + +export interface ApmServicesListItem { + 'service.name': string; + 'agent.name'?: string; + 'transaction.type'?: string; + alertsCount: number; + healthStatus: ServiceHealthStatus; + 'service.environment'?: string[]; +} + +export function registerGetApmServicesListFunction({ + apmEventClient, + resources, + registerFunction, +}: FunctionRegistrationParameters) { + registerFunction( + { + name: 'get_apm_services_list', + contexts: ['apm'], + description: `Gets a list of services`, + descriptionForUser: i18n.translate( + 'xpack.apm.observabilityAiAssistant.functions.registerGetApmServicesList.descriptionForUser', + { + defaultMessage: `Gets the list of monitored services, their health status, and alerts.`, + } + ), + parameters: { + type: 'object', + additionalProperties: false, + properties: { + 'service.environment': { + ...NON_EMPTY_STRING, + description: + 'Optionally filter the services by the environments that they are running in', + }, + start: { + ...NON_EMPTY_STRING, + description: + 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + ...NON_EMPTY_STRING, + description: + 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + healthStatus: { + type: 'array', + description: 'Filter service list by health status', + additionalProperties: false, + additionalItems: false, + items: { + type: 'string', + enum: [ + ServiceHealthStatus.unknown, + ServiceHealthStatus.healthy, + ServiceHealthStatus.warning, + ServiceHealthStatus.critical, + ], + }, + }, + }, + required: ['start', 'end'], + } as const, + }, + async ({ arguments: args }, signal) => { + const { healthStatus } = args; + const [apmAlertsClient, mlClient, randomSampler] = await Promise.all([ + getApmAlertsClient(resources), + getMlClient(resources), + getRandomSampler({ + security: resources.plugins.security, + probability: 1, + request: resources.request, + }), + ]); + + const start = datemath.parse(args.start)?.valueOf()!; + const end = datemath.parse(args.end)?.valueOf()!; + + const serviceItems = await getServicesItems({ + apmAlertsClient, + apmEventClient, + documentType: ApmDocumentType.TransactionMetric, + start, + end, + environment: args['service.environment'] || ENVIRONMENT_ALL.value, + kuery: '', + logger: resources.logger, + randomSampler, + rollupInterval: RollupInterval.OneMinute, + serviceGroup: null, + mlClient, + useDurationSummary: false, + }); + + let mappedItems = serviceItems.items.map((item): ApmServicesListItem => { + return { + 'service.name': item.serviceName, + 'agent.name': item.agentName, + alertsCount: item.alertsCount ?? 0, + healthStatus: item.healthStatus ?? ServiceHealthStatus.unknown, + 'service.environment': item.environments, + 'transaction.type': item.transactionType, + }; + }); + + if (healthStatus && healthStatus.length) { + mappedItems = mappedItems.filter((item): boolean => + healthStatus.includes(item.healthStatus) + ); + } + + return { + content: mappedItems, + }; + } + ); +} diff --git a/x-pack/plugins/apm/server/assistant_functions/get_apm_timeseries.ts b/x-pack/plugins/apm/server/assistant_functions/get_apm_timeseries.ts new file mode 100644 index 0000000000000..0d5be32611eb4 --- /dev/null +++ b/x-pack/plugins/apm/server/assistant_functions/get_apm_timeseries.ts @@ -0,0 +1,174 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { FromSchema } from 'json-schema-to-ts'; +import { omit } from 'lodash'; +import { FunctionRegistrationParameters } from '.'; +import { + ApmTimeseries, + getApmTimeseries, +} from '../routes/assistant_functions/get_apm_timeseries'; +import { NON_EMPTY_STRING } from '../utils/non_empty_string_ref'; + +const parameters = { + type: 'object', + properties: { + start: { + type: 'string', + description: + 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + type: 'string', + description: + 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + stats: { + type: 'array', + items: { + type: 'object', + properties: { + timeseries: { + description: 'The metric to be displayed', + oneOf: [ + { + type: 'object', + properties: { + name: { + type: 'string', + enum: [ + 'transaction_throughput', + 'transaction_failure_rate', + ], + }, + 'transaction.type': { + type: 'string', + description: 'The transaction type', + }, + }, + required: ['name'], + }, + { + type: 'object', + properties: { + name: { + type: 'string', + enum: [ + 'exit_span_throughput', + 'exit_span_failure_rate', + 'exit_span_latency', + ], + }, + 'span.destination.service.resource': { + type: 'string', + description: + 'The name of the downstream dependency for the service', + }, + }, + required: ['name'], + }, + { + type: 'object', + properties: { + name: { + type: 'string', + const: 'error_event_rate', + }, + }, + required: ['name'], + }, + { + type: 'object', + properties: { + name: { + type: 'string', + const: 'transaction_latency', + }, + 'transaction.type': { + type: 'string', + }, + function: { + type: 'string', + enum: ['avg', 'p95', 'p99'], + }, + }, + required: ['name', 'function'], + }, + ], + }, + 'service.name': { + ...NON_EMPTY_STRING, + description: 'The name of the service', + }, + 'service.environment': { + description: + 'The environment that the service is running in. If undefined, all environments will be included. Only use this if you have confirmed the environment that the service is running in.', + }, + filter: { + type: 'string', + description: + 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', + }, + title: { + type: 'string', + description: + 'A unique, human readable, concise title for this specific group series.', + }, + offset: { + type: 'string', + description: + 'The offset. Right: 15m. 8h. 1d. Wrong: -15m. -8h. -1d.', + }, + }, + required: ['service.name', 'timeseries', 'title'], + }, + }, + }, + required: ['stats', 'start', 'end'], +} as const; + +export function registerGetApmTimeseriesFunction({ + apmEventClient, + registerFunction, +}: FunctionRegistrationParameters) { + registerFunction( + { + contexts: ['apm'], + name: 'get_apm_timeseries', + descriptionForUser: i18n.translate( + 'xpack.apm.observabilityAiAssistant.functions.registerGetApmTimeseries.descriptionForUser', + { + defaultMessage: `Display different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions`, + } + ), + description: `Visualise and analyse different APM metrics, like throughput, failure rate, or latency, for any service or all services, or any or all of its dependencies, both as a timeseries and as a single statistic. A visualisation will be displayed above your reply - DO NOT attempt to display or generate an image yourself, or any other placeholder. Additionally, the function will return any changes, such as spikes, step and trend changes, or dips. You can also use it to compare data by requesting two different time ranges, or for instance two different service versions.`, + parameters, + }, + async ( + { arguments: args }, + signal + ): Promise => { + const timeseries = await getApmTimeseries({ + apmEventClient, + arguments: args as any, + }); + + return { + content: timeseries.map( + (series): Omit => omit(series, 'data') + ), + data: timeseries, + }; + } + ); +} + +export type GetApmTimeseriesFunctionArguments = FromSchema; +export interface GetApmTimeseriesFunctionResponse { + content: Array>; + data: ApmTimeseries[]; +} diff --git a/x-pack/plugins/apm/server/assistant_functions/index.ts b/x-pack/plugins/apm/server/assistant_functions/index.ts new file mode 100644 index 0000000000000..81521a233ad1d --- /dev/null +++ b/x-pack/plugins/apm/server/assistant_functions/index.ts @@ -0,0 +1,186 @@ +/* + * 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 { CoreSetup } from '@kbn/core-lifecycle-server'; +import type { Logger } from '@kbn/logging'; +import type { + ChatRegistrationFunction, + RegisterFunction, +} from '@kbn/observability-ai-assistant-plugin/server/service/types'; +import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; +import type { APMConfig } from '..'; +import type { ApmFeatureFlags } from '../../common/apm_feature_flags'; +import { APMEventClient } from '../lib/helpers/create_es_client/create_apm_event_client'; +import { getApmEventClient } from '../lib/helpers/get_apm_event_client'; +import type { APMRouteHandlerResources } from '../routes/apm_routes/register_apm_server_routes'; +import { hasHistoricalAgentData } from '../routes/historical_data/has_historical_agent_data'; +import { registerGetApmCorrelationsFunction } from './get_apm_correlations'; +import { registerGetApmDownstreamDependenciesFunction } from './get_apm_downstream_dependencies'; +import { registerGetApmErrorDocumentFunction } from './get_apm_error_document'; +import { registerGetApmServicesListFunction } from './get_apm_services_list'; +import { registerGetApmServiceSummaryFunction } from './get_apm_service_summary'; +import { registerGetApmTimeseriesFunction } from './get_apm_timeseries'; + +export interface FunctionRegistrationParameters { + apmEventClient: APMEventClient; + registerFunction: RegisterFunction; + resources: APMRouteHandlerResources; +} + +export function registerAssistantFunctions({ + coreSetup, + config, + featureFlags, + logger, + kibanaVersion, + ruleDataClient, + plugins, +}: { + coreSetup: CoreSetup; + config: APMConfig; + featureFlags: ApmFeatureFlags; + logger: Logger; + kibanaVersion: string; + ruleDataClient: IRuleDataClient; + plugins: APMRouteHandlerResources['plugins']; +}): ChatRegistrationFunction { + return async ({ resources, registerContext, registerFunction }) => { + const apmRouteHandlerResources: APMRouteHandlerResources = { + context: resources.context, + request: resources.request, + core: { + setup: coreSetup, + start: () => + coreSetup.getStartServices().then(([coreStart]) => coreStart), + }, + params: { + query: { + _inspect: false, + }, + }, + config, + featureFlags, + logger, + kibanaVersion, + ruleDataClient, + plugins, + getApmIndices: async () => { + const coreContext = await resources.context.core; + const apmIndices = await plugins.apmDataAccess.setup.getApmIndices( + coreContext.savedObjects.client + ); + return apmIndices; + }, + }; + + const apmEventClient = await getApmEventClient(apmRouteHandlerResources); + + const hasData = await hasHistoricalAgentData(apmEventClient); + + if (!hasData) { + return; + } + + const parameters: FunctionRegistrationParameters = { + resources: apmRouteHandlerResources, + apmEventClient, + registerFunction, + }; + + registerGetApmServicesListFunction(parameters); + registerGetApmServiceSummaryFunction(parameters); + registerGetApmErrorDocumentFunction(parameters); + registerGetApmDownstreamDependenciesFunction(parameters); + registerGetApmCorrelationsFunction(parameters); + registerGetApmTimeseriesFunction(parameters); + + registerContext({ + name: 'apm', + description: ` + When analyzing APM data, prefer the APM specific functions over the generic Lens, + Elasticsearch or Kibana ones, unless those are explicitly requested by the user. + + When requesting metrics for a service, make sure you also know what environment + it is running in. Metrics aggregated over multiple environments are useless. + + There are four important data types in Elastic APM. Each of them have the + following fields: + - service.name: the name of the service + - service.node.name: the id of the service instance (often the hostname) + - service.environment: the environment (often production, development) + - agent.name: the name of the agent (go, java, etc) + + The four data types are transactions, exit spans, error events, and application + metrics. + + Transactions have three metrics: throughput, failure rate, and latency. The + fields are: + + - transaction.type: often request or page-load (the main transaction types), + but can also be worker, or route-change. + - transaction.name: The name of the transaction group, often something like + 'GET /api/product/:productId' + - transaction.result: The result. Used to capture HTTP response codes + (2xx,3xx,4xx,5xx) for request transactions. + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Exit spans have three metrics: throughput, failure rate and latency. The fields + are: + - span.type: db, external + - span.subtype: the type of database (redis, postgres) or protocol (http, grpc) + - span.destination.service.resource: the address of the destination of the call + - event.outcome: whether the transaction was succesful or not. success, + failure, or unknown. + + Error events have one metric, error event rate. The fields are: + - error.grouping_name: a human readable keyword that identifies the error group + + For transaction metrics we also collect anomalies. These are scored 0 (low) to + 100 (critical). + + For root cause analysis, locate a change point in the relevant metrics for a + service or downstream dependency. You can locate a change point by using a + sliding window, e.g. start with a small time range, like 30m, and make it + bigger until you identify a change point. It's very important to identify a + change point. If you don't have a change point, ask the user for next steps. + You can also use an anomaly or a deployment as a change point. Then, compare + data before the change with data after the change. You can either use the + groupBy parameter in get_apm_chart to get the most occuring values in a certain + data set, or you can use correlations to see for which field and value the + frequency has changed when comparing the foreground set to the background set. + This is useful when comparing data from before the change point with after the + change point. For instance, you might see a specific error pop up more often + after the change point. + + When comparing anomalies and changes in timeseries, first, zoom in to a smaller + time window, at least 30 minutes before and 30 minutes after the change + occured. E.g., if the anomaly occured at 2023-07-05T08:15:00.000Z, request a + time window that starts at 2023-07-05T07:45:00.000Z and ends at + 2023-07-05T08:45:00.000Z. When comparing changes in different timeseries and + anomalies to determine a correlation, make sure to compare the timestamps. If + in doubt, rate the likelihood of them being related, given the time difference, + between 1 and 10. If below 5, assume it's not related. Mention this likelihood + (and the time difference) to the user. + + Your goal is to help the user determine the root cause of an issue quickly and + transparently. If you see a change or + anomaly in a metric for a service, try to find similar changes in the metrics + for the traffic to its downstream dependencies, by comparing transaction + metrics to span metrics. To inspect the traffic from one service to a + downstream dependency, first get the downstream dependencies for a service, + then get the span metrics from that service (\`service.name\`) to its + downstream dependency (\`span.destination.service.resource\`). For instance, + for an anomaly in throughput, first inspect \`transaction_throughput\` for + \`service.name\`. Then, inspect \`exit_span_throughput\` for its downstream + dependencies, by grouping by \`span.destination.service.resource\`. Repeat this + process over the next service its downstream dependencies until you identify a + root cause. If you can not find any similar changes, use correlations or + grouping to find attributes that could be causes for the change.`, + }); + }; +} diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 07010d5f8dc5b..220bdebbf32d7 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -49,6 +49,7 @@ import { scheduleSourceMapMigration } from './routes/source_maps/schedule_source import { createApmSourceMapIndexTemplate } from './routes/source_maps/create_apm_source_map_index_template'; import { addApiKeysToEveryPackagePolicyIfMissing } from './routes/fleet/api_keys/add_api_keys_to_policies_if_missing'; import { apmTutorialCustomIntegration } from '../common/tutorial/tutorials'; +import { registerAssistantFunctions } from './assistant_functions'; export class APMPlugin implements @@ -167,6 +168,8 @@ export class APMPlugin APM_SERVER_FEATURE_ID ); + const kibanaVersion = this.initContext.env.packageInfo.version; + registerRoutes({ core: { setup: core, @@ -179,7 +182,7 @@ export class APMPlugin ruleDataClient, plugins: resourcePlugins, telemetryUsageCounter, - kibanaVersion: this.initContext.env.packageInfo.version, + kibanaVersion, }); const { getApmIndices } = plugins.apmDataAccess; @@ -230,6 +233,18 @@ export class APMPlugin this.logger?.error(e); }); + plugins.observabilityAIAssistant.service.register( + registerAssistantFunctions({ + config: this.currentConfig!, + coreSetup: core, + featureFlags: this.currentConfig!.featureFlags, + kibanaVersion, + logger: this.logger.get('assistant'), + plugins: resourcePlugins, + ruleDataClient, + }) + ); + return { config$ }; } diff --git a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts index df7bb7e7a146d..5aed2451858a9 100644 --- a/x-pack/plugins/apm/server/routes/assistant_functions/route.ts +++ b/x-pack/plugins/apm/server/routes/assistant_functions/route.ts @@ -4,21 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import datemath from '@elastic/datemath'; import { ElasticsearchClient } from '@kbn/core/server'; import * as t from 'io-ts'; import { omit } from 'lodash'; -import { ApmDocumentType } from '../../../common/document_type'; -import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; -import { RollupInterval } from '../../../common/rollup'; -import { ServiceHealthStatus } from '../../../common/service_health_status'; -import type { APMError } from '../../../typings/es_schemas/ui/apm_error'; import { getApmAlertsClient } from '../../lib/helpers/get_apm_alerts_client'; import { getApmEventClient } from '../../lib/helpers/get_apm_event_client'; import { getMlClient } from '../../lib/helpers/get_ml_client'; -import { getRandomSampler } from '../../lib/helpers/get_random_sampler'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { getServicesItems } from '../services/get_services/get_services_items'; import { CorrelationValue, correlationValuesRouteRt, @@ -29,7 +21,6 @@ import { getAssistantDownstreamDependencies, type APMDownstreamDependency, } from './get_apm_downstream_dependencies'; -import { errorRouteRt, getApmErrorDocument } from './get_apm_error_document'; import { getApmServiceSummary, serviceSummaryRouteRt, @@ -167,130 +158,9 @@ const getApmCorrelationValuesRoute = createApmServerRoute({ }, }); -const getApmErrorDocRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/assistant/get_error_document', - params: t.type({ - query: errorRouteRt, - }), - options: { - tags: ['access:apm'], - }, - handler: async ( - resources - ): Promise<{ content: Array> }> => { - const { params } = resources; - const apmEventClient = await getApmEventClient(resources); - const { query } = params; - - return { - content: await getApmErrorDocument({ - apmEventClient, - arguments: query, - }), - }; - }, -}); - -export interface ApmServicesListItem { - 'service.name': string; - 'agent.name'?: string; - 'transaction.type'?: string; - alertsCount: number; - healthStatus: ServiceHealthStatus; - 'service.environment'?: string[]; -} - -type ApmServicesListContent = ApmServicesListItem[]; - -const getApmServicesListRoute = createApmServerRoute({ - endpoint: 'POST /internal/apm/assistant/get_services_list', - params: t.type({ - body: t.intersection([ - t.type({ - start: t.string, - end: t.string, - }), - t.partial({ - 'service.environment': t.string, - healthStatus: t.array( - t.union([ - t.literal(ServiceHealthStatus.unknown), - t.literal(ServiceHealthStatus.healthy), - t.literal(ServiceHealthStatus.warning), - t.literal(ServiceHealthStatus.critical), - ]) - ), - }), - ]), - }), - options: { - tags: ['access:apm'], - }, - handler: async (resources): Promise<{ content: ApmServicesListContent }> => { - const { params } = resources; - const { body } = params; - - const { healthStatus } = body; - - const [apmEventClient, apmAlertsClient, mlClient, randomSampler] = - await Promise.all([ - getApmEventClient(resources), - getApmAlertsClient(resources), - getMlClient(resources), - getRandomSampler({ - security: resources.plugins.security, - probability: 1, - request: resources.request, - }), - ]); - - const start = datemath.parse(body.start)?.valueOf()!; - const end = datemath.parse(body.end)?.valueOf()!; - - const serviceItems = await getServicesItems({ - apmAlertsClient, - apmEventClient, - documentType: ApmDocumentType.TransactionMetric, - start, - end, - environment: body['service.environment'] || ENVIRONMENT_ALL.value, - kuery: '', - logger: resources.logger, - randomSampler, - rollupInterval: RollupInterval.OneMinute, - serviceGroup: null, - mlClient, - useDurationSummary: false, - }); - - let mappedItems = serviceItems.items.map((item): ApmServicesListItem => { - return { - 'service.name': item.serviceName, - 'agent.name': item.agentName, - alertsCount: item.alertsCount ?? 0, - healthStatus: item.healthStatus ?? ServiceHealthStatus.unknown, - 'service.environment': item.environments, - 'transaction.type': item.transactionType, - }; - }); - - if (healthStatus && healthStatus.length) { - mappedItems = mappedItems.filter((item): boolean => - healthStatus.includes(item.healthStatus) - ); - } - - return { - content: mappedItems, - }; - }, -}); - export const assistantRouteRepository = { ...getApmTimeSeriesRoute, ...getApmServiceSummaryRoute, - ...getApmErrorDocRoute, ...getApmCorrelationValuesRoute, ...getDownstreamDependenciesRoute, - ...getApmServicesListRoute, }; diff --git a/x-pack/plugins/apm/server/types.ts b/x-pack/plugins/apm/server/types.ts index 10687e3757849..fa77e52e76836 100644 --- a/x-pack/plugins/apm/server/types.ts +++ b/x-pack/plugins/apm/server/types.ts @@ -65,6 +65,10 @@ import { ProfilingDataAccessPluginSetup, ProfilingDataAccessPluginStart, } from '@kbn/profiling-data-access-plugin/server'; +import type { + ObservabilityAIAssistantPluginSetup, + ObservabilityAIAssistantPluginStart, +} from '@kbn/observability-ai-assistant-plugin/server'; import { APMConfig } from '.'; export interface APMPluginSetup { @@ -82,7 +86,7 @@ export interface APMPluginSetupDependencies { metricsDataAccess: MetricsDataPluginSetup; dataViews: {}; share: SharePluginSetup; - + observabilityAIAssistant: ObservabilityAIAssistantPluginSetup; // optional dependencies actions?: ActionsPlugin['setup']; alerting?: AlertingPlugin['setup']; @@ -108,7 +112,7 @@ export interface APMPluginStartDependencies { metricsDataAccess: MetricsDataPluginSetup; dataViews: DataViewsServerPluginStart; share: undefined; - + observabilityAIAssistant: ObservabilityAIAssistantPluginStart; // optional dependencies actions?: ActionsPlugin['start']; alerting?: AlertingPlugin['start']; diff --git a/x-pack/plugins/apm/public/utils/non_empty_string_ref.ts b/x-pack/plugins/apm/server/utils/non_empty_string_ref.ts similarity index 100% rename from x-pack/plugins/apm/public/utils/non_empty_string_ref.ts rename to x-pack/plugins/apm/server/utils/non_empty_string_ref.ts diff --git a/x-pack/plugins/apm/tsconfig.json b/x-pack/plugins/apm/tsconfig.json index db829dc3ed5f8..ba23f19f78c4a 100644 --- a/x-pack/plugins/apm/tsconfig.json +++ b/x-pack/plugins/apm/tsconfig.json @@ -106,7 +106,8 @@ "@kbn/custom-icons", "@kbn/elastic-agent-utils", "@kbn/shared-ux-link-redirect-app", - "@kbn/observability-get-padded-alert-time-range-util" + "@kbn/observability-get-padded-alert-time-range-util", + "@kbn/core-lifecycle-server" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/asset_manager/docs/api.md b/x-pack/plugins/asset_manager/docs/api.md index 66a1984297c16..60810dce22911 100644 --- a/x-pack/plugins/asset_manager/docs/api.md +++ b/x-pack/plugins/asset_manager/docs/api.md @@ -41,7 +41,7 @@ publicMethodA(...options: MethodAPublicOptions) injects some internal dependencies from the plugin's config on your behalf ``` -The public and server clientss are both accessible to plugin dependants, but the REST API is NOT. +The public and server clients are both accessible to plugin dependants, but the REST API is NOT. ### Required dependency setup @@ -175,14 +175,40 @@ Get a list of host assets found within a specified time range. | :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- | | from | datetime string | yes | ISO date string representing the START of the time range being queried | | to | datetime string | yes | ISO date string representing the END of the time range being queried | +| filters | object | no | key/value pairs filtering the assets returned. See [supported filters](https://github.com/klacabane/kibana/blob/main/x-pack/plugins/asset_manager/common/types_api.ts#L168-L178) | + +**Example** + +```js +getHosts({ + from: '2023-12-04T09:42:00.000Z', + to: '2023-12-04T09:44:00.000Z', + filters: { + 'cloud.provider': 'gcp' + } +}) +``` **Response** ```json { - "hosts": [ - ...found host assets - ] + "hosts": [ + { + "@timestamp": "2023-12-04T09:42:52.538Z", + "asset.kind": "host", + "asset.id": "gcp-host-2zze1241", + "asset.name": "gcp-host-2zze1241", + "asset.ean": "host:gcp-host-2zze1241", + "cloud.provider": "gcp", + "cloud.instance.id": "235111598995020799", + "cloud.service.name": "GCE", + "cloud.region": "us-central1", + "asset.children": [ + "pod:3ca933f5-effa-47f6-b991-fa1b528cc2e4" + ] + } + ] } ``` @@ -194,14 +220,159 @@ Get a list of service assets found within a specified time range. | :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- | | from | datetime string | yes | ISO date string representing the START of the time range being queried | | to | datetime string | yes | ISO date string representing the END of the time range being queried | -| parent | string | no | EAN value for a given parent service to filter services by | +| filters | object | no | key/value pairs filtering the assets returned. See [supported filters](https://github.com/klacabane/kibana/blob/main/x-pack/plugins/asset_manager/common/types_api.ts#L168-L178) | + +**Example** + +```js +getServices({ + from: '2023-12-04T09:42:00.000Z', + to: '2023-12-04T09:44:00.000Z' +}) +``` + +**Response** + +```json +{ + "services": [ + { + "@timestamp": "2023-12-03T09:44:00.000Z", + "asset.kind": "service", + "asset.id": "adservice", + "asset.ean": "service:adservice", + "asset.parents": [ + "container:50041db622002301a71b15e3c8468aa2b0cdb716b2ebd3091e20975580a397ae" + ] + } + ] +} +``` + +#### getContainers + +Get a list of container assets found within a specified time range. + +| Parameter | Type | Required? | Description | +| :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- | +| from | datetime string | yes | ISO date string representing the START of the time range being queried | +| to | datetime string | yes | ISO date string representing the END of the time range being queried | +| filters | object | no | key/value pairs filtering the assets returned. See [supported filters](https://github.com/klacabane/kibana/blob/main/x-pack/plugins/asset_manager/common/types_api.ts#L168-L178) | + +**Example** + +```js +getContainers({ + from: '2023-12-04T09:42:00.000Z', + to: '2023-12-04T09:44:00.000Z' +}) +``` + +**Response** + +```json +{ + "containers": [ + { + "@timestamp": "2023-12-03T09:42:11.427Z", + "asset.kind": "container", + "asset.id": "040744a58fdbdf9a7d628c4e71842301ccc3ed54a1efa8ff47747af251e5896c", + "asset.ean": "container:040744a58fdbdf9a7d628c4e71842301ccc3ed54a1efa8ff47747af251e5896c", + "asset.parents": [ + "pod:928db0ae-2b63-48f3-8725-a8ddc490d69e" + ], + "asset.references": [ + "host:gcp-host-2zze1241" + ] + } + ] +} +``` + +#### getPods + +Get a list of pod assets found within a specified time range. + +| Parameter | Type | Required? | Description | +| :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- | +| from | datetime string | yes | ISO date string representing the START of the time range being queried | +| to | datetime string | yes | ISO date string representing the END of the time range being queried | +| filters | object | no | key/value pairs filtering the assets returned. See [supported filters](https://github.com/klacabane/kibana/blob/main/x-pack/plugins/asset_manager/common/types_api.ts#L168-L178) | + +**Example** + +```js +getPods({ + from: '2023-12-04T09:42:00.000Z', + to: '2023-12-04T09:44:00.000Z' +}) +``` + +**Response** + +```json +{ + "pods": [ + { + "@timestamp": "2023-12-03T09:42:14.680Z", + "asset.kind": "pod", + "asset.id": "00b2bad4-b878-4647-aa00-d8b24c9216f1", + "asset.ean": "pod:00b2bad4-b878-4647-aa00-d8b24c9216f1", + "asset.parents": [ + "host:gcp-host-2zze1241" + ], + "cloud.provider": "gcp" + } + ] +} +``` + +#### getAssets + +Get a list of service assets found within a specified time range, sorted by timestamp desc. + +| Parameter | Type | Required? | Description | +| :-------- | :-------------- | :-------- | :--------------------------------------------------------------------- | +| from | datetime string | yes | ISO date string representing the START of the time range being queried | +| to | datetime string | yes | ISO date string representing the END of the time range being queried | +| filters | object | no | key/value pairs filtering the assets returned. See [supported filters](https://github.com/klacabane/kibana/blob/main/x-pack/plugins/asset_manager/common/types_api.ts#L168-L178) | + +**Example** + +```js +getAssets({ + from: '2023-12-04T09:42:00.000Z', + to: '2023-12-04T09:44:00.000Z' +}) +``` **Response** ```json { - "services": [ - ...found service assets - ] + "assets": [ + { + "@timestamp": "2023-12-03T09:44:00.000Z", + "asset.kind": "service", + "asset.id": "adservice", + "asset.ean": "service:adservice", + "asset.parents": [ + "container:50041db622002301a71b15e3c8468aa2b0cdb716b2ebd3091e20975580a397ae" + ] + }, + { + "@timestamp": "2023-12-04T09:42:52.538Z", + "asset.kind": "host", + "asset.id": "gcp-host-2zze1241", + "asset.name": "gcp-host-2zze1241", + "asset.ean": "host:gcp-host-2zze1241", + "cloud.provider": "gcp", + "cloud.instance.id": "235111598995020799", + "cloud.region": "us-central1", + "asset.children": [ + "pod:3ca933f5-effa-47f6-b991-fa1b528cc2e4" + ] + } + ] } ``` diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts b/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts index c9d0e8379dbdd..2012e05912487 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts @@ -8,6 +8,7 @@ import { estypes } from '@elastic/elasticsearch'; import { Asset } from '../../../common/types_api'; import { CollectorOptions, QUERY_MAX_SIZE } from '.'; +import { extractFieldValue } from '../utils'; export async function collectContainers({ client, @@ -33,6 +34,7 @@ export async function collectContainers({ sort: [{ 'container.id': 'asc' }], _source: false, fields: [ + '@timestamp', 'kubernetes.*', 'cloud.provider', 'orchestrator.cluster.name', @@ -70,14 +72,14 @@ export async function collectContainers({ const assets = esResponse.hits.hits.reduce((acc: Asset[], hit: any) => { const { fields = {} } = hit; - const containerId = fields['container.id']; - const podUid = fields['kubernetes.pod.uid']; - const nodeName = fields['kubernetes.node.name']; + const containerId = extractFieldValue(fields['container.id']); + const podUid = extractFieldValue(fields['kubernetes.pod.uid']); + const nodeName = extractFieldValue(fields['kubernetes.node.name']); const parentEan = podUid ? `pod:${podUid}` : `host:${fields['host.hostname']}`; const container: Asset = { - '@timestamp': new Date().toISOString(), + '@timestamp': extractFieldValue(fields['@timestamp']), 'asset.kind': 'container', 'asset.id': containerId, 'asset.ean': `container:${containerId}`, diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts b/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts index a082cafc8546c..b624373010f10 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts @@ -8,6 +8,7 @@ import { estypes } from '@elastic/elasticsearch'; import { Asset } from '../../../common/types_api'; import { CollectorOptions, QUERY_MAX_SIZE } from '.'; +import { extractFieldValue } from '../utils'; export async function collectHosts({ client, @@ -69,14 +70,14 @@ export async function collectHosts({ const assets = esResponse.hits.hits.reduce((acc: Asset[], hit: any) => { const { fields = {} } = hit; - const hostName = fields['host.hostname']; - const k8sNode = fields['kubernetes.node.name']; - const k8sPod = fields['kubernetes.pod.uid']; + const hostName = extractFieldValue(fields['host.hostname']); + const k8sNode = extractFieldValue(fields['kubernetes.node.name']); + const k8sPod = extractFieldValue(fields['kubernetes.pod.uid']); const hostEan = `host:${k8sNode || hostName}`; const host: Asset = { - '@timestamp': new Date().toISOString(), + '@timestamp': extractFieldValue(fields['@timestamp']), 'asset.kind': 'host', 'asset.id': k8sNode || hostName, 'asset.name': k8sNode || hostName, @@ -84,23 +85,23 @@ export async function collectHosts({ }; if (fields['cloud.provider']) { - host['cloud.provider'] = fields['cloud.provider']; + host['cloud.provider'] = extractFieldValue(fields['cloud.provider']); } if (fields['cloud.instance.id']) { - host['cloud.instance.id'] = fields['cloud.instance.id']; + host['cloud.instance.id'] = extractFieldValue(fields['cloud.instance.id']); } if (fields['cloud.service.name']) { - host['cloud.service.name'] = fields['cloud.service.name']; + host['cloud.service.name'] = extractFieldValue(fields['cloud.service.name']); } if (fields['cloud.region']) { - host['cloud.region'] = fields['cloud.region']; + host['cloud.region'] = extractFieldValue(fields['cloud.region']); } if (fields['orchestrator.cluster.name']) { - host['orchestrator.cluster.name'] = fields['orchestrator.cluster.name']; + host['orchestrator.cluster.name'] = extractFieldValue(fields['orchestrator.cluster.name']); } if (k8sPod) { diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/pods.ts b/x-pack/plugins/asset_manager/server/lib/collectors/pods.ts index f9a4e2e22ae51..e78fa106452ca 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/pods.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/pods.ts @@ -8,6 +8,7 @@ import { estypes } from '@elastic/elasticsearch'; import { Asset } from '../../../common/types_api'; import { CollectorOptions, QUERY_MAX_SIZE } from '.'; +import { extractFieldValue } from '../utils'; export async function collectPods({ client, @@ -37,6 +38,7 @@ export async function collectPods({ sort: [{ 'kubernetes.pod.uid': 'asc' }], _source: false, fields: [ + '@timestamp', 'kubernetes.*', 'cloud.provider', 'orchestrator.cluster.name', @@ -68,12 +70,12 @@ export async function collectPods({ const assets = esResponse.hits.hits.reduce((acc: Asset[], hit: any) => { const { fields = {} } = hit; - const podUid = fields['kubernetes.pod.uid']; - const nodeName = fields['kubernetes.node.name']; - const clusterName = fields['orchestrator.cluster.name']; + const podUid = extractFieldValue(fields['kubernetes.pod.uid']); + const nodeName = extractFieldValue(fields['kubernetes.node.name']); + const clusterName = extractFieldValue(fields['orchestrator.cluster.name']); const pod: Asset = { - '@timestamp': new Date().toISOString(), + '@timestamp': extractFieldValue(fields['@timestamp']), 'asset.kind': 'pod', 'asset.id': podUid, 'asset.ean': `pod:${podUid}`, @@ -81,7 +83,7 @@ export async function collectPods({ }; if (fields['cloud.provider']) { - pod['cloud.provider'] = fields['cloud.provider']; + pod['cloud.provider'] = extractFieldValue(fields['cloud.provider']); } if (clusterName) { diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/services.ts b/x-pack/plugins/asset_manager/server/lib/collectors/services.ts index e000860c9f4c5..4c49f75d13594 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/services.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/services.ts @@ -74,6 +74,9 @@ export async function collectServices({ ], }, aggs: { + last_seen: { + max: { field: '@timestamp' }, + }, container_and_hosts: { multi_terms: { terms: [ @@ -104,6 +107,7 @@ export async function collectServices({ const { key: { serviceName, serviceEnvironment }, container_and_hosts: containerHosts, + last_seen: lastSeen, } = bucket; if (!serviceName) { @@ -111,7 +115,7 @@ export async function collectServices({ } const service: Asset = { - '@timestamp': new Date().toISOString(), + '@timestamp': lastSeen.value_as_string, 'asset.kind': 'service', 'asset.id': serviceName, 'asset.ean': `service:${serviceName}`, diff --git a/x-pack/plugins/asset_manager/server/lib/utils.ts b/x-pack/plugins/asset_manager/server/lib/utils.ts index fa9cf965771ef..d948ac28bda31 100644 --- a/x-pack/plugins/asset_manager/server/lib/utils.ts +++ b/x-pack/plugins/asset_manager/server/lib/utils.ts @@ -35,3 +35,7 @@ export function isStringOrNonEmptyArray( } return true; } + +export function extractFieldValue(maybeArray: T | T[] | undefined): T { + return toArray(maybeArray)[0]; +} diff --git a/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/help_menu_links.tsx b/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/help_menu_links.tsx index 05ea7b9ce30cd..14edb22d97665 100644 --- a/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/help_menu_links.tsx +++ b/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/help_menu_links.tsx @@ -53,7 +53,6 @@ export const createHelpMenuLinks = ({ title: i18n.translate('xpack.cloudLinks.helpMenuLinks.connectionDetails', { defaultMessage: 'Connection details', }), - iconType: 'console', dataTestSubj: 'connectionDetailsHelpLink', onClick: () => { const modal = overlays.openModal( diff --git a/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/maybe_add_cloud_links.test.ts b/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/maybe_add_cloud_links.test.ts index c22b2bfdfd6ce..5fc4a9549682f 100644 --- a/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/maybe_add_cloud_links.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_links/public/maybe_add_cloud_links/maybe_add_cloud_links.test.ts @@ -95,7 +95,6 @@ describe('maybeAddCloudLinks', () => { }, Object { "dataTestSubj": "connectionDetailsHelpLink", - "iconType": "console", "onClick": [Function], "title": "Connection details", }, @@ -169,7 +168,6 @@ describe('maybeAddCloudLinks', () => { }, Object { "dataTestSubj": "connectionDetailsHelpLink", - "iconType": "console", "onClick": [Function], "title": "Connection details", }, diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index d2fffa9d26a2b..770f4ef5d06e3 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -10,7 +10,7 @@ import { VulnSeverity, AwsCredentialsTypeFieldMap, GcpCredentialsTypeFieldMap, -} from './types'; +} from './types_old'; export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; export const STATUS_API_CURRENT_VERSION = '1'; @@ -23,8 +23,8 @@ export const VULNERABILITIES_DASHBOARD_ROUTE_PATH = export const BENCHMARKS_ROUTE_PATH = '/internal/cloud_security_posture/benchmarks'; export const BENCHMARKS_API_CURRENT_VERSION = '1'; -export const FIND_CSP_RULE_TEMPLATE_ROUTE_PATH = '/internal/cloud_security_posture/rules/_find'; -export const FIND_CSP_RULE_TEMPLATE_API_CURRENT_VERSION = '1'; +export const FIND_CSP_BENCHMARK_RULE_ROUTE_PATH = '/internal/cloud_security_posture/rules/_find'; +export const FIND_CSP_BENCHMARK_RULE_API_CURRENT_VERSION = '1'; export const DETECTION_RULE_ALERTS_STATUS_API_CURRENT_VERSION = '1'; export const DETECTION_RULE_RULES_API_CURRENT_VERSION = '2023-10-31'; @@ -85,7 +85,7 @@ export const INTERNAL_FEATURE_FLAGS = { showFindingFlyoutEvidence: true, } as const; -export const CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE = 'csp-rule-template'; +export const CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE = 'csp-rule-template'; export const CLOUDBEAT_VANILLA = 'cloudbeat/cis_k8s'; export const CLOUDBEAT_EKS = 'cloudbeat/cis_eks'; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts index bfe825b59d31b..bef70384b98cf 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts @@ -7,7 +7,7 @@ // TODO: this needs to be defined in a versioned schema import type { EcsEvent } from '@kbn/ecs'; -import type { CspRuleTemplateMetadata } from './csp_rule_template_metadata'; +import { CspBenchmarkRuleMetadata } from '../types/latest'; export interface CspFinding { '@timestamp': string; @@ -16,7 +16,7 @@ export interface CspFinding { cloud?: CspFindingCloud; // only available on CSPM findings result: CspFindingResult; resource: CspFindingResource; - rule: CspRuleTemplateMetadata; + rule: CspBenchmarkRuleMetadata; host: CspFindingHost; event: EcsEvent; agent: CspFindingAgent; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template.ts deleted file mode 100644 index 0ed56fb5d7e3b..0000000000000 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template.ts +++ /dev/null @@ -1,47 +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 { schema as rt, TypeOf } from '@kbn/config-schema'; -import { - cspRuleTemplateMetadataSchemaV840, - cspRuleTemplateMetadataSchemaV870, -} from './csp_rule_template_metadata'; - -export const cspRuleTemplateSchemaV830 = rt.object({ - audit: rt.string(), - benchmark: rt.object({ name: rt.string(), version: rt.string() }), - default_value: rt.maybe(rt.string()), - description: rt.string(), - enabled: rt.boolean(), - id: rt.string(), - impact: rt.maybe(rt.string()), - muted: rt.boolean(), - name: rt.string(), - profile_applicability: rt.string(), - rationale: rt.string(), - references: rt.maybe(rt.string()), - rego_rule_id: rt.string(), - remediation: rt.string(), - section: rt.string(), - tags: rt.arrayOf(rt.string()), - version: rt.string(), -}); - -export const cspRuleTemplateSchemaV840 = rt.object({ - enabled: rt.boolean(), - metadata: cspRuleTemplateMetadataSchemaV840, - muted: rt.boolean(), -}); - -export const cspRuleTemplateSchemaV870 = rt.object({ - metadata: cspRuleTemplateMetadataSchemaV870, -}); - -export type CspRuleTemplateV830 = TypeOf; -export type CspRuleTemplateV840 = TypeOf; -export type CspRuleTemplateV870 = TypeOf; - -export type CspRuleTemplate = CspRuleTemplateV870; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_metadata.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_metadata.ts deleted file mode 100644 index b466ed7e70d2d..0000000000000 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_metadata.ts +++ /dev/null @@ -1,60 +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 { schema as rt, TypeOf } from '@kbn/config-schema'; -import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../constants'; - -export const cspRuleTemplateMetadataSchemaV840 = rt.object({ - audit: rt.string(), - benchmark: rt.object({ - name: rt.string(), - id: rt.string(), - version: rt.string(), - }), - default_value: rt.maybe(rt.string()), - description: rt.string(), - id: rt.string(), - impact: rt.maybe(rt.string()), - name: rt.string(), - profile_applicability: rt.string(), - rationale: rt.string(), - references: rt.maybe(rt.string()), - rego_rule_id: rt.string(), - remediation: rt.string(), - section: rt.string(), - tags: rt.arrayOf(rt.string()), - version: rt.string(), -}); - -export const cspRuleTemplateMetadataSchemaV870 = rt.object({ - audit: rt.string(), - benchmark: rt.object({ - name: rt.string(), - posture_type: rt.maybe( - rt.oneOf([rt.literal(CSPM_POLICY_TEMPLATE), rt.literal(KSPM_POLICY_TEMPLATE)]) - ), - id: rt.string(), - version: rt.string(), - rule_number: rt.maybe(rt.string()), - }), - default_value: rt.maybe(rt.string()), - description: rt.string(), - id: rt.string(), - impact: rt.maybe(rt.string()), - name: rt.string(), - profile_applicability: rt.string(), - rationale: rt.string(), - references: rt.maybe(rt.string()), - rego_rule_id: rt.string(), - remediation: rt.string(), - section: rt.string(), - tags: rt.arrayOf(rt.string()), - version: rt.string(), -}); - -export type CspRuleMetadataV840 = TypeOf; -export type CspRuleMetadataV870 = TypeOf; -export type CspRuleTemplateMetadata = CspRuleMetadataV870; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts index f650b115316df..efe26dc6648ba 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_vulnerability_finding.ts @@ -7,7 +7,7 @@ // TODO: this needs to be defined in a versioned schema import type { EcsEvent } from '@kbn/ecs'; -import { VulnSeverity } from '../types'; +import { VulnSeverity } from '../types_old'; export interface CspVulnerabilityFinding { '@timestamp': string; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/index.ts b/x-pack/plugins/cloud_security_posture/common/schemas/index.ts index c7730abc06dba..8c8dcdc52f0f4 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/index.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/index.ts @@ -4,7 +4,4 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export * from './csp_rule_template_metadata'; -export * from './csp_rule_template'; export * from './csp_vulnerability_finding'; diff --git a/x-pack/plugins/cloud_security_posture/common/types/index.ts b/x-pack/plugins/cloud_security_posture/common/types/index.ts new file mode 100644 index 0000000000000..a2aaa3b2ef14e --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/common/types/index.ts @@ -0,0 +1,19 @@ +/* + * 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 * as rulesV1 from './rules/v1'; +export * as rulesV2 from './rules/v2'; +export * as rulesV3 from './rules/v3'; + +// Explicit export of everything from latest +export type { + cspBenchmarkRuleMetadataSchema, + CspBenchmarkRuleMetadata, + CspBenchmarkRule, + FindCspBenchmarkRuleRequest, + FindCspBenchmarkRuleResponse, +} from './latest'; diff --git a/x-pack/plugins/observability_log_explorer/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/types/latest.ts similarity index 76% rename from x-pack/plugins/observability_log_explorer/common/constants.ts rename to x-pack/plugins/cloud_security_posture/common/types/latest.ts index 90cd311f05940..8b55674005249 100644 --- a/x-pack/plugins/observability_log_explorer/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/latest.ts @@ -5,4 +5,4 @@ * 2.0. */ -export const OBSERVABILITY_LOG_EXPLORER_APP_ID = 'observability-log-explorer'; +export * from './rules/v3'; diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v1.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v1.ts new file mode 100644 index 0000000000000..afc2b705ab5c3 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v1.ts @@ -0,0 +1,30 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; + +// Since version 8.3.0 +export const cspBenchmarkRuleSchema = schema.object({ + audit: schema.string(), + benchmark: schema.object({ name: schema.string(), version: schema.string() }), + default_value: schema.maybe(schema.string()), + description: schema.string(), + enabled: schema.boolean(), + id: schema.string(), + impact: schema.maybe(schema.string()), + muted: schema.boolean(), + name: schema.string(), + profile_applicability: schema.string(), + rationale: schema.string(), + references: schema.maybe(schema.string()), + rego_rule_id: schema.string(), + remediation: schema.string(), + section: schema.string(), + tags: schema.arrayOf(schema.string()), + version: schema.string(), +}); + +export type CspBenchmarkRule = TypeOf; diff --git a/x-pack/plugins/cloud_security_posture/common/types/rules/v2.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v2.ts new file mode 100644 index 0000000000000..d88ae6adc089a --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v2.ts @@ -0,0 +1,38 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; + +// Since version 8.4.0 +export const cspBenchmarkRuleMetadataSchema = schema.object({ + audit: schema.string(), + benchmark: schema.object({ + name: schema.string(), + id: schema.string(), + version: schema.string(), + }), + default_value: schema.maybe(schema.string()), + description: schema.string(), + id: schema.string(), + impact: schema.maybe(schema.string()), + name: schema.string(), + profile_applicability: schema.string(), + rationale: schema.string(), + references: schema.maybe(schema.string()), + rego_rule_id: schema.string(), + remediation: schema.string(), + section: schema.string(), + tags: schema.arrayOf(schema.string()), + version: schema.string(), +}); + +export const cspBenchmarkRuleSchema = schema.object({ + enabled: schema.boolean(), + metadata: cspBenchmarkRuleMetadataSchema, + muted: schema.boolean(), +}); + +export type CspBenchmarkRule = TypeOf; diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_api/get_csp_rule_template.ts b/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts similarity index 50% rename from x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_api/get_csp_rule_template.ts rename to x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts index 350909e540d4d..0b7b90339dff1 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_rule_template_api/get_csp_rule_template.ts +++ b/x-pack/plugins/cloud_security_posture/common/types/rules/v3.ts @@ -5,13 +5,48 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; +import { schema, TypeOf } from '@kbn/config-schema'; -// this pages follows versioning interface strategy https://docs.elastic.dev/kibana-dev-docs/versioning-interfaces +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../constants'; -const DEFAULT_RULES_TEMPLATE_PER_PAGE = 25; +const DEFAULT_BENCHMARK_RULES_PER_PAGE = 25; -export const findCspRuleTemplateRequest = schema.object({ +// Since version 8.7.0 +export const cspBenchmarkRuleMetadataSchema = schema.object({ + audit: schema.string(), + benchmark: schema.object({ + name: schema.string(), + posture_type: schema.maybe( + schema.oneOf([schema.literal(CSPM_POLICY_TEMPLATE), schema.literal(KSPM_POLICY_TEMPLATE)]) + ), + id: schema.string(), + version: schema.string(), + rule_number: schema.maybe(schema.string()), + }), + default_value: schema.maybe(schema.string()), + description: schema.string(), + id: schema.string(), + impact: schema.maybe(schema.string()), + name: schema.string(), + profile_applicability: schema.string(), + rationale: schema.string(), + references: schema.maybe(schema.string()), + rego_rule_id: schema.string(), + remediation: schema.string(), + section: schema.string(), + tags: schema.arrayOf(schema.string()), + version: schema.string(), +}); + +export type CspBenchmarkRuleMetadata = TypeOf; + +export const cspBenchmarkRuleSchema = schema.object({ + metadata: cspBenchmarkRuleMetadataSchema, +}); + +export type CspBenchmarkRule = TypeOf; + +export const findCspBenchmarkRuleRequestSchema = schema.object({ /** * An Elasticsearch simple_query_string */ @@ -25,16 +60,16 @@ export const findCspRuleTemplateRequest = schema.object({ /** * The number of objects to include in each page */ - perPage: schema.number({ defaultValue: DEFAULT_RULES_TEMPLATE_PER_PAGE, min: 0 }), + perPage: schema.number({ defaultValue: DEFAULT_BENCHMARK_RULES_PER_PAGE, min: 0 }), /** - * Fields to retrieve from CspRuleTemplate saved object + * Fields to retrieve from CspBenchmarkRule saved object */ fields: schema.maybe(schema.arrayOf(schema.string())), /** * The fields to perform the parsed query against. - * Valid fields are fields which mapped to 'text' in cspRuleTemplateSavedObjectMapping + * Valid fields are fields which mapped to 'text' in cspBenchmarkRuleSavedObjectMapping */ searchFields: schema.arrayOf( schema.oneOf([schema.literal('metadata.name.text'), schema.literal('metadata.section.text')]), @@ -85,3 +120,12 @@ export const findCspRuleTemplateRequest = schema.object({ */ section: schema.maybe(schema.string()), }); + +export type FindCspBenchmarkRuleRequest = TypeOf; + +export interface FindCspBenchmarkRuleResponse { + items: CspBenchmarkRule[]; + total: number; + page: number; + perPage: number; +} diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types_old.ts similarity index 90% rename from x-pack/plugins/cloud_security_posture/common/types.ts rename to x-pack/plugins/cloud_security_posture/common/types_old.ts index aa25c70eb247d..abfd590b55ae0 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types_old.ts @@ -8,10 +8,9 @@ import { type TypeOf } from '@kbn/config-schema'; import type { PackagePolicy, AgentPolicy } from '@kbn/fleet-plugin/common'; import { CspFinding } from './schemas/csp_finding'; import { SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES } from './constants'; -import { CspRuleTemplateMetadata } from './schemas/csp_rule_template_metadata'; -import { CspRuleTemplate } from './schemas'; -import { findCspRuleTemplateRequest } from './schemas/csp_rule_template_api/get_csp_rule_template'; + import { getComplianceDashboardSchema } from './schemas/stats'; +import type { CspBenchmarkRuleMetadata } from './types/latest'; export type AwsCredentialsType = | 'assume_role' @@ -32,11 +31,11 @@ export type GcpCredentialsTypeFieldMap = { export type AzureCredentialsType = | 'arm_template' + | 'manual' // TODO: remove for stack version 8.13 | 'service_principal_with_client_secret' | 'service_principal_with_client_certificate' | 'service_principal_with_client_username_and_password' - | 'managed_identity' - | 'manual'; + | 'managed_identity'; export type AzureCredentialsTypeFieldMap = { [key in AzureCredentialsType]: string[]; @@ -151,9 +150,9 @@ export interface Benchmark { rules_count: number; } -export type BenchmarkId = CspRuleTemplateMetadata['benchmark']['id']; -export type BenchmarkName = CspRuleTemplateMetadata['benchmark']['name']; -export type RuleSection = CspRuleTemplateMetadata['section']; +export type BenchmarkId = CspBenchmarkRuleMetadata['benchmark']['id']; +export type BenchmarkName = CspBenchmarkRuleMetadata['benchmark']['name']; +export type RuleSection = CspBenchmarkRuleMetadata['section']; // Fleet Integration types export type PostureInput = typeof SUPPORTED_CLOUDBEAT_INPUTS[number]; @@ -167,17 +166,8 @@ export interface GetBenchmarkResponse { perPage: number; } -export type GetCspRuleTemplateRequest = TypeOf; - export type GetComplianceDashboardRequest = TypeOf; -export interface GetCspRuleTemplateResponse { - items: CspRuleTemplate[]; - total: number; - page: number; - perPage: number; -} - // CNVM DASHBOARD interface AccountVulnStats { diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index ba8e6f9813832..fd04733bb17c9 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -17,7 +17,7 @@ import { import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME, CLOUDBEAT_VANILLA, - CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, + CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, AWS_CREDENTIALS_TYPE_TO_FIELDS_MAP, GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP, AZURE_CREDENTIALS_TYPE_TO_FIELDS_MAP, @@ -30,7 +30,7 @@ import type { GcpCredentialsType, AzureCredentialsType, RuleSection, -} from '../types'; +} from '../types_old'; /** * @example @@ -50,9 +50,9 @@ export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error' }; export const getBenchmarkFilter = (type: BenchmarkId, section?: RuleSection): string => - `${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"${ + `${CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE}.attributes.metadata.benchmark.id: "${type}"${ section - ? ` AND ${CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE}.attributes.metadata.section: "${section}"` + ? ` AND ${CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE}.attributes.metadata.section: "${section}"` : '' }`; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts index afb7a89c69e6f..35f49282a475e 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_setup_status_api.ts @@ -7,7 +7,7 @@ import { useQuery, type UseQueryOptions } from '@tanstack/react-query'; import { useKibana } from '../hooks/use_kibana'; -import { type CspSetupStatus } from '../../../common/types'; +import { type CspSetupStatus } from '../../../common/types_old'; import { STATUS_API_CURRENT_VERSION, STATUS_ROUTE_PATH } from '../../../common/constants'; const getCspSetupStatusQueryKey = 'csp_status_key'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts index 834a75581519f..dd893ff356865 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts @@ -7,7 +7,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; import { useKibana } from '../hooks/use_kibana'; -import { ComplianceDashboardDataV2, PosturePolicyTemplate } from '../../../common/types'; +import { ComplianceDashboardDataV2, PosturePolicyTemplate } from '../../../common/types_old'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE, diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_vulnerability_dashboard_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_vulnerability_dashboard_api.ts index 11113949d0972..4114a49cdf181 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_vulnerability_dashboard_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_vulnerability_dashboard_api.ts @@ -6,7 +6,7 @@ */ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; -import { CnvmDashboardData } from '../../../common/types'; +import { CnvmDashboardData } from '../../../common/types_old'; import { useKibana } from '../hooks/use_kibana'; import { VULNERABILITIES_DASHBOARD_ROUTE_PATH } from '../../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 60e15f54b1687..404ea0f036017 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; -import type { CloudSecurityPolicyTemplate, PostureInput } from '../../common/types'; +import type { CloudSecurityPolicyTemplate, PostureInput } from '../../common/types_old'; import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA, diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts index ff88d9c38707f..e89d7d610bc9c 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/constants.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; -import { PosturePolicyTemplate } from '../../../common/types'; +import { PosturePolicyTemplate } from '../../../common/types_old'; import type { CspBenchmarksPage, CspIntegrationDocNavigationItem, diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts index fb255a9545ad4..1dac88397e8be 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts @@ -6,7 +6,7 @@ */ import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public'; -import type { CloudSecurityPolicyTemplate } from '../../../common/types'; +import type { CloudSecurityPolicyTemplate } from '../../../common/types_old'; import { useCisKubernetesIntegration } from '../api/use_cis_kubernetes_integration'; import { useKibana } from '../hooks/use_kibana'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration_policies.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration_policies.ts index af1dc5e795485..f5c7a6e5cc5e4 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration_policies.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration_policies.ts @@ -9,7 +9,7 @@ import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public import { useCisKubernetesIntegration } from '../api/use_cis_kubernetes_integration'; import { useKibana } from '../hooks/use_kibana'; import { useCspBenchmarkIntegrations } from '../../pages/benchmarks/use_csp_benchmark_integrations'; -import { PostureTypes } from '../../../common/types'; +import { PostureTypes } from '../../../common/types_old'; export const useCISIntegrationPoliciesLink = ({ postureType, diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts index 4cf3d7d129f0c..cd0a413648bed 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts @@ -6,7 +6,7 @@ */ import type { PackagePolicy } from '@kbn/fleet-plugin/common'; -import type { PostureInput } from '../../../common/types'; +import type { PostureInput } from '../../../common/types_old'; import { SUPPORTED_CLOUDBEAT_INPUTS } from '../../../common/constants'; import { cloudPostureIntegrations, type CloudPostureIntegrations } from '../constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/get_vulnerability_colors.ts b/x-pack/plugins/cloud_security_posture/public/common/utils/get_vulnerability_colors.ts index 6cb1423a77511..db5776bb82ccc 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/utils/get_vulnerability_colors.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/utils/get_vulnerability_colors.ts @@ -7,7 +7,7 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { VULNERABILITIES_SEVERITY } from '../../../common/constants'; -import { VulnSeverity } from '../../../common/types'; +import { VulnSeverity } from '../../../common/types_old'; export const getCvsScoreColor = (score: number): string | undefined => { if (score <= 4) { diff --git a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx index 4feee3a5e2287..98f99fbd29245 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/accounts_evaluated_widget.tsx @@ -11,7 +11,7 @@ import { CIS_AWS, CIS_GCP, CIS_AZURE, CIS_K8S, CIS_EKS } from '../../common/cons import { CISBenchmarkIcon } from './cis_benchmark_icon'; import { CompactFormattedNumber } from './compact_formatted_number'; import { useNavigateFindings } from '../common/hooks/use_navigate_findings'; -import { BenchmarkData } from '../../common/types'; +import { BenchmarkData } from '../../common/types_old'; // order in array will determine order of appearance in the dashboard const benchmarks = [ diff --git a/x-pack/plugins/cloud_security_posture/public/components/cis_benchmark_icon.tsx b/x-pack/plugins/cloud_security_posture/public/components/cis_benchmark_icon.tsx index 50f9ca1b15d9d..b0b5703937c90 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cis_benchmark_icon.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cis_benchmark_icon.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiIcon, EuiToolTip, IconSize } from '@elastic/eui'; import { CSSInterpolation } from '@emotion/serialize'; -import type { BenchmarkId } from '../../common/types'; +import type { BenchmarkId } from '../../common/types_old'; import cisEksIcon from '../assets/icons/cis_eks_logo.svg'; import googleCloudLogo from '../assets/icons/google_cloud_logo.svg'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx index 4be4ac082f60f..947e48f434554 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/aws_credentials_form.tsx @@ -35,7 +35,7 @@ import { } from '../utils'; import { SetupFormat, useAwsCredentialsForm } from './hooks'; import { AWS_ORGANIZATION_ACCOUNT } from '../policy_template_form'; -import { AwsCredentialsType } from '../../../../common/types'; +import { AwsCredentialsType } from '../../../../common/types_old'; interface AWSSetupInfoContentProps { integrationLink: string; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/get_aws_credentials_form_options.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/get_aws_credentials_form_options.tsx index 71882d4cc67cf..c4b19f87636b6 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/get_aws_credentials_form_options.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/get_aws_credentials_form_options.tsx @@ -10,7 +10,7 @@ import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { AwsCredentialsType } from '../../../../common/types'; +import { AwsCredentialsType } from '../../../../common/types_old'; const AssumeRoleDescription = (

diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/hooks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/hooks.ts index 190ae47a61aec..d4824f5bc04b6 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/hooks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/aws_credentials_form/hooks.ts @@ -19,7 +19,7 @@ import { getInputVarsFields, } from './get_aws_credentials_form_options'; import { CLOUDBEAT_AWS } from '../../../../common/constants'; -import { AwsCredentialsType } from '../../../../common/types'; +import { AwsCredentialsType } from '../../../../common/types_old'; /** * Update CloudFormation template and stack name in the Agent Policy * based on the selected policy template diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx index ab8770b20f0cf..06de63c3cff0c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/azure_credentials_form.tsx @@ -29,7 +29,7 @@ import { AzureOptions, getAzureCredentialsFormManualOptions, } from './get_azure_credentials_form_options'; -import { AzureCredentialsType } from '../../../../common/types'; +import { AzureCredentialsType } from '../../../../common/types_old'; import { SetupFormat, useAzureCredentialsForm } from './hooks'; import { getPosturePolicy, NewPackagePolicyPostureInput } from '../utils'; import { CspRadioOption, RadioGroup } from '../csp_boxed_radio_group'; @@ -248,18 +248,6 @@ const TemporaryManualSetup = ({ integrationLink }: { integrationLink: string }) const AZURE_MINIMUM_PACKAGE_VERSION = '1.6.0'; const AZURE_MANUAL_FIELDS_PACKAGE_VERSION = '1.7.0'; -export const getDefaultAzureManualCredentialType = (packageInfo: PackageInfo) => { - const packageSemanticVersion = semverValid(packageInfo.version); - const cleanPackageVersion = semverCoerce(packageSemanticVersion) || ''; - - const isPackageVersionValidForManualFields = !semverLt( - cleanPackageVersion, - AZURE_MANUAL_FIELDS_PACKAGE_VERSION - ); - - return isPackageVersionValidForManualFields ? 'managed_identity' : 'manual'; -}; - const AzureInputVarFields = ({ fields, onChange, diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx index 455fe9352ba00..d6044118f1afd 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/get_azure_credentials_form_options.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiText } from '@elastic/eui'; -import { AzureCredentialsType } from '../../../../common/types'; +import { AzureCredentialsType } from '../../../../common/types_old'; export type AzureCredentialsFields = Record; @@ -26,12 +26,15 @@ export const getAzureCredentialsFormManualOptions = (): Array<{ value: AzureCredentialsType; text: string; }> => { - return Object.entries(getAzureCredentialsFormOptions()) - .map(([key, value]) => ({ - value: key as AzureCredentialsType, - text: value.label, - })) - .filter(({ value }) => value !== 'arm_template'); + return ( + Object.entries(getAzureCredentialsFormOptions()) + .map(([key, value]) => ({ + value: key as AzureCredentialsType, + text: value.label, + })) + // TODO: remove 'manual' for stack version 8.13 + .filter(({ value }) => value !== 'arm_template' && value !== 'manual') + ); }; export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AzureCredentialsFields) => @@ -75,6 +78,12 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({ info: [], fields: {}, }, + // TODO: remove for stack version 8.13 + manual: { + label: 'Manual', + info: [], + fields: {}, + }, service_principal_with_client_secret: { label: i18n.translate('xpack.csp.azureIntegration.servicePrincipalWithClientSecretLabel', { defaultMessage: 'Service principal with Client Secret', @@ -131,18 +140,4 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({ }, }, }, - manual: { - label: i18n.translate('xpack.csp.azureIntegration.credentialType.manualLabel', { - defaultMessage: 'Manual', - }), - info: ( - - - - ), - fields: {}, - }, }); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts index b68828be58117..2eb56fc6ace83 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/azure_credentials_form/hooks.ts @@ -7,10 +7,7 @@ import { useEffect, useRef } from 'react'; import { NewPackagePolicy, PackageInfo } from '@kbn/fleet-plugin/common'; -import { - AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE, - getDefaultAzureManualCredentialType, -} from './azure_credentials_form'; +import { AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE } from './azure_credentials_form'; import { cspIntegrationDocsNavigation } from '../../../common/navigation/constants'; import { getArmTemplateUrlFromCspmPackage, @@ -22,7 +19,7 @@ import { getInputVarsFields, } from './get_azure_credentials_form_options'; import { CLOUDBEAT_AZURE } from '../../../../common/constants'; -import { AzureCredentialsType } from '../../../../common/types'; +import { AzureCredentialsType } from '../../../../common/types_old'; export type SetupFormat = 'arm_template' | 'manual'; @@ -151,7 +148,7 @@ export const useAzureCredentialsForm = ({ setupFormat, }); - const defaultAzureManualCredentialType = getDefaultAzureManualCredentialType(packageInfo); + const defaultAzureManualCredentialType = 'managed_identity'; const onSetupFormatChange = (newSetupFormat: SetupFormat) => { if (newSetupFormat === AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE) { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/custom_assets_extension.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/custom_assets_extension.tsx index 774acadbd03ba..c7708cba837cc 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/custom_assets_extension.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/custom_assets_extension.tsx @@ -10,7 +10,7 @@ import { type CustomAssetsAccordionProps, CustomAssetsAccordion } from '@kbn/fle import { i18n } from '@kbn/i18n'; import { useParams } from 'react-router-dom'; import { EuiSpacer } from '@elastic/eui'; -import { CloudSecurityPolicyTemplate } from '../../../common/types'; +import { CloudSecurityPolicyTemplate } from '../../../common/types_old'; import { VULN_MGMT_POLICY_TEMPLATE } from '../../../common/constants'; import { useKibana } from '../../common/hooks/use_kibana'; import { benchmarksNavigation, cloudPosturePages } from '../../common/navigation/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx index 4f0adecb60e5b..45a3f8a6639a5 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/gcp_credential_form.tsx @@ -25,7 +25,7 @@ import type { NewPackagePolicy } from '@kbn/fleet-plugin/public'; import { NewPackagePolicyInput, PackageInfo } from '@kbn/fleet-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { GcpCredentialsType } from '../../../common/types'; +import { GcpCredentialsType } from '../../../common/types_old'; import { CLOUDBEAT_GCP, SETUP_ACCESS_CLOUD_SHELL, diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts index 4c1b04a260df1..ae933a0f941a8 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts @@ -15,7 +15,7 @@ import { CLOUDBEAT_AWS, CLOUDBEAT_VULN_MGMT_AWS, } from '../../../common/constants'; -import type { PostureInput } from '../../../common/types'; +import type { PostureInput } from '../../../common/types_old'; export const getMockPolicyAWS = () => getPolicyMock(CLOUDBEAT_AWS, 'cspm', 'aws'); export const getMockPolicyGCP = () => getPolicyMock(CLOUDBEAT_GCP, 'cspm', 'gcp'); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx index d0c1f4d454b4f..5764b5af44357 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.test.tsx @@ -1330,6 +1330,7 @@ describe('', () => { ).toBeInTheDocument(); }); + // TODO: remove for stack version 8.13 it(`doesnt render ${CLOUDBEAT_AZURE} Manual fields when version is not at least version 1.7.0`, () => { let policy = getMockPolicyAzure(); policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx index 163857b27e0f9..89ec1007f7d53 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_form.tsx @@ -32,7 +32,7 @@ import { i18n } from '@kbn/i18n'; import { AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE } from './azure_credentials_form/azure_credentials_form'; import { CspRadioGroupProps, RadioGroup } from './csp_boxed_radio_group'; import { assert } from '../../../common/utils/helpers'; -import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types'; +import type { CloudSecurityPolicyTemplate, PostureInput } from '../../../common/types_old'; import { CLOUDBEAT_AWS, CLOUDBEAT_VANILLA, @@ -41,14 +41,14 @@ import { SUPPORTED_POLICY_TEMPLATES, } from '../../../common/constants'; import { - getPosturePolicy, + getMaxPackageName, getPostureInputHiddenVars, + getPosturePolicy, getVulnMgmtCloudFormationDefaultValue, - POSTURE_NAMESPACE, - type NewPackagePolicyPostureInput, isPostureInput, - getMaxPackageName, isBelowMinVersion, + type NewPackagePolicyPostureInput, + POSTURE_NAMESPACE, } from './utils'; import { PolicyTemplateInfo, @@ -58,6 +58,8 @@ import { } from './policy_template_selectors'; import { usePackagePolicyList } from '../../common/api/use_package_policy_list'; import { gcpField, getInputVarsFields } from './gcp_credential_form'; +import { SetupTechnologySelector } from './setup_technology_selector/setup_technology_selector'; +import { useSetupTechnology } from './setup_technology_selector/use_setup_technology'; const DEFAULT_INPUT_TYPE = { kspm: CLOUDBEAT_VANILLA, @@ -520,7 +522,16 @@ const IntegrationSettings = ({ onChange, fields }: IntegrationInfoFieldsProps) = ); export const CspPolicyTemplateForm = memo( - ({ newPolicy, onChange, validationResults, isEditPage, packageInfo }) => { + ({ + agentPolicy, + newPolicy, + onChange, + validationResults, + isEditPage, + packageInfo, + handleSetupTechnologyChange, + agentlessPolicy, + }) => { const integrationParam = useParams<{ integration: CloudSecurityPolicyTemplate }>().integration; const integration = SUPPORTED_POLICY_TEMPLATES.includes(integrationParam) ? integrationParam @@ -528,6 +539,12 @@ export const CspPolicyTemplateForm = memo { @@ -722,6 +739,13 @@ export const CspPolicyTemplateForm = memo updatePolicy({ ...newPolicy, [field]: value })} /> + {isAgentlessAvailable && ( + + )} + {/* Defines the vars of the enabled input of the active policy template */} void; +}) => { + const options = [ + { + value: SetupTechnology.AGENTLESS, + inputDisplay: ( + + ), + dropdownDisplay: ( + <> + + + + +

+ +

+
+ + ), + }, + { + value: SetupTechnology.AGENT_BASED, + inputDisplay: ( + + ), + dropdownDisplay: ( + <> + + + + +

+ +

+
+ + ), + }, + ]; + + return ( + <> + + + + + } + > + + + } + > + + } + onChange={onSetupTechnologyChange} + itemLayoutAlign="top" + hasDividers + fullWidth + /> + + + + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts new file mode 100644 index 0000000000000..a5aa5e2df9734 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.test.ts @@ -0,0 +1,59 @@ +/* + * 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-hooks'; + +import { SetupTechnology } from '@kbn/fleet-plugin/public'; +import { AgentPolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; + +import { CLOUDBEAT_AWS } from '../../../../common/constants'; +import { useSetupTechnology } from './use_setup_technology'; + +describe('useSetupTechnology', () => { + it('initializes with AGENT_BASED technology', () => { + const { result } = renderHook(() => + useSetupTechnology({ + input: { type: 'cloudbeat/no-agentless-support' } as NewPackagePolicyInput, + }) + ); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('sets to AGENTLESS when agentless is available', () => { + const agentlessPolicy = { id: 'agentlessPolicyId' } as AgentPolicy; + const input = { type: CLOUDBEAT_AWS } as NewPackagePolicyInput; + const { result } = renderHook(() => useSetupTechnology({ input, agentlessPolicy })); + expect(result.current.isAgentlessAvailable).toBeTruthy(); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENTLESS); + }); + + it('sets to AGENT_BASED when agentPolicyId differs from agentlessPolicyId', () => { + const input = { type: CLOUDBEAT_AWS } as NewPackagePolicyInput; + const agentPolicy = { id: 'agentPolicyId' } as AgentPolicy; + const agentlessPolicy = { id: 'agentlessPolicyId' } as AgentPolicy; + const { result } = renderHook(() => + useSetupTechnology({ input, agentPolicy, agentlessPolicy }) + ); + expect(result.current.setupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('calls handleSetupTechnologyChange when setupTechnology changes', () => { + const handleSetupTechnologyChangeMock = jest.fn(); + const { result } = renderHook(() => + useSetupTechnology({ + input: { type: 'someType' } as NewPackagePolicyInput, + handleSetupTechnologyChange: handleSetupTechnologyChangeMock, + }) + ); + + act(() => { + result.current.setSetupTechnology(SetupTechnology.AGENTLESS); + }); + + expect(handleSetupTechnologyChangeMock).toHaveBeenCalledWith(SetupTechnology.AGENTLESS); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts new file mode 100644 index 0000000000000..898017d6daef5 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/setup_technology_selector/use_setup_technology.ts @@ -0,0 +1,64 @@ +/* + * 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 { useEffect, useMemo, useState } from 'react'; + +import { AgentPolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; +import { SetupTechnology } from '@kbn/fleet-plugin/public'; +import { CLOUDBEAT_AWS } from '../../../../common/constants'; + +export const useSetupTechnology = ({ + input, + agentPolicy, + agentlessPolicy, + handleSetupTechnologyChange, +}: { + input: NewPackagePolicyInput; + agentPolicy?: AgentPolicy; + agentlessPolicy?: AgentPolicy; + handleSetupTechnologyChange?: (value: SetupTechnology) => void; +}) => { + const [setupTechnology, setSetupTechnology] = useState( + SetupTechnology.AGENT_BASED + ); + const isCspmAws = input.type === CLOUDBEAT_AWS; + const isAgentlessAvailable = useMemo( + () => Boolean(isCspmAws && agentlessPolicy), + [isCspmAws, agentlessPolicy] + ); + const agentPolicyId = useMemo(() => agentPolicy?.id, [agentPolicy]); + const agentlessPolicyId = useMemo(() => agentlessPolicy?.id, [agentlessPolicy]); + + useEffect(() => { + if (agentPolicyId && agentPolicyId !== agentlessPolicyId) { + /* + handle case when agent policy is coming from outside, + e.g. from the get param or when coming to integration from a specific agent policy + */ + setSetupTechnology(SetupTechnology.AGENT_BASED); + } else if (isAgentlessAvailable) { + /* + preselecting agenteless when available + and resetting to agent-based when switching to another integration type, which doesn't support agentless + */ + setSetupTechnology(SetupTechnology.AGENTLESS); + } else { + setSetupTechnology(SetupTechnology.AGENT_BASED); + } + }, [agentPolicyId, agentlessPolicyId, isAgentlessAvailable]); + + useEffect(() => { + if (handleSetupTechnologyChange) { + handleSetupTechnologyChange(setupTechnology); + } + }, [handleSetupTechnologyChange, setupTechnology]); + + return { + isAgentlessAvailable, + setupTechnology, + setSetupTechnology, + }; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index ae7c02ade79d1..1f005ccb950f4 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -30,7 +30,7 @@ import { VULN_MGMT_POLICY_TEMPLATE, } from '../../../common/constants'; import { getDefaultAwsVarsGroup } from './aws_credentials_form/aws_credentials_form'; -import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types'; +import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types_old'; import { cloudPostureIntegrations } from '../../common/constants'; import { DEFAULT_EKS_VARS_GROUP } from './eks_credentials_form'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx index 422695c7ff576..f070b1e0ad345 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states.tsx @@ -30,7 +30,7 @@ import { } from './test_subjects'; import { CloudPosturePage, PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from './cloud_posture_page'; import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import type { IndexDetails, PostureTypes } from '../../common/types'; +import type { IndexDetails, PostureTypes } from '../../common/types_old'; import { cspIntegrationDocsNavigation } from '../common/navigation/constants'; import noDataIllustration from '../assets/illustrations/no_data_illustration.svg'; import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx index 7dee3e94e70a6..14872bcc19210 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_vulnerabilities_states.tsx @@ -25,7 +25,7 @@ import { VULN_MGMT_POLICY_TEMPLATE } from '../../common/constants'; import { FullSizeCenteredPage } from './full_size_centered_page'; import { CloudPosturePage } from './cloud_posture_page'; import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import type { IndexDetails } from '../../common/types'; +import type { IndexDetails } from '../../common/types_old'; import { NO_VULNERABILITIES_STATUS_TEST_SUBJ, CNVM_NOT_INSTALLED_ACTION_SUBJ, @@ -33,7 +33,7 @@ import { import noDataIllustration from '../assets/illustrations/no_data_illustration.svg'; import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; import { useCISIntegrationPoliciesLink } from '../common/navigation/use_navigate_to_cis_integration_policies'; -import { PostureTypes } from '../../common/types'; +import { PostureTypes } from '../../common/types_old'; const REFETCH_INTERVAL_MS = 20000; diff --git a/x-pack/plugins/cloud_security_posture/public/components/vulnerability_badges.tsx b/x-pack/plugins/cloud_security_posture/public/components/vulnerability_badges.tsx index b94efbd2de1a0..20b1326d65526 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/vulnerability_badges.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/vulnerability_badges.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { css } from '@emotion/react'; import { float } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getCvsScoreColor, getSeverityStatusColor } from '../common/utils/get_vulnerability_colors'; -import { VulnSeverity } from '../../common/types'; +import { VulnSeverity } from '../../common/types_old'; import { VULNERABILITIES_CVSS_SCORE_BADGE_SUBJ } from './test_subjects'; interface CVSScoreBadgeProps { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index e37a9d6fcbe9c..d2b6495667372 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import type { PackagePolicy } from '@kbn/fleet-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; import { TimestampTableCell } from '../../components/timestamp_table_cell'; -import type { Benchmark } from '../../../common/types'; +import type { Benchmark } from '../../../common/types_old'; import { useKibana } from '../../common/hooks/use_kibana'; import { benchmarksNavigation } from '../../common/navigation/constants'; import * as TEST_SUBJ from './test_subjects'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/use_csp_benchmark_integrations.ts b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/use_csp_benchmark_integrations.ts index 95d955c69047e..8704846407fc7 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/use_csp_benchmark_integrations.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/use_csp_benchmark_integrations.ts @@ -10,7 +10,7 @@ import type { ListResult } from '@kbn/fleet-plugin/common'; import { BENCHMARKS_API_CURRENT_VERSION, BENCHMARKS_ROUTE_PATH } from '../../../common/constants'; import type { BenchmarksQueryParams } from '../../../common/schemas/benchmark'; import { useKibana } from '../../common/hooks/use_kibana'; -import type { Benchmark } from '../../../common/types'; +import type { Benchmark } from '../../../common/types_old'; const QUERY_KEY = 'csp_benchmark_integrations'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/compliance_score_chart.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/compliance_score_chart.tsx index 2067a9c98fd23..01821e04403ff 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/compliance_score_chart.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/compliance_score_chart.tsx @@ -35,7 +35,7 @@ import { DASHBOARD_COMPLIANCE_SCORE_CHART } from '../test_subjects'; import { statusColors } from '../../../common/constants'; import { RULE_FAILED, RULE_PASSED } from '../../../../common/constants'; import { CompactFormattedNumber } from '../../../components/compact_formatted_number'; -import type { Evaluation, PostureTrend, Stats } from '../../../../common/types'; +import type { Evaluation, PostureTrend, Stats } from '../../../../common/types_old'; import { useKibana } from '../../../common/hooks/use_kibana'; interface ComplianceScoreChartProps { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx index ac7048533ead5..d8fce2e0bfaa0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx @@ -17,7 +17,7 @@ import { import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import { ComplianceScoreBar } from '../../../components/compliance_score_bar'; -import { ComplianceDashboardData, GroupedFindingsEvaluation } from '../../../../common/types'; +import { ComplianceDashboardData, GroupedFindingsEvaluation } from '../../../../common/types_old'; export interface RisksTableProps { data: ComplianceDashboardData['groupedFindingsEvaluation']; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx index 18e5118f772e5..adf85dd5f84db 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx @@ -36,7 +36,7 @@ import { BaseCspSetupStatus, ComplianceDashboardDataV2, CspStatusCode, -} from '../../../common/types'; +} from '../../../common/types_old'; jest.mock('../../common/api/use_setup_status_api'); jest.mock('../../common/api/use_stats_api'); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index 9e3b8df0c1d3e..61a56ecd3187c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -17,7 +17,7 @@ import type { PosturePolicyTemplate, ComplianceDashboardDataV2, BaseCspSetupStatus, -} from '../../../common/types'; +} from '../../../common/types_old'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import { CloudPosturePage, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx index de982b50f48f6..dc140fef121b3 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmark_details_box.tsx @@ -18,7 +18,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { i18n } from '@kbn/i18n'; import { getBenchmarkIdQuery } from './benchmarks_section'; -import { BenchmarkData } from '../../../../common/types'; +import { BenchmarkData } from '../../../../common/types_old'; import { useNavigateFindings } from '../../../common/hooks/use_navigate_findings'; import { CISBenchmarkIcon } from '../../../components/cis_benchmark_icon'; import cisLogoIcon from '../../../assets/icons/cis_logo.svg'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx index 2ac91288475de..d3a6cf3ab12d7 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx @@ -17,7 +17,7 @@ import type { ComplianceDashboardDataV2, Evaluation, PosturePolicyTemplate, -} from '../../../../common/types'; +} from '../../../../common/types_old'; import { RisksTable } from '../compliance_charts/risks_table'; import { RULE_FAILED } from '../../../../common/constants'; import { LOCAL_STORAGE_DASHBOARD_BENCHMARK_SORT_KEY } from '../../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx index ca4a55c45ebdd..e63152a00590e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx @@ -25,7 +25,7 @@ import type { ComplianceDashboardDataV2, Evaluation, PosturePolicyTemplate, -} from '../../../../common/types'; +} from '../../../../common/types_old'; import { RisksTable } from '../compliance_charts/risks_table'; import { NavFilter, useNavigateFindings } from '../../../common/hooks/use_navigate_findings'; import { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/mock.ts b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/mock.ts index b4a8eae816b24..93eddb2d6454d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { BenchmarkData, ComplianceDashboardDataV2 } from '../../../common/types'; +import { BenchmarkData, ComplianceDashboardDataV2 } from '../../../common/types_old'; export const getMockDashboardData = () => ({ ...mockDashboardData, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx index 2542c57aab44f..edc8e7f35bb35 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/findings_flyout/findings_flyout.tsx @@ -35,9 +35,9 @@ import { TableTab } from './table_tab'; import { JsonTab } from './json_tab'; import { OverviewTab } from './overview_tab'; import { RuleTab } from './rule_tab'; -import type { BenchmarkId } from '../../../../common/types'; +import type { BenchmarkId } from '../../../../common/types_old'; import { CISBenchmarkIcon } from '../../../components/cis_benchmark_icon'; -import { BenchmarkName } from '../../../../common/types'; +import { BenchmarkName } from '../../../../common/types_old'; import { FINDINGS_FLYOUT } from '../test_subjects'; import { createDetectionRuleFromFinding } from '../utils/create_detection_rule_from_finding'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx index be5253cc710b7..9d092de673edf 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx @@ -15,7 +15,7 @@ import { } from '@kbn/securitysolution-grouping/src'; import { useMemo } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; -import { Evaluation } from '../../../../common/types'; +import { Evaluation } from '../../../../common/types_old'; import { LATEST_FINDINGS_RETENTION_POLICY } from '../../../../common/constants'; import { FindingsGroupingAggregation, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_table.tsx index 2bcc895ddd4b0..50ebb01f363f0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_table.tsx @@ -9,7 +9,7 @@ import { DataView } from '@kbn/data-views-plugin/common'; import { Filter } from '@kbn/es-query'; import { useMemo } from 'react'; import { FindingsBaseURLQuery } from '../../../common/types'; -import { Evaluation } from '../../../../common/types'; +import { Evaluation } from '../../../../common/types_old'; import { LOCAL_STORAGE_DATA_TABLE_PAGE_SIZE_KEY } from '../../../common/constants'; import { useCloudPostureDataTable } from '../../../common/hooks/use_cloud_posture_data_table'; import { getFilters } from '../utils/get_filters'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/findings_by_resource_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/findings_by_resource_container.tsx index 3054ad352a5bd..85095b149bce4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/findings_by_resource_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/findings_by_resource_container.tsx @@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; import { CspFinding } from '../../../../common/schemas/csp_finding'; -import type { Evaluation } from '../../../../common/types'; +import type { Evaluation } from '../../../../common/types_old'; import { FindingsSearchBar } from '../layout/findings_search_bar'; import * as TEST_SUBJECTS from '../test_subjects'; import { usePageSlice } from '../../../common/hooks/use_page_slice'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/resource_findings/resource_findings_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/resource_findings/resource_findings_container.tsx index f606241862ee2..bc6e67b887096 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/resource_findings/resource_findings_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings_by_resource/resource_findings/resource_findings_container.tsx @@ -17,7 +17,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { generatePath } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { CspInlineDescriptionList } from '../../../../components/csp_inline_description_list'; -import type { Evaluation } from '../../../../../common/types'; +import type { Evaluation } from '../../../../../common/types_old'; import { CspFinding } from '../../../../../common/schemas/csp_finding'; import { CloudPosturePageTitle } from '../../../../components/cloud_posture_page_title'; import * as TEST_SUBJECTS from '../../test_subjects'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx index 1cf084220ea29..35f6fd008d4b9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_distribution_bar.tsx @@ -20,7 +20,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { getAbbreviatedNumber } from '../../../common/utils/get_abbreviated_number'; import { RULE_FAILED, RULE_PASSED } from '../../../../common/constants'; import { statusColors } from '../../../common/constants'; -import type { Evaluation } from '../../../../common/types'; +import type { Evaluation } from '../../../../common/types_old'; interface Props { passed: number; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index 6b0998d4ce218..6301c9cc20b7c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -9,19 +9,19 @@ import React from 'react'; import { RulesContainer } from './rules_container'; import { render, screen } from '@testing-library/react'; import { QueryClient } from '@tanstack/react-query'; -import { useFindCspRuleTemplates } from './use_csp_rules'; +import { useFindCspBenchmarkRule } from './use_csp_benchmark_rules'; import * as TEST_SUBJECTS from './test_subjects'; import { Chance } from 'chance'; import { TestProvider } from '../../test/test_provider'; +import type { CspBenchmarkRule } from '../../../common/types/latest'; import { useParams } from 'react-router-dom'; import { coreMock } from '@kbn/core/public/mocks'; -import { CspRuleTemplate } from '../../../common/schemas'; const chance = new Chance(); -jest.mock('./use_csp_rules', () => ({ - useFindCspRuleTemplates: jest.fn(), - useBulkUpdateCspRuleTemplates: jest.fn(), +jest.mock('./use_csp_benchmark_rules', () => ({ + useFindCspBenchmarkRule: jest.fn(), + useBulkUpdateCspBenchmarkRule: jest.fn(), })); jest.mock('react-router-dom', () => ({ @@ -52,7 +52,7 @@ const getWrapper = return {children}; }; -const getRuleMock = (id = chance.guid()): CspRuleTemplate => +const getRuleMock = (id = chance.guid()): CspBenchmarkRule => ({ metadata: { audit: chance.sentence(), @@ -75,7 +75,7 @@ const getRuleMock = (id = chance.guid()): CspRuleTemplate => tags: [chance.word(), chance.word()], version: chance.sentence(), }, - } as CspRuleTemplate); + } as CspBenchmarkRule); const params = { packagePolicyId: chance.guid(), @@ -93,7 +93,7 @@ describe('', () => { const Wrapper = getWrapper(); const rule1 = getRuleMock(); - (useFindCspRuleTemplates as jest.Mock).mockReturnValue({ + (useFindCspBenchmarkRule as jest.Mock).mockReturnValue({ status: 'success', data: { total: 1, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 81472e29b6ee7..5ec1971b1f0ac 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -7,20 +7,23 @@ import React, { useState, useMemo } from 'react'; import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { useParams } from 'react-router-dom'; -import { CspRuleTemplate } from '../../../common/schemas'; import { extractErrorMessage } from '../../../common/utils/helpers'; import { RulesTable } from './rules_table'; import { RulesTableHeader } from './rules_table_header'; -import { useFindCspRuleTemplates, type RulesQuery, type RulesQueryResult } from './use_csp_rules'; +import { + useFindCspBenchmarkRule, + type RulesQuery, + type RulesQueryResult, +} from './use_csp_benchmark_rules'; import * as TEST_SUBJECTS from './test_subjects'; import { RuleFlyout } from './rules_flyout'; import { LOCAL_STORAGE_PAGE_SIZE_RULES_KEY } from '../../common/constants'; import { usePageSize } from '../../common/hooks/use_page_size'; - +import type { CspBenchmarkRule } from '../../../common/types/latest'; interface RulesPageData { - rules_page: CspRuleTemplate[]; - all_rules: CspRuleTemplate[]; - rules_map: Map; + rules_page: CspBenchmarkRule[]; + all_rules: CspBenchmarkRule[]; + rules_map: Map; total: number; error?: string; loading: boolean; @@ -32,7 +35,7 @@ const getRulesPageData = ( { status, data, error }: Pick, query: RulesQuery ): RulesPageData => { - const rules = data?.items || ([] as CspRuleTemplate[]); + const rules = data?.items || ([] as CspBenchmarkRule[]); const page = getPage(rules, query); @@ -46,7 +49,7 @@ const getRulesPageData = ( }; }; -const getPage = (data: CspRuleTemplate[], { page, perPage }: RulesQuery) => +const getPage = (data: CspBenchmarkRule[], { page, perPage }: RulesQuery) => data.slice(page * perPage, (page + 1) * perPage); const MAX_ITEMS_PER_PAGE = 10000; @@ -64,7 +67,7 @@ export const RulesContainer = () => { perPage: pageSize || 10, }); - const { data, status, error } = useFindCspRuleTemplates( + const { data, status, error } = useFindCspBenchmarkRule( { section: rulesQuery.section, search: rulesQuery.search, @@ -80,7 +83,7 @@ export const RulesContainer = () => { ); // We need to make this call again without the filters. this way the section list is always full - const allRules = useFindCspRuleTemplates( + const allRules = useFindCspBenchmarkRule( { page: 1, perPage: MAX_ITEMS_PER_PAGE, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx index 49ab9bb79fab8..da9fe29ee26c7 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx @@ -18,14 +18,15 @@ import { EuiFlexGroup, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { CspRuleTemplate, CspRuleTemplateMetadata } from '../../../common/schemas'; + +import { CspBenchmarkRule, CspBenchmarkRuleMetadata } from '../../../common/types/latest'; import { getRuleList } from '../configurations/findings_flyout/rule_tab'; import { getRemediationList } from '../configurations/findings_flyout/overview_tab'; import * as TEST_SUBJECTS from './test_subjects'; interface RuleFlyoutProps { onClose(): void; - rule: CspRuleTemplate; + rule: CspBenchmarkRule; } const tabs = [ @@ -85,7 +86,7 @@ export const RuleFlyout = ({ onClose, rule }: RuleFlyoutProps) => { ); }; -const RuleOverviewTab = ({ rule }: { rule: CspRuleTemplateMetadata }) => ( +const RuleOverviewTab = ({ rule }: { rule: CspBenchmarkRuleMetadata }) => ( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx index 167589024529b..c6ce3485f68db 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx @@ -14,7 +14,7 @@ import { useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { CspRuleTemplate } from '../../../common/schemas'; +import { CspBenchmarkRule } from '../../../common/types/latest'; import type { RulesState } from './rules_container'; import * as TEST_SUBJECTS from './test_subjects'; @@ -41,20 +41,20 @@ export const RulesTable = ({ const { euiTheme } = useEuiTheme(); const columns = useMemo(() => getColumns({ setSelectedRuleId }), [setSelectedRuleId]); - const euiPagination: EuiBasicTableProps['pagination'] = { + const euiPagination: EuiBasicTableProps['pagination'] = { pageIndex: page, pageSize, totalItemCount: total, pageSizeOptions: [10, 25, 100], }; - const onTableChange = ({ page: pagination }: Criteria) => { + const onTableChange = ({ page: pagination }: Criteria) => { if (!pagination) return; setPagination({ page: pagination.index, perPage: pagination.size }); }; - const rowProps = (row: CspRuleTemplate) => ({ - ['data-test-subj']: TEST_SUBJECTS.getCspRuleTemplatesTableRowItemTestId(row.metadata.id), + const rowProps = (row: CspBenchmarkRule) => ({ + ['data-test-subj']: TEST_SUBJECTS.getCspBenchmarkRuleTableRowItemTestId(row.metadata.id), style: { background: row.metadata.id === selectedRuleId ? euiTheme.colors.highlight : undefined, }, @@ -79,7 +79,7 @@ type GetColumnProps = Pick; const getColumns = ({ setSelectedRuleId, -}: GetColumnProps): Array> => [ +}: GetColumnProps): Array> => [ { field: 'metadata.benchmark.rule_number', name: i18n.translate('xpack.csp.rules.rulesTable.ruleNumberColumnLabel', { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts index dbbc6877e2dcf..5f7de36484609 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts @@ -13,5 +13,5 @@ export const CSP_RULES_TABLE = 'csp_rules_table'; export const CSP_RULES_TABLE_ROW_ITEM_NAME = 'csp_rules_table_row_item_name'; export const CSP_RULES_FLYOUT_CONTAINER = 'csp_rules_flyout_container'; -export const getCspRuleTemplatesTableRowItemTestId = (id: string) => +export const getCspBenchmarkRuleTableRowItemTestId = (id: string) => `${CSP_RULES_TABLE_ROW_ITEM_NAME}_${id}`; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts new file mode 100644 index 0000000000000..8dca9b63c1930 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_benchmark_rules.ts @@ -0,0 +1,41 @@ +/* + * 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 { useQuery } from '@tanstack/react-query'; +import { + FindCspBenchmarkRuleRequest, + FindCspBenchmarkRuleResponse, +} from '../../../common/types/latest'; +import { useKibana } from '../../common/hooks/use_kibana'; + +import { + CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, + FIND_CSP_BENCHMARK_RULE_API_CURRENT_VERSION, + FIND_CSP_BENCHMARK_RULE_ROUTE_PATH, +} from '../../../common/constants'; + +export type RulesQuery = Pick< + FindCspBenchmarkRuleRequest, + 'section' | 'search' | 'page' | 'perPage' +>; +export type RulesQueryResult = ReturnType; + +export const useFindCspBenchmarkRule = ( + { search, page, perPage, section }: RulesQuery, + packagePolicyId: string +) => { + const { http } = useKibana().services; + + return useQuery( + [CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, { section, search, page, perPage, packagePolicyId }], + () => { + return http.get(FIND_CSP_BENCHMARK_RULE_ROUTE_PATH, { + query: { packagePolicyId, page, perPage, search, section }, + version: FIND_CSP_BENCHMARK_RULE_API_CURRENT_VERSION, + }); + } + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_integration.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_integration.tsx index 6d1a01b3d3c2e..76477b1705e97 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_integration.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_integration.tsx @@ -18,7 +18,7 @@ import { useKibana } from '../../common/hooks/use_kibana'; export const useCspIntegrationInfo = ({ packagePolicyId, policyId }: PageUrlParams) => { const { http } = useKibana().services; - return useQuery(['cspRulesInfo', { packagePolicyId, policyId }], () => + return useQuery(['cspBenchmarkRuleInfo', { packagePolicyId, policyId }], () => Promise.all([ http .get(packagePolicyRouteService.getInfoPath(packagePolicyId), { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts deleted file mode 100644 index ac150e05bf95e..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/use_csp_rules.ts +++ /dev/null @@ -1,35 +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 { useQuery } from '@tanstack/react-query'; -import { GetCspRuleTemplateRequest, GetCspRuleTemplateResponse } from '../../../common/types'; -import { useKibana } from '../../common/hooks/use_kibana'; - -import { - CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - FIND_CSP_RULE_TEMPLATE_API_CURRENT_VERSION, - FIND_CSP_RULE_TEMPLATE_ROUTE_PATH, -} from '../../../common/constants'; - -export type RulesQuery = Pick; -export type RulesQueryResult = ReturnType; - -export const useFindCspRuleTemplates = ( - { search, page, perPage, section }: RulesQuery, - packagePolicyId: string -) => { - const { http } = useKibana().services; - - return useQuery( - [CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, { section, search, page, perPage, packagePolicyId }], - () => { - return http.get(FIND_CSP_RULE_TEMPLATE_ROUTE_PATH, { - query: { packagePolicyId, page, perPage, search, section }, - version: FIND_CSP_RULE_TEMPLATE_API_CURRENT_VERSION, - }); - } - ); -}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/severity_map.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/severity_map.tsx index 94ebaf30572b3..af47c20ddc50f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/severity_map.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_by_resource/severity_map.tsx @@ -17,7 +17,7 @@ import { import { PaletteColorStop } from '@elastic/eui/src/components/color_picker/color_palette_picker'; import { i18n } from '@kbn/i18n'; import { getSeverityStatusColor } from '../../../common/utils/get_vulnerability_colors'; -import { VulnSeverity } from '../../../../common/types'; +import { VulnSeverity } from '../../../../common/types_old'; import { SeverityStatusBadge } from '../../../components/vulnerability_badges'; interface Props { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/_mocks_/vulnerability_dashboard.mock.ts b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/_mocks_/vulnerability_dashboard.mock.ts index 6d7f909a82e53..0148105bbc83a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/_mocks_/vulnerability_dashboard.mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/_mocks_/vulnerability_dashboard.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CnvmDashboardData } from '../../../../common/types'; +import { CnvmDashboardData } from '../../../../common/types_old'; export const mockCnvmDashboardData: CnvmDashboardData = { cnvmStatistics: { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx index 14c3451fd2731..1ba912b1d125b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx @@ -21,7 +21,7 @@ import { VulnerabilityStat, VulnerableResourceStat, VulnSeverity, -} from '../../../common/types'; +} from '../../../common/types_old'; import { DASHBOARD_TABLE_TYPES } from './vulnerability_table_panel.config'; import { VulnerabilityTablePanel } from './vulnerability_table_panel'; import { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx index a8c528f7f8804..493d38348ed62 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_trend_graph.tsx @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { truthy } from '../../../common/utils/helpers'; import { useNavigateVulnerabilities } from '../../common/hooks/use_navigate_findings'; -import { VulnStatsTrend, VulnSeverity } from '../../../common/types'; +import { VulnStatsTrend, VulnSeverity } from '../../../common/types_old'; import { useVulnerabilityDashboardApi } from '../../common/api/use_vulnerability_dashboard_api'; import { getSeverityStatusColor } from '../../common/utils/get_vulnerability_colors'; import { ChartPanel } from '../../components/chart_panel'; diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index bc9243fad2792..4b5d4f1bfe028 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -8,7 +8,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import Chance from 'chance'; -import type { Benchmark } from '../../../common/types'; +import type { Benchmark } from '../../../common/types_old'; type CreateCspBenchmarkIntegrationFixtureInput = { chance?: Chance.Chance; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts index ebce74d89b2dc..67eb611f9557e 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient, type Logger } from '@kbn/core/server'; import { getSafePostureTypeRuntimeMapping } from '../../common/runtime_mappings/get_safe_posture_type_runtime_mapping'; -import { IndexStatus, PostureTypes } from '../../common/types'; +import { IndexStatus, PostureTypes } from '../../common/types_old'; export interface PostureTypeAndRetention { postureType?: PostureTypes; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts index cd67f29cef1b4..109d1b46986c9 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts @@ -19,7 +19,7 @@ import type { PackagePolicyInput, } from '@kbn/fleet-plugin/common'; import { errors } from '@elastic/elasticsearch'; -import { CloudSecurityPolicyTemplate, PostureTypes } from '../../common/types'; +import { CloudSecurityPolicyTemplate, PostureTypes } from '../../common/types_old'; import { SUPPORTED_POLICY_TEMPLATES, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts index cb8d6eec64dcb..f9eb6094277a4 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts @@ -6,7 +6,7 @@ */ import { AggregationsMultiBucketBase } from '@elastic/elasticsearch/lib/api/types'; -import { CspStatusCode } from '../../../../common/types'; +import { CspStatusCode } from '../../../../common/types_old'; export type CloudSecurityUsageCollectorType = | 'Indices' diff --git a/x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_templates.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts similarity index 68% rename from x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_templates.test.ts rename to x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts index f894d031c4bc0..ffec7d5b9b261 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_templates.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.test.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { getSortedCspRulesTemplates } from './get_csp_rule_template'; -import { CspRuleTemplate } from '../../../common/schemas'; +import { getSortedCspBenchmarkRulesTemplates } from './v1'; +import { CspBenchmarkRule } from '../../../../common/types/latest'; -describe('getSortedCspRulesTemplates', () => { +describe('getSortedCspBenchmarkRules', () => { it('sorts by metadata.benchmark.rule_number, invalid semantic version still should still get sorted and empty values should be sorted last', () => { - const cspRulesTemplates = [ + const cspBenchmarkRules = [ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: '2.0.0' } } }, { metadata: { benchmark: { rule_number: '1.1.0' } } }, @@ -18,11 +18,11 @@ describe('getSortedCspRulesTemplates', () => { { metadata: { benchmark: { rule_number: 'invalid' } } }, { metadata: { benchmark: { rule_number: '3.0' } } }, { metadata: { benchmark: {} } }, - ] as CspRuleTemplate[]; + ] as CspBenchmarkRule[]; - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); - expect(sortedCspRulesTemplates).toEqual([ + expect(sortedCspBenchmarkRules).toEqual([ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: '1.0.1' } } }, { metadata: { benchmark: { rule_number: '1.1.0' } } }, @@ -34,36 +34,36 @@ describe('getSortedCspRulesTemplates', () => { }); it('edge case - returns empty array if input is empty', () => { - const cspRulesTemplates: CspRuleTemplate[] = []; + const cspBenchmarkRules: CspBenchmarkRule[] = []; - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); - expect(sortedCspRulesTemplates).toEqual([]); + expect(sortedCspBenchmarkRules).toEqual([]); }); it('edge case - returns sorted array even if input only has one element', () => { - const cspRulesTemplates = [ + const cspBenchmarkRules = [ { metadata: { benchmark: { rule_number: '1.0.0' } } }, - ] as CspRuleTemplate[]; + ] as CspBenchmarkRule[]; - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); - expect(sortedCspRulesTemplates).toEqual([ + expect(sortedCspBenchmarkRules).toEqual([ { metadata: { benchmark: { rule_number: '1.0.0' } } }, ]); }); it('returns sorted array even with undefined or null properties', () => { - const cspRulesTemplates = [ + const cspBenchmarkRules = [ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: undefined } } }, { metadata: { benchmark: { rule_number: '2.0.0' } } }, { metadata: { benchmark: { rule_number: null } } }, - ] as CspRuleTemplate[]; + ] as CspBenchmarkRule[]; - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); - expect(sortedCspRulesTemplates).toEqual([ + expect(sortedCspBenchmarkRules).toEqual([ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: '2.0.0' } } }, { metadata: { benchmark: { rule_number: null } } }, @@ -72,15 +72,15 @@ describe('getSortedCspRulesTemplates', () => { }); it('returns sorted array with invalid semantic versions', () => { - const cspRulesTemplates = [ + const cspBenchmarkRules = [ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: '2.0' } } }, { metadata: { benchmark: { rule_number: '3.0.0' } } }, - ] as CspRuleTemplate[]; + ] as CspBenchmarkRule[]; - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); - expect(sortedCspRulesTemplates).toEqual([ + expect(sortedCspBenchmarkRules).toEqual([ { metadata: { benchmark: { rule_number: '1.0.0' } } }, { metadata: { benchmark: { rule_number: '2.0' } } }, { metadata: { benchmark: { rule_number: '3.0.0' } } }, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts new file mode 100644 index 0000000000000..aa4856fd9bada --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/find.ts @@ -0,0 +1,56 @@ +/* + * 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 { transformError } from '@kbn/securitysolution-es-utils'; +import { + FindCspBenchmarkRuleRequest, + FindCspBenchmarkRuleResponse, + findCspBenchmarkRuleRequestSchema, +} from '../../../../common/types/latest'; + +import { FIND_CSP_BENCHMARK_RULE_ROUTE_PATH } from '../../../../common/constants'; +import { CspRouter } from '../../../types'; +import { findRuleHandler as findRuleHandlerV1 } from './v1'; + +export const defineFindCspBenchmarkRuleRoute = (router: CspRouter) => + router.versioned + .get({ + access: 'internal', + path: FIND_CSP_BENCHMARK_RULE_ROUTE_PATH, + }) + .addVersion( + { + version: '1', + validate: { + request: { + query: findCspBenchmarkRuleRequestSchema, + }, + }, + }, + async (context, request, response) => { + if (!(await context.fleet).authz.fleet.all) { + return response.forbidden(); + } + + const requestBody: FindCspBenchmarkRuleRequest = request.query; + const cspContext = await context.csp; + + try { + const cspBenchmarkRules: FindCspBenchmarkRuleResponse = await findRuleHandlerV1( + cspContext.soClient, + requestBody + ); + return response.ok({ body: cspBenchmarkRules }); + } catch (err) { + const error = transformError(err); + cspContext.logger.error(`Failed to fetch csp rules templates ${err}`); + return response.customError({ + body: { message: error.message }, + statusCode: error.statusCode, + }); + } + } + ); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts new file mode 100644 index 0000000000000..6bd0d14a2f540 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmark_rules/find/v1.ts @@ -0,0 +1,88 @@ +/* + * 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 semverValid from 'semver/functions/valid'; +import semverCompare from 'semver/functions/compare'; +import { NewPackagePolicy } from '@kbn/fleet-plugin/common'; +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { getBenchmarkFilter } from '../../../../common/utils/helpers'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../../common/constants'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../benchmarks/benchmarks'; +import { getBenchmarkFromPackagePolicy } from '../../../../common/utils/helpers'; + +import type { + CspBenchmarkRule, + FindCspBenchmarkRuleRequest, + FindCspBenchmarkRuleResponse, +} from '../../../../common/types/latest'; + +export const getSortedCspBenchmarkRulesTemplates = (cspBenchmarkRules: CspBenchmarkRule[]) => { + return cspBenchmarkRules.slice().sort((a, b) => { + const ruleNumberA = a?.metadata?.benchmark?.rule_number; + const ruleNumberB = b?.metadata?.benchmark?.rule_number; + + const versionA = semverValid(ruleNumberA); + const versionB = semverValid(ruleNumberB); + + if (versionA !== null && versionB !== null) { + return semverCompare(versionA, versionB); + } else { + return String(ruleNumberA).localeCompare(String(ruleNumberB)); + } + }); +}; + +export const getBenchmarkIdFromPackagePolicyId = async ( + soClient: SavedObjectsClientContract, + packagePolicyId: string +): Promise => { + const res = await soClient.get( + PACKAGE_POLICY_SAVED_OBJECT_TYPE, + packagePolicyId + ); + return getBenchmarkFromPackagePolicy(res.attributes.inputs); +}; + +export const findRuleHandler = async ( + soClient: SavedObjectsClientContract, + options: FindCspBenchmarkRuleRequest +): Promise => { + if ( + (!options.packagePolicyId && !options.benchmarkId) || + (options.packagePolicyId && options.benchmarkId) + ) { + throw new Error('Please provide either benchmarkId or packagePolicyId, but not both'); + } + + const benchmarkId = options.benchmarkId + ? options.benchmarkId + : await getBenchmarkIdFromPackagePolicyId(soClient, options.packagePolicyId!); + + const cspCspBenchmarkRulesSo = await soClient.find({ + type: CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, + searchFields: options.searchFields, + search: options.search ? `"${options.search}"*` : '', + page: options.page, + perPage: options.perPage, + sortField: options.sortField, + fields: options?.fields, + filter: getBenchmarkFilter(benchmarkId, options.section), + }); + + const cspBenchmarkRules = cspCspBenchmarkRulesSo.saved_objects.map( + (cspBenchmarkRule) => cspBenchmarkRule.attributes + ); + + // Semantic version sorting using semver for valid versions and custom comparison for invalid versions + const sortedCspBenchmarkRules = getSortedCspBenchmarkRulesTemplates(cspBenchmarkRules); + + return { + items: sortedCspBenchmarkRules, + total: cspCspBenchmarkRulesSo.total, + page: options.page, + perPage: options.perPage, + }; +}; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 25fc95e1f8a20..42209b205e177 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -174,7 +174,7 @@ describe('benchmarks API', () => { }); }); - describe('test addPackagePolicyCspRuleTemplates', () => { + describe('test addPackagePolicyCspBenchmarkRule', () => { it('should retrieve the rules count by the filtered benchmark type', async () => { const benchmark = 'cis_k8s'; mockSoClient.find.mockResolvedValueOnce({ diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 4c78265c1c15e..0c920754fb77b 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -7,15 +7,15 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { AgentPolicy, ListResult, PackagePolicy } from '@kbn/fleet-plugin/common'; -import { CspRuleTemplate } from '../../../common/schemas'; -import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants'; +import { CspBenchmarkRule } from '../../../common/types/latest'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { BENCHMARKS_ROUTE_PATH, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, POSTURE_TYPE_ALL, } from '../../../common/constants'; import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark'; -import type { Benchmark } from '../../../common/types'; +import type { Benchmark } from '../../../common/types_old'; import { getBenchmarkFromPackagePolicy, getBenchmarkFilter, @@ -28,7 +28,7 @@ import { getCspAgentPolicies, getCspPackagePolicies, } from '../../lib/fleet_util'; -import { BenchmarkId } from '../../../common/types'; +import { BenchmarkId } from '../../../common/types_old'; export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; @@ -36,8 +36,8 @@ export const getRulesCountForPolicy = async ( soClient: SavedObjectsClientContract, benchmarkId: BenchmarkId ): Promise => { - const rules = await soClient.find({ - type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, + const rules = await soClient.find({ + type: CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, filter: getBenchmarkFilter(benchmarkId), perPage: 0, }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts index 88c7afd5aca11..614f85dcf9374 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts @@ -15,7 +15,7 @@ import type { ComplianceDashboardData, GetComplianceDashboardRequest, ComplianceDashboardDataV2, -} from '../../../common/types'; +} from '../../../common/types_old'; import { LATEST_FINDINGS_INDEX_DEFAULT_NS, STATS_ROUTE_PATH } from '../../../common/constants'; import { getGroupedFindingsEvaluation } from './get_grouped_findings_evaluation'; import { ClusterWithoutTrend, getClusters } from './get_clusters'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_benchmarks.ts index b1f8335a61866..130af8d20a2b8 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_benchmarks.ts @@ -13,7 +13,7 @@ import type { } from '@elastic/elasticsearch/lib/api/types'; import type { Logger } from '@kbn/core/server'; import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; -import type { BenchmarkData } from '../../../common/types'; +import type { BenchmarkData } from '../../../common/types_old'; import { failedFindingsAggQuery, BenchmarkVersionQueryResult, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts index 51d5c71673ed1..e793863621340 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts @@ -16,7 +16,7 @@ import type { import type { Logger } from '@kbn/core/server'; import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import { CspFinding } from '../../../common/schemas/csp_finding'; -import type { Cluster } from '../../../common/types'; +import type { Cluster } from '../../../common/types_old'; import { getPostureStatsFromAggs, failedFindingsAggQuery } from './get_grouped_findings_evaluation'; import type { FailedFindingsQueryResult } from './get_grouped_findings_evaluation'; import { findingsEvaluationAggsQuery, getStatsFromFindingsEvaluationsAggs } from './get_stats'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_grouped_findings_evaluation.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_grouped_findings_evaluation.ts index 74b239f14d242..ec915d0d62330 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_grouped_findings_evaluation.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_grouped_findings_evaluation.ts @@ -14,7 +14,7 @@ import type { import type { Logger } from '@kbn/core/server'; import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import { calculatePostureScore } from '../../../common/utils/helpers'; -import type { ComplianceDashboardData } from '../../../common/types'; +import type { ComplianceDashboardData } from '../../../common/types_old'; import { KeyDocCount } from './compliance_dashboard'; export interface FailedFindingsQueryResult { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts index f639f8a7e1421..e02b355f27e18 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts @@ -10,7 +10,7 @@ import type { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsear import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import type { Logger } from '@kbn/core/server'; import { calculatePostureScore } from '../../../common/utils/helpers'; -import type { ComplianceDashboardData } from '../../../common/types'; +import type { ComplianceDashboardData } from '../../../common/types_old'; export interface FindingsEvaluationsQueryResult { failed_findings: { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts index 00acd14d960fa..150c531f4a1fa 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts @@ -8,7 +8,7 @@ import { ElasticsearchClient, Logger } from '@kbn/core/server'; import { calculatePostureScore } from '../../../common/utils/helpers'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS } from '../../../common/constants'; -import type { PosturePolicyTemplate, Stats } from '../../../common/types'; +import type { PosturePolicyTemplate, Stats } from '../../../common/types_old'; import { toBenchmarkDocFieldKey } from '../../lib/mapping_field_util'; import { CSPM_FINDINGS_STATS_INTERVAL } from '../../tasks/findings_stats_task'; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_template.ts b/x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_template.ts deleted file mode 100644 index 0b249e9f3656e..0000000000000 --- a/x-pack/plugins/cloud_security_posture/server/routes/csp_rule_template/get_csp_rule_template.ts +++ /dev/null @@ -1,131 +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 { NewPackagePolicy } from '@kbn/fleet-plugin/common'; -import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; -import { transformError } from '@kbn/securitysolution-es-utils'; -import semverCompare from 'semver/functions/compare'; -import semverValid from 'semver/functions/valid'; -import { GetCspRuleTemplateRequest, GetCspRuleTemplateResponse } from '../../../common/types'; -import { CspRuleTemplate } from '../../../common/schemas'; -import { findCspRuleTemplateRequest } from '../../../common/schemas/csp_rule_template_api/get_csp_rule_template'; -import { getBenchmarkFromPackagePolicy, getBenchmarkFilter } from '../../../common/utils/helpers'; - -import { - CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - FIND_CSP_RULE_TEMPLATE_ROUTE_PATH, -} from '../../../common/constants'; -import { CspRouter } from '../../types'; -import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../benchmarks/benchmarks'; - -export const getSortedCspRulesTemplates = (cspRulesTemplates: CspRuleTemplate[]) => { - return cspRulesTemplates.slice().sort((a, b) => { - const ruleNumberA = a?.metadata?.benchmark?.rule_number; - const ruleNumberB = b?.metadata?.benchmark?.rule_number; - - const versionA = semverValid(ruleNumberA); - const versionB = semverValid(ruleNumberB); - - if (versionA !== null && versionB !== null) { - return semverCompare(versionA, versionB); - } else { - return String(ruleNumberA).localeCompare(String(ruleNumberB)); - } - }); -}; - -const getBenchmarkIdFromPackagePolicyId = async ( - soClient: SavedObjectsClientContract, - packagePolicyId: string -): Promise => { - const res = await soClient.get( - PACKAGE_POLICY_SAVED_OBJECT_TYPE, - packagePolicyId - ); - return getBenchmarkFromPackagePolicy(res.attributes.inputs); -}; - -const findCspRuleTemplateHandler = async ( - soClient: SavedObjectsClientContract, - options: GetCspRuleTemplateRequest -): Promise => { - if ( - (!options.packagePolicyId && !options.benchmarkId) || - (options.packagePolicyId && options.benchmarkId) - ) { - throw new Error('Please provide either benchmarkId or packagePolicyId, but not both'); - } - - const benchmarkId = options.benchmarkId - ? options.benchmarkId - : await getBenchmarkIdFromPackagePolicyId(soClient, options.packagePolicyId!); - - const cspRulesTemplatesSo = await soClient.find({ - type: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, - searchFields: options.searchFields, - search: options.search ? `"${options.search}"*` : '', - page: options.page, - perPage: options.perPage, - sortField: options.sortField, - fields: options?.fields, - filter: getBenchmarkFilter(benchmarkId, options.section), - }); - - const cspRulesTemplates = cspRulesTemplatesSo.saved_objects.map( - (cspRuleTemplate) => cspRuleTemplate.attributes - ); - - // Semantic version sorting using semver for valid versions and custom comparison for invalid versions - const sortedCspRulesTemplates = getSortedCspRulesTemplates(cspRulesTemplates); - - return { - items: sortedCspRulesTemplates, - total: cspRulesTemplatesSo.total, - page: options.page, - perPage: options.perPage, - }; -}; - -export const defineFindCspRuleTemplateRoute = (router: CspRouter) => - router.versioned - .get({ - access: 'internal', - path: FIND_CSP_RULE_TEMPLATE_ROUTE_PATH, - }) - .addVersion( - { - version: '1', - validate: { - request: { - query: findCspRuleTemplateRequest, - }, - }, - }, - async (context, request, response) => { - if (!(await context.fleet).authz.fleet.all) { - return response.forbidden(); - } - - const requestBody: GetCspRuleTemplateRequest = request.query; - const cspContext = await context.csp; - - try { - const cspRulesTemplates: GetCspRuleTemplateResponse = await findCspRuleTemplateHandler( - cspContext.soClient, - requestBody - ); - return response.ok({ body: cspRulesTemplates }); - } catch (err) { - const error = transformError(err); - cspContext.logger.error(`Failed to fetch csp rules templates ${err}`); - return response.customError({ - body: { message: error.message }, - statusCode: error.statusCode, - }); - } - } - ); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/setup_routes.ts b/x-pack/plugins/cloud_security_posture/server/routes/setup_routes.ts index a0e33bce73d3f..49022dd1f5fe6 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/setup_routes.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/setup_routes.ts @@ -17,7 +17,7 @@ import { defineGetComplianceDashboardRoute } from './compliance_dashboard/compli import { defineGetVulnerabilitiesDashboardRoute } from './vulnerabilities_dashboard/vulnerabilities_dashboard'; import { defineGetBenchmarksRoute } from './benchmarks/benchmarks'; import { defineGetCspStatusRoute } from './status/status'; -import { defineFindCspRuleTemplateRoute } from './csp_rule_template/get_csp_rule_template'; +import { defineFindCspBenchmarkRuleRoute } from './benchmark_rules/find/find'; import { defineGetDetectionEngineAlertsStatus } from './detection_engine/get_detection_engine_alerts_count_by_rule_tags'; /** @@ -38,7 +38,7 @@ export async function setupRoutes({ defineGetVulnerabilitiesDashboardRoute(router); defineGetBenchmarksRoute(router); defineGetCspStatusRoute(router); - defineFindCspRuleTemplateRoute(router); + defineFindCspBenchmarkRuleRoute(router); defineGetDetectionEngineAlertsStatus(router); core.http.registerRouteHandlerContext( diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts index ed3bcd99746fc..df2fc0d36fc63 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts @@ -44,7 +44,7 @@ import type { CspStatusCode, IndexStatus, PostureTypes, -} from '../../../common/types'; +} from '../../../common/types_old'; import { getAgentStatusesByAgentPolicies, getCspAgentPolicies, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts index 6eec795e2dad6..3f4db5e90a526 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_patchable_vulnerabilities.ts @@ -7,7 +7,7 @@ import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { AggFieldBucket, PatchableVulnerabilityStat } from '../../../common/types'; +import { AggFieldBucket, PatchableVulnerabilityStat } from '../../../common/types_old'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; interface VulnerabilityBucket { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts index cd8c5b64f532d..8efb0fd33c61e 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerabilities.ts @@ -7,7 +7,7 @@ import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { VulnerabilityStat } from '../../../common/types'; +import { VulnerabilityStat } from '../../../common/types_old'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; interface VulnerabilityBucket { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts index 0a41a11aeedea..50f54f69e0a64 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_top_vulnerable_resources.ts @@ -7,7 +7,7 @@ import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { AggFieldBucket, VulnerableResourceStat } from '../../../common/types'; +import { AggFieldBucket, VulnerableResourceStat } from '../../../common/types_old'; import { LATEST_VULNERABILITIES_INDEX_DEFAULT_NS } from '../../../common/constants'; interface ResourceBucket { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_trend.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_trend.ts index a3e335734e74c..5a619b125deab 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_trend.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/get_vulnerabilities_trend.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS } from '../../../common/constants'; -import { VulnStatsTrend } from '../../../common/types'; +import { VulnStatsTrend } from '../../../common/types_old'; interface LastDocBucket { key_as_string: string; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts index 7f676226559aa..f7de7f1be4b65 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/vulnerabilities_dashboard/vulnerabilities_dashboard.ts @@ -7,7 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { getVulnerabilitiesTrends } from './get_vulnerabilities_trend'; -import type { CnvmDashboardData } from '../../../common/types'; +import type { CnvmDashboardData } from '../../../common/types_old'; import { VULNERABILITIES_DASHBOARD_ROUTE_PATH } from '../../../common/constants'; import { CspRouter } from '../../types'; import { getVulnerabilitiesStatistics } from './get_vulnerabilities_statistics'; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts new file mode 100644 index 0000000000000..ebf90aa500097 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_benchmark_rule.ts @@ -0,0 +1,31 @@ +/* + * 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 { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import { SavedObjectsType } from '@kbn/core/server'; +import { rulesV1, rulesV2, rulesV3 } from '../../common/types'; +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { cspBenchmarkRuleMigrations } from './migrations'; +import { cspBenchmarkRuleSavedObjectMapping } from './mappings'; + +export const cspBenchmarkRule: SavedObjectsType = { + name: CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, + indexPattern: SECURITY_SOLUTION_SAVED_OBJECT_INDEX, + hidden: false, + namespaceType: 'agnostic', + management: { + importableAndExportable: true, + visibleInManagement: true, + }, + schemas: { + '8.3.0': rulesV1.cspBenchmarkRuleSchema, + '8.4.0': rulesV2.cspBenchmarkRuleSchema, + '8.7.0': rulesV3.cspBenchmarkRuleSchema, + }, + migrations: cspBenchmarkRuleMigrations, + mappings: cspBenchmarkRuleSavedObjectMapping, +}; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts index f4befec2e4811..f672d271c8b5f 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/mappings.ts @@ -7,7 +7,7 @@ import { SavedObjectsTypeMappingDefinition } from '@kbn/core/server'; -export const cspRuleTemplateSavedObjectMapping: SavedObjectsTypeMappingDefinition = { +export const cspBenchmarkRuleSavedObjectMapping: SavedObjectsTypeMappingDefinition = { dynamic: false, properties: { metadata: { diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_rule_template.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts similarity index 68% rename from x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_rule_template.ts rename to x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts index f6f59b21b4a68..e440342d2083d 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_rule_template.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/csp_benchmark_rule.ts @@ -10,16 +10,12 @@ import { SavedObjectUnsanitizedDoc, SavedObjectMigrationContext, } from '@kbn/core/server'; -import { - CspRuleTemplateV830, - CspRuleTemplateV840, - CspRuleTemplateV870, -} from '../../../common/schemas/csp_rule_template'; +import { rulesV1, rulesV2, rulesV3 } from '../../../common/types'; -function migrateCspRuleTemplatesToV840( - doc: SavedObjectUnsanitizedDoc, +function migrateCspBenchmarkRuleToV840( + doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext -): SavedObjectUnsanitizedDoc { +): SavedObjectUnsanitizedDoc { const { enabled, muted, benchmark, ...metadata } = doc.attributes; return { ...doc, @@ -37,10 +33,10 @@ function migrateCspRuleTemplatesToV840( }; } -function migrateCspRuleTemplatesToV870( - doc: SavedObjectUnsanitizedDoc, +function migrateCspBenchmarkRuleToV870( + doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext -): SavedObjectUnsanitizedDoc { +): SavedObjectUnsanitizedDoc { // Keeps only metadata, deprecated state const { muted, enabled, ...attributes } = doc.attributes; @@ -59,7 +55,7 @@ function migrateCspRuleTemplatesToV870( }; } -export const cspRuleTemplateMigrations: SavedObjectMigrationMap = { - '8.4.0': migrateCspRuleTemplatesToV840, - '8.7.0': migrateCspRuleTemplatesToV870, +export const cspBenchmarkRuleMigrations: SavedObjectMigrationMap = { + '8.4.0': migrateCspBenchmarkRuleToV840, + '8.7.0': migrateCspBenchmarkRuleToV870, }; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/index.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/index.ts index 991b7469a9129..595a9566f9b77 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/index.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/migrations/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './csp_rule_template'; +export * from './csp_benchmark_rule'; diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/saved_objects.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/saved_objects.ts index e218808caa420..eed21b5b91916 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/saved_objects.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/saved_objects.ts @@ -7,20 +7,17 @@ import { SavedObjectsServiceSetup } from '@kbn/core/server'; import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; -import { cspRuleTemplateSavedObjectMapping } from './mappings'; -import { cspRuleTemplateMigrations } from './migrations'; -import { - cspRuleTemplateSchemaV830, - cspRuleTemplateSchemaV840, - cspRuleTemplateSchemaV870, - CspRuleTemplate, -} from '../../common/schemas'; +import { rulesV1, rulesV2, rulesV3 } from '../../common/types'; +import { cspBenchmarkRuleSavedObjectMapping } from './mappings'; +import { cspBenchmarkRuleMigrations } from './migrations'; -import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { CspBenchmarkRule } from '../../common/types/latest'; + +import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '../../common/constants'; export function setupSavedObjects(savedObjects: SavedObjectsServiceSetup) { - savedObjects.registerType({ - name: CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE, + savedObjects.registerType({ + name: CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, indexPattern: SECURITY_SOLUTION_SAVED_OBJECT_INDEX, hidden: false, namespaceType: 'agnostic', @@ -29,11 +26,11 @@ export function setupSavedObjects(savedObjects: SavedObjectsServiceSetup) { visibleInManagement: true, }, schemas: { - '8.3.0': cspRuleTemplateSchemaV830, - '8.4.0': cspRuleTemplateSchemaV840, - '8.7.0': cspRuleTemplateSchemaV870, + '8.3.0': rulesV1.cspBenchmarkRuleSchema, + '8.4.0': rulesV2.cspBenchmarkRuleSchema, + '8.7.0': rulesV3.cspBenchmarkRuleSchema, }, - migrations: cspRuleTemplateMigrations, - mappings: cspRuleTemplateSavedObjectMapping, + migrations: cspBenchmarkRuleMigrations, + mappings: cspBenchmarkRuleSavedObjectMapping, }); } diff --git a/x-pack/plugins/cloud_security_posture/server/types.ts b/x-pack/plugins/cloud_security_posture/server/types.ts index 1b3c4fd840347..3c84de12decf6 100644 --- a/x-pack/plugins/cloud_security_posture/server/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/types.ts @@ -34,7 +34,7 @@ import type { import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { FleetStartContract, FleetRequestHandlerContext } from '@kbn/fleet-plugin/server'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; -import { CspStatusCode, IndexDetails } from '../common/types'; +import { CspStatusCode, IndexDetails } from '../common/types_old'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CspServerPluginSetup {} diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json index 48fc1a30594f5..ad1a97748967f 100755 --- a/x-pack/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/plugins/cloud_security_posture/tsconfig.json @@ -60,7 +60,7 @@ "@kbn/core-http-server-mocks", "@kbn/field-formats-plugin", "@kbn/data-view-field-editor-plugin", - "@kbn/securitysolution-grouping" + "@kbn/securitysolution-grouping", ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/pipeline_select.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/pipeline_select.tsx index 582348fd86e2b..1a682d37e439d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/pipeline_select.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/pipeline_select.tsx @@ -45,19 +45,10 @@ export const PipelineSelect: React.FC = () => { } }; - const getActiveOptionIndex = (): number | undefined => { - const index = existingInferencePipelines.findIndex( - (pipelineOption) => pipelineOption.pipelineName === pipelineName - ); - - return index >= 0 ? index : undefined; - }; - return ( { + const makeUsageCollectorStub = jest.fn(); + const registerStub = jest.fn(); + const usageCollectionMock = { + makeUsageCollector: makeUsageCollectorStub, + registerCollector: registerStub, + } as any; + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('registerTelemetryUsageCollector', () => { + it('should make and register the usage collector', () => { + registerTelemetryUsageCollector(usageCollectionMock); + + expect(registerStub).toHaveBeenCalledTimes(1); + expect(makeUsageCollectorStub).toHaveBeenCalledTimes(1); + expect(makeUsageCollectorStub.mock.calls[0][0].type).toBe('connectors'); + expect(makeUsageCollectorStub.mock.calls[0][0].isReady()).toBe(true); + }); + }); + + describe('fetchTelemetryMetrics', () => { + it('should return telemetry data', async () => { + const fetchContextMock = createCollectorFetchContextMock(); + fetchContextMock.esClient.count = jest.fn().mockImplementation((query: any) => + Promise.resolve({ + count: query.query.bool.filter[0].term.is_native ? 5 : 2, + }) + ); + registerTelemetryUsageCollector(usageCollectionMock); + const telemetryMetrics = await makeUsageCollectorStub.mock.calls[0][0].fetch( + fetchContextMock + ); + + expect(telemetryMetrics).toEqual({ + native: { + total: 5, + }, + clients: { + total: 2, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/collectors/connectors/telemetry.ts b/x-pack/plugins/enterprise_search/server/collectors/connectors/telemetry.ts new file mode 100644 index 0000000000000..d5a61dff0a692 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/collectors/connectors/telemetry.ts @@ -0,0 +1,98 @@ +/* + * 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/server'; + +import { CONNECTORS_INDEX } from '@kbn/search-connectors'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; + +interface Telemetry { + native: { + total: number; + }; + clients: { + total: number; + }; +} + +/** + * Register the telemetry collector + */ + +export const registerTelemetryUsageCollector = (usageCollection: UsageCollectionSetup) => { + const telemetryUsageCollector = usageCollection.makeUsageCollector({ + type: 'connectors', + isReady: () => true, + schema: { + native: { + total: { type: 'long' }, + }, + clients: { + total: { type: 'long' }, + }, + }, + async fetch({ esClient }) { + return await fetchTelemetryMetrics(esClient); + }, + }); + usageCollection.registerCollector(telemetryUsageCollector); +}; + +/** + * Fetch the aggregated telemetry metrics + */ + +export const fetchTelemetryMetrics = async (client: ElasticsearchClient): Promise => { + const [nativeCountResponse, clientsCountResponse] = await Promise.all([ + client.count({ + index: CONNECTORS_INDEX, + query: { + bool: { + filter: [ + { + term: { + is_native: true, + }, + }, + ], + must_not: [ + { + term: { + service_type: { + value: 'elastic-crawler', + }, + }, + }, + ], + }, + }, + }), + client.count({ + index: CONNECTORS_INDEX, + query: { + bool: { + filter: [ + { + term: { + is_native: false, + }, + }, + ], + }, + }, + }), + ]); + + return { + native: { + total: nativeCountResponse.count, + }, + clients: { + total: clientsCountResponse.count, + }, + } as Telemetry; +}; diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 6231673a8a153..1132de4fbcccf 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -50,6 +50,7 @@ import { } from '../common/guided_onboarding/search_guide_config'; import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry'; +import { registerTelemetryUsageCollector as registerCNTelemetryUsageCollector } from './collectors/connectors/telemetry'; import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry'; import { registerTelemetryUsageCollector as registerWSTelemetryUsageCollector } from './collectors/workplace_search/telemetry'; import { registerEnterpriseSearchIntegrations } from './integrations'; @@ -262,6 +263,7 @@ export class EnterpriseSearchPlugin implements Plugin { if (usageCollection) { registerESTelemetryUsageCollector(usageCollection, savedObjectsStarted, this.logger); + registerCNTelemetryUsageCollector(usageCollection); if (config.canDeployEntSearch) { registerASTelemetryUsageCollector(usageCollection, savedObjectsStarted, this.logger); registerWSTelemetryUsageCollector(usageCollection, savedObjectsStarted, this.logger); diff --git a/x-pack/plugins/fleet/common/experimental_features.ts b/x-pack/plugins/fleet/common/experimental_features.ts index 3ac7abb927b95..0c4a6b91fdb83 100644 --- a/x-pack/plugins/fleet/common/experimental_features.ts +++ b/x-pack/plugins/fleet/common/experimental_features.ts @@ -25,6 +25,7 @@ export const allowedExperimentalValues = Object.freeze>( kafkaOutput: true, outputSecretsStorage: true, remoteESOutput: true, + agentless: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/fleet/common/types/models/index.ts b/x-pack/plugins/fleet/common/types/models/index.ts index babbe3a8ce1ac..5af1294e52657 100644 --- a/x-pack/plugins/fleet/common/types/models/index.ts +++ b/x-pack/plugins/fleet/common/types/models/index.ts @@ -19,3 +19,4 @@ export * from './download_sources'; export * from './fleet_server_policy_config'; export * from './fleet_proxy'; export * from './secret'; +export * from './setup_technology'; diff --git a/x-pack/plugins/fleet/common/types/models/setup_technology.ts b/x-pack/plugins/fleet/common/types/models/setup_technology.ts new file mode 100644 index 0000000000000..66fb4a09ff9a2 --- /dev/null +++ b/x-pack/plugins/fleet/common/types/models/setup_technology.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. + */ + +export enum SetupTechnology { + AGENTLESS = 'agentless', + AGENT_BASED = 'agent-based', +} diff --git a/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts b/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts index 28b124116502a..5101c4d93fd39 100644 --- a/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/fleet_settings_outputs.cy.ts @@ -21,6 +21,7 @@ import { loadESOutput, loadKafkaOutput, loadLogstashOutput, + loadRemoteESOutput, resetKafkaOutputForm, selectESOutput, selectKafkaOutput, @@ -134,6 +135,80 @@ describe('Outputs', () => { }); }); + describe('Remote ES', () => { + it('displays proper error messages', () => { + selectRemoteESOutput(); + cy.getBySel(SETTINGS_SAVE_BTN).click(); + + cy.contains('Name is required'); + cy.contains('URL is required'); + cy.contains('Service Token is required'); + shouldDisplayError(SETTINGS_OUTPUTS.NAME_INPUT); + shouldDisplayError('serviceTokenSecretInput'); + }); + + describe('Form submit', () => { + let outputId: string; + + before(() => { + interceptOutputId((id) => { + outputId = id; + }); + }); + + after(() => { + cleanupOutput(outputId); + }); + + it('saves the output', () => { + selectRemoteESOutput(); + + cy.getBySel(SETTINGS_OUTPUTS.NAME_INPUT).type('name'); + cy.get('[placeholder="Specify host URL"').clear().type('https://localhost:5000'); + cy.getBySel('serviceTokenSecretInput').type('service_token'); + + cy.intercept('POST', '**/api/fleet/outputs').as('saveOutput'); + + cy.getBySel(SETTINGS_SAVE_BTN).click(); + + cy.wait('@saveOutput').then((interception) => { + const responseBody = interception.response?.body; + cy.visit(`/app/fleet/settings/outputs/${responseBody?.item?.id}`); + expect(responseBody?.item.service_token).to.equal(undefined); + expect(responseBody?.item.secrets.service_token.id).not.to.equal(undefined); + }); + + cy.get('[placeholder="Specify host URL"').should('have.value', 'https://localhost:5000'); + cy.getBySel(SETTINGS_OUTPUTS.NAME_INPUT).should('have.value', 'name'); + }); + }); + + describe('Form edit', () => { + let outputId: string; + + before(() => { + loadRemoteESOutput().then((data) => { + outputId = data.item.id; + }); + }); + after(() => { + cleanupOutput(outputId); + }); + + it('edits the output', () => { + visit(`/app/fleet/settings/outputs/${outputId}`); + + cy.get('[placeholder="Specify host URL"').clear().type('https://localhost:5001'); + + cy.getBySel(SETTINGS_SAVE_BTN).click(); + cy.getBySel(SETTINGS_CONFIRM_MODAL_BTN).click(); + visit(`/app/fleet/settings/outputs/${outputId}`); + + cy.get('[placeholder="Specify host URL"').should('have.value', 'https://localhost:5001'); + }); + }); + }); + describe('Kafka', () => { describe('Form validation', () => { it('renders all form fields', () => { @@ -301,7 +376,7 @@ describe('Outputs', () => { cy.contains('Name is required'); cy.contains('Host is required'); cy.contains('Username is required'); - // cy.contains('Password is required'); + cy.contains('Password is required'); cy.contains('Default topic is required'); cy.contains('Topic is required'); cy.contains( @@ -310,7 +385,7 @@ describe('Outputs', () => { cy.contains('Must be a key, value pair i.e. "http.response.code: 200"'); shouldDisplayError(SETTINGS_OUTPUTS.NAME_INPUT); shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_INPUT); - // shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_PASSWORD_INPUT); // TODO + shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_PASSWORD_INPUT); shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.TOPICS_DEFAULT_TOPIC_INPUT); shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.TOPICS_CONDITION_INPUT); shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.TOPICS_TOPIC_INPUT); diff --git a/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts b/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts index e1d1a3530df9a..e439961e287d7 100644 --- a/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts +++ b/x-pack/plugins/fleet/cypress/screens/fleet_outputs.ts @@ -84,6 +84,17 @@ export const loadESOutput = () => hosts: ['https://bla.co'], }); +export const loadRemoteESOutput = () => + loadOutput({ + name: 'remote_es', + type: 'remote_elasticsearch', + is_default: false, + is_default_monitoring: false, + hosts: ['https://bla.co'], + secrets: { service_token: 'token' }, + preset: 'balanced', + }); + export const loadLogstashOutput = () => loadOutput({ name: 'ls', diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx index 33d1cee841590..2d8b96c562e85 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/index.tsx @@ -7,3 +7,4 @@ export { useDevToolsRequest } from './devtools_request'; export { useOnSubmit } from './form'; +export { useSetupTechnology } from './setup_technology'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts new file mode 100644 index 0000000000000..dd2a1dcc81c79 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -0,0 +1,204 @@ +/* + * 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-hooks'; + +import { SetupTechnology } from '../../../../../../../../common/types'; +import { ExperimentalFeaturesService } from '../../../../../services'; +import { sendGetOneAgentPolicy, useStartServices } from '../../../../../hooks'; +import { SelectedPolicyTab } from '../../components'; + +import { useSetupTechnology } from './setup_technology'; + +jest.mock('../../../../../services'); +jest.mock('../../../../../hooks', () => ({ + ...jest.requireActual('../../../../../hooks'), + sendGetOneAgentPolicy: jest.fn(), + useStartServices: jest.fn(), +})); + +type MockFn = jest.MockedFunction; + +describe('useSetupTechnology', () => { + const updateNewAgentPolicyMock = jest.fn(); + const updateAgentPolicyMock = jest.fn(); + const setSelectedPolicyTabMock = jest.fn(); + const newAgentPolicyMock = { + name: 'mock_new_agent_policy', + namespace: 'default', + }; + const mockedExperimentalFeaturesService = jest.mocked(ExperimentalFeaturesService); + + beforeEach(() => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: true, + } as any); + (sendGetOneAgentPolicy as MockFn).mockResolvedValue({ + data: { + item: { id: 'agentless-policy-id' }, + }, + }); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isServerlessEnabled: true, + }, + }); + jest.clearAllMocks(); + }); + + it('should initialize with default values when agentless is disabled', () => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: false, + } as any); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(sendGetOneAgentPolicy).not.toHaveBeenCalled(); + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + expect(result.current.agentlessPolicy).toBeUndefined(); + }); + + it('should fetch agentless policy if agentless is enabled', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.agentlessPolicy).toEqual({ id: 'agentless-policy-id' }); + }); + + it('should not fetch agentless policy if agentless is enabled but serverless is disabled', async () => { + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isServerlessEnabled: false, + }, + }); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(sendGetOneAgentPolicy).not.toHaveBeenCalled(); + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + expect(result.current.agentlessPolicy).toBeUndefined(); + }); + + it('should update agent policy and selected policy tab when setup technology is agentless', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(updateAgentPolicyMock).toHaveBeenCalledWith({ id: 'agentless-policy-id' }); + expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.EXISTING); + }); + + it('should update new agent policy and selected policy tab when setup technology is agent-based', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + expect(updateNewAgentPolicyMock).toHaveBeenCalledWith(newAgentPolicyMock); + expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.NEW); + }); + + it('should not update agent policy and selected policy tab when agentless is disabled', async () => { + mockedExperimentalFeaturesService.get.mockReturnValue({ + agentless: false, + } as any); + + const { result } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + }); + + it('should not update agent policy and selected policy tab when setup technology matches the current one ', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useSetupTechnology({ + updateNewAgentPolicy: updateNewAgentPolicyMock, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicy: updateAgentPolicyMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + }) + ); + + await waitForNextUpdate(); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + act(() => { + result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED); + }); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED); + + expect(updateNewAgentPolicyMock).not.toHaveBeenCalled(); + expect(setSelectedPolicyTabMock).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts new file mode 100644 index 0000000000000..22972f4a9a6d4 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts @@ -0,0 +1,86 @@ +/* + * 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, useEffect, useState } from 'react'; + +import { ExperimentalFeaturesService } from '../../../../../services'; +import type { AgentPolicy, NewAgentPolicy } from '../../../../../types'; +import { SetupTechnology } from '../../../../../types'; +import { sendGetOneAgentPolicy, useStartServices } from '../../../../../hooks'; +import { SelectedPolicyTab } from '../../components'; + +const AGENTLESS_POLICY_ID = 'agentless'; + +export function useSetupTechnology({ + updateNewAgentPolicy, + newAgentPolicy, + updateAgentPolicy, + setSelectedPolicyTab, +}: { + updateNewAgentPolicy: (policy: NewAgentPolicy) => void; + newAgentPolicy: NewAgentPolicy; + updateAgentPolicy: (policy: AgentPolicy) => void; + setSelectedPolicyTab: (tab: SelectedPolicyTab) => void; +}) { + const { agentless: isAgentlessEnabled } = ExperimentalFeaturesService.get(); + const { cloud } = useStartServices(); + const isServerless = cloud?.isServerlessEnabled ?? false; + const [selectedSetupTechnology, setSelectedSetupTechnology] = useState( + SetupTechnology.AGENT_BASED + ); + const [agentlessPolicy, setAgentlessPolicy] = useState(); + + useEffect(() => { + const fetchAgentlessPolicy = async () => { + const { data, error } = await sendGetOneAgentPolicy(AGENTLESS_POLICY_ID); + const isAgentlessAvailable = !error && data && data.item; + + if (isAgentlessAvailable) { + setAgentlessPolicy(data.item); + } + }; + + if (isAgentlessEnabled && isServerless) { + fetchAgentlessPolicy(); + } + }, [isAgentlessEnabled, isServerless]); + + const handleSetupTechnologyChange = useCallback( + (setupTechnology) => { + if (!isAgentlessEnabled || setupTechnology === selectedSetupTechnology) { + return; + } + + if (setupTechnology === SetupTechnology.AGENTLESS) { + if (agentlessPolicy) { + updateAgentPolicy(agentlessPolicy); + setSelectedPolicyTab(SelectedPolicyTab.EXISTING); + } + } else if (setupTechnology === SetupTechnology.AGENT_BASED) { + updateNewAgentPolicy(newAgentPolicy); + setSelectedPolicyTab(SelectedPolicyTab.NEW); + } + + setSelectedSetupTechnology(setupTechnology); + }, + [ + isAgentlessEnabled, + selectedSetupTechnology, + agentlessPolicy, + updateAgentPolicy, + setSelectedPolicyTab, + updateNewAgentPolicy, + newAgentPolicy, + ] + ); + + return { + handleSetupTechnologyChange, + agentlessPolicy, + selectedSetupTechnology, + }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx index d0b82cf66e641..b5e29245c63cc 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx @@ -5,21 +5,21 @@ * 2.0. */ -import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useRouteMatch } from 'react-router-dom'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { - EuiButtonEmpty, - EuiButton, - EuiSteps, EuiBottomBar, + EuiButton, + EuiButtonEmpty, + EuiCallOut, + EuiErrorBoundary, EuiFlexGroup, EuiFlexItem, EuiSpacer, - EuiErrorBoundary, - EuiCallOut, + EuiSteps, } from '@elastic/eui'; import type { EuiStepProps } from '@elastic/eui/src/components/steps/step'; @@ -31,35 +31,38 @@ import { import { useCancelAddPackagePolicy } from '../hooks'; import { isRootPrivilegesRequired, splitPkgKey } from '../../../../../../../common/services'; -import type { NewAgentPolicy } from '../../../../types'; -import { useConfig, sendGetAgentStatus, useGetPackageInfoByKeyQuery } from '../../../../hooks'; +import type { NewAgentPolicy, PackagePolicyEditExtensionComponentProps } from '../../../../types'; +import { SetupTechnology } from '../../../../types'; import { - Loading, + sendGetAgentStatus, + useConfig, + useGetPackageInfoByKeyQuery, + useUIExtension, +} from '../../../../hooks'; +import { + DevtoolsRequestFlyoutButton, Error as ErrorComponent, ExtensionWrapper, - DevtoolsRequestFlyoutButton, + Loading, } from '../../../../components'; import { agentPolicyFormValidation, ConfirmDeployAgentPolicyModal } from '../../components'; -import { useUIExtension } from '../../../../hooks'; -import type { PackagePolicyEditExtensionComponentProps } from '../../../../types'; import { pkgKeyFromPackageInfo } from '../../../../services'; import type { AddToPolicyParams, CreatePackagePolicyParams } from '../types'; -import { IntegrationBreadcrumb } from '../components'; - import { + IntegrationBreadcrumb, + SelectedPolicyTab, StepConfigurePackagePolicy, StepDefinePackagePolicy, - SelectedPolicyTab, StepSelectHosts, } from '../components'; import { generateNewAgentPolicyWithDefaults } from '../../../../../../../common/services/generate_new_agent_policy'; import { CreatePackagePolicySinglePageLayout, PostInstallAddAgentModal } from './components'; -import { useDevToolsRequest, useOnSubmit } from './hooks'; +import { useDevToolsRequest, useOnSubmit, useSetupTechnology } from './hooks'; import { PostInstallCloudFormationModal } from './components/post_install_cloud_formation_modal'; import { PostInstallGoogleCloudShellModal } from './components/post_install_google_cloud_shell_modal'; import { PostInstallAzureArmTemplateModal } from './components/post_install_azure_arm_template_modal'; @@ -293,6 +296,14 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ ); } + const { agentlessPolicy, handleSetupTechnologyChange, selectedSetupTechnology } = + useSetupTechnology({ + newAgentPolicy, + updateNewAgentPolicy, + updateAgentPolicy, + setSelectedPolicyTab, + }); + const replaceStepConfigurePackagePolicy = replaceDefineStepView && packageInfo?.name ? ( !isInitialized ? ( @@ -306,6 +317,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ onChange={handleExtensionViewOnChange} validationResults={validationResults} isEditPage={false} + handleSetupTechnologyChange={handleSetupTechnologyChange} + agentlessPolicy={agentlessPolicy} /> ) @@ -374,13 +387,16 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ 'data-test-subj': 'dataCollectionSetupStep', children: replaceStepConfigurePackagePolicy || stepConfigurePackagePolicy, }, - { + ]; + + if (selectedSetupTechnology !== SetupTechnology.AGENTLESS) { + steps.push({ title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle', { defaultMessage: 'Where to add this integration?', }), children: stepSelectAgentPolicy, - }, - ]; + }); + } // Display package error if there is one if (packageInfoError) { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx index d9fa988aa55cc..3023cf1397faa 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx @@ -227,6 +227,7 @@ export const EditOutputFlyout: React.FunctionComponent = })} {...inputs.sslKeySecretInput.formRowProps} onUsePlainText={onUsePlainText} + cancelEdit={inputs.sslKeySecretInput.cancelEdit} > = (props) defaultMessage: 'Service Token', })} {...inputs.serviceTokenSecretInput.formRowProps} + cancelEdit={inputs.serviceTokenSecretInput.cancelEdit} onUsePlainText={onUsePlainText} > { const initialValue = 'initial value'; const clear = jest.fn(); const onUsePlainText = jest.fn(); + const cancelEdit = jest.fn(); it('should switch to edit mode when the replace button is clicked', () => { const { getByText, queryByText, container } = render( @@ -23,6 +24,7 @@ describe('SecretFormRow', () => { initialValue={initialValue} clear={clear} onUsePlainText={onUsePlainText} + cancelEdit={cancelEdit} > @@ -38,13 +40,14 @@ describe('SecretFormRow', () => { expect(queryByText(initialValue)).not.toBeInTheDocument(); }); - it('should call the clear function when the cancel button is clicked', () => { + it('should call the cancelEdit function when the cancel button is clicked', () => { const { getByText } = render( @@ -53,12 +56,17 @@ describe('SecretFormRow', () => { fireEvent.click(getByText('Replace Test Secret')); fireEvent.click(getByText('Cancel Test Secret change')); - expect(clear).toHaveBeenCalled(); + expect(cancelEdit).toHaveBeenCalled(); }); it('should call the onUsePlainText function when the revert link is clicked', () => { const { getByText } = render( - + ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_secret_form_row.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_secret_form_row.tsx index fc55835557403..f483503af9e43 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_secret_form_row.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_secret_form_row.tsx @@ -29,7 +29,18 @@ export const SecretFormRow: React.FC<{ clear: () => void; initialValue?: any; onUsePlainText: () => void; -}> = ({ fullWidth, error, isInvalid, children, clear, title, initialValue, onUsePlainText }) => { + cancelEdit: () => void; +}> = ({ + fullWidth, + error, + isInvalid, + children, + clear, + title, + initialValue, + onUsePlainText, + cancelEdit, +}) => { const hasInitialValue = initialValue !== undefined; const [editMode, setEditMode] = useState(!initialValue); const valueHiddenPanel = ( @@ -66,7 +77,7 @@ export const SecretFormRow: React.FC<{ { setEditMode(false); - clear(); + cancelEdit(); }} color="primary" iconType="refresh" diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx index 28218fed7e942..26e63803df0e7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx @@ -11,11 +11,11 @@ import { safeLoad } from 'js-yaml'; const toSecretValidator = (validator: (value: string) => string[] | undefined) => (value: string | { id: string } | undefined) => { - if (!value || typeof value === 'object') { + if (typeof value === 'object') { return undefined; } - return validator(value); + return validator(value ?? ''); }; export function validateKafkaHosts(value: string[]) { diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index 30ccf9c9c657d..1efc18a53e1e8 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -16,6 +16,7 @@ export const plugin = (initializerContext: PluginInitializerContext) => { }; export type { NewPackagePolicy, KibanaSavedObjectType } from './types'; +export { SetupTechnology } from './types'; export type { AgentDetailsReassignPolicyAction, AgentPolicyDetailsDeployAgentAction, diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 63837dc809559..fe1c49af887d9 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -144,6 +144,7 @@ export { ElasticsearchAssetType, KibanaAssetType, InstallStatus, + SetupTechnology, } from '../../common/types'; export * from './intra_app_route_state'; diff --git a/x-pack/plugins/fleet/public/types/ui_extensions.ts b/x-pack/plugins/fleet/public/types/ui_extensions.ts index 53ae5322f0d9d..b5ae9dacf54bc 100644 --- a/x-pack/plugins/fleet/public/types/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/types/ui_extensions.ts @@ -36,6 +36,8 @@ export type PackagePolicyReplaceDefineStepExtensionComponentProps = ( validationResults?: PackagePolicyValidationResults; agentPolicy?: AgentPolicy; packageInfo: PackageInfo; + agentlessPolicy?: AgentPolicy; + handleSetupTechnologyChange?: (setupTechnology: string) => void; }; /** diff --git a/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts b/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts index 1202876c754a8..f68a700865708 100644 --- a/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts +++ b/x-pack/plugins/fleet/server/collectors/agents_per_output.test.ts @@ -19,11 +19,13 @@ jest.mock('../services', () => { { agents: 1, data_output_id: 'logstash1' }, { agents: 1, monitoring_output_id: 'kafka1' }, { agents: 1, data_output_id: 'elasticsearch2', monitoring_output_id: 'elasticsearch2' }, + { agents: 1, data_output_id: 'elasticsearch3', monitoring_output_id: 'elasticsearch3' }, { agents: 1, data_output_id: 'es-containerhost', monitoring_output_id: 'es-containerhost', }, + { agents: 1, data_output_id: 'remote-es', monitoring_output_id: 'remote-es' }, ], }), }, @@ -35,11 +37,14 @@ jest.mock('../services', () => { is_default: true, is_default_monitoring: true, type: 'elasticsearch', + preset: 'balanced', }, { id: 'logstash1', type: 'logstash' }, { id: 'kafka1', type: 'kafka' }, - { id: 'elasticsearch2', type: 'elasticsearch' }, - { id: 'es-containerhost', type: 'elasticsearch' }, + { id: 'elasticsearch2', type: 'elasticsearch', preset: 'custom' }, + { id: 'elasticsearch3', type: 'elasticsearch', preset: 'balanced' }, + { id: 'es-containerhost', type: 'elasticsearch', preset: 'throughput' }, + { id: 'remote-es', type: 'remote_elasticsearch', preset: 'scale' }, ], }), }, @@ -52,9 +57,32 @@ describe('agents_per_output', () => { it('should return agent count by output type', async () => { const res = await getAgentsPerOutput(soClientMock, {} as unknown as ElasticsearchClient); expect(res).toEqual([ - { output_type: 'elasticsearch', count_as_data: 4, count_as_monitoring: 4 }, + { + output_type: 'elasticsearch', + count_as_data: 5, + count_as_monitoring: 5, + preset_counts: { + custom: 1, + balanced: 2, + throughput: 1, + scale: 0, + latency: 0, + }, + }, { output_type: 'logstash', count_as_data: 1, count_as_monitoring: 0 }, { output_type: 'kafka', count_as_data: 0, count_as_monitoring: 1 }, + { + output_type: 'remote_elasticsearch', + count_as_data: 1, + count_as_monitoring: 1, + preset_counts: { + custom: 0, + balanced: 0, + throughput: 0, + scale: 1, + latency: 0, + }, + }, ]); }); }); diff --git a/x-pack/plugins/fleet/server/collectors/agents_per_output.ts b/x-pack/plugins/fleet/server/collectors/agents_per_output.ts index 3ad09bcb51177..b7ed480fc61fc 100644 --- a/x-pack/plugins/fleet/server/collectors/agents_per_output.ts +++ b/x-pack/plugins/fleet/server/collectors/agents_per_output.ts @@ -6,8 +6,12 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; + import _ from 'lodash'; +import { outputTypeSupportPresets } from '../../common/services/output_helpers'; +import type { AgentPolicy } from '../../common/types'; + import { SO_SEARCH_LIMIT } from '../../common'; import { agentPolicyService, outputService } from '../services'; @@ -15,6 +19,13 @@ export interface AgentsPerOutputType { output_type: string; count_as_data: number; count_as_monitoring: number; + preset_counts?: { + balanced: number; + custom: number; + latency: number; + scale: number; + throughput: number; + }; } export async function getAgentsPerOutput( @@ -28,38 +39,69 @@ export async function getAgentsPerOutput( outputs.find((output) => output.is_default_monitoring)?.id || ''; const outputsById = _.keyBy(outputs, 'id'); - const getOutputTypeById = (outputId: string): string => outputsById[outputId]?.type ?? ''; + const getDataOutputForAgentPolicy = (agentPolicy: AgentPolicy) => + outputsById[agentPolicy.data_output_id || defaultOutputId]; + const getMonitoringOutputForAgentPolicy = (agentPolicy: AgentPolicy) => + outputsById[agentPolicy.monitoring_output_id || defaultMonitoringOutputId]; - const { items } = await agentPolicyService.list(soClient, { + const { items: agentPolicies } = await agentPolicyService.list(soClient, { esClient, withAgentCount: true, page: 1, perPage: SO_SEARCH_LIMIT, }); + const outputTypes: { [key: string]: AgentsPerOutputType } = {}; - items - .filter((item) => (item.agents ?? 0) > 0) - .forEach((item) => { - const dataOutputType = getOutputTypeById(item.data_output_id || defaultOutputId); - if (!outputTypes[dataOutputType]) { - outputTypes[dataOutputType] = { - output_type: dataOutputType, + + agentPolicies + .filter((agentPolicy) => (agentPolicy.agents ?? 0) > 0) + .forEach((agentPolicy) => { + const dataOutput = getDataOutputForAgentPolicy(agentPolicy); + const monitoringOutput = getMonitoringOutputForAgentPolicy(agentPolicy); + + if (!outputTypes[dataOutput.type]) { + outputTypes[dataOutput.type] = { + output_type: dataOutput.type, count_as_data: 0, count_as_monitoring: 0, }; } - outputTypes[dataOutputType].count_as_data += item.agents ?? 0; - const monitoringOutputType = getOutputTypeById( - item.monitoring_output_id || defaultMonitoringOutputId - ); - if (!outputTypes[monitoringOutputType]) { - outputTypes[monitoringOutputType] = { - output_type: monitoringOutputType, + + outputTypes[dataOutput.type].count_as_data += agentPolicy.agents ?? 0; + + if (!outputTypes[monitoringOutput.type]) { + outputTypes[monitoringOutput.type] = { + output_type: monitoringOutput.type, count_as_data: 0, count_as_monitoring: 0, }; } - outputTypes[monitoringOutputType].count_as_monitoring += item.agents ?? 0; + outputTypes[monitoringOutput.type].count_as_monitoring += agentPolicy.agents ?? 0; }); + + outputs.forEach((output) => { + if (!outputTypeSupportPresets(output.type)) { + return; + } + + const outputTelemetryRecord = outputTypes[output.type]; + + if (!outputTelemetryRecord.preset_counts) { + outputTelemetryRecord.preset_counts = { + balanced: 0, + custom: 0, + latency: 0, + scale: 0, + throughput: 0, + }; + } + + if (output.preset && output.preset in outputTelemetryRecord.preset_counts) { + outputTelemetryRecord.preset_counts[ + output.preset as keyof typeof outputTelemetryRecord.preset_counts + ] += 1; + } + }); + return Object.values(outputTypes); } diff --git a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts index e2e7e9f7887e6..19eb7aa750658 100644 --- a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts @@ -221,6 +221,20 @@ describe('fleet usage telemetry', () => { active: true, policy_id: 'policy2', }, + { + create: { + _id: 'agent4', + }, + }, + { + agent: { + version: '8.6.0', + }, + last_checkin_status: 'online', + last_checkin: new Date(Date.now() - 1000 * 60 * 6).toISOString(), + active: true, + policy_id: 'policy3', + }, ], refresh: 'wait_for', }); @@ -361,6 +375,21 @@ describe('fleet usage telemetry', () => { }, { id: 'output3' } ); + await soClient.create( + 'ingest-outputs', + { + name: 'output4', + type: 'elasticsearch', + hosts: ['http://localhost:9200'], + is_default: false, + is_default_monitoring: false, + config_yaml: '', + ca_trusted_fingerprint: '', + proxy_id: null, + preset: 'balanced', + }, + { id: 'output4' } + ); await soClient.create( 'ingest-agent-policies', @@ -380,6 +409,24 @@ describe('fleet usage telemetry', () => { }, { id: 'policy2' } ); + await soClient.create( + 'ingest-agent-policies', + { + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + name: 'Yet another policy', + description: 'Policy 3', + inactivity_timeout: 1209600, + status: 'active', + is_managed: false, + revision: 2, + updated_by: 'system', + schema_version: '1.0.0', + data_output_id: 'output4', + monitoring_output_id: 'output4', + }, + { id: 'policy3' } + ); }); afterAll(async () => { @@ -397,13 +444,13 @@ describe('fleet usage telemetry', () => { expect.objectContaining({ agents_enabled: true, agents: { - total_enrolled: 3, + total_enrolled: 4, healthy: 0, unhealthy: 0, inactive: 0, unenrolled: 1, - offline: 3, - total_all_statuses: 4, + offline: 4, + total_all_statuses: 5, updating: 0, }, fleet_server: { @@ -419,10 +466,10 @@ describe('fleet usage telemetry', () => { agents_per_version: [ { version: '8.6.0', - count: 2, + count: 3, healthy: 0, inactive: 0, - offline: 2, + offline: 3, unenrolled: 0, unhealthy: 0, updating: 0, @@ -439,7 +486,7 @@ describe('fleet usage telemetry', () => { }, ], agent_checkin_status: { error: 1, degraded: 1 }, - agents_per_policy: [2, 1], + agents_per_policy: [2, 1, 1], agents_per_os: [ { name: 'Ubuntu', @@ -463,6 +510,18 @@ describe('fleet usage telemetry', () => { count_as_monitoring: 1, output_type: 'logstash', }, + { + count_as_data: 1, + count_as_monitoring: 1, + output_type: 'elasticsearch', + preset_counts: { + balanced: 2, + custom: 0, + latency: 0, + scale: 0, + throughput: 0, + }, + }, ], fleet_server_config: { policies: [ @@ -477,7 +536,7 @@ describe('fleet usage telemetry', () => { ], }, agent_policies: { - count: 2, + count: 3, output_types: expect.arrayContaining(['elasticsearch', 'logstash', 'third_type']), }, agent_logs_panics_last_hour: [ diff --git a/x-pack/plugins/fleet/server/services/agents/versions.test.ts b/x-pack/plugins/fleet/server/services/agents/versions.test.ts index 513fba910705d..15fa38d4949bc 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.test.ts @@ -179,4 +179,29 @@ describe('getAvailableVersions', () => { expect(mockedFetch).toBeCalledTimes(1); expect(res2).not.toContain('300.0.0'); }); + + it('should gracefully handle 400 errors when fetching from product versions API', async () => { + mockKibanaVersion = '300.0.0'; + mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`); + mockedFetch.mockResolvedValue({ + status: 400, + text: 'Bad request', + } as any); + + const res = await getAvailableVersions({ ignoreCache: true }); + + // Should sort, uniquify and filter out versions < 7.17 + expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); + }); + + it('should gracefully handle network errors when fetching from product versions API', async () => { + mockKibanaVersion = '300.0.0'; + mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`); + mockedFetch.mockRejectedValue('ECONNREFUSED'); + + const res = await getAvailableVersions({ ignoreCache: true }); + + // Should sort, uniquify and filter out versions < 7.17 + expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); + }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/versions.ts b/x-pack/plugins/fleet/server/services/agents/versions.ts index 8f31d3f12b344..b5a09bc99e2cb 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.ts @@ -24,6 +24,7 @@ const AGENT_VERSION_BUILD_FILE = 'x-pack/plugins/fleet/target/agent_versions_lis // Endpoint maintained by the web-team and hosted on the elastic website const PRODUCT_VERSIONS_URL = 'https://www.elastic.co/api/product_versions'; +const MAX_REQUEST_TIMEOUT = 60 * 1000; // Only attempt to fetch product versions for one minute total // Cache available versions in memory for 1 hour const CACHE_DURATION = 1000 * 60 * 60; @@ -118,21 +119,29 @@ async function fetchAgentVersionsFromApi() { }, }; - const response = await pRetry(() => fetch(PRODUCT_VERSIONS_URL, options), { retries: 1 }); - const rawBody = await response.text(); - - // We need to handle non-200 responses gracefully here to support airgapped environments where - // Kibana doesn't have internet access to query this API - if (response.status >= 400) { - logger.debug(`Status code ${response.status} received from versions API: ${rawBody}`); - return []; - } + try { + const response = await pRetry(() => fetch(PRODUCT_VERSIONS_URL, options), { + retries: 1, + maxRetryTime: MAX_REQUEST_TIMEOUT, + }); + const rawBody = await response.text(); + + // We need to handle non-200 responses gracefully here to support airgapped environments where + // Kibana doesn't have internet access to query this API + if (response.status >= 400) { + logger.debug(`Status code ${response.status} received from versions API: ${rawBody}`); + return []; + } - const jsonBody = JSON.parse(rawBody); + const jsonBody = JSON.parse(rawBody); - const versions: string[] = (jsonBody.length ? jsonBody[0] : []) - .filter((item: any) => item?.title?.includes('Elastic Agent')) - .map((item: any) => item?.version_number); + const versions: string[] = (jsonBody.length ? jsonBody[0] : []) + .filter((item: any) => item?.title?.includes('Elastic Agent')) + .map((item: any) => item?.version_number); - return versions; + return versions; + } catch (error) { + logger.debug(`Error fetching available versions from API: ${error.message}`); + return []; + } } diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts index e59de684264bf..fa7d2d769b900 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts @@ -76,6 +76,49 @@ export const fleetAgentsSchema: RootSchema = { description: 'Output type used by agent', }, }, + presets_counts: { + _meta: { + description: 'Count of agents per preset', + }, + properties: { + balanced: { + type: 'long', + _meta: { + description: 'Number of agents enrolled whose output uses the balanced preset', + }, + }, + custom: { + type: 'long', + _meta: { + description: 'Number of agents enrolled whose outputs uses the custom preset', + }, + }, + throughput: { + type: 'long', + _meta: { + description: 'Number of agents enrolled whose output uses the throughput preset', + }, + }, + scale: { + type: 'long', + _meta: { + description: 'Number of agents enrolled whose output uses the scale preset', + }, + }, + latency: { + type: 'long', + _meta: { + description: 'Number of agents enrolled whose output uses the latency preset', + }, + }, + }, + }, + output_preset: { + type: 'keyword', + _meta: { + description: 'Output preset used by agent, if applicable', + }, + }, count_as_data: { type: 'long', _meta: { diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index e36ae54746b3d..517b020eaeace 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -7,11 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; -import { - AlertsLocatorParams, - getAlertDetailsUrl, - getAlertUrl, -} from '@kbn/observability-plugin/common'; +import { AlertsLocatorParams, getAlertDetailsUrl } from '@kbn/observability-plugin/common'; import { ALERT_CONTEXT, ALERT_EVALUATION_THRESHOLD, @@ -63,7 +59,6 @@ import { InfraBackendLibs } from '../../infra_types'; import { AdditionalContext, flattenAdditionalContext, - getAlertDetailsPageEnabledForApp, getContextForRecoveredAlerts, getGroupByObject, unflattenObject, @@ -138,7 +133,6 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => getAlertByAlertUuid, } = services; const { basePath, alertsLocator } = libs; - const config = libs.getAlertDetailsConfig(); const alertFactory: LogThresholdAlertFactory = ( id, @@ -189,15 +183,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => alert.scheduleActions(actionGroup, { ...sharedContext, ...context, - alertDetailsUrl: getAlertDetailsPageEnabledForApp(config, 'logs') - ? getAlertDetailsUrl(libs.basePath, spaceId, alertUuid) - : await getAlertUrl( - alertUuid, - spaceId, - indexedStartedAt, - libs.alertsLocator, - libs.basePath.publicBaseUrl - ), + alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), }); }); } @@ -254,7 +240,6 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => validatedParams, getAlertByAlertUuid, alertsLocator, - isAlertDetailsPageEnabled: getAlertDetailsPageEnabledForApp(config, 'logs'), }); } catch (e) { throw new Error(e); @@ -868,7 +853,6 @@ const processRecoveredAlerts = async ({ validatedParams, getAlertByAlertUuid, alertsLocator, - isAlertDetailsPageEnabled = false, }: { basePath: IBasePath; getAlertStartedDate: (alertId: string) => string | null; @@ -881,7 +865,6 @@ const processRecoveredAlerts = async ({ alertUuid: string ) => Promise | null> | null; alertsLocator?: LocatorPublic; - isAlertDetailsPageEnabled?: boolean; }) => { const groupByKeysObjectForRecovered = getGroupByObject( validatedParams.groupBy, @@ -898,15 +881,7 @@ const processRecoveredAlerts = async ({ const viewInAppUrl = addSpaceIdToPath(basePath.publicBaseUrl, spaceId, relativeViewInAppUrl); const baseContext = { - alertDetailsUrl: isAlertDetailsPageEnabled - ? getAlertDetailsUrl(basePath, spaceId, alertUuid) - : await getAlertUrl( - alertUuid, - spaceId, - indexedStartedAt, - alertsLocator, - basePath.publicBaseUrl - ), + alertDetailsUrl: getAlertDetailsUrl(basePath, spaceId, alertUuid), group: hasGroupBy(validatedParams) ? recoveredAlertId : null, groupByKeys: groupByKeysObjectForRecovered[recoveredAlertId], timestamp: startedAt.toISOString(), diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/layer_configuration_section.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/layer_configuration_section.tsx index 7ae7b456ab669..86f2cde79ee56 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/layer_configuration_section.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/layer_configuration_section.tsx @@ -26,6 +26,7 @@ export function LayerConfiguration({ framePublicAPI, hasPadding, setIsInlineFlyoutVisible, + getUserMessages, }: LayerConfigurationProps) { const dispatch = useLensDispatch(); const { euiTheme } = useEuiTheme(); @@ -58,6 +59,7 @@ export function LayerConfiguration({ hideLayerHeader: datasourceId === 'textBased', indexPatternService, setIsInlineFlyoutVisible, + getUserMessages, }; return (
state.lens); + const { datasourceStates, visualization, isLoading, annotationGroups } = useLensSelector( + (state) => state.lens + ); const framePublicAPI = useLensSelector((state) => selectFramePublicAPI(state, datasourceMap)); const suggestsLimitedColumns = activeDatasource?.suggestsLimitedColumns?.(datasourceState); @@ -113,10 +116,33 @@ export function LensEditConfigurationFlyout({ : false; const visualizationState = visualization.state; - return ( - !isEqual(visualizationState, previousAttrs.state.visualization) || !datasourceStatesAreSame - ); - }, [attributes.references, datasourceId, datasourceMap, datasourceStates, visualization.state]); + const customIsEqual = visualizationMap[previousAttrs.visualizationType]?.isEqual; + const visualizationStateIsEqual = customIsEqual + ? (() => { + try { + return customIsEqual( + previousAttrs.state.visualization, + previousAttrs.references, + visualizationState, + attributes.references, + annotationGroups + ); + } catch (err) { + return false; + } + })() + : isEqual(visualizationState, previousAttrs.state.visualization); + + return !visualizationStateIsEqual || !datasourceStatesAreSame; + }, [ + attributes.references, + datasourceId, + datasourceMap, + datasourceStates, + visualizationMap, + annotationGroups, + visualization.state, + ]); const onCancel = useCallback(() => { const previousAttrs = previousAttributes.current; @@ -195,6 +221,18 @@ export function LensEditConfigurationFlyout({ datasourceMap, ]); + const { getUserMessages } = useApplicationUserMessages({ + coreStart, + framePublicAPI, + activeDatasourceId: datasourceId, + datasourceState: datasourceStates[datasourceId], + datasource: datasourceMap[datasourceId], + dispatch, + visualization: activeVisualization, + visualizationType: visualization.activeId, + visualizationState: visualization, + }); + // needed for text based languages mode which works ONLY with adHoc dataviews const adHocDataViews = Object.values(attributes.state.adHocDataViews ?? {}); @@ -240,6 +278,7 @@ export function LensEditConfigurationFlyout({ attributesChanged={attributesChanged} > void; + getUserMessages: UserMessagesGetter; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/error_helper.tsx b/x-pack/plugins/lens/public/editor_frame_service/error_helper.tsx index c336101033eae..475e2e17da2ea 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/error_helper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/error_helper.tsx @@ -10,7 +10,7 @@ import { isEqual, uniqWith } from 'lodash'; import { estypes } from '@elastic/elasticsearch'; import { ExpressionRenderError } from '@kbn/expressions-plugin/public'; import type { CoreStart } from '@kbn/core/public'; -import { isEsError } from '@kbn/data-plugin/public'; +import { isEsError } from '@kbn/search-errors'; import React from 'react'; import { EuiLink } from '@elastic/eui'; import { RemovableUserMessage } from '../types'; diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json index 8958e1db8abfd..dd714b72c998d 100644 --- a/x-pack/plugins/lens/tsconfig.json +++ b/x-pack/plugins/lens/tsconfig.json @@ -87,6 +87,7 @@ "@kbn/serverless", "@kbn/ebt-tools", "@kbn/chart-expressions-common", + "@kbn/search-errors", "@kbn/search-response-warnings", "@kbn/logging", "@kbn/core-plugins-server", diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx index 66c4788a32ae2..8f1da5cbfc18d 100644 --- a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx @@ -10,6 +10,7 @@ import { FlyoutProps, LogDocument } from './types'; import { useDocDetail } from './use_doc_detail'; import { FlyoutHeader } from './flyout_header'; import { FlyoutHighlights } from './flyout_highlights'; +import { DiscoverActionsProvider } from '../../hooks/use_discover_action'; export function FlyoutDetail({ dataView, @@ -19,9 +20,9 @@ export function FlyoutDetail({ const parsedDoc = useDocDetail(doc as LogDocument, { dataView }); return ( - <> + - + ); } diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_header.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_header.tsx index fd1c78787c8e4..f49e3d9003949 100644 --- a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_header.tsx +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_header.tsx @@ -13,6 +13,7 @@ import { LogLevel } from './sub_components/log_level'; import { Timestamp } from './sub_components/timestamp'; import * as constants from '../../../common/constants'; import { flyoutMessageLabel } from './translations'; +import { HoverActionPopover } from './sub_components/hover_popover_action'; export function FlyoutHeader({ doc }: { doc: FlyoutDoc }) { const { hasTimestamp, hasLogLevel, hasMessage, hasBadges, hasFlyoutHeader } = @@ -23,9 +24,14 @@ export function FlyoutHeader({ doc }: { doc: FlyoutDoc }) { {hasBadges && ( {hasLogLevel && ( - - - + + + + + )} {hasTimestamp && ( @@ -49,9 +55,15 @@ export function FlyoutHeader({ doc }: { doc: FlyoutDoc }) { - - {flyoutMessageLabel} - + + + {flyoutMessageLabel} + + {logLevelAndTimestamp} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_highlights.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_highlights.tsx index 97b924b00a307..cdfc30d2145b5 100644 --- a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_highlights.tsx +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_highlights.tsx @@ -34,7 +34,6 @@ import { serviceAccordionTitle, } from './translations'; import { HighlightSection } from './sub_components/highlight_section'; -import { DiscoverActionsProvider } from '../../hooks/use_discover_action'; import { HighlightContainer } from './sub_components/highlight_container'; import { useFlyoutColumnWidth } from '../../hooks/use_flyouot_column_width'; @@ -50,173 +49,171 @@ export function FlyoutHighlights({ const [ref, dimensions] = useMeasure(); const { columns, fieldWidth } = useFlyoutColumnWidth(dimensions.width); return ( - - - {/* Service highlight */} - - {formattedDoc[constants.SERVICE_NAME_FIELD] && ( - - } - label={flyoutServiceLabel} - value={flattenedDoc[constants.SERVICE_NAME_FIELD]} - width={fieldWidth} - /> - )} - {formattedDoc[constants.TRACE_ID_FIELD] && ( - - )} - - {/* Infrastructure highlight */} - - {formattedDoc[constants.HOST_NAME_FIELD] && ( - - )} - {formattedDoc[constants.ORCHESTRATOR_CLUSTER_NAME_FIELD] && ( - - )} - {formattedDoc[constants.ORCHESTRATOR_RESOURCE_ID_FIELD] && ( - - )} - - {/* Cloud highlight */} - - {formattedDoc[constants.CLOUD_PROVIDER_FIELD] && ( - - } - label={flyoutCloudProviderLabel} - value={flattenedDoc[constants.CLOUD_PROVIDER_FIELD]} - width={fieldWidth} - /> - )} - {formattedDoc[constants.CLOUD_REGION_FIELD] && ( - - )} - {formattedDoc[constants.CLOUD_AVAILABILITY_ZONE_FIELD] && ( - - )} - {formattedDoc[constants.CLOUD_PROJECT_ID_FIELD] && ( - - )} - {formattedDoc[constants.CLOUD_INSTANCE_ID_FIELD] && ( - - )} - - {/* Other highlights */} - - {formattedDoc[constants.LOG_FILE_PATH_FIELD] && ( - - )} - {formattedDoc[constants.DATASTREAM_NAMESPACE_FIELD] && ( - - )} - {formattedDoc[constants.DATASTREAM_DATASET_FIELD] && ( - - )} - {formattedDoc[constants.AGENT_NAME_FIELD] && ( - - )} - - - + + {/* Service highlight */} + + {formattedDoc[constants.SERVICE_NAME_FIELD] && ( + + } + label={flyoutServiceLabel} + value={flattenedDoc[constants.SERVICE_NAME_FIELD]} + width={fieldWidth} + /> + )} + {formattedDoc[constants.TRACE_ID_FIELD] && ( + + )} + + {/* Infrastructure highlight */} + + {formattedDoc[constants.HOST_NAME_FIELD] && ( + + )} + {formattedDoc[constants.ORCHESTRATOR_CLUSTER_NAME_FIELD] && ( + + )} + {formattedDoc[constants.ORCHESTRATOR_RESOURCE_ID_FIELD] && ( + + )} + + {/* Cloud highlight */} + + {formattedDoc[constants.CLOUD_PROVIDER_FIELD] && ( + + } + label={flyoutCloudProviderLabel} + value={flattenedDoc[constants.CLOUD_PROVIDER_FIELD]} + width={fieldWidth} + /> + )} + {formattedDoc[constants.CLOUD_REGION_FIELD] && ( + + )} + {formattedDoc[constants.CLOUD_AVAILABILITY_ZONE_FIELD] && ( + + )} + {formattedDoc[constants.CLOUD_PROJECT_ID_FIELD] && ( + + )} + {formattedDoc[constants.CLOUD_INSTANCE_ID_FIELD] && ( + + )} + + {/* Other highlights */} + + {formattedDoc[constants.LOG_FILE_PATH_FIELD] && ( + + )} + {formattedDoc[constants.DATASTREAM_NAMESPACE_FIELD] && ( + + )} + {formattedDoc[constants.DATASTREAM_DATASET_FIELD] && ( + + )} + {formattedDoc[constants.AGENT_NAME_FIELD] && ( + + )} + + ); } diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/highlight_field.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/highlight_field.tsx index d6c8d81030b5b..8d3368bfd8e33 100644 --- a/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/highlight_field.tsx +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/highlight_field.tsx @@ -5,18 +5,10 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiText, copyToClipboard, EuiTextTruncate } from '@elastic/eui'; -import React, { ReactNode, useMemo, useState } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTextTruncate } from '@elastic/eui'; +import React, { ReactNode } from 'react'; import { ValuesType } from 'utility-types'; -import { - flyoutHoverActionFilterForText, - flyoutHoverActionFilterOutText, - flyoutHoverActionFilterForFieldPresentText, - flyoutHoverActionToggleColumnText, - flyoutHoverActionCopyToClipboardText, -} from '../translations'; -import { useDiscoverActionsContext } from '../../../hooks/use_discover_action'; -import { HoverActionPopover, HoverActionType } from './hover_popover_action'; +import { HoverActionPopover } from './hover_popover_action'; import { LogDocument } from '../types'; interface HighlightFieldProps { @@ -37,61 +29,6 @@ export function HighlightField({ width, ...props }: HighlightFieldProps) { - const filterForText = flyoutHoverActionFilterForText(value); - const filterOutText = flyoutHoverActionFilterOutText(value); - const actions = useDiscoverActionsContext(); - const [columnAdded, setColumnAdded] = useState(false); - - const hoverActions: HoverActionType[] = useMemo( - () => [ - { - id: 'addToFilterAction', - tooltipContent: filterForText, - iconType: 'plusInCircle', - onClick: () => actions?.addFilter && actions.addFilter(field, value, '+'), - display: true, - }, - { - id: 'removeFromFilterAction', - tooltipContent: filterOutText, - iconType: 'minusInCircle', - onClick: () => actions?.addFilter && actions.addFilter(field, value, '-'), - display: true, - }, - { - id: 'filterForFieldPresentAction', - tooltipContent: flyoutHoverActionFilterForFieldPresentText, - iconType: 'filter', - onClick: () => actions?.addFilter && actions.addFilter('_exists_', field, '+'), - display: true, - }, - { - id: 'toggleColumnAction', - tooltipContent: flyoutHoverActionToggleColumnText, - iconType: 'listAdd', - onClick: () => { - if (actions) { - if (columnAdded) { - actions?.removeColumn?.(field); - } else { - actions?.addColumn?.(field); - } - setColumnAdded(!columnAdded); - } - }, - display: true, - }, - { - id: 'copyToClipboardAction', - tooltipContent: flyoutHoverActionCopyToClipboardText, - iconType: 'copyClipboard', - onClick: () => copyToClipboard(value as string), - display: true, - }, - ], - [filterForText, filterOutText, actions, field, value, columnAdded] - ); - return formattedValue ? ( @@ -100,7 +37,7 @@ export function HighlightField({ - + void; - display: boolean; -} +import { ValuesType } from 'utility-types'; +import { useHoverActions } from '../../../hooks/use_hover_actions'; +import { LogDocument } from '..'; interface HoverPopoverActionProps { children: React.ReactChild; - actions: HoverActionType[]; - title: string; + field: string; + value: ValuesType; + title?: string; + anchorPosition?: PopoverAnchorPosition; } -export const HoverActionPopover = ({ children, actions, title }: HoverPopoverActionProps) => { +export const HoverActionPopover = ({ + children, + title, + field, + value, + anchorPosition = 'upCenter', +}: HoverPopoverActionProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const leaveTimer = useRef(null); + const hoverActions = useHoverActions({ field, value }); // The timeout hack is required because we are using a Popover which ideally should be used with a mouseclick, // but we are using it as a Tooltip. Which means we now need to manually handle the open and close @@ -53,15 +57,17 @@ export const HoverActionPopover = ({ children, actions, title }: HoverPopoverAct - - {title} - + {title && ( + + {title} + + )} - {actions.map((action) => ( + {hoverActions.map((action) => ( ; +} + +export interface HoverActionType { + id: string; + tooltipContent: string; + iconType: IconType; + onClick: () => void; + display: boolean; +} + +export const useHoverActions = ({ field, value }: HoverActionProps): HoverActionType[] => { + const filterForText = flyoutHoverActionFilterForText(value); + const filterOutText = flyoutHoverActionFilterOutText(value); + const actions = useDiscoverActionsContext(); + const [columnAdded, setColumnAdded] = useState(false); + + return useMemo( + () => [ + { + id: 'addToFilterAction', + tooltipContent: filterForText, + iconType: 'plusInCircle', + onClick: () => actions?.addFilter && actions.addFilter(field, value, '+'), + display: true, + }, + { + id: 'removeFromFilterAction', + tooltipContent: filterOutText, + iconType: 'minusInCircle', + onClick: () => actions?.addFilter && actions.addFilter(field, value, '-'), + display: true, + }, + { + id: 'filterForFieldPresentAction', + tooltipContent: flyoutHoverActionFilterForFieldPresentText, + iconType: 'filter', + onClick: () => actions?.addFilter && actions.addFilter('_exists_', field, '+'), + display: true, + }, + { + id: 'toggleColumnAction', + tooltipContent: flyoutHoverActionToggleColumnText, + iconType: 'listAdd', + onClick: () => { + if (actions) { + if (columnAdded) { + actions?.removeColumn?.(field); + } else { + actions?.addColumn?.(field); + } + setColumnAdded(!columnAdded); + } + }, + display: true, + }, + { + id: 'copyToClipboardAction', + tooltipContent: flyoutHoverActionCopyToClipboardText, + iconType: 'copyClipboard', + onClick: () => copyToClipboard(value as string), + display: true, + }, + ], + [filterForText, filterOutText, actions, field, value, columnAdded] + ); +}; diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 4202032964e86..e24da30482d66 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -826,6 +826,14 @@ export function setTileState( newValue: tileErrors, }); + if (!isLayerGroup(layer) && layer.getSource().isESSource()) { + getInspectorAdapters(getState()).vectorTiles.setTileResults( + layerId, + tileMetaFeatures, + tileErrors + ); + } + if (!tileMetaFeatures && !layer.getDescriptor().__tileMetaFeatures) { return; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 70cdc8ace4cf1..1031faaf06963 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import type { Map as MbMap } from '@kbn/mapbox-gl'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import type { Query } from '@kbn/es-query'; import { getWarningsTitle, @@ -46,6 +47,7 @@ import { IStyle } from '../styles/style'; import { LICENSED_FEATURES } from '../../licensed_features'; import { IESSource } from '../sources/es_source'; import { TileErrorsList } from './tile_errors_list'; +import { isLayerGroup } from './layer_group'; export const INCOMPLETE_RESULTS_WARNING = i18n.translate( 'xpack.maps.layer.incompleteResultsWarning', @@ -90,7 +92,7 @@ export interface ILayer { isLayerLoading(zoom: number): boolean; isFilteredByGlobalTime(): Promise; hasErrors(): boolean; - getErrors(): LayerMessage[]; + getErrors(inspectorAdapters: Adapters): LayerMessage[]; hasWarnings(): boolean; getWarnings(): LayerMessage[]; @@ -411,7 +413,8 @@ export class AbstractLayer implements ILayer { } hasErrors(): boolean { - return this.getErrors().length > 0; + const inspectorAdapters = {}; // errors are not interacted with so empty Adapters can be passed to getErrors + return this.getErrors(inspectorAdapters).length > 0; } _getSourceErrorTitle() { @@ -420,7 +423,7 @@ export class AbstractLayer implements ILayer { }); } - getErrors(): LayerMessage[] { + getErrors(inspectorAdapters: Adapters): LayerMessage[] { const errors: LayerMessage[] = []; const sourceError = this.getSourceDataRequest()?.renderError(); @@ -436,7 +439,14 @@ export class AbstractLayer implements ILayer { title: i18n.translate('xpack.maps.layer.tileErrorTitle', { defaultMessage: `An error occurred when loading layer tiles`, }), - body: , + body: ( + + ), }); } diff --git a/x-pack/plugins/maps/public/classes/layers/tile_errors_list.tsx b/x-pack/plugins/maps/public/classes/layers/tile_errors_list.tsx index 40a427dd29837..38bb078cd98d0 100644 --- a/x-pack/plugins/maps/public/classes/layers/tile_errors_list.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tile_errors_list.tsx @@ -6,11 +6,17 @@ */ import React, { useEffect, useState } from 'react'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { i18n } from '@kbn/i18n'; -import { EuiButtonEmpty, EuiContextMenu, EuiPopover } from '@elastic/eui'; +import { EuiButton, EuiButtonEmpty, EuiCodeBlock, EuiContextMenu, EuiPopover } from '@elastic/eui'; import type { TileError } from '../../../common/descriptor_types'; +import { getInspector } from '../../kibana_services'; +import { RESPONSE_VIEW_ID } from '../../inspector/vector_tile_adapter/components/vector_tile_inspector'; interface Props { + inspectorAdapters: Adapters; + isESSource: boolean; + layerId: string; tileErrors: TileError[]; } @@ -75,7 +81,28 @@ export function TileErrorsList(props: Props) { > -

{getDescription(selectedTileError)}

+ + {getDescription(selectedTileError)} + + {props.isESSource && ( + { + getInspector().open(props.inspectorAdapters, { + options: { + initialLayerId: props.layerId, + initialTileKey: selectedTileError?.tileKey, + initialTab: [RESPONSE_VIEW_ID], + }, + }); + }} + size="s" + > + {i18n.translate('xpack.maps.tileError.viewDetailsButtonLabel', { + defaultMessage: 'View details', + })} + + )} ); } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx index dfcdeecb42430..4d41807f511d0 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx @@ -7,6 +7,7 @@ import _ from 'lodash'; import React from 'react'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { i18n } from '@kbn/i18n'; import { EuiIcon } from '@elastic/eui'; import { Feature, FeatureCollection } from 'geojson'; @@ -157,8 +158,8 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { ); } - getErrors(): LayerMessage[] { - const errors = super.getErrors(); + getErrors(inspectorAdapters: Adapters): LayerMessage[] { + const errors = super.getErrors(inspectorAdapters); this.getValidJoins().forEach((join) => { const joinDescriptor = join.toDescriptor(); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 0d60b2dc1b6bd..fa246f899639c 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { v4 as uuidv4 } from 'uuid'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { asyncForEach } from '@kbn/std'; import type { FilterSpecification, Map as MbMap, LayerSpecification } from '@kbn/mapbox-gl'; import type { KibanaExecutionContext } from '@kbn/core/public'; @@ -274,8 +275,8 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { }); } - getErrors(): LayerMessage[] { - const errors = super.getErrors(); + getErrors(inspectorAdapters: Adapters): LayerMessage[] { + const errors = super.getErrors(inspectorAdapters); this.getValidJoins().forEach((join) => { const joinDataRequest = this.getDataRequest(join.getSourceDataRequestId()); diff --git a/x-pack/plugins/maps/public/classes/sources/source_registry.ts b/x-pack/plugins/maps/public/classes/sources/source_registry.ts index f1dd02148cd19..970e5a9e17fe2 100644 --- a/x-pack/plugins/maps/public/classes/sources/source_registry.ts +++ b/x-pack/plugins/maps/public/classes/sources/source_registry.ts @@ -7,13 +7,11 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import type { ISource } from './source'; export type SourceRegistryEntry = { ConstructorFunction: new ( - sourceDescriptor: any, // this is the source-descriptor that corresponds specifically to the particular ISource instance - inspectorAdapters?: Adapters + sourceDescriptor: any // this is the source-descriptor that corresponds specifically to the particular ISource instance ) => ISource; type: string; }; diff --git a/x-pack/plugins/maps/public/classes/util/data_request.tsx b/x-pack/plugins/maps/public/classes/util/data_request.tsx index 3cb493f138441..62fd17cc44277 100644 --- a/x-pack/plugins/maps/public/classes/util/data_request.tsx +++ b/x-pack/plugins/maps/public/classes/util/data_request.tsx @@ -8,7 +8,7 @@ /* eslint-disable max-classes-per-file */ import React, { ReactNode } from 'react'; -import { getSearchErrorOverrideDisplay } from '@kbn/data-plugin/public'; +import { renderSearchError } from '@kbn/search-errors'; import { getApplication } from '../../kibana_services'; import type { DataRequestDescriptor, DataRequestMeta } from '../../../common/descriptor_types'; @@ -60,21 +60,21 @@ export class DataRequest { return null; } - const overrideDisplay = getSearchErrorOverrideDisplay({ + const searchErrorDisplay = renderSearchError({ error: this._descriptor.error, application: getApplication(), }); - const body = overrideDisplay?.body ? ( - overrideDisplay.body + const body = searchErrorDisplay?.body ? ( + searchErrorDisplay.body ) : (

{this._descriptor.error.message}

); - return overrideDisplay?.actions ? ( + return searchErrorDisplay?.actions ? ( <> {body} - {overrideDisplay.actions} + {searchErrorDisplay.actions} ) : ( body diff --git a/x-pack/plugins/maps/public/classes/util/geo_tile_utils.ts b/x-pack/plugins/maps/public/classes/util/geo_tile_utils.ts index 32343e7275841..5ed8bc64f600f 100644 --- a/x-pack/plugins/maps/public/classes/util/geo_tile_utils.ts +++ b/x-pack/plugins/maps/public/classes/util/geo_tile_utils.ts @@ -174,3 +174,13 @@ export function expandToTileBoundaries(extent: MapExtent, zoom: number): MapExte maxLat: tileToLatitude(upperLeftY, tileCount), }; } + +export function isPointInTile(lat: number, lon: number, x: number, y: number, z: number) { + const tileCount = getTileCount(z); + const lonX = longitudeToTile(lon, tileCount); + if (lonX !== x) { + return false; + } + const latY = latitudeToTile(lat, tileCount); + return latY === y; +} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap index f770aeed87494..63edb4bff381c 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap @@ -479,6 +479,7 @@ exports[`TOCEntry props should display layer details when isLegendDetailsOpen is data-test-subj="mapLayerTOCDetailslayer_1" > { } as unknown as ILayer; test('Should only render errors when layer contains errors', () => { - render(); + render(); screen.getByTestId('layer-error'); const error = screen.queryByTestId('layer-error'); expect(error).not.toBeNull(); @@ -47,6 +47,7 @@ describe('LegendDetails', () => { test('Should render warnings and legend when layer contains warnings', () => { render( { diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx index 1561d47aa4945..3f9e5c8f11627 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx @@ -6,15 +6,17 @@ */ import React from 'react'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import type { ILayer } from '../../../../../classes/layers/layer'; interface Props { + inspectorAdapters: Adapters; layer: ILayer; } -export function LegendDetails({ layer }: Props) { - const errors = layer.getErrors(); +export function LegendDetails({ inspectorAdapters, layer }: Props) { + const errors = layer.getErrors(inspectorAdapters); if (errors.length) { return ( <> diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.test.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.test.tsx index 76fe008efbc73..81c7933fe4f72 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.test.tsx @@ -63,6 +63,7 @@ const mockLayer = { const defaultProps = { depth: 0, + inspectorAdapters: {}, layer: mockLayer, selectedLayer: undefined, openLayerPanel: async () => {}, diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx index 488f9a64083db..1798d063d4243 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx @@ -8,6 +8,7 @@ import React, { Component } from 'react'; import classNames from 'classnames'; import type { DraggableProvidedDragHandleProps } from '@hello-pangea/dnd'; +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiIcon, EuiButtonIcon, EuiConfirmModal, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -27,6 +28,7 @@ function escapeLayerName(name: string) { } export interface ReduxStateProps { + inspectorAdapters: Adapters; isReadOnly: boolean; zoom: number; selectedLayer: ILayer | undefined; @@ -337,7 +339,10 @@ export class TOCEntry extends Component { className="mapTocEntry__layerDetails" data-test-subj={`mapLayerTOCDetails${escapeLayerName(this.state.displayName)}`} > - +
) : null} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/index.ts b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/index.ts index b1f835648dfca..7b318619d84f7 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/index.ts +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/index.ts @@ -8,10 +8,12 @@ import { connect } from 'react-redux'; import { MapStoreState } from '../../../../../../reducers/store'; import { getMapZoom, isUsingSearch } from '../../../../../../selectors/map_selectors'; +import { getInspectorAdapters } from '../../../../../../reducers/non_serializable_instances'; import { TOCEntryButton, ReduxStateProps, OwnProps } from './toc_entry_button'; function mapStateToProps(state: MapStoreState, ownProps: OwnProps): ReduxStateProps { return { + inspectorAdapters: getInspectorAdapters(state), isUsingSearch: isUsingSearch(state), zoom: getMapZoom(state), }; diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx index ba832f2aa3210..1fa4b8c916f69 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx @@ -6,7 +6,7 @@ */ import React, { Component, Fragment, ReactNode } from 'react'; - +import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { EuiButtonEmpty, EuiIcon, EuiToolTip, EuiLoadingSpinner } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { type ILayer, INCOMPLETE_RESULTS_WARNING } from '../../../../../../classes/layers/layer'; @@ -19,6 +19,7 @@ interface Footnote { } export interface ReduxStateProps { + inspectorAdapters: Adapters; isUsingSearch: boolean; zoom: number; } @@ -69,7 +70,7 @@ export class TOCEntryButton extends Component { footnotes: Footnote[]; postScript?: string; } { - const errors = this.props.layer.getErrors(); + const errors = this.props.layer.getErrors(this.props.inspectorAdapters); if (errors.length) { const errorIcon = ( { : { icon: errorIcon, tooltipContent: this.props.layer - .getErrors() + .getErrors(this.props.inspectorAdapters) .map(({ title }) =>
{title}
), footnotes: [], }; diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.test.tsx b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.test.tsx new file mode 100644 index 0000000000000..6d3e78bbe2aaf --- /dev/null +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.test.tsx @@ -0,0 +1,83 @@ +/* + * 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. + */ + +jest.mock('./tile_request_tab', () => ({ + TileRequestTab: () => { + return
mockTileRequestTab
; + }, +})); + +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import VectorTileInspector, { RESPONSE_VIEW_ID } from './vector_tile_inspector'; +import { VectorTileAdapter } from '../vector_tile_adapter'; + +describe('VectorTileInspector', () => { + let vectorTileAdapter: VectorTileAdapter | undefined; + beforeEach(() => { + vectorTileAdapter = new VectorTileAdapter(); + vectorTileAdapter.addLayer( + 'layer1', + 'layer1 label', + '/pof/internal/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&hasLabels=false&buffer=7&index=kibana_sample_data_logs&gridPrecision=8&requestBody=()&renderAs=heatmap&token=1' + ); + vectorTileAdapter.addLayer( + 'layer2', + 'layer2 label', + '/pof/internal/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&hasLabels=false&buffer=7&index=kibana_sample_data_logs&gridPrecision=8&requestBody=()&renderAs=heatmap&token=1' + ); + vectorTileAdapter.setTiles([ + { + x: 0, + y: 0, + z: 1, + }, + { + x: 1, + y: 0, + z: 1, + }, + { + x: 0, + y: 1, + z: 1, + }, + { + x: 1, + y: 1, + z: 1, + }, + ]); + }); + + test('should show first layer, first tile, and request tab when options not provided', () => { + render( + + ); + screen.getByText('layer1 label'); + screen.getByText('1/0/0'); + screen.getByText('mockTileRequestTab'); + }); + + test('should show layer, tile, and tab specified by options', () => { + const options = { + initialLayerId: 'layer2', + initialTileKey: '1/1/1', + initialTab: RESPONSE_VIEW_ID, + }; + render( + + ); + screen.getByText('layer2 label'); + screen.getByText('1/1/1'); + screen.getByText('Not available'); // response is not available because tileMetaFeature or tileError where not provided + }); +}); diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.tsx b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.tsx index 9a9356ad1a6d2..32f16f0f18346 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.tsx +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/vector_tile_inspector.tsx @@ -8,33 +8,56 @@ import _ from 'lodash'; import React, { Component } from 'react'; import { i18n } from '@kbn/i18n'; -import type { Adapters } from '@kbn/inspector-plugin/public'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiSpacer, EuiTabs, EuiTab } from '@elastic/eui'; +import type { InspectorViewProps } from '@kbn/inspector-plugin/public'; +import { XJsonLang } from '@kbn/monaco'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormRow, + EuiSpacer, + EuiTabs, + EuiTab, + EuiText, +} from '@elastic/eui'; +import { CodeEditor } from '@kbn/kibana-react-plugin/public'; import { EmptyPrompt } from './empty_prompt'; import type { TileRequest } from '../types'; import { TileRequestTab } from './tile_request_tab'; import { RequestsViewCallout } from './requests_view_callout'; -interface Props { - adapters: Adapters; +const REQUEST_VIEW_ID = 'request_view'; +export const RESPONSE_VIEW_ID = 'response_view'; + +interface Options { + initialLayerId?: string; + initialTileKey?: string; + initialTab?: typeof REQUEST_VIEW_ID | typeof RESPONSE_VIEW_ID; } interface State { selectedLayer: EuiComboBoxOptionOption | null; selectedTileRequest: TileRequest | null; + selectedView: typeof REQUEST_VIEW_ID | typeof RESPONSE_VIEW_ID; tileRequests: TileRequest[]; layerOptions: Array>; } -class VectorTileInspector extends Component { +class VectorTileInspector extends Component { private _isMounted = false; - state: State = { - selectedLayer: null, - selectedTileRequest: null, - tileRequests: [], - layerOptions: [], - }; + constructor(props: InspectorViewProps) { + super(props); + this.state = { + selectedLayer: null, + selectedTileRequest: null, + selectedView: + props.options && (props.options as Options).initialTab + ? (props.options as Options).initialTab! + : REQUEST_VIEW_ID, + tileRequests: [], + layerOptions: [], + }; + } componentDidMount() { this._isMounted = true; @@ -47,6 +70,62 @@ class VectorTileInspector extends Component { this.props.adapters.vectorTiles.removeListener('change', this._debouncedOnAdapterChange); } + _getDefaultLayer(layerOptions: Array>) { + if ( + this.state.selectedLayer && + layerOptions.some((layerOption) => { + return this.state.selectedLayer?.value === layerOption.value; + }) + ) { + return this.state.selectedLayer; + } + + if (this.props.options && (this.props.options as Options).initialLayerId) { + const initialLayer = layerOptions.find((layerOption) => { + return (this.props.options as Options).initialLayerId === layerOption.value; + }); + if (initialLayer) { + return initialLayer; + } + } + + return layerOptions[0]; + } + + _getDefaultTileRequest(tileRequests: TileRequest[]) { + if ( + this.state.selectedTileRequest && + tileRequests.some((tileRequest: TileRequest) => { + return ( + this.state.selectedTileRequest?.layerId === tileRequest.layerId && + this.state.selectedTileRequest?.x === tileRequest.x && + this.state.selectedTileRequest?.y === tileRequest.y && + this.state.selectedTileRequest?.z === tileRequest.z + ); + }) + ) { + return this.state.selectedTileRequest; + } + + if (tileRequests.length === 0) { + return null; + } + + if (this.props.options && (this.props.options as Options).initialTileKey) { + const initialTileRequest = tileRequests.find((tileRequest) => { + return ( + (this.props.options as Options).initialTileKey === + `${tileRequest.z}/${tileRequest.x}/${tileRequest.y}` + ); + }); + if (initialTileRequest) { + return initialTileRequest; + } + } + + return tileRequests[0]; + } + _onAdapterChange = () => { const layerOptions = this.props.adapters.vectorTiles.getLayerOptions() as Array< EuiComboBoxOptionOption @@ -61,32 +140,11 @@ class VectorTileInspector extends Component { return; } - const selectedLayer = - this.state.selectedLayer && - layerOptions.some((layerOption) => { - return this.state.selectedLayer?.value === layerOption.value; - }) - ? this.state.selectedLayer - : layerOptions[0]; + const selectedLayer = this._getDefaultLayer(layerOptions); const tileRequests = this.props.adapters.vectorTiles.getTileRequests(selectedLayer.value); - const selectedTileRequest = - this.state.selectedTileRequest && - tileRequests.some((tileRequest: TileRequest) => { - return ( - this.state.selectedTileRequest?.layerId === tileRequest.layerId && - this.state.selectedTileRequest?.x === tileRequest.x && - this.state.selectedTileRequest?.y === tileRequest.y && - this.state.selectedTileRequest?.z === tileRequest.z - ); - }) - ? this.state.selectedTileRequest - : tileRequests.length - ? tileRequests[0] - : null; - this.setState({ selectedLayer, - selectedTileRequest, + selectedTileRequest: this._getDefaultTileRequest(tileRequests), tileRequests, layerOptions, }); @@ -117,26 +175,60 @@ class VectorTileInspector extends Component { }); }; - renderTabs() { - return this.state.tileRequests.map((tileRequest) => { - const tileLabel = `${tileRequest.z}/${tileRequest.x}/${tileRequest.y}`; + _onTileSelect = (selectedOptions: Array>) => { + if (selectedOptions.length === 0) { + this.setState({ selectedTileRequest: null }); + return; + } + + this.setState({ + selectedTileRequest: selectedOptions[0].value ? selectedOptions[0].value : null, + }); + }; + + _renderTileRequest() { + if (!this.state.selectedTileRequest) { + return null; + } + + if (this.state.selectedView === REQUEST_VIEW_ID) { return ( - { - this.setState({ selectedTileRequest: tileRequest }); - }} - isSelected={ - tileRequest.layerId === this.state.selectedTileRequest?.layerId && - tileRequest.x === this.state.selectedTileRequest?.x && - tileRequest.y === this.state.selectedTileRequest?.y && - tileRequest.z === this.state.selectedTileRequest?.z - } - > - {tileLabel} - + ); - }); + } + + const tileResponse = getTileResponse(this.state.selectedTileRequest); + + return tileResponse ? ( + + ) : ( + +

+ {i18n.translate('xpack.maps.inspector.vectorTile.tileMetaFeatureNotAvailable', { + defaultMessage: 'Not available', + })} +

+
+ ); } render() { @@ -148,31 +240,102 @@ class VectorTileInspector extends Component { ) : ( <> + - - - {this.renderTabs()} - - {this.state.selectedTileRequest && ( - + - )} + + + + { + return { + label: `${tileRequest.z}/${tileRequest.x}/${tileRequest.y}`, + value: tileRequest, + }; + })} + selectedOptions={ + this.state.selectedTileRequest + ? [ + { + label: `${this.state.selectedTileRequest.z}/${this.state.selectedTileRequest.x}/${this.state.selectedTileRequest.y}`, + value: this.state.selectedTileRequest, + }, + ] + : [] + } + onChange={this._onTileSelect} + isClearable={false} + /> + + + + <> + { + this.setState({ selectedView: REQUEST_VIEW_ID }); + }} + isSelected={this.state.selectedView === REQUEST_VIEW_ID} + > + {i18n.translate('xpack.maps.inspector.vectorTile.requestTabLabel', { + defaultMessage: 'Request', + })} + + { + this.setState({ selectedView: RESPONSE_VIEW_ID }); + }} + isSelected={this.state.selectedView === RESPONSE_VIEW_ID} + > + {i18n.translate('xpack.maps.inspector.vectorTile.responseTabLabel', { + defaultMessage: 'Response', + })} + + + + + {this._renderTileRequest()} ); } } +function getTileResponse(tileRequest: TileRequest) { + if (tileRequest.tileError) { + return { + error: tileRequest.tileError.error + ? tileRequest.tileError.error + : tileRequest.tileError.message, + }; + } + + return tileRequest.tileMetaFeature + ? { + meta: tileRequest.tileMetaFeature.properties, + } + : undefined; +} + // default export required for React.Lazy // eslint-disable-next-line import/no-default-export export default VectorTileInspector; diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/types.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/types.ts index 5fead09165fad..1d25a52bfb6ad 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/types.ts +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/types.ts @@ -5,9 +5,13 @@ * 2.0. */ +import type { TileError, TileMetaFeature } from '../../../common/descriptor_types'; + export interface TileRequest { layerId: string; tileUrl: string; + tileError?: TileError; + tileMetaFeature?: TileMetaFeature; x: number; y: number; z: number; diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.test.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.test.ts new file mode 100644 index 0000000000000..5daad610d323d --- /dev/null +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.test.ts @@ -0,0 +1,73 @@ +/* + * 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 { TileMetaFeature } from '../../../common/descriptor_types'; +import { getTileError, getTileMetaFeature } from './vector_tile_adapter'; + +describe('getTileError', () => { + test('should find tileError for tile', () => { + const tileErrors = [ + { + message: 'simulated failure 1', + tileKey: '1/0/0', + }, + { + message: 'simulated failure 2', + tileKey: '1/1/0', + }, + ]; + const tileError = getTileError(0, 0, 1, tileErrors); + expect(tileError).not.toBeUndefined(); + expect(tileError!.message).toBe('simulated failure 1'); + }); +}); + +describe('getTileMetaFeature', () => { + test('should find tileMetaFeature for tile', () => { + const tileMetaFeatures = [ + { + geometry: { + coordinates: [ + [ + [0, -85.05112877980659], + [0, 0], + [180, 0], + [180, -85.05112877980659], + [0, -85.05112877980659], + ], + ], + type: 'Polygon', + }, + properties: { + 'hits.total.value': 0, + }, + type: 'Feature', + } as TileMetaFeature, + { + geometry: { + coordinates: [ + [ + [-180, 0], + [-180, 85.05112877980659], + [0, 85.05112877980659], + [0, 0], + [-180, 0], + ], + ], + type: 'Polygon', + }, + properties: { + 'hits.total.value': 182, + }, + type: 'Feature', + } as TileMetaFeature, + ]; + const tileMetaFeature = getTileMetaFeature(0, 0, 1, tileMetaFeatures); + expect(tileMetaFeature).not.toBeUndefined(); + expect(tileMetaFeature!.properties['hits.total.value']).toBe(182); + }); +}); diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.ts index 51a12368d6ad4..05f256bd67e33 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.ts +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_adapter.ts @@ -5,33 +5,62 @@ * 2.0. */ +// @ts-expect-error +import turfCenterOfMass from '@turf/center-of-mass'; import { EventEmitter } from 'events'; +import { LAT_INDEX, LON_INDEX } from '../../../common/constants'; +import type { TileError, TileMetaFeature } from '../../../common/descriptor_types'; import { TileRequest } from './types'; +import { isPointInTile } from '../../classes/util/geo_tile_utils'; + +interface LayerState { + label: string; + tileErrors?: TileError[]; + tileMetaFeatures?: TileMetaFeature[]; + tileUrl: string; +} export class VectorTileAdapter extends EventEmitter { - private _layers: Record = {}; + private _layers: Record = {}; private _tiles: Array<{ x: number; y: number; z: number }> = []; - addLayer(layerId: string, label: string, tileUrl: string) { + public addLayer(layerId: string, label: string, tileUrl: string) { this._layers[layerId] = { label, tileUrl }; this._onChange(); } - removeLayer(layerId: string) { + public removeLayer(layerId: string) { delete this._layers[layerId]; this._onChange(); } - hasLayers() { + public hasLayers() { return Object.keys(this._layers).length > 0; } - setTiles(tiles: Array<{ x: number; y: number; z: number }>) { + public setTiles(tiles: Array<{ x: number; y: number; z: number }>) { this._tiles = tiles; this._onChange(); } - getLayerOptions(): Array<{ value: string; label: string }> { + public setTileResults( + layerId: string, + tileMetaFeatures?: TileMetaFeature[], + tileErrors?: TileError[] + ) { + if (!this._layers[layerId]) { + return; + } + + this._layers[layerId] = { + ...this._layers[layerId], + tileErrors, + tileMetaFeatures, + }; + this._onChange(); + } + + public getLayerOptions(): Array<{ value: string; label: string }> { return Object.keys(this._layers).map((layerId) => { return { value: layerId, @@ -40,22 +69,58 @@ export class VectorTileAdapter extends EventEmitter { }); } - getTileRequests(layerId: string): TileRequest[] { + public getTileRequests(layerId: string): TileRequest[] { if (!this._layers[layerId]) { return []; } - const { tileUrl } = this._layers[layerId]; + const { tileErrors, tileMetaFeatures, tileUrl } = this._layers[layerId]; return this._tiles.map((tile) => { return { layerId, tileUrl, + tileError: getTileError(tile.x, tile.y, tile.z, tileErrors), + tileMetaFeature: getTileMetaFeature(tile.x, tile.y, tile.z, tileMetaFeatures), ...tile, }; }); } - _onChange() { + private _onChange() { this.emit('change'); } } + +export function getTileMetaFeature( + x: number, + y: number, + z: number, + tileMetaFeatures?: TileMetaFeature[] +) { + if (!tileMetaFeatures || tileMetaFeatures.length === 0) { + return; + } + + return tileMetaFeatures.find((tileMetaFeature) => { + const centerGeometry = turfCenterOfMass(tileMetaFeature).geometry; + return isPointInTile( + centerGeometry.coordinates[LAT_INDEX], + centerGeometry.coordinates[LON_INDEX], + x, + y, + z + ); + }); +} + +export function getTileError(x: number, y: number, z: number, tileErrors?: TileError[]) { + if (!tileErrors || tileErrors.length === 0) { + return; + } + + const tileKey = `${z}/${x}/${y}`; + + return tileErrors.find((tileError) => { + return tileError.tileKey === tileKey; + }); +} diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_inspector_view.tsx b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_inspector_view.tsx index 560b2789d5a74..ffae36cafba0f 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_inspector_view.tsx +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/vector_tile_inspector_view.tsx @@ -6,7 +6,7 @@ */ import React, { lazy } from 'react'; -import type { Adapters } from '@kbn/inspector-plugin/public'; +import type { Adapters, InspectorViewProps } from '@kbn/inspector-plugin/public'; import { i18n } from '@kbn/i18n'; import { LazyWrapper } from '../../lazy_wrapper'; @@ -25,7 +25,7 @@ export const VectorTileInspectorView = { shouldShow(adapters: Adapters) { return Boolean(adapters.vectorTiles?.hasLayers()); }, - component: (props: { adapters: Adapters }) => { + component: (props: InspectorViewProps) => { return ; }, }; diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json index a8a75988ba5b1..d2972dcd3e6f3 100644 --- a/x-pack/plugins/maps/tsconfig.json +++ b/x-pack/plugins/maps/tsconfig.json @@ -74,6 +74,7 @@ "@kbn/content-management-table-list-view", "@kbn/serverless", "@kbn/logging", + "@kbn/search-errors", "@kbn/search-response-warnings", "@kbn/calculate-width-from-char-count", "@kbn/content-management-table-list-view-common", diff --git a/x-pack/plugins/observability/common/field_names/slo.ts b/x-pack/plugins/observability/common/field_names/slo.ts index 2b93accf03d8e..d397cc56e5ac6 100644 --- a/x-pack/plugins/observability/common/field_names/slo.ts +++ b/x-pack/plugins/observability/common/field_names/slo.ts @@ -8,3 +8,5 @@ export const SLO_ID_FIELD = 'slo.id'; export const SLO_REVISION_FIELD = 'slo.revision'; export const SLO_INSTANCE_ID_FIELD = 'slo.instanceId'; + +export const SLO_BURN_RATE_AAD_FIELDS = [SLO_ID_FIELD, SLO_REVISION_FIELD, SLO_INSTANCE_ID_FIELD]; diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx index eb7da89d3441d..3b385fee702f5 100644 --- a/x-pack/plugins/observability/public/application/application.test.tsx +++ b/x-pack/plugins/observability/public/application/application.test.tsx @@ -77,7 +77,6 @@ describe('renderApp', () => { const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx b/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx index 756f90ecd97cf..f2a7a4d72d66f 100644 --- a/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx +++ b/x-pack/plugins/observability/public/pages/alert_details/alert_details.test.tsx @@ -90,7 +90,6 @@ const params = { const config: Subset = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx index 247a700acfa6c..cf59af003a788 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts.test.tsx @@ -53,12 +53,10 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ slo: { enabled: false }, alertDetails: { apm: { enabled: false }, - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, }, - thresholdRule: { enabled: false }, }, aiAssistant: { enabled: false, diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx index cbdb9aa068dad..b8e216ded52fb 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.test.tsx @@ -59,7 +59,6 @@ jest.mock('@kbn/triggers-actions-ui-plugin/public/common/lib/kibana/kibana_react const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.tsx index c8f9e422f10be..ca5bdff47bac1 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/alert_actions.tsx @@ -79,13 +79,13 @@ export function AlertActions({ const observabilityAlert = parseObservabilityAlert(alert); useEffect(() => { - const alertLink = alert.link as unknown as string; - if (!alert.hasBasePath) { + const alertLink = observabilityAlert.link as unknown as string; + if (!observabilityAlert.hasBasePath) { setViewInAppUrl(prepend(alertLink ?? '')); } else { setViewInAppUrl(alertLink); } - }, [alert.hasBasePath, alert.link, prepend]); + }, [observabilityAlert.hasBasePath, observabilityAlert.link, prepend]); const [isPopoverOpen, setIsPopoverOpen] = useState(false); diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx index 6da498042f8fb..23d3af1167b99 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.test.tsx @@ -48,7 +48,6 @@ describe('APMSection', () => { const config = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index d0937d1f2c72b..a1023f33f4313 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -81,12 +81,10 @@ const withCore = makeDecorator({ const config: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, }, - thresholdRule: { enabled: false }, }, }; diff --git a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx index 8be89be03d57b..6f18d308780ad 100644 --- a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx @@ -40,12 +40,10 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ slo: { enabled: false }, alertDetails: { apm: { enabled: false }, - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, }, - thresholdRule: { enabled: false }, }, }, observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(), diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 12848e1bb4974..57ef081903869 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -94,7 +94,7 @@ export interface ConfigSchema { metrics: { enabled: boolean; }; - logs: { + logs?: { enabled: boolean; }; uptime: { @@ -104,7 +104,7 @@ export interface ConfigSchema { enabled: boolean; }; }; - thresholdRule: { + thresholdRule?: { enabled: boolean; }; }; diff --git a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts index a1faec27f6c83..643d5ffd4f337 100644 --- a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts +++ b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts @@ -115,52 +115,49 @@ export const registerObservabilityRuleTypes = async ( priority: 100, }); - if (config.unsafe.thresholdRule.enabled) { - observabilityRuleTypeRegistry.register({ - id: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, - description: i18n.translate( - 'xpack.observability.customThreshold.rule.alertFlyout.alertDescription', - { - defaultMessage: - 'Alert when any Observability data type reaches or exceeds a given value.', - } - ), - iconClass: 'bell', - documentationUrl(docLinks) { - return `${docLinks.links.observability.customThreshold}`; - }, - ruleParamsExpression: lazy( - () => import('../components/custom_threshold/custom_threshold_rule_expression') - ), - validate: validateCustomThreshold, - defaultActionMessage: thresholdDefaultActionMessage, - defaultRecoveryMessage: thresholdDefaultRecoveryMessage, - requiresAppContext: false, - format: ({ fields }) => { - const searchConfiguration = fields[ALERT_RULE_PARAMETERS]?.searchConfiguration as - | SerializedSearchSourceFields - | undefined; - const criteria = fields[ALERT_RULE_PARAMETERS]?.criteria as MetricExpression[]; - const metrics: CustomThresholdExpressionMetric[] = - criteria.length === 1 ? criteria[0].metrics : []; - - const dataViewId = getDataViewId(searchConfiguration); - return { - reason: fields[ALERT_REASON] ?? '-', - link: getViewInAppUrl( - metrics, - fields[ALERT_START], - logExplorerLocator, - (searchConfiguration?.query as { query: string }).query, - dataViewId - ), - hasBasePath: true, - }; - }, - alertDetailsAppSection: lazy( - () => import('../components/custom_threshold/components/alert_details_app_section') - ), - priority: 5, - }); - } + observabilityRuleTypeRegistry.register({ + id: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, + description: i18n.translate( + 'xpack.observability.customThreshold.rule.alertFlyout.alertDescription', + { + defaultMessage: 'Alert when any Observability data type reaches or exceeds a given value.', + } + ), + iconClass: 'bell', + documentationUrl(docLinks) { + return `${docLinks.links.observability.customThreshold}`; + }, + ruleParamsExpression: lazy( + () => import('../components/custom_threshold/custom_threshold_rule_expression') + ), + validate: validateCustomThreshold, + defaultActionMessage: thresholdDefaultActionMessage, + defaultRecoveryMessage: thresholdDefaultRecoveryMessage, + requiresAppContext: false, + format: ({ fields }) => { + const searchConfiguration = fields[ALERT_RULE_PARAMETERS]?.searchConfiguration as + | SerializedSearchSourceFields + | undefined; + const criteria = fields[ALERT_RULE_PARAMETERS]?.criteria as MetricExpression[]; + const metrics: CustomThresholdExpressionMetric[] = + criteria.length === 1 ? criteria[0].metrics : []; + + const dataViewId = getDataViewId(searchConfiguration); + return { + reason: fields[ALERT_REASON] ?? '-', + link: getViewInAppUrl( + metrics, + fields[ALERT_START], + logExplorerLocator, + (searchConfiguration?.query as { query: string }).query, + dataViewId + ), + hasBasePath: true, + }; + }, + alertDetailsAppSection: lazy( + () => import('../components/custom_threshold/components/alert_details_app_section') + ), + priority: 5, + }); }; diff --git a/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.test.ts b/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.test.ts index ddef182541466..9aef93d6333a5 100644 --- a/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.test.ts +++ b/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.test.ts @@ -11,6 +11,13 @@ describe('formatAlertEvaluationValue', () => { it('returns - when there is no evaluationValue passed', () => { expect(formatAlertEvaluationValue('apm.transaction_error_rate', undefined)).toBe('-'); }); + it('returns - when there is null evaluationValue passed', () => { + // @ts-expect-error + expect(formatAlertEvaluationValue('apm.transaction_error_rate', null)).toBe('-'); + }); + it('returns the evaluation value when the value is 0', () => { + expect(formatAlertEvaluationValue('.es-query', 0)).toBe(0); + }); it('returns the evaluation value when ruleTypeId in unknown aka unformatted', () => { expect(formatAlertEvaluationValue('unknown.rule.type', 2000)).toBe(2000); }); diff --git a/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.ts b/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.ts index 92629934f2cea..7d0c5664568ec 100644 --- a/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.ts +++ b/x-pack/plugins/observability/public/utils/format_alert_evaluation_value.ts @@ -12,7 +12,7 @@ import { } from './get_alert_evaluation_unit_type_by_rule_type_id'; export const formatAlertEvaluationValue = (ruleTypeId?: string, evaluationValue?: number) => { - if (!evaluationValue || !ruleTypeId) return '-'; + if (null == evaluationValue || !ruleTypeId) return '-'; const unitType = getAlertEvaluationUnitTypeByRuleTypeId(ruleTypeId); switch (unitType) { case ALERT_EVALUATION_UNIT_TYPE.DURATION: diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts index a39c4cd00b576..101e10a314451 100644 --- a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts @@ -31,7 +31,6 @@ import type { TopAlert } from '../typings/alerts'; const defaultConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -63,15 +62,10 @@ describe('isAlertDetailsEnabled', () => { start: 1630587249674, lastUpdated: 1630588131750, } as unknown as TopAlert; - it('returns FALSE when logs: { enabled: false }', () => { - expect(isAlertDetailsEnabledPerApp(logsAlert, defaultConfig)).toBeFalsy(); - }); - - it('returns TRUE when logs: { enabled: true }', () => { + it('returns TRUE when rule type is logs.alert.document.count', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -113,7 +107,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, }, @@ -159,7 +152,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: true }, uptime: { enabled: false }, }, @@ -201,7 +193,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: true }, }, @@ -243,7 +234,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, @@ -255,7 +245,6 @@ describe('isAlertDetailsEnabled', () => { const updatedConfig = { unsafe: { alertDetails: { - logs: { enabled: true }, metrics: { enabled: true }, uptime: { enabled: true }, }, diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts index 15b9589be60f6..2b628f26ee794 100644 --- a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts @@ -9,12 +9,12 @@ import { ALERT_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import type { ConfigSchema } from '../plugin'; import type { TopAlert } from '../typings/alerts'; -const ALLOWED_RULE_TYPES = ['apm.transaction_duration']; +const ALLOWED_RULE_TYPES = ['apm.transaction_duration', 'logs.alert.document.count']; const isUnsafeAlertDetailsFlag = ( subject: string -): subject is keyof ConfigSchema['unsafe']['alertDetails'] => - ['uptime', 'logs', 'metrics', 'observability'].includes(subject); +): subject is keyof Omit => + ['uptime', 'metrics', 'observability'].includes(subject); // We are mapping the ruleTypeId from the feature flag with the ruleTypeId from the alert // to know whether the feature flag is enabled or not. diff --git a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx index d5714924bdc97..2051da5f43036 100644 --- a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx +++ b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx @@ -28,12 +28,10 @@ export function KibanaReactStorybookDecorator(Story: ComponentType) { const config: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, }, - thresholdRule: { enabled: false }, }, }; diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index 6c1610ac059c9..9428f887ed93c 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -32,12 +32,10 @@ export const data = dataPluginMock.createStartContract(); const defaultConfig: ConfigSchema = { unsafe: { alertDetails: { - logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, observability: { enabled: false }, }, - thresholdRule: { enabled: false }, }, }; diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index ce2279db23203..46e294f603227 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -36,8 +36,7 @@ const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), }), logs: schema.object({ - // Enable it by default: https://github.com/elastic/kibana/issues/159945 - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), }), uptime: schema.object({ enabled: schema.boolean({ defaultValue: false }), @@ -48,8 +47,8 @@ const configSchema = schema.object({ }), thresholdRule: schema.object({ enabled: offeringBasedSchema({ - serverless: schema.boolean({ defaultValue: true }), - traditional: schema.boolean({ defaultValue: true }), + serverless: schema.boolean({ defaultValue: false }), + traditional: schema.boolean({ defaultValue: false }), }), }), }), @@ -71,6 +70,10 @@ export const config: PluginConfigDescriptor = { }, }, schema: configSchema, + deprecations: ({ unused }) => [ + unused('unsafe.thresholdRule.enabled', { level: 'warning' }), + unused('unsafe.alertDetails.logs.enabled', { level: 'warning' }), + ], }; export type ObservabilityConfig = TypeOf; diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/constants.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/constants.ts index 084c039609899..f2f24232efe34 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/constants.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/constants.ts @@ -28,3 +28,12 @@ export const NO_DATA_ACTION = { } ), }; + +export const CUSTOM_THRESHOLD_AAD_FIELDS = [ + 'cloud.*', + 'host.*', + 'orchestrator.*', + 'container.*', + 'labels.*', + 'tags', +]; diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/register_custom_threshold_rule_type.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/register_custom_threshold_rule_type.ts index cf27867125cad..56dc9fd721e02 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/register_custom_threshold_rule_type.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/register_custom_threshold_rule_type.ts @@ -40,7 +40,7 @@ import { createCustomThresholdExecutor, CustomThresholdLocators, } from './custom_threshold_executor'; -import { FIRED_ACTION, NO_DATA_ACTION } from './constants'; +import { CUSTOM_THRESHOLD_AAD_FIELDS, FIRED_ACTION, NO_DATA_ACTION } from './constants'; import { ObservabilityConfig } from '../../..'; export const MetricsRulesTypeAlertDefinition: IRuleTypeAlerts = { @@ -110,6 +110,7 @@ export function thresholdRuleType( name: i18n.translate('xpack.observability.threshold.ruleName', { defaultMessage: 'Custom threshold (Beta)', }), + fieldsForAAD: CUSTOM_THRESHOLD_AAD_FIELDS, validate: { params: schema.object( { diff --git a/x-pack/plugins/observability/server/lib/rules/register_rule_types.ts b/x-pack/plugins/observability/server/lib/rules/register_rule_types.ts index c90ee35f86552..f705cf6416459 100644 --- a/x-pack/plugins/observability/server/lib/rules/register_rule_types.ts +++ b/x-pack/plugins/observability/server/lib/rules/register_rule_types.ts @@ -58,35 +58,32 @@ export function registerRuleTypes( sloBurnRateRuleType(createLifecycleRuleExecutorSLO, basePath, locators.alertsLocator) ); - // Threshold RULE - if (config.unsafe.thresholdRule.enabled) { - const ruleDataClientThreshold = ruleDataService.initializeIndex({ - feature: observabilityFeatureId, - registrationContext: THRESHOLD_RULE_REGISTRATION_CONTEXT, - dataset: Dataset.alerts, - componentTemplateRefs: [], - componentTemplates: [ - { - name: 'mappings', - mappings: mappingFromFieldMap({ ...legacyExperimentalFieldMap }, 'strict'), - }, - ], - }); + const ruleDataClientThreshold = ruleDataService.initializeIndex({ + feature: observabilityFeatureId, + registrationContext: THRESHOLD_RULE_REGISTRATION_CONTEXT, + dataset: Dataset.alerts, + componentTemplateRefs: [], + componentTemplates: [ + { + name: 'mappings', + mappings: mappingFromFieldMap({ ...legacyExperimentalFieldMap }, 'strict'), + }, + ], + }); - const createLifecycleRuleExecutorThreshold = createLifecycleExecutor( - logger.get('rules'), - ruleDataClientThreshold - ); + const createLifecycleRuleExecutorThreshold = createLifecycleExecutor( + logger.get('rules'), + ruleDataClientThreshold + ); - alertingPlugin.registerType( - thresholdRuleType( - createLifecycleRuleExecutorThreshold, - basePath, - config, - logger, - ruleDataClientThreshold, - locators - ) - ); - } + alertingPlugin.registerType( + thresholdRuleType( + createLifecycleRuleExecutorThreshold, + basePath, + config, + logger, + ruleDataClientThreshold, + locators + ) + ); } diff --git a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts index c454df48e485c..40873338d5e9f 100644 --- a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts +++ b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts @@ -14,6 +14,7 @@ import { createLifecycleExecutor } from '@kbn/rule-registry-plugin/server'; import { legacyExperimentalFieldMap } from '@kbn/alerts-as-data-utils'; import { IBasePath } from '@kbn/core/server'; import { LocatorPublic } from '@kbn/share-plugin/common'; +import { SLO_BURN_RATE_AAD_FIELDS } from '../../../../common/field_names/slo'; import { AlertsLocatorParams, observabilityPaths, sloFeatureId } from '../../../../common'; import { SLO_RULE_REGISTRATION_CONTEXT } from '../../../common/constants'; @@ -54,6 +55,7 @@ export function sloBurnRateRuleType( name: i18n.translate('xpack.observability.slo.rules.burnRate.name', { defaultMessage: 'SLO burn rate', }), + fieldsForAAD: SLO_BURN_RATE_AAD_FIELDS, validate: { params: schema.object({ sloId: schema.string(), diff --git a/x-pack/plugins/observability_ai_assistant/common/conversation_complete.ts b/x-pack/plugins/observability_ai_assistant/common/conversation_complete.ts new file mode 100644 index 0000000000000..f7e513efe3d01 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/conversation_complete.ts @@ -0,0 +1,109 @@ +/* + * 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. + */ +/* eslint-disable max-classes-per-file*/ +import { i18n } from '@kbn/i18n'; +import { Message } from './types'; + +export enum StreamingChatResponseEventType { + ChatCompletionChunk = 'chatCompletionChunk', + ConversationCreate = 'conversationCreate', + ConversationUpdate = 'conversationUpdate', + MessageAdd = 'messageAdd', + ConversationCompletionError = 'conversationCompletionError', +} + +type StreamingChatResponseEventBase< + TEventType extends StreamingChatResponseEventType, + TData extends {} +> = { + type: TEventType; +} & TData; + +type ChatCompletionChunkEvent = StreamingChatResponseEventBase< + StreamingChatResponseEventType.ChatCompletionChunk, + { + id: string; + message: { + content?: string; + function_call?: { + name?: string; + arguments?: string; + }; + }; + } +>; + +export type ConversationCreateEvent = StreamingChatResponseEventBase< + StreamingChatResponseEventType.ConversationCreate, + { + conversation: { + id: string; + title: string; + last_updated: string; + }; + } +>; + +export type ConversationUpdateEvent = StreamingChatResponseEventBase< + StreamingChatResponseEventType.ConversationUpdate, + { + conversation: { + id: string; + title: string; + last_updated: string; + }; + } +>; + +export type MessageAddEvent = StreamingChatResponseEventBase< + StreamingChatResponseEventType.MessageAdd, + { message: Message; id: string } +>; + +export type ConversationCompletionErrorEvent = StreamingChatResponseEventBase< + StreamingChatResponseEventType.ConversationCompletionError, + { error: { message: string; stack?: string; code?: ChatCompletionErrorCode } } +>; + +export type StreamingChatResponseEvent = + | ChatCompletionChunkEvent + | ConversationCreateEvent + | ConversationUpdateEvent + | MessageAddEvent + | ConversationCompletionErrorEvent; + +export enum ChatCompletionErrorCode { + InternalError = 'internalError', + NotFound = 'notFound', +} + +export class ConversationCompletionError extends Error { + code: ChatCompletionErrorCode; + + constructor(code: ChatCompletionErrorCode, message: string) { + super(message); + this.code = code; + } +} + +export class ConversationNotFoundError extends ConversationCompletionError { + constructor() { + super( + ChatCompletionErrorCode.NotFound, + i18n.translate( + 'xpack.observabilityAiAssistant.conversationCompletionError.conversationNotFound', + { + defaultMessage: 'Conversation not found', + } + ) + ); + } +} + +export function isChatCompletionError(error: Error): error is ConversationCompletionError { + return error instanceof ConversationCompletionError; +} diff --git a/x-pack/plugins/observability_ai_assistant/common/functions/lens.tsx b/x-pack/plugins/observability_ai_assistant/common/functions/lens.tsx new file mode 100644 index 0000000000000..a3d8487a83b8a --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/functions/lens.tsx @@ -0,0 +1,122 @@ +/* + * 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 { FromSchema } from 'json-schema-to-ts'; +import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common'; + +export enum SeriesType { + Bar = 'bar', + Line = 'line', + Area = 'area', + BarStacked = 'bar_stacked', + AreaStacked = 'area_stacked', + BarHorizontal = 'bar_horizontal', + BarPercentageStacked = 'bar_percentage_stacked', + AreaPercentageStacked = 'area_percentage_stacked', + BarHorizontalPercentageStacked = 'bar_horizontal_percentage_stacked', +} + +export const lensFunctionDefinition = { + name: 'lens', + contexts: ['core'], + description: + "Use this function to create custom visualizations, using Lens, that can be saved to dashboards. This function does not return data to the assistant, it only shows it to the user. When using this function, make sure to use the recall function to get more information about how to use it, with how you want to use it. Make sure the query also contains information about the user's request. The visualisation is displayed to the user above your reply, DO NOT try to generate or display an image yourself.", + descriptionForUser: + 'Use this function to create custom visualizations, using Lens, that can be saved to dashboards.', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + layers: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + properties: { + label: { + type: 'string', + }, + formula: { + type: 'string', + description: + 'The formula for calculating the value, e.g. sum(my_field_name). Query the knowledge base to get more information about the syntax and available formulas.', + }, + filter: { + type: 'string', + description: 'A KQL query that will be used as a filter for the series', + }, + format: { + type: 'object', + additionalProperties: false, + properties: { + id: { + type: 'string', + description: + 'How to format the value. When using duration, make sure the value is seconds OR is converted to seconds using math functions. Ask the user for clarification in which unit the value is stored, or derive it from the field name.', + enum: [ + FIELD_FORMAT_IDS.BYTES, + FIELD_FORMAT_IDS.CURRENCY, + FIELD_FORMAT_IDS.DURATION, + FIELD_FORMAT_IDS.NUMBER, + FIELD_FORMAT_IDS.PERCENT, + FIELD_FORMAT_IDS.STRING, + ], + }, + }, + required: ['id'], + }, + }, + required: ['label', 'formula', 'format'], + }, + }, + timeField: { + type: 'string', + default: '@timefield', + description: + 'time field to use for XY chart. Use @timefield if its available on the index.', + }, + breakdown: { + type: 'object', + additionalProperties: false, + properties: { + field: { + type: 'string', + }, + }, + required: ['field'], + }, + indexPattern: { + type: 'string', + }, + seriesType: { + type: 'string', + enum: [ + SeriesType.Area, + SeriesType.AreaPercentageStacked, + SeriesType.AreaStacked, + SeriesType.Bar, + SeriesType.BarHorizontal, + SeriesType.BarHorizontalPercentageStacked, + SeriesType.BarPercentageStacked, + SeriesType.BarStacked, + SeriesType.Line, + ], + }, + start: { + type: 'string', + description: 'The start of the time range, in Elasticsearch datemath', + }, + end: { + type: 'string', + description: 'The end of the time range, in Elasticsearch datemath', + }, + }, + required: ['layers', 'indexPattern', 'start', 'end', 'timeField'], + } as const, +}; + +export type LensFunctionArguments = FromSchema; diff --git a/x-pack/plugins/observability_ai_assistant/common/types.ts b/x-pack/plugins/observability_ai_assistant/common/types.ts index bf4f2210538ca..2584a1c7083fd 100644 --- a/x-pack/plugins/observability_ai_assistant/common/types.ts +++ b/x-pack/plugins/observability_ai_assistant/common/types.ts @@ -5,10 +5,20 @@ * 2.0. */ -import type { FromSchema } from 'json-schema-to-ts'; import type { JSONSchema } from 'json-schema-to-ts'; -import React from 'react'; -import { Observable } from 'rxjs'; +import type { + CreateChatCompletionResponse, + CreateChatCompletionResponseChoicesInner, +} from 'openai'; +import type { Observable } from 'rxjs'; + +export type CreateChatCompletionResponseChunk = Omit & { + choices: Array< + Omit & { + delta: { content?: string; function_call?: { name?: string; arguments?: string } }; + } + >; +}; export enum MessageRole { System = 'system', @@ -89,12 +99,12 @@ export interface ContextDefinition { description: string; } -type FunctionResponse = +export type FunctionResponse = | { content?: any; data?: any; } - | Observable; + | Observable; export enum FunctionVisibility { System = 'system', @@ -102,7 +112,9 @@ export enum FunctionVisibility { All = 'all', } -interface FunctionOptions { +export interface FunctionDefinition< + TParameters extends CompatibleJSONSchema = CompatibleJSONSchema +> { name: string; description: string; visibility?: FunctionVisibility; @@ -111,36 +123,7 @@ interface FunctionOptions = ( - options: { arguments: TArguments; messages: Message[]; connectorId: string }, - signal: AbortSignal -) => Promise; - -type RenderFunction = (options: { - arguments: TArguments; - response: TResponse; -}) => React.ReactNode; - -export interface FunctionDefinition { - options: FunctionOptions; - respond: ( - options: { arguments: any; messages: Message[]; connectorId: string }, - signal: AbortSignal - ) => Promise; - render?: RenderFunction; -} - export type RegisterContextDefinition = (options: ContextDefinition) => void; -export type RegisterFunctionDefinition = < - TParameters extends CompatibleJSONSchema, - TResponse extends FunctionResponse, - TArguments = FromSchema ->( - options: FunctionOptions, - respond: RespondFunction, - render?: RenderFunction -) => void; - export type ContextRegistry = Map; export type FunctionRegistry = Map; diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/concatenate_openai_chunks.ts b/x-pack/plugins/observability_ai_assistant/common/utils/concatenate_openai_chunks.ts new file mode 100644 index 0000000000000..f15a193908a4e --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/concatenate_openai_chunks.ts @@ -0,0 +1,34 @@ +/* + * 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 { cloneDeep } from 'lodash'; +import { type Observable, scan } from 'rxjs'; +import { CreateChatCompletionResponseChunk, MessageRole } from '../types'; + +export const concatenateOpenAiChunks = + () => (source: Observable) => + source.pipe( + scan( + (acc, { choices }) => { + acc.message.content += choices[0].delta.content ?? ''; + acc.message.function_call.name += choices[0].delta.function_call?.name ?? ''; + acc.message.function_call.arguments += choices[0].delta.function_call?.arguments ?? ''; + return cloneDeep(acc); + }, + { + message: { + content: '', + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant as const, + }, + role: MessageRole.Assistant, + }, + } + ) + ); diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/filter_function_definitions.ts b/x-pack/plugins/observability_ai_assistant/common/utils/filter_function_definitions.ts new file mode 100644 index 0000000000000..3de6c3bce2484 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/filter_function_definitions.ts @@ -0,0 +1,29 @@ +/* + * 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 { FunctionDefinition } from '../types'; + +export function filterFunctionDefinitions({ + contexts, + filter, + definitions, +}: { + contexts?: string[]; + filter?: string; + definitions: FunctionDefinition[]; +}) { + return contexts || filter + ? definitions.filter((fn) => { + const matchesContext = + !contexts || fn.contexts.some((context) => contexts.includes(context)); + const matchesFilter = + !filter || fn.name.includes(filter) || fn.description.includes(filter); + + return matchesContext && matchesFilter; + }) + : definitions; +} diff --git a/x-pack/plugins/observability_ai_assistant/common/utils/process_openai_stream.ts b/x-pack/plugins/observability_ai_assistant/common/utils/process_openai_stream.ts new file mode 100644 index 0000000000000..e0d66bbf85132 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/common/utils/process_openai_stream.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ +/* eslint-disable max-classes-per-file*/ +import { filter, map, Observable, tap } from 'rxjs'; +import type { CreateChatCompletionResponseChunk } from '../types'; + +class TokenLimitReachedError extends Error { + constructor() { + super(`Token limit reached`); + } +} + +class ServerError extends Error {} + +export function processOpenAiStream() { + return (source: Observable): Observable => + source.pipe( + map((line) => line.substring(6)), + filter((line) => !!line && line !== '[DONE]'), + map( + (line) => + JSON.parse(line) as CreateChatCompletionResponseChunk | { error: { message: string } } + ), + tap((line) => { + if ('error' in line) { + throw new ServerError(line.error.message); + } + if ( + 'choices' in line && + line.choices.length && + line.choices[0].finish_reason === 'length' + ) { + throw new TokenLimitReachedError(); + } + }), + filter( + (line): line is CreateChatCompletionResponseChunk => + 'object' in line && line.object === 'chat.completion.chunk' + ) + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/jest.config.js b/x-pack/plugins/observability_ai_assistant/jest.config.js index 1d6798f6c7623..ff54dbc08c2b0 100644 --- a/x-pack/plugins/observability_ai_assistant/jest.config.js +++ b/x-pack/plugins/observability_ai_assistant/jest.config.js @@ -11,5 +11,8 @@ module.exports = { roots: ['/x-pack/plugins/observability_ai_assistant'], setupFiles: ['/x-pack/plugins/observability_ai_assistant/.storybook/jest_setup.js'], collectCoverage: true, + collectCoverageFrom: [ + '/x-pack/plugins/observability_ai_assistant/{common,public,server}/**/*.{js,ts,tsx}', + ], coverageReporters: ['html'], }; diff --git a/x-pack/plugins/observability_ai_assistant/kibana.jsonc b/x-pack/plugins/observability_ai_assistant/kibana.jsonc index 291c7e658de18..cd2d4b788bc78 100644 --- a/x-pack/plugins/observability_ai_assistant/kibana.jsonc +++ b/x-pack/plugins/observability_ai_assistant/kibana.jsonc @@ -8,6 +8,7 @@ "browser": true, "configPath": ["xpack", "observabilityAIAssistant"], "requiredPlugins": [ + "alerting", "actions", "dataViews", "features", @@ -21,7 +22,7 @@ "triggersActionsUi", "dataViews" ], - "requiredBundles": ["fieldFormats", "kibanaReact", "kibanaUtils"], + "requiredBundles": [ "kibanaReact", "kibanaUtils"], "optionalPlugins": [], "extraPublicDirs": [] } diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx index cc3c7c5a7a99f..cf3b57e3ebed6 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx @@ -73,7 +73,7 @@ export function ChatBody({ connectorsManagementHref: string; currentUser?: Pick; startedFrom?: StartedFrom; - onConversationUpdate: (conversation: Conversation) => void; + onConversationUpdate: (conversation: { conversation: Conversation['conversation'] }) => void; }) { const license = useLicense(); const hasCorrectLicense = license?.hasAtLeast('enterprise'); diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/function_list_popover.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/function_list_popover.tsx index 6156d86d9761b..8e4c7bbd56116 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/function_list_popover.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/function_list_popover.tsx @@ -186,12 +186,12 @@ function mapFunctions({ selectedFunctionName: string | undefined; }) { return functions - .filter((func) => func.options.visibility !== FunctionVisibility.System) + .filter((func) => func.visibility !== FunctionVisibility.System) .map((func) => ({ - label: func.options.name, - searchableLabel: func.options.descriptionForUser || func.options.description, + label: func.name, + searchableLabel: func.descriptionForUser || func.description, checked: - func.options.name === selectedFunctionName + func.name === selectedFunctionName ? ('on' as EuiSelectableOptionCheckedType) : ('off' as EuiSelectableOptionCheckedType), })); diff --git a/x-pack/plugins/observability_ai_assistant/public/components/insight/insight.tsx b/x-pack/plugins/observability_ai_assistant/public/components/insight/insight.tsx index d629a6f911f40..ad26d8a51cd3e 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/insight/insight.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/insight/insight.tsx @@ -45,6 +45,7 @@ function ChatContent({ chatService, connectorId, initialMessages, + persist: false, }); const lastAssistantResponse = last( diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts b/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts deleted file mode 100644 index b4c0d0bd1bdfd..0000000000000 --- a/x-pack/plugins/observability_ai_assistant/public/functions/alerts.ts +++ /dev/null @@ -1,86 +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 type { RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; - -const DEFAULT_FEATURE_IDS = [ - 'apm', - 'infrastructure', - 'logs', - 'uptime', - 'slo', - 'observability', -] as const; - -export function registerAlertsFunction({ - service, - registerFunction, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; -}) { - registerFunction( - { - name: 'alerts', - contexts: ['core'], - description: - 'Get alerts for Observability. Display the response in tabular format if appropriate.', - descriptionForUser: 'Get alerts for Observability', - parameters: { - type: 'object', - additionalProperties: false, - properties: { - featureIds: { - type: 'array', - additionalItems: false, - items: { - type: 'string', - enum: DEFAULT_FEATURE_IDS, - }, - description: - 'The Observability apps for which to retrieve alerts. By default it will return alerts for all apps.', - }, - start: { - type: 'string', - description: 'The start of the time range, in Elasticsearch date math, like `now`.', - }, - end: { - type: 'string', - description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.', - }, - filter: { - type: 'string', - description: - 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', - }, - includeRecovered: { - type: 'boolean', - description: - 'Whether to include recovered/closed alerts. Defaults to false, which means only active alerts will be returned', - }, - }, - required: ['start', 'end'], - } as const, - }, - ({ arguments: { start, end, featureIds, filter, includeRecovered } }, signal) => { - return service.callApi('POST /internal/observability_ai_assistant/functions/alerts', { - params: { - body: { - start, - end, - featureIds: - featureIds && featureIds.length > 0 ? featureIds : DEFAULT_FEATURE_IDS.concat(), - filter, - includeRecovered, - }, - }, - signal, - }); - } - ); -} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/get_dataset_info.ts b/x-pack/plugins/observability_ai_assistant/public/functions/get_dataset_info.ts deleted file mode 100644 index cbb6167cf684e..0000000000000 --- a/x-pack/plugins/observability_ai_assistant/public/functions/get_dataset_info.ts +++ /dev/null @@ -1,153 +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 { chunk, groupBy, uniq } from 'lodash'; -import { CreateChatCompletionResponse } from 'openai'; -import { FunctionVisibility, MessageRole, RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; - -export function registerGetDatasetInfoFunction({ - service, - registerFunction, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; -}) { - registerFunction( - { - name: 'get_dataset_info', - contexts: ['core'], - visibility: FunctionVisibility.System, - description: `Use this function to get information about indices/datasets available and the fields available on them. - - providing empty string as index name will retrieve all indices - else list of all fields for the given index will be given. if no fields are returned this means no indices were matched by provided index pattern. - wildcards can be part of index name.`, - descriptionForUser: - 'This function allows the assistant to get information about available indices and their fields.', - parameters: { - type: 'object', - additionalProperties: false, - properties: { - index: { - type: 'string', - description: - 'index pattern the user is interested in or empty string to get information about all available indices', - }, - }, - required: ['index'], - } as const, - }, - async ({ arguments: { index }, messages, connectorId }, signal) => { - const response = await service.callApi( - 'POST /internal/observability_ai_assistant/functions/get_dataset_info', - { - params: { - body: { - index, - }, - }, - signal, - } - ); - - const allFields = response.fields; - - const fieldNames = uniq(allFields.map((field) => field.name)); - - const groupedFields = groupBy(allFields, (field) => field.name); - - const relevantFields = await Promise.all( - chunk(fieldNames, 500).map(async (fieldsInChunk) => { - const chunkResponse = (await service.callApi( - 'POST /internal/observability_ai_assistant/chat', - { - signal, - params: { - query: { - stream: false, - }, - body: { - connectorId, - messages: [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: `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.`, - }, - }, - ...messages.slice(1), - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.User, - content: `This is the list: - - ${fieldsInChunk.join('\n')}`, - }, - }, - ], - functions: [ - { - name: 'fields', - description: 'The fields you consider relevant to the conversation', - parameters: { - type: 'object', - additionalProperties: false, - properties: { - fields: { - type: 'array', - additionalProperties: false, - addditionalItems: false, - items: { - type: 'string', - additionalProperties: false, - addditionalItems: false, - }, - }, - }, - required: ['fields'], - }, - }, - ], - functionCall: 'fields', - }, - }, - } - )) as CreateChatCompletionResponse; - - return chunkResponse.choices[0].message?.function_call?.arguments - ? ( - JSON.parse(chunkResponse.choices[0].message?.function_call?.arguments) as { - fields: string[]; - } - ).fields - .filter((field) => fieldNames.includes(field)) - .map((field) => { - const fieldDescriptors = groupedFields[field]; - return `${field}:${fieldDescriptors - .map((descriptor) => descriptor.type) - .join(',')}`; - }) - : [chunkResponse.choices[0].message?.content ?? '']; - }) - ); - - return { - content: { - indices: response.indices, - fields: relevantFields.flat(), - }, - }; - } - ); -} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/index.ts b/x-pack/plugins/observability_ai_assistant/public/functions/index.ts index fe35f66593a19..4bdbb31b15dcc 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/index.ts +++ b/x-pack/plugins/observability_ai_assistant/public/functions/index.ts @@ -5,88 +5,21 @@ * 2.0. */ -import dedent from 'dedent'; -import type { CoreStart } from '@kbn/core/public'; -import type { RegisterContextDefinition, RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantPluginStartDependencies } from '../types'; -import type { ObservabilityAIAssistantService } from '../types'; -import { registerElasticsearchFunction } from './elasticsearch'; -import { registerKibanaFunction } from './kibana'; -import { registerLensFunction } from './lens'; -import { registerRecallFunction } from './recall'; -import { registerGetDatasetInfoFunction } from './get_dataset_info'; -import { registerSummarizationFunction } from './summarize'; -import { registerAlertsFunction } from './alerts'; -import { registerEsqlFunction } from './esql'; +import type { + ObservabilityAIAssistantPluginStartDependencies, + ObservabilityAIAssistantService, + RegisterRenderFunctionDefinition, +} from '../types'; +import { registerLensRenderFunction } from './lens'; export async function registerFunctions({ - registerFunction, - registerContext, + registerRenderFunction, service, pluginsStart, - coreStart, - signal, }: { - registerFunction: RegisterFunctionDefinition; - registerContext: RegisterContextDefinition; + registerRenderFunction: RegisterRenderFunctionDefinition; service: ObservabilityAIAssistantService; pluginsStart: ObservabilityAIAssistantPluginStartDependencies; - coreStart: CoreStart; - signal: AbortSignal; }) { - return service - .callApi('GET /internal/observability_ai_assistant/kb/status', { - signal, - }) - .then((response) => { - const isReady = response.ready; - - let description = dedent( - `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. - - It's very important to not assume what the user is meaning. Ask them for clarification if needed. - - If you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation. - - In KQL, 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! - - You can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response. - - If multiple functions are suitable, use the most specific and easy one. E.g., when the user asks to visualise APM data, use the APM functions (if available) rather than Lens. - - If a function call fails, DO NOT UNDER ANY CIRCUMSTANCES execute it again. Ask the user for guidance and offer them options. - - Note that ES|QL (the Elasticsearch query language, which is NOT Elasticsearch SQL, but a new piped language) is the preferred query language. - - If the user asks about a query, or ES|QL, always call the "esql" function. DO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries yourself. Even if the "recall" function was used before that, follow it up with the "esql" function.` - ); - - if (isReady) { - description += `You can use the "summarize" functions to store new information you have learned in a knowledge database. Once you have established that you did not know the answer to a question, and the user gave you this information, it's important that you create a summarisation of what you have learned and store it in the knowledge database. Don't create a new summarization if you see a similar summarization in the conversation, instead, update the existing one by re-using its ID. - - Additionally, you can use the "recall" function to retrieve relevant information from the knowledge database. - `; - - description += `Here are principles you MUST adhere to, in order: - - DO NOT make any assumptions about where and how users have stored their data. ALWAYS first call get_dataset_info function with empty string to get information about available indices. Once you know about available indices you MUST use this function again to get a list of available fields for specific index. If user provides an index name make sure its a valid index first before using it to retrieve the field list by calling this function with an empty string! - `; - registerSummarizationFunction({ service, registerFunction }); - registerRecallFunction({ service, registerFunction }); - registerLensFunction({ service, pluginsStart, registerFunction }); - } else { - description += `You do not have a working memory. Don't try to recall information via the "recall" function. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base. A banner is available at the top of the conversation to set this up.`; - } - - registerElasticsearchFunction({ service, registerFunction }); - registerEsqlFunction({ service, registerFunction }); - registerKibanaFunction({ service, registerFunction, coreStart }); - registerAlertsFunction({ service, registerFunction }); - registerGetDatasetInfoFunction({ service, registerFunction }); - - registerContext({ - name: 'core', - description: dedent(description), - }); - }); + registerLensRenderFunction({ service, pluginsStart, registerRenderFunction }); } diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx b/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx index fa8dc66dce294..22d4b91a5f906 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/functions/lens.tsx @@ -6,17 +6,18 @@ */ import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; -import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common'; +import { i18n } from '@kbn/i18n'; import { LensAttributesBuilder, XYChart, XYDataLayer } from '@kbn/lens-embeddable-utils'; import type { LensEmbeddableInput, LensPublicStart } from '@kbn/lens-plugin/public'; import React, { useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { i18n } from '@kbn/i18n'; import { Assign } from 'utility-types'; -import type { RegisterFunctionDefinition } from '../../common/types'; +import type { LensFunctionArguments } from '../../common/functions/lens'; import type { ObservabilityAIAssistantPluginStartDependencies, ObservabilityAIAssistantService, + RegisterRenderFunctionDefinition, + RenderFunction, } from '../types'; export enum SeriesType { @@ -137,120 +138,20 @@ function Lens({ ); } -export function registerLensFunction({ +export function registerLensRenderFunction({ service, - registerFunction, + registerRenderFunction, pluginsStart, }: { service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; + registerRenderFunction: RegisterRenderFunctionDefinition; pluginsStart: ObservabilityAIAssistantPluginStartDependencies; }) { - registerFunction( - { - name: 'lens', - contexts: ['core'], - description: - "Use this function to create custom visualizations, using Lens, that can be saved to dashboards. This function does not return data to the assistant, it only shows it to the user. When using this function, make sure to use the recall function to get more information about how to use it, with how you want to use it. Make sure the query also contains information about the user's request. The visualisation is displayed to the user above your reply, DO NOT try to generate or display an image yourself.", - descriptionForUser: - 'Use this function to create custom visualizations, using Lens, that can be saved to dashboards.', - parameters: { - type: 'object', - additionalProperties: false, - properties: { - layers: { - type: 'array', - items: { - type: 'object', - additionalProperties: false, - properties: { - label: { - type: 'string', - }, - formula: { - type: 'string', - description: - 'The formula for calculating the value, e.g. sum(my_field_name). Query the knowledge base to get more information about the syntax and available formulas.', - }, - filter: { - type: 'string', - description: 'A KQL query that will be used as a filter for the series', - }, - format: { - type: 'object', - additionalProperties: false, - properties: { - id: { - type: 'string', - description: - 'How to format the value. When using duration, make sure the value is seconds OR is converted to seconds using math functions. Ask the user for clarification in which unit the value is stored, or derive it from the field name.', - enum: [ - FIELD_FORMAT_IDS.BYTES, - FIELD_FORMAT_IDS.CURRENCY, - FIELD_FORMAT_IDS.DURATION, - FIELD_FORMAT_IDS.NUMBER, - FIELD_FORMAT_IDS.PERCENT, - FIELD_FORMAT_IDS.STRING, - ], - }, - }, - required: ['id'], - }, - }, - required: ['label', 'formula', 'format'], - }, - }, - timeField: { - type: 'string', - default: '@timefield', - description: - 'time field to use for XY chart. Use @timefield if its available on the index.', - }, - breakdown: { - type: 'object', - additionalProperties: false, - properties: { - field: { - type: 'string', - }, - }, - required: ['field'], - }, - indexPattern: { - type: 'string', - }, - seriesType: { - type: 'string', - enum: [ - SeriesType.Area, - SeriesType.AreaPercentageStacked, - SeriesType.AreaStacked, - SeriesType.Bar, - SeriesType.BarHorizontal, - SeriesType.BarHorizontalPercentageStacked, - SeriesType.BarPercentageStacked, - SeriesType.BarStacked, - SeriesType.Line, - ], - }, - start: { - type: 'string', - description: 'The start of the time range, in Elasticsearch datemath', - }, - end: { - type: 'string', - description: 'The end of the time range, in Elasticsearch datemath', - }, - }, - required: ['layers', 'indexPattern', 'start', 'end', 'timeField'], - } as const, - }, - async () => { - return { - content: {}, - }; - }, - ({ arguments: { layers, indexPattern, breakdown, seriesType, start, end, timeField } }) => { + registerRenderFunction( + 'lens', + ({ + arguments: { layers, indexPattern, breakdown, seriesType, start, end, timeField }, + }: Parameters>[0]) => { const xyDataLayer = new XYDataLayer({ data: layers.map((layer) => ({ type: 'formula', diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.test.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.test.ts index a1e5d3283b095..a2ef68899877e 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.test.ts +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.test.ts @@ -8,20 +8,26 @@ import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { type RenderHookResult, renderHook, act } from '@testing-library/react-hooks'; import { Observable, Subject } from 'rxjs'; import { MessageRole } from '../../common'; -import type { ObservabilityAIAssistantChatService, PendingMessage } from '../types'; +import { + ChatCompletionErrorCode, + ConversationCompletionError, + StreamingChatResponseEvent, + StreamingChatResponseEventType, +} from '../../common/conversation_complete'; +import type { ObservabilityAIAssistantChatService } from '../types'; import { type UseChatResult, useChat, type UseChatProps, ChatState } from './use_chat'; import * as useKibanaModule from './use_kibana'; type MockedChatService = DeeplyMockedKeys; const mockChatService: MockedChatService = { + chat: jest.fn(), + complete: jest.fn(), analytics: { optIn: jest.fn(), reportEvent: jest.fn(), telemetryCounter$: new Observable() as any, }, - chat: jest.fn(), - executeFunction: jest.fn(), getContexts: jest.fn().mockReturnValue([{ name: 'core', description: '' }]), getFunctions: jest.fn().mockReturnValue([]), hasFunction: jest.fn().mockReturnValue(false), @@ -63,6 +69,7 @@ describe('useChat', () => { }, }, ], + persist: false, } as UseChatProps, }); }); @@ -80,7 +87,7 @@ describe('useChat', () => { }); describe('when calling next()', () => { - let subject: Subject; + let subject: Subject; beforeEach(() => { hookResult = renderHook(useChat, { @@ -88,12 +95,13 @@ describe('useChat', () => { connectorId: 'my-connector', chatService: mockChatService, initialMessages: [], + persist: false, } as UseChatProps, }); subject = new Subject(); - mockChatService.chat.mockReturnValueOnce(subject); + mockChatService.complete.mockReturnValueOnce(subject); act(() => { hookResult.result.current.next([ @@ -118,11 +126,23 @@ describe('useChat', () => { act(() => { hookResult.result.current.next([]); subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { - role: MessageRole.User, content: 'goodbye', }, }); + subject.next({ + type: StreamingChatResponseEventType.MessageAdd, + id: 'my-message-id', + message: { + '@timestamp': new Date().toISOString(), + message: { + content: 'goodbye', + role: MessageRole.Assistant, + }, + }, + }); subject.complete(); }); }); @@ -141,9 +161,10 @@ describe('useChat', () => { it('updates the returned messages', () => { act(() => { subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { content: 'good', - role: MessageRole.Assistant, }, }); }); @@ -156,15 +177,28 @@ describe('useChat', () => { it('updates the returned messages and the loading state', () => { act(() => { subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { content: 'good', - role: MessageRole.Assistant, }, }); subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { - content: 'goodbye', - role: MessageRole.Assistant, + content: 'bye', + }, + }); + subject.next({ + type: StreamingChatResponseEventType.MessageAdd, + id: 'my-message-id', + message: { + '@timestamp': new Date().toISOString(), + message: { + content: 'goodbye', + role: MessageRole.Assistant, + }, }, }); subject.complete(); @@ -179,13 +213,13 @@ describe('useChat', () => { beforeEach(() => { act(() => { subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { content: 'good', - role: MessageRole.Assistant, }, - aborted: true, }); - subject.complete(); + hookResult.result.current.stop(); }); }); @@ -203,13 +237,15 @@ describe('useChat', () => { beforeEach(() => { act(() => { subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message-id', message: { content: 'good', - role: MessageRole.Assistant, }, - error: new Error('foo'), }); - subject.complete(); + subject.error( + new ConversationCompletionError(ChatCompletionErrorCode.InternalError, 'foo') + ); }); }); @@ -222,248 +258,5 @@ describe('useChat', () => { expect(addErrorMock).toHaveBeenCalled(); }); }); - - describe('after the LLM responds with a function call', () => { - let resolve: (data: any) => void; - let reject: (error: Error) => void; - - beforeEach(() => { - mockChatService.executeFunction.mockResolvedValueOnce( - new Promise((...args) => { - resolve = args[0]; - reject = args[1]; - }) - ); - - act(() => { - subject.next({ - message: { - content: '', - role: MessageRole.Assistant, - function_call: { - name: 'my_function', - arguments: JSON.stringify({ foo: 'bar' }), - trigger: MessageRole.Assistant, - }, - }, - }); - subject.complete(); - }); - }); - - it('the chat state stays loading', () => { - expect(hookResult.result.current.state).toBe(ChatState.Loading); - }); - - it('adds a message', () => { - const { messages } = hookResult.result.current; - - expect(messages.length).toBe(3); - expect(messages[2]).toEqual({ - '@timestamp': expect.any(String), - message: { - content: '', - function_call: { - arguments: JSON.stringify({ foo: 'bar' }), - name: 'my_function', - trigger: MessageRole.Assistant, - }, - role: MessageRole.Assistant, - }, - }); - }); - - describe('the function call succeeds', () => { - beforeEach(async () => { - subject = new Subject(); - mockChatService.chat.mockReturnValueOnce(subject); - - await act(async () => { - resolve({ content: { foo: 'bar' }, data: { bar: 'foo' } }); - }); - }); - - it('adds a message', () => { - const { messages } = hookResult.result.current; - - expect(messages.length).toBe(4); - expect(messages[3]).toEqual({ - '@timestamp': expect.any(String), - message: { - content: JSON.stringify({ foo: 'bar' }), - data: JSON.stringify({ bar: 'foo' }), - name: 'my_function', - role: MessageRole.User, - }, - }); - }); - - it('keeps the chat state in loading', () => { - expect(hookResult.result.current.state).toBe(ChatState.Loading); - }); - it('sends the function call back to the LLM for a response', () => { - expect(mockChatService.chat).toHaveBeenCalledTimes(2); - expect(mockChatService.chat).toHaveBeenLastCalledWith({ - connectorId: 'my-connector', - messages: hookResult.result.current.messages, - }); - }); - }); - - describe('the function call fails', () => { - beforeEach(async () => { - subject = new Subject(); - mockChatService.chat.mockReturnValue(subject); - - await act(async () => { - reject(new Error('connection error')); - }); - }); - - it('keeps the chat state in loading', () => { - expect(hookResult.result.current.state).toBe(ChatState.Loading); - }); - - it('adds a message', () => { - const { messages } = hookResult.result.current; - - expect(messages.length).toBe(4); - expect(messages[3]).toEqual({ - '@timestamp': expect.any(String), - message: { - content: JSON.stringify({ - message: 'Error: connection error', - error: {}, - }), - name: 'my_function', - role: MessageRole.User, - }, - }); - }); - - it('does not show an error toast', () => { - expect(addErrorMock).not.toHaveBeenCalled(); - }); - - it('sends the function call back to the LLM for a response', () => { - expect(mockChatService.chat).toHaveBeenCalledTimes(2); - expect(mockChatService.chat).toHaveBeenLastCalledWith({ - connectorId: 'my-connector', - messages: hookResult.result.current.messages, - }); - }); - }); - - describe('stop() is called', () => { - beforeEach(() => { - act(() => { - hookResult.result.current.stop(); - }); - }); - - it('sets the chatState to aborted', () => { - expect(hookResult.result.current.state).toBe(ChatState.Aborted); - }); - - it('has called the abort controller', () => { - const signal = mockChatService.executeFunction.mock.calls[0][0].signal; - - expect(signal.aborted).toBe(true); - }); - - it('is not updated after the promise is rejected', () => { - const numRenders = hookResult.result.all.length; - - act(() => { - reject(new Error('Request aborted')); - }); - - expect(numRenders).toBe(hookResult.result.all.length); - }); - - it('removes all subscribers', () => { - expect(subject.observed).toBe(false); - }); - }); - - describe('setMessages() is called', () => {}); - }); - }); - - describe('when calling next() with the recall function available', () => { - let subject: Subject; - - beforeEach(async () => { - hookResult = renderHook(useChat, { - initialProps: { - connectorId: 'my-connector', - chatService: mockChatService, - initialMessages: [], - } as UseChatProps, - }); - - subject = new Subject(); - - mockChatService.hasFunction.mockReturnValue(true); - mockChatService.executeFunction.mockResolvedValueOnce({ - content: [ - { - id: 'my_document', - text: 'My text', - }, - ], - }); - - mockChatService.chat.mockReturnValueOnce(subject); - - await act(async () => { - hookResult.result.current.next([ - ...hookResult.result.current.messages, - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.User, - content: 'hello', - }, - }, - ]); - }); - }); - - it('adds a user message and a recall function request', () => { - expect(hookResult.result.current.messages[1].message.content).toBe('hello'); - expect(hookResult.result.current.messages[2].message.function_call?.name).toBe('recall'); - expect(hookResult.result.current.messages[2].message.content).toBe(''); - expect(hookResult.result.current.messages[2].message.function_call?.arguments).toBe( - JSON.stringify({ queries: [], contexts: [] }) - ); - expect(hookResult.result.current.messages[3].message.name).toBe('recall'); - expect(hookResult.result.current.messages[3].message.content).toBe( - JSON.stringify([ - { - id: 'my_document', - text: 'My text', - }, - ]) - ); - }); - - it('executes the recall function', () => { - expect(mockChatService.executeFunction).toHaveBeenCalled(); - expect(mockChatService.executeFunction).toHaveBeenCalledWith({ - signal: expect.any(AbortSignal), - connectorId: 'my-connector', - args: JSON.stringify({ queries: [], contexts: [] }), - name: 'recall', - messages: [...hookResult.result.current.messages.slice(0, -1)], - }); - }); - - it('sends the user message, function request and recall response to the LLM', () => { - expect(mockChatService.chat).toHaveBeenCalledWith({ - connectorId: 'my-connector', - messages: [...hookResult.result.current.messages], - }); - }); }); }); diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.ts index aeef36127f6c4..989b3fdcb23a8 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.ts +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_chat.ts @@ -6,12 +6,16 @@ */ import { i18n } from '@kbn/i18n'; -import { last } from 'lodash'; +import { merge } from 'lodash'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { isObservable } from 'rxjs'; -import { type Message, MessageRole } from '../../common'; +import { MessageRole, type Message } from '../../common'; +import { + ConversationCreateEvent, + ConversationUpdateEvent, + StreamingChatResponseEventType, +} from '../../common/conversation_complete'; import { getAssistantSetupMessage } from '../service/get_assistant_setup_message'; -import type { ObservabilityAIAssistantChatService, PendingMessage } from '../types'; +import type { ObservabilityAIAssistantChatService } from '../types'; import { useKibana } from './use_kibana'; import { useOnce } from './use_once'; @@ -22,6 +26,13 @@ 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; @@ -32,16 +43,22 @@ export interface UseChatResult { export interface UseChatProps { initialMessages: Message[]; + initialConversationId?: string; chatService: ObservabilityAIAssistantChatService; connectorId?: string; + persist: boolean; + onConversationUpdate?: (event: ConversationCreateEvent | ConversationUpdateEvent) => void; onChatComplete?: (messages: Message[]) => void; } export function useChat({ initialMessages, + initialConversationId: initialConversationIdFromProps, chatService, connectorId, + onConversationUpdate, onChatComplete, + persist, }: UseChatProps): UseChatResult { const [chatState, setChatState] = useState(ChatState.Ready); @@ -51,9 +68,11 @@ export function useChat({ useOnce(initialMessages); + const initialConversationId = useOnce(initialConversationIdFromProps); + const [messages, setMessages] = useState(initialMessages); - const [pendingMessage, setPendingMessage] = useState(); + const [pendingMessages, setPendingMessages] = useState(); const abortControllerRef = useRef(new AbortController()); @@ -62,13 +81,27 @@ export function useChat({ } = useKibana(); const onChatCompleteRef = useRef(onChatComplete); - onChatCompleteRef.current = onChatComplete; + const onConversationUpdateRef = useRef(onConversationUpdate); + onConversationUpdateRef.current = onConversationUpdate; + const handleSignalAbort = useCallback(() => { setChatState(ChatState.Aborted); }, []); + const handleError = useCallback( + (error: Error) => { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.observabilityAiAssistant.failedToLoadResponse', { + defaultMessage: 'Failed to load response from the AI Assistant', + }), + }); + setChatState(ChatState.Error); + }, + [notifications.toasts] + ); + const next = useCallback( async (nextMessages: Message[]) => { // make sure we ignore any aborts for the previous signal @@ -77,173 +110,134 @@ export function useChat({ // cancel running requests abortControllerRef.current.abort(); - const lastMessage = last(nextMessages); + abortControllerRef.current = new AbortController(); - const allMessages = [ - systemMessage, - ...nextMessages.filter((message) => message.message.role !== MessageRole.System), - ]; + setPendingMessages([]); + setMessages(nextMessages); - setMessages(allMessages); - - if (!lastMessage || !connectorId) { + if (!connectorId || !nextMessages.length) { setChatState(ChatState.Ready); - onChatCompleteRef.current?.(nextMessages); return; } - const isUserMessage = lastMessage.message.role === MessageRole.User; - const functionCall = lastMessage.message.function_call; - const isAssistantMessageWithFunctionRequest = - lastMessage.message.role === MessageRole.Assistant && functionCall && !!functionCall.name; - - const isFunctionResult = isUserMessage && !!lastMessage.message.name; - - const isRecallFunctionAvailable = chatService.hasFunction('recall'); - - if (!isUserMessage && !isAssistantMessageWithFunctionRequest) { - setChatState(ChatState.Ready); - onChatCompleteRef.current?.(nextMessages); - return; - } - - const abortController = (abortControllerRef.current = new AbortController()); - - abortController.signal.addEventListener('abort', handleSignalAbort); - setChatState(ChatState.Loading); - if (isUserMessage && !isFunctionResult && isRecallFunctionAvailable) { - const allMessagesWithRecall = allMessages.concat({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.Assistant, - content: '', - function_call: { - name: 'recall', - arguments: JSON.stringify({ queries: [], contexts: [] }), - trigger: MessageRole.Assistant, - }, - }, - }); - next(allMessagesWithRecall); - return; - } - - function handleError(error: Error) { - setChatState(ChatState.Error); - notifications.toasts.addError(error, { - title: i18n.translate('xpack.observabilityAiAssistant.failedToLoadResponse', { - defaultMessage: 'Failed to load response from the AI Assistant', - }), - }); - } - - const response = isAssistantMessageWithFunctionRequest - ? await chatService - .executeFunction({ - name: functionCall.name, - signal: abortController.signal, - args: functionCall.arguments, - connectorId, - messages: allMessages, - }) - .catch((error) => { - return { - content: { - message: error.toString(), - error, - }, - data: undefined, - }; - }) - : chatService.chat({ - messages: allMessages, - connectorId, - }); - - if (abortController.signal.aborted) { - return; + const next$ = chatService.complete({ + connectorId, + messages: getWithSystemMessage(nextMessages, systemMessage), + persist, + signal: abortControllerRef.current.signal, + conversationId: initialConversationId, + }); + + function getPendingMessages() { + return [ + ...completedMessages, + ...(pendingMessage + ? [ + merge( + { + message: { + role: MessageRole.Assistant, + function_call: { trigger: MessageRole.Assistant as const }, + }, + }, + pendingMessage + ), + ] + : []), + ]; } - if (isObservable(response)) { - let localPendingMessage: PendingMessage = { - message: { - content: '', - role: MessageRole.User, - }, - }; - - const subscription = response.subscribe({ - next: (nextPendingMessage) => { - localPendingMessage = nextPendingMessage; - setPendingMessage(nextPendingMessage); - }, - complete: () => { - setPendingMessage(undefined); - const allMessagesWithResolved = allMessages.concat({ - message: { - ...localPendingMessage.message, - }, - '@timestamp': new Date().toISOString(), - }); - if (localPendingMessage.aborted) { - setChatState(ChatState.Aborted); - setMessages(allMessagesWithResolved); - } else if (localPendingMessage.error) { - handleError(localPendingMessage.error); - setMessages(allMessagesWithResolved); - } else { - next(allMessagesWithResolved); - } - }, - error: (error) => { - handleError(error); - }, - }); - - abortController.signal.addEventListener('abort', () => { - subscription.unsubscribe(); - }); - } else { - const allMessagesWithFunctionReply = allMessages.concat({ - '@timestamp': new Date().toISOString(), - message: { - name: functionCall!.name, - role: MessageRole.User, - content: JSON.stringify(response.content), - data: JSON.stringify(response.data), - }, - }); - next(allMessagesWithFunctionReply); - } + const completedMessages: Message[] = []; + + let pendingMessage: + | { + '@timestamp': string; + message: { content: string; function_call: { name: string; arguments: string } }; + } + | undefined; + + const subscription = next$.subscribe({ + next: (event) => { + switch (event.type) { + case StreamingChatResponseEventType.ChatCompletionChunk: + if (!pendingMessage) { + pendingMessage = { + '@timestamp': new Date().toISOString(), + message: { + content: event.message.content || '', + function_call: { + name: event.message.function_call?.name || '', + arguments: event.message.function_call?.arguments || '', + }, + }, + }; + } else { + pendingMessage.message.content += event.message.content || ''; + pendingMessage.message.function_call.name += + event.message.function_call?.name || ''; + pendingMessage.message.function_call.arguments += + event.message.function_call?.arguments || ''; + } + break; + + case StreamingChatResponseEventType.MessageAdd: + pendingMessage = undefined; + completedMessages.push(event.message); + break; + + case StreamingChatResponseEventType.ConversationCreate: + case StreamingChatResponseEventType.ConversationUpdate: + onConversationUpdateRef.current?.(event); + break; + } + setPendingMessages(getPendingMessages()); + }, + complete: () => { + setChatState(ChatState.Ready); + const completed = nextMessages.concat(completedMessages); + setMessages(completed); + setPendingMessages([]); + onChatCompleteRef.current?.(completed); + }, + error: (error) => { + setPendingMessages([]); + setMessages(nextMessages.concat(getPendingMessages())); + handleError(error); + }, + }); + + abortControllerRef.current.signal.addEventListener('abort', () => { + handleSignalAbort(); + subscription.unsubscribe(); + }); }, - [connectorId, chatService, handleSignalAbort, notifications.toasts, systemMessage] + [ + connectorId, + chatService, + handleSignalAbort, + systemMessage, + handleError, + persist, + initialConversationId, + ] ); useEffect(() => { + const controller = abortControllerRef.current; return () => { - abortControllerRef.current.abort(); + controller.abort(); }; }, []); const memoizedMessages = useMemo(() => { - const includingSystemMessage = [ - systemMessage, - ...messages.filter((message) => message.message.role !== MessageRole.System), - ]; - - return pendingMessage - ? includingSystemMessage.concat({ - ...pendingMessage, - '@timestamp': new Date().toISOString(), - }) - : includingSystemMessage; - }, [systemMessage, messages, pendingMessage]); + return getWithSystemMessage(messages.concat(pendingMessages ?? []), systemMessage); + }, [systemMessage, messages, pendingMessages]); const setMessagesWithAbort = useCallback((nextMessages: Message[]) => { abortControllerRef.current.abort(); - setPendingMessage(undefined); + setPendingMessages([]); setChatState(ChatState.Ready); setMessages(nextMessages); }, []); diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.test.tsx b/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.test.tsx index f55cd3250bd5f..0b95de715a5dd 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.test.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.test.tsx @@ -4,28 +4,32 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -import { - useConversation, - type UseConversationProps, - type UseConversationResult, -} from './use_conversation'; +import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { act, renderHook, type RenderHookResult, type WrapperComponent, } from '@testing-library/react-hooks'; -import type { ObservabilityAIAssistantService, PendingMessage } from '../types'; -import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; -import { ObservabilityAIAssistantProvider } from '../context/observability_ai_assistant_provider'; -import * as useKibanaModule from './use_kibana'; -import { Message, MessageRole } from '../../common'; -import { ChatState } from './use_chat'; -import { createMockChatService } from '../service/create_mock_chat_service'; +import { merge } from 'lodash'; +import React from 'react'; import { Subject } from 'rxjs'; +import { MessageRole } from '../../common'; +import { + StreamingChatResponseEvent, + StreamingChatResponseEventType, +} from '../../common/conversation_complete'; +import { ObservabilityAIAssistantProvider } from '../context/observability_ai_assistant_provider'; import { EMPTY_CONVERSATION_TITLE } from '../i18n'; -import { merge, omit } from 'lodash'; +import { createMockChatService } from '../service/create_mock_chat_service'; +import type { ObservabilityAIAssistantService } from '../types'; +import { ChatState } from './use_chat'; +import { + useConversation, + type UseConversationProps, + type UseConversationResult, +} from './use_conversation'; +import * as useKibanaModule from './use_kibana'; let hookResult: RenderHookResult; @@ -270,8 +274,9 @@ describe('useConversation', () => { }); }); - describe('when chat completes without an initial conversation id', () => { - let subject: Subject; + describe('when chat completes', () => { + const subject: Subject = new Subject(); + let onConversationUpdate: jest.Mock; const expectedMessages = [ { '@timestamp': expect.any(String), @@ -310,7 +315,6 @@ describe('useConversation', () => { }, ]; beforeEach(() => { - subject = new Subject(); mockService.callApi.mockImplementation(async (endpoint, request) => merge( { @@ -323,6 +327,8 @@ describe('useConversation', () => { ) ); + onConversationUpdate = jest.fn(); + hookResult = renderHook(useConversation, { initialProps: { chatService: mockChatService, @@ -343,224 +349,66 @@ describe('useConversation', () => { }, }, ], + onConversationUpdate, }, wrapper, }); - mockChatService.chat.mockImplementationOnce(() => { + mockChatService.complete.mockImplementationOnce(() => { return subject; }); - - act(() => { - hookResult.result.current.next( - hookResult.result.current.messages.concat({ - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.User, - content: 'Hello again', - }, - }) - ); - }); }); - describe('when chat completes with an error', () => { + describe('and the conversation is created or updated', () => { beforeEach(async () => { - mockService.callApi.mockClear(); - act(() => { + await act(async () => { + hookResult.result.current.next( + hookResult.result.current.messages.concat({ + '@timestamp': new Date().toISOString(), + message: { + content: 'Hello again', + role: MessageRole.User, + }, + }) + ); subject.next({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: 'my-message', message: { - role: MessageRole.Assistant, content: 'Goodbye', }, - error: new Error(), }); - subject.complete(); - }); - await act(async () => {}); - }); - - it('does not store the conversation', () => { - expect(mockService.callApi).not.toHaveBeenCalled(); - }); - }); - - describe('when chat completes without an error', () => { - beforeEach(async () => { - act(() => { subject.next({ + type: StreamingChatResponseEventType.MessageAdd, + id: 'my-message', message: { - role: MessageRole.Assistant, - content: 'Goodbye again', - }, - }); - subject.complete(); - }); - - await act(async () => {}); - }); - it('the conversation is created including the initial messages', async () => { - expect(mockService.callApi.mock.calls[0]).toEqual([ - 'POST /internal/observability_ai_assistant/conversation', - { - params: { - body: { - conversation: { - '@timestamp': expect.any(String), - conversation: { - title: EMPTY_CONVERSATION_TITLE, - }, - messages: expectedMessages, - labels: {}, - numeric_labels: {}, - public: false, - }, + '@timestamp': new Date().toISOString(), + message: { + content: 'Goodbye', + role: MessageRole.Assistant, }, }, - signal: null, - }, - ]); - - expect(hookResult.result.current.conversation.error).toBeUndefined(); - - expect(hookResult.result.current.messages).toEqual(expectedMessages); - }); - }); - }); - - describe('when chat completes with an initial conversation id', () => { - let subject: Subject; - - const initialMessages: Message[] = [ - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.System, - content: '', - }, - }, - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.User, - content: 'user', - }, - }, - { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.Assistant, - content: 'assistant', - }, - }, - ]; - - beforeEach(async () => { - mockService.callApi.mockImplementation(async (endpoint, request) => ({ - '@timestamp': new Date().toISOString(), - conversation: { - id: 'my-conversation-id', - title: EMPTY_CONVERSATION_TITLE, - }, - labels: {}, - numeric_labels: {}, - public: false, - messages: initialMessages, - })); - - hookResult = renderHook(useConversation, { - initialProps: { - chatService: mockChatService, - connectorId: 'my-connector', - initialConversationId: 'my-conversation-id', - }, - wrapper, - }); - - await act(async () => {}); - }); - - it('the conversation is loadeded', async () => { - expect(mockService.callApi.mock.calls[0]).toEqual([ - 'GET /internal/observability_ai_assistant/conversation/{conversationId}', - { - signal: expect.anything(), - params: { - path: { - conversationId: 'my-conversation-id', + }); + subject.next({ + type: StreamingChatResponseEventType.ConversationUpdate, + conversation: { + id: 'my-conversation-id', + title: 'My title', + last_updated: new Date().toISOString(), }, - }, - }, - ]); - - expect(hookResult.result.current.messages).toEqual( - initialMessages.map((msg) => ({ ...msg, '@timestamp': expect.any(String) })) - ); - }); - - describe('after chat completes', () => { - const nextUserMessage: Message = { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.User, - content: 'Hello again', - }, - }; - - const nextAssistantMessage: Message = { - '@timestamp': new Date().toISOString(), - message: { - role: MessageRole.Assistant, - content: 'Goodbye again', - }, - }; - - beforeEach(async () => { - mockService.callApi.mockClear(); - subject = new Subject(); - - mockChatService.chat.mockImplementationOnce(() => { - return subject; - }); - - act(() => { - hookResult.result.current.next( - hookResult.result.current.messages.concat(nextUserMessage) - ); - subject.next(omit(nextAssistantMessage, '@timestamp')); + }); subject.complete(); }); - - await act(async () => {}); }); - it('saves the updated message', () => { - expect(mockService.callApi.mock.calls[0]).toEqual([ - 'PUT /internal/observability_ai_assistant/conversation/{conversationId}', - { - params: { - path: { - conversationId: 'my-conversation-id', - }, - body: { - conversation: { - '@timestamp': expect.any(String), - conversation: { - title: EMPTY_CONVERSATION_TITLE, - id: 'my-conversation-id', - }, - messages: initialMessages - .concat([nextUserMessage, nextAssistantMessage]) - .map((msg) => ({ ...msg, '@timestamp': expect.any(String) })), - labels: {}, - numeric_labels: {}, - public: false, - }, - }, - }, - signal: null, + it('calls the onConversationUpdate hook', () => { + expect(onConversationUpdate).toHaveBeenCalledWith({ + conversation: { + id: 'my-conversation-id', + last_updated: expect.any(String), + title: 'My title', }, - ]); + }); }); }); }); diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.ts index c753f7c7b1929..e9d5b3f8073e4 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.ts +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_conversation.ts @@ -38,7 +38,7 @@ export interface UseConversationProps { initialTitle?: string; chatService: ObservabilityAIAssistantChatService; connectorId: string | undefined; - onConversationUpdate?: (conversation: Conversation) => void; + onConversationUpdate?: (conversation: { conversation: Conversation['conversation'] }) => void; } export type UseConversationResult = { @@ -101,76 +101,16 @@ export function useConversation({ }); }; - const save = (nextMessages: Message[]) => { - const conversationObject = conversation.value!; - - const nextConversationObject = merge({}, omit(conversationObject, 'messages'), { - messages: nextMessages, - }); - - return ( - displayedConversationId - ? update( - merge( - { conversation: { id: displayedConversationId } }, - nextConversationObject - ) as Conversation - ) - : service - .callApi(`POST /internal/observability_ai_assistant/conversation`, { - signal: null, - params: { - body: { - conversation: nextConversationObject, - }, - }, - }) - .then((nextConversation) => { - setDisplayedConversationId(nextConversation.conversation.id); - if (connectorId) { - service - .callApi( - `PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title`, - { - signal: null, - params: { - path: { - conversationId: nextConversation.conversation.id, - }, - body: { - connectorId, - }, - }, - } - ) - .then(() => { - onConversationUpdate?.(nextConversation); - return conversation.refresh(); - }); - } - return nextConversation; - }) - .catch((err) => { - notifications.toasts.addError(err, { - title: i18n.translate('xpack.observabilityAiAssistant.errorCreatingConversation', { - defaultMessage: 'Could not create conversation', - }), - }); - throw err; - }) - ).then((nextConversation) => { - onConversationUpdate?.(nextConversation); - return nextConversation; - }); - }; - const { next, messages, setMessages, state, stop } = useChat({ initialMessages, + initialConversationId, chatService, connectorId, - onChatComplete: (nextMessages) => { - save(nextMessages); + onConversationUpdate: (event) => { + setDisplayedConversationId(event.conversation.id); + onConversationUpdate?.({ conversation: event.conversation }); }, + persist: true, }); const [displayedConversationId, setDisplayedConversationId] = useState(initialConversationId); diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_json_editor_model.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_json_editor_model.ts index e6d1f81dabd2f..44122614abd5d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_json_editor_model.ts +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_json_editor_model.ts @@ -23,21 +23,19 @@ export const useJsonEditorModel = ({ }) => { const chatService = useObservabilityAIAssistantChatService(); - const functionDefinition = chatService - .getFunctions() - .find((func) => func.options.name === functionName); + const functionDefinition = chatService.getFunctions().find((func) => func.name === functionName); return useMemo(() => { if (!functionDefinition) { return {}; } - const schema = { ...functionDefinition.options.parameters }; + const schema = { ...functionDefinition.parameters }; const initialJsonString = initialJson ? initialJson - : functionDefinition.options.parameters.properties - ? JSON.stringify(createInitializedObject(functionDefinition.options.parameters), null, 4) + : functionDefinition.parameters.properties + ? JSON.stringify(createInitializedObject(functionDefinition.parameters), null, 4) : ''; languages.json.jsonDefaults.setDiagnosticsOptions({ diff --git a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx index e71562f6de26c..3a684bb870e1e 100644 --- a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx @@ -107,19 +107,19 @@ export class ObservabilityAIAssistantPlugin shareStart: pluginsStart.share, })); - service.register(async ({ signal, registerContext, registerFunction }) => { + service.register(async ({ registerRenderFunction }) => { const mod = await import('./functions'); return mod.registerFunctions({ service, - signal, pluginsStart, - coreStart, - registerContext, - registerFunction, + registerRenderFunction, }); }); - return { service, useGenAIConnectors: () => useGenAIConnectorsWithoutContext(service) }; + return { + service, + useGenAIConnectors: () => useGenAIConnectorsWithoutContext(service), + }; } } diff --git a/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.test.ts b/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.test.ts index 0f760f3823b2f..0e946f4b0986d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.test.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.test.ts @@ -39,6 +39,12 @@ describe('createChatService', () => { } beforeEach(async () => { + clientSpy.mockImplementationOnce(async () => { + return { + functionDefinitions: [], + contextDefinitions: [], + }; + }); service = await createChatService({ analytics: { optIn: () => {}, diff --git a/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.ts b/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.ts index 4dbd61c55ecea..5de057934ad9e 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/create_chat_service.ts @@ -4,8 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -/* eslint-disable max-classes-per-file*/ -import { Validator, type Schema, type OutputUnit } from '@cfworker/json-schema'; import { AnalyticsServiceStart, HttpResponse } from '@kbn/core/public'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; @@ -16,45 +14,82 @@ import { catchError, concatMap, delay, - filter as rxJsFilter, finalize, - map, of, scan, shareReplay, - tap, + Subject, timestamp, + map, + tap, } from 'rxjs'; import { - ContextRegistry, - FunctionRegistry, + ChatCompletionErrorCode, + ConversationCompletionError, + type StreamingChatResponseEvent, + StreamingChatResponseEventType, +} from '../../common/conversation_complete'; +import { FunctionVisibility, - Message, MessageRole, - type RegisterContextDefinition, - type RegisterFunctionDefinition, + type FunctionRegistry, + type FunctionResponse, + type Message, } from '../../common/types'; -import { ObservabilityAIAssistantAPIClient } from '../api'; +import { filterFunctionDefinitions } from '../../common/utils/filter_function_definitions'; +import { processOpenAiStream } from '../../common/utils/process_openai_stream'; +import type { ObservabilityAIAssistantAPIClient } from '../api'; import type { - AssistantRegistrationFunction, - CreateChatCompletionResponseChunk, + ChatRegistrationRenderFunction, ObservabilityAIAssistantChatService, PendingMessage, + RenderFunction, } from '../types'; import { readableStreamReaderIntoObservable } from '../utils/readable_stream_reader_into_observable'; -class TokenLimitReachedError extends Error { - constructor() { - super(`Token limit reached`); +const MIN_DELAY = 35; + +function toObservable(response: HttpResponse) { + const status = response.response?.status; + + if (!status || status >= 400) { + throw new Error(response.response?.statusText || 'Unexpected error'); } -} -class ServerError extends Error {} + const reader = response.response.body?.getReader(); -export class FunctionArgsValidationError extends Error { - constructor(public readonly errors: OutputUnit[]) { - super('Function arguments are invalid'); + if (!reader) { + throw new Error('Could not get reader from response'); } + + return readableStreamReaderIntoObservable(reader).pipe( + // append a timestamp of when each value was emitted + timestamp(), + // use the previous timestamp to calculate a target + // timestamp for emitting the next value + scan((acc, value) => { + const lastTimestamp = acc.timestamp || 0; + const emitAt = Math.max(lastTimestamp + MIN_DELAY, value.timestamp); + return { + timestamp: emitAt, + value: value.value, + }; + }), + // add the delay based on the elapsed time + // using concatMap(of(value).pipe(delay(50)) + // leads to browser issues because timers + // are throttled when the tab is not active + concatMap((value) => { + const now = Date.now(); + const delayFor = value.timestamp - now; + + if (delayFor <= 0) { + return of(value.value); + } + + return of(value.value).pipe(delay(delayFor)); + }) + ); } export async function createChatService({ @@ -65,73 +100,41 @@ export async function createChatService({ }: { analytics: AnalyticsServiceStart; signal: AbortSignal; - registrations: AssistantRegistrationFunction[]; + registrations: ChatRegistrationRenderFunction[]; client: ObservabilityAIAssistantAPIClient; }): Promise { - const contextRegistry: ContextRegistry = new Map(); const functionRegistry: FunctionRegistry = new Map(); - const validators = new Map(); - - const registerContext: RegisterContextDefinition = (context) => { - contextRegistry.set(context.name, context); - }; - - const registerFunction: RegisterFunctionDefinition = (def, respond, render) => { - validators.set(def.name, new Validator(def.parameters as Schema, '2020-12', true)); - functionRegistry.set(def.name, { options: def, respond, render }); - }; - - const getContexts: ObservabilityAIAssistantChatService['getContexts'] = () => { - return Array.from(contextRegistry.values()); - }; - const getFunctions: ObservabilityAIAssistantChatService['getFunctions'] = ({ - contexts, - filter, - } = {}) => { - const allFunctions = Array.from(functionRegistry.values()); + const renderFunctionRegistry: Map> = new Map(); - return contexts || filter - ? allFunctions.filter((fn) => { - const matchesContext = - !contexts || fn.options.contexts.some((context) => contexts.includes(context)); - const matchesFilter = - !filter || fn.options.name.includes(filter) || fn.options.description.includes(filter); - - return matchesContext && matchesFilter; - }) - : allFunctions; + const [{ functionDefinitions, contextDefinitions }] = await Promise.all([ + client('GET /internal/observability_ai_assistant/functions', { + signal: setupAbortSignal, + }), + ...registrations.map((registration) => { + return registration({ + registerRenderFunction: (name, renderFn) => { + renderFunctionRegistry.set(name, renderFn); + }, + }); + }), + ]); + + functionDefinitions.forEach((fn) => { + functionRegistry.set(fn.name, fn); + }); + + const getFunctions = (options?: { contexts?: string[]; filter?: string }) => { + return filterFunctionDefinitions({ + ...options, + definitions: functionDefinitions, + }); }; - await Promise.all( - registrations.map((fn) => fn({ signal: setupAbortSignal, registerContext, registerFunction })) - ); - - function validate(name: string, parameters: unknown) { - const validator = validators.get(name)!; - const result = validator.validate(parameters); - if (!result.valid) { - throw new FunctionArgsValidationError(result.errors); - } - } - return { analytics, - executeFunction: async ({ name, args, signal, messages, connectorId }) => { - const fn = functionRegistry.get(name); - - if (!fn) { - throw new Error(`Function ${name} not found`); - } - - const parsedArguments = args ? JSON.parse(args) : {}; - - validate(name, parsedArguments); - - return await fn.respond({ arguments: parsedArguments, messages, connectorId }, signal); - }, renderFunction: (name, args, response) => { - const fn = functionRegistry.get(name); + const fn = renderFunctionRegistry.get(name); if (!fn) { throw new Error(`Function ${name} not found`); @@ -144,15 +147,57 @@ export async function createChatService({ data: JSON.parse(response.data ?? '{}'), }; - return fn.render?.({ response: parsedResponse, arguments: parsedArguments }); + return fn?.({ response: parsedResponse, arguments: parsedArguments }); }, - getContexts, + getContexts: () => contextDefinitions, getFunctions, hasFunction: (name: string) => { - return !!getFunctions().find((fn) => fn.options.name === name); + return functionRegistry.has(name); }, hasRenderFunction: (name: string) => { - return !!getFunctions().find((fn) => fn.options.name === name)?.render; + return renderFunctionRegistry.has(name); + }, + complete({ connectorId, messages, conversationId, persist, signal }) { + const subject = new Subject(); + + client('POST /internal/observability_ai_assistant/chat/complete', { + params: { + body: { + messages, + connectorId, + conversationId, + persist, + }, + }, + signal, + asResponse: true, + rawResponse: true, + }) + .then((_response) => { + const response = _response as unknown as HttpResponse; + const response$ = toObservable(response) + .pipe( + map((line) => JSON.parse(line) as StreamingChatResponseEvent), + tap((event) => { + if (event.type === StreamingChatResponseEventType.ConversationCompletionError) { + const code = event.error.code ?? ChatCompletionErrorCode.InternalError; + const message = event.error.message; + throw new ConversationCompletionError(code, message); + } + }) + ) + .subscribe(subject); + + signal.addEventListener('abort', () => { + response$.unsubscribe(); + }); + }) + .catch((err) => { + subject.error(err); + subject.complete(); + }); + + return subject; }, chat({ connectorId, @@ -184,8 +229,8 @@ export async function createChatService({ callFunctions === 'none' ? [] : functions - .filter((fn) => fn.options.visibility !== FunctionVisibility.User) - .map((fn) => pick(fn.options, 'name', 'description', 'parameters')), + .filter((fn) => fn.visibility !== FunctionVisibility.User) + .map((fn) => pick(fn, 'name', 'description', 'parameters')), }, }, signal: controller.signal, @@ -195,51 +240,9 @@ export async function createChatService({ .then((_response) => { const response = _response as unknown as HttpResponse; - const status = response.response?.status; - - if (!status || status >= 400) { - throw new Error(response.response?.statusText || 'Unexpected error'); - } - - const reader = response.response.body?.getReader(); - - if (!reader) { - throw new Error('Could not get reader from response'); - } - - const subscription = readableStreamReaderIntoObservable(reader) + const subscription = toObservable(response) .pipe( - // lines start with 'data: ' - map((line) => line.substring(6)), - // a message completes with the line '[DONE]' - rxJsFilter((line) => !!line && line !== '[DONE]'), - // parse the JSON, add the type - map( - (line) => - JSON.parse(line) as - | CreateChatCompletionResponseChunk - | { error: { message: string } } - ), - // validate the message. in some cases OpenAI - // will throw halfway through the message - tap((line) => { - if ('error' in line) { - throw new ServerError(line.error.message); - } - }), - // there also might be some metadata that we need - // to exclude - rxJsFilter( - (line): line is CreateChatCompletionResponseChunk => - 'object' in line && line.object === 'chat.completion.chunk' - ), - // this is how OpenAI signals that the context window - // limit has been exceeded - tap((line) => { - if (line.choices[0].finish_reason === 'length') { - throw new TokenLimitReachedError(); - } - }), + processOpenAiStream(), // merge the messages scan( (acc, { choices }) => { @@ -301,8 +304,6 @@ export async function createChatService({ subject.complete(); }); - const MIN_DELAY = 35; - const pendingMessages$ = subject.pipe( // make sure the request is only triggered once, // even with multiple subscribers @@ -311,32 +312,6 @@ export async function createChatService({ // abort the running request finalize(() => { controller.abort(); - }), - // append a timestamp of when each value was emitted - timestamp(), - // use the previous timestamp to calculate a target - // timestamp for emitting the next value - scan((acc, value) => { - const lastTimestamp = acc.timestamp || 0; - const emitAt = Math.max(lastTimestamp + MIN_DELAY, value.timestamp); - return { - timestamp: emitAt, - value: value.value, - }; - }), - // add the delay based on the elapsed time - // using concatMap(of(value).pipe(delay(50)) - // leads to browser issues because timers - // are throttled when the tab is not active - concatMap((value) => { - const now = Date.now(); - const delayFor = value.timestamp - now; - - if (delayFor <= 0) { - return of(value.value); - } - - return of(value.value).pipe(delay(delayFor)); }) ); diff --git a/x-pack/plugins/observability_ai_assistant/public/service/create_mock_chat_service.ts b/x-pack/plugins/observability_ai_assistant/public/service/create_mock_chat_service.ts index 4b10debab5c0a..64946cc862d5e 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/create_mock_chat_service.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/create_mock_chat_service.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { TelemetryCounter } from '@kbn/analytics-client'; +import type { TelemetryCounter } from '@kbn/analytics-client'; import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; import { Observable } from 'rxjs'; import type { ObservabilityAIAssistantChatService } from '../types'; @@ -14,13 +14,13 @@ type MockedChatService = DeeplyMockedKeys; export const createMockChatService = (): MockedChatService => { const mockChatService: MockedChatService = { + chat: jest.fn(), + complete: jest.fn(), analytics: { optIn: jest.fn(), reportEvent: jest.fn(), telemetryCounter$: new Observable() as any, }, - chat: jest.fn(), - executeFunction: jest.fn(), getContexts: jest.fn().mockReturnValue([{ name: 'core', description: '' }]), getFunctions: jest.fn().mockReturnValue([]), hasFunction: jest.fn().mockReturnValue(false), diff --git a/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts b/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts index c83f9fb8178e1..721f13234591b 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts @@ -10,7 +10,7 @@ import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import { createCallObservabilityAIAssistantAPI } from '../api'; -import type { AssistantRegistrationFunction, ObservabilityAIAssistantService } from '../types'; +import type { ChatRegistrationRenderFunction, ObservabilityAIAssistantService } from '../types'; export function createService({ analytics, @@ -29,7 +29,7 @@ export function createService({ }): ObservabilityAIAssistantService { const client = createCallObservabilityAIAssistantAPI(coreStart); - const registrations: AssistantRegistrationFunction[] = []; + const registrations: ChatRegistrationRenderFunction[] = []; return { isEnabled: () => { @@ -42,7 +42,6 @@ export function createService({ const mod = await import('./create_chat_service'); return await mod.createChatService({ analytics, client, signal, registrations }); }, - callApi: client, getCurrentUser: () => securityStart.authc.getCurrentUser(), getLicense: () => licenseStart.license$, diff --git a/x-pack/plugins/observability_ai_assistant/public/types.ts b/x-pack/plugins/observability_ai_assistant/public/types.ts index 274dc953e679e..a664638365eaf 100644 --- a/x-pack/plugins/observability_ai_assistant/public/types.ts +++ b/x-pack/plugins/observability_ai_assistant/public/types.ts @@ -20,11 +20,6 @@ import type { TriggersAndActionsUIPublicPluginSetup, TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; -import type { Serializable } from '@kbn/utility-types'; -import type { - CreateChatCompletionResponse, - CreateChatCompletionResponseChoicesInner, -} from 'openai'; import type { Observable } from 'rxjs'; import type { LensPublicSetup, LensPublicStart } from '@kbn/lens-plugin/public'; import type { @@ -36,23 +31,17 @@ import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { ContextDefinition, FunctionDefinition, + FunctionResponse, Message, - RegisterContextDefinition, - RegisterFunctionDefinition, } from '../common/types'; import type { ObservabilityAIAssistantAPIClient } from './api'; import type { PendingMessage } from '../common/types'; -import { UseGenAIConnectorsResult } from './hooks/use_genai_connectors'; +import type { StreamingChatResponseEvent } from '../common/conversation_complete'; +import type { UseGenAIConnectorsResult } from './hooks/use_genai_connectors'; /* eslint-disable @typescript-eslint/no-empty-interface*/ -export type CreateChatCompletionResponseChunk = Omit & { - choices: Array< - Omit & { - delta: { content?: string; function_call?: { name?: string; arguments?: string } }; - } - >; -}; +export type { CreateChatCompletionResponseChunk } from '../common/types'; export interface ObservabilityAIAssistantChatService { analytics: AnalyticsServiceStart; @@ -61,17 +50,17 @@ export interface ObservabilityAIAssistantChatService { connectorId: string; function?: 'none' | 'auto'; }) => Observable; + complete: (options: { + messages: Message[]; + connectorId: string; + persist: boolean; + conversationId?: string; + signal: AbortSignal; + }) => Observable; getContexts: () => ContextDefinition[]; getFunctions: (options?: { contexts?: string[]; filter?: string }) => FunctionDefinition[]; hasFunction: (name: string) => boolean; hasRenderFunction: (name: string) => boolean; - executeFunction: ({}: { - name: string; - args: string | undefined; - messages: Message[]; - signal: AbortSignal; - connectorId: string; - }) => Promise<{ content?: Serializable; data?: Serializable } | Observable>; renderFunction: ( name: string, args: string | undefined, @@ -79,12 +68,6 @@ export interface ObservabilityAIAssistantChatService { ) => React.ReactNode; } -export type AssistantRegistrationFunction = ({}: { - signal: AbortSignal; - registerFunction: RegisterFunctionDefinition; - registerContext: RegisterContextDefinition; -}) => Promise; - export interface ObservabilityAIAssistantService { isEnabled: () => boolean; callApi: ObservabilityAIAssistantAPIClient; @@ -92,9 +75,23 @@ export interface ObservabilityAIAssistantService { getLicense: () => Observable; getLicenseManagementLocator: () => SharePluginStart; start: ({}: { signal: AbortSignal }) => Promise; - register: (fn: AssistantRegistrationFunction) => void; + register: (fn: ChatRegistrationRenderFunction) => void; } +export type RenderFunction = (options: { + arguments: TArguments; + response: TResponse; +}) => React.ReactNode; + +export type RegisterRenderFunctionDefinition< + TFunctionArguments = any, + TFunctionResponse extends FunctionResponse = FunctionResponse +> = (name: string, render: RenderFunction) => void; + +export type ChatRegistrationRenderFunction = ({}: { + registerRenderFunction: RegisterRenderFunctionDefinition; +}) => Promise; + export interface ObservabilityAIAssistantPluginStart { service: ObservabilityAIAssistantService; useGenAIConnectors: () => UseGenAIConnectorsResult; diff --git a/x-pack/plugins/observability_ai_assistant/public/utils/builders.ts b/x-pack/plugins/observability_ai_assistant/public/utils/builders.ts index 6f2d1e5c2f090..6ba40e8bc692d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/utils/builders.ts +++ b/x-pack/plugins/observability_ai_assistant/public/utils/builders.ts @@ -7,7 +7,12 @@ import { merge, uniqueId } from 'lodash'; import { DeepPartial } from 'utility-types'; -import { MessageRole, Conversation, FunctionDefinition, Message } from '../../common/types'; +import { + type Conversation, + type FunctionDefinition, + type Message, + MessageRole, +} from '../../common/types'; import { getAssistantSetupMessage } from '../service/get_assistant_setup_message'; type BuildMessageProps = DeepPartial & { @@ -121,28 +126,25 @@ export function buildConversation(params?: Partial) { export function buildFunction(): FunctionDefinition { return { - options: { - name: 'elasticsearch', - contexts: ['core'], - description: 'Call Elasticsearch APIs on behalf of the user', - descriptionForUser: 'Call Elasticsearch APIs on behalf of the user', - parameters: { - type: 'object', - properties: { - method: { - type: 'string', - description: 'The HTTP method of the Elasticsearch endpoint', - enum: ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'] as const, - }, - path: { - type: 'string', - description: 'The path of the Elasticsearch endpoint, including query parameters', - }, + name: 'elasticsearch', + contexts: ['core'], + description: 'Call Elasticsearch APIs on behalf of the user', + descriptionForUser: 'Call Elasticsearch APIs on behalf of the user', + parameters: { + type: 'object', + properties: { + method: { + type: 'string', + description: 'The HTTP method of the Elasticsearch endpoint', + enum: ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'] as const, + }, + path: { + type: 'string', + description: 'The path of the Elasticsearch endpoint, including query parameters', }, - required: ['method' as const, 'path' as const], }, + required: ['method' as const, 'path' as const], }, - respond: async (options: { arguments: any }, signal: AbortSignal) => ({}), }; } @@ -150,16 +152,13 @@ export const buildFunctionElasticsearch = buildFunction; export function buildFunctionServiceSummary(): FunctionDefinition { return { - options: { - name: 'get_service_summary', - contexts: ['core'], - description: - 'Gets a summary of a single service, including: the language, service version, deployments, infrastructure, alerting, etc. ', - descriptionForUser: 'Get a summary for a single service.', - parameters: { - type: 'object', - }, + name: 'get_service_summary', + contexts: ['core'], + description: + 'Gets a summary of a single service, including: the language, service version, deployments, infrastructure, alerting, etc. ', + descriptionForUser: 'Get a summary for a single service.', + parameters: { + type: 'object', }, - respond: async (options: { arguments: any }, signal: AbortSignal) => ({}), }; } diff --git a/x-pack/plugins/observability_ai_assistant/public/utils/create_initialized_object.ts b/x-pack/plugins/observability_ai_assistant/public/utils/create_initialized_object.ts index 42f314766dca9..6ae23042a63e6 100644 --- a/x-pack/plugins/observability_ai_assistant/public/utils/create_initialized_object.ts +++ b/x-pack/plugins/observability_ai_assistant/public/utils/create_initialized_object.ts @@ -7,7 +7,7 @@ import { FunctionDefinition } from '../../common/types'; -type Params = FunctionDefinition['options']['parameters']; +type Params = FunctionDefinition['parameters']; export function createInitializedObject(parameters: Params) { const emptyObject: Record = {}; diff --git a/x-pack/plugins/observability_ai_assistant/public/utils/storybook_decorator.tsx b/x-pack/plugins/observability_ai_assistant/public/utils/storybook_decorator.tsx index 6311c64308073..04a30ce53059d 100644 --- a/x-pack/plugins/observability_ai_assistant/public/utils/storybook_decorator.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/utils/storybook_decorator.tsx @@ -4,22 +4,22 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { ComponentType } from 'react'; -import { Observable } from 'rxjs'; +import { i18n } from '@kbn/i18n'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import type { Serializable } from '@kbn/utility-types'; import type { AuthenticatedUser } from '@kbn/security-plugin/common'; import type { SharePluginStart } from '@kbn/share-plugin/public'; -import { ObservabilityAIAssistantProvider } from '../context/observability_ai_assistant_provider'; +import React, { ComponentType } from 'react'; +import { Observable } from 'rxjs'; +import type { StreamingChatResponseEvent } from '../../common/conversation_complete'; import { ObservabilityAIAssistantAPIClient } from '../api'; -import type { Message } from '../../common'; +import { ObservabilityAIAssistantChatServiceProvider } from '../context/observability_ai_assistant_chat_service_provider'; +import { ObservabilityAIAssistantProvider } from '../context/observability_ai_assistant_provider'; import type { ObservabilityAIAssistantChatService, ObservabilityAIAssistantService, PendingMessage, } from '../types'; import { buildFunctionElasticsearch, buildFunctionServiceSummary } from './builders'; -import { ObservabilityAIAssistantChatServiceProvider } from '../context/observability_ai_assistant_chat_service_provider'; const chatService: ObservabilityAIAssistantChatService = { analytics: { @@ -27,18 +27,17 @@ const chatService: ObservabilityAIAssistantChatService = { reportEvent: () => {}, telemetryCounter$: new Observable(), }, - chat: (options: { messages: Message[]; connectorId: string }) => new Observable(), + chat: (options) => new Observable(), + complete: (options) => new Observable(), getContexts: () => [], getFunctions: () => [buildFunctionElasticsearch(), buildFunctionServiceSummary()], - executeFunction: async ({}: { - name: string; - args: string | undefined; - messages: Message[]; - signal: AbortSignal; - }): Promise<{ content?: Serializable; data?: Serializable }> => ({}), - renderFunction: (name: string, args: string | undefined, response: {}) => ( - // eslint-disable-next-line @kbn/i18n/strings_should_be_translated_with_i18n -
Hello! {name}
+ renderFunction: (name) => ( +
+ {i18n.translate('xpack.observabilityAiAssistant.chatService.div.helloLabel', { + defaultMessage: 'Hello', + })} + {name} +
), hasFunction: () => true, hasRenderFunction: () => true, diff --git a/x-pack/plugins/observability_ai_assistant/server/functions/alerts.ts b/x-pack/plugins/observability_ai_assistant/server/functions/alerts.ts new file mode 100644 index 0000000000000..e58d75c52cf74 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/functions/alerts.ts @@ -0,0 +1,153 @@ +/* + * 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 datemath from '@elastic/datemath'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import { + ALERT_STATUS, + ALERT_STATUS_ACTIVE, +} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import { omit } from 'lodash'; +import { FunctionRegistrationParameters } from '.'; + +const OMITTED_ALERT_FIELDS = [ + 'tags', + 'event.action', + 'event.kind', + 'kibana.alert.rule.execution.uuid', + 'kibana.alert.rule.revision', + 'kibana.alert.rule.tags', + 'kibana.alert.rule.uuid', + 'kibana.alert.workflow_status', + 'kibana.space_ids', + 'kibana.alert.time_range', + 'kibana.version', +] as const; + +const DEFAULT_FEATURE_IDS = [ + 'apm', + 'infrastructure', + 'logs', + 'uptime', + 'slo', + 'observability', +] as const; + +export function registerAlertsFunction({ + client, + registerFunction, + resources, +}: FunctionRegistrationParameters) { + registerFunction( + { + name: 'alerts', + contexts: ['core'], + description: + 'Get alerts for Observability. Display the response in tabular format if appropriate.', + descriptionForUser: 'Get alerts for Observability', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + featureIds: { + type: 'array', + additionalItems: false, + items: { + type: 'string', + enum: DEFAULT_FEATURE_IDS, + }, + description: + 'The Observability apps for which to retrieve alerts. By default it will return alerts for all apps.', + }, + start: { + type: 'string', + description: 'The start of the time range, in Elasticsearch date math, like `now`.', + }, + end: { + type: 'string', + description: 'The end of the time range, in Elasticsearch date math, like `now-24h`.', + }, + filter: { + type: 'string', + description: + 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', + }, + includeRecovered: { + type: 'boolean', + description: + 'Whether to include recovered/closed alerts. Defaults to false, which means only active alerts will be returned', + }, + }, + required: ['start', 'end'], + } as const, + }, + async ( + { + arguments: { + start: startAsDatemath, + end: endAsDatemath, + featureIds, + filter, + includeRecovered, + }, + }, + signal + ) => { + const racContext = await resources.context.rac; + const alertsClient = await racContext.getAlertsClient(); + + const start = datemath.parse(startAsDatemath)!.valueOf(); + const end = datemath.parse(endAsDatemath)!.valueOf(); + + const kqlQuery = !filter ? [] : [toElasticsearchQuery(fromKueryExpression(filter))]; + + const response = await alertsClient.find({ + featureIds: + !!featureIds && !!featureIds.length + ? featureIds + : (DEFAULT_FEATURE_IDS as unknown as string[]), + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: start, + lte: end, + }, + }, + }, + ...kqlQuery, + ...(!includeRecovered + ? [ + { + term: { + [ALERT_STATUS]: ALERT_STATUS_ACTIVE, + }, + }, + ] + : []), + ], + }, + }, + }); + + // trim some fields + const alerts = response.hits.hits.map((hit) => + omit(hit._source, ...OMITTED_ALERT_FIELDS) + ) as unknown as ParsedTechnicalFields[]; + + return { + content: { + total: (response.hits as { total: { value: number } }).total.value, + alerts, + }, + }; + } + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts b/x-pack/plugins/observability_ai_assistant/server/functions/elasticsearch.ts similarity index 65% rename from x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts rename to x-pack/plugins/observability_ai_assistant/server/functions/elasticsearch.ts index 546bd2bea4574..44cb30233504a 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/elasticsearch.ts +++ b/x-pack/plugins/observability_ai_assistant/server/functions/elasticsearch.ts @@ -5,17 +5,12 @@ * 2.0. */ -import type { Serializable } from '@kbn/utility-types'; -import type { RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; +import type { FunctionRegistrationParameters } from '.'; export function registerElasticsearchFunction({ - service, registerFunction, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; -}) { + resources, +}: FunctionRegistrationParameters) { registerFunction( { name: 'elasticsearch', @@ -43,19 +38,16 @@ export function registerElasticsearchFunction({ required: ['method', 'path'] as const, }, }, - ({ arguments: { method, path, body } }, signal) => { - return service - .callApi(`POST /internal/observability_ai_assistant/functions/elasticsearch`, { - signal, - params: { - body: { - method, - path, - body, - }, - }, - }) - .then((response) => ({ content: response as Serializable })); + async ({ arguments: { method, path, body } }) => { + const response = await ( + await resources.context.core + ).elasticsearch.client.asCurrentUser.transport.request({ + method, + path, + body, + }); + + return { content: response }; } ); } diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/esql.ts b/x-pack/plugins/observability_ai_assistant/server/functions/esql.ts similarity index 89% rename from x-pack/plugins/observability_ai_assistant/public/functions/esql.ts rename to x-pack/plugins/observability_ai_assistant/server/functions/esql.ts index 56c3c83360821..88997452c0ad8 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/esql.ts +++ b/x-pack/plugins/observability_ai_assistant/server/functions/esql.ts @@ -6,22 +6,21 @@ */ import dedent from 'dedent'; -import type { Serializable } from '@kbn/utility-types'; -import { concat, last, map } from 'rxjs'; +import { Observable } from 'rxjs'; +import type { FunctionRegistrationParameters } from '.'; import { + type CreateChatCompletionResponseChunk, FunctionVisibility, MessageRole, - type RegisterFunctionDefinition, } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; +import { processOpenAiStream } from '../../common/utils/process_openai_stream'; +import { streamIntoObservable } from '../service/util/stream_into_observable'; export function registerEsqlFunction({ - service, + client, registerFunction, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; -}) { + resources, +}: FunctionRegistrationParameters) { registerFunction( { name: 'execute_query', @@ -39,21 +38,18 @@ export function registerEsqlFunction({ required: ['query'], } as const, }, - ({ arguments: { query } }, signal) => { - return service - .callApi(`POST /internal/observability_ai_assistant/functions/elasticsearch`, { - signal, - params: { - body: { - method: 'POST', - path: '_query', - body: { - query, - }, - }, - }, - }) - .then((response) => ({ content: response as Serializable })); + async ({ arguments: { query } }) => { + const response = await ( + await resources.context.core + ).elasticsearch.client.asCurrentUser.transport.request({ + method: 'POST', + path: '_query', + body: { + query, + }, + }); + + return { content: response }; } ); @@ -73,10 +69,10 @@ export function registerEsqlFunction({ }, } as const, }, - ({ messages, connectorId }, signal) => { + async ({ messages, connectorId }, signal) => { const systemMessage = dedent(`You are a helpful assistant for Elastic ES|QL. Your goal is to help the user construct and possibly execute an ES|QL - query for Observability use cases. + query for Observability use cases. ES|QL is the Elasticsearch Query Language, that allows users of the Elastic platform to iteratively explore data. An ES|QL query consists @@ -92,7 +88,7 @@ export function registerEsqlFunction({ the context of this conversation. # Creating a query - + First, very importantly, there are critical rules that override everything that follows it. Always repeat these rules, verbatim. @@ -144,6 +140,10 @@ export function registerEsqlFunction({ -- Let's break down the query step-by-step: + + \`\`\`esql + + \`\`\` \`\`\` Always format a complete query as follows: @@ -203,7 +203,7 @@ export function registerEsqlFunction({ - \`1 year\` - \`2 milliseconds\` - ## Aliasing + ## Aliasing Aliasing happens through the \`=\` operator. Example: \`STATS total_salary_expenses = COUNT(salary)\` @@ -211,7 +211,7 @@ export function registerEsqlFunction({ # Source commands - There are three source commands: FROM (which selects an index), ROW + There are three source commands: FROM (which selects an index), ROW (which creates data from the command) and SHOW (which returns information about the deployment). You do not support SHOW for now. @@ -276,10 +276,10 @@ export function registerEsqlFunction({ This is right: \`| STATS avg_cpu = AVG(cpu) | SORT avg_cpu\` ### EVAL - + \`EVAL\` appends a new column to the documents by using aliasing. It also supports functions, but not aggregation functions like COUNT: - + - \`\`\` | EVAL monthly_salary = yearly_salary / 12, total_comp = ROUND(yearly_salary + yearly+bonus), @@ -396,7 +396,7 @@ export function registerEsqlFunction({ can be expressed using the timespan literal syntax. Use this together with STATS ... BY to group data into time buckets with a fixed interval. Some examples: - + - \`| EVAL year_hired = DATE_TRUNC(1 year, hire_date)\` - \`| EVAL month_logged = DATE_TRUNC(1 month, @timestamp)\` - \`| EVAL bucket = DATE_TRUNC(1 minute, @timestamp) | STATS avg_salary = AVG(salary) BY bucket\` @@ -431,7 +431,7 @@ export function registerEsqlFunction({ Returns the greatest or least of two or numbers. Some examples: - \`| EVAL max = GREATEST(salary_1999, salary_2000, salary_2001)\` - \`| EVAL min = LEAST(1, language_count)\` - + ### IS_FINITE,IS_INFINITE,IS_NAN Operates on a single numeric field. Some examples: @@ -459,7 +459,7 @@ export function registerEsqlFunction({ - \`| EVAL version = TO_VERSION("1.2.3")\` - \`| EVAL as_bool = TO_BOOLEAN(my_boolean_string)\` - \`| EVAL percent = TO_DOUBLE(part) / TO_DOUBLE(total)\` - + ### TRIM Trims leading and trailing whitespace. Some examples: @@ -482,7 +482,7 @@ export function registerEsqlFunction({ argument, and does not support wildcards. One single argument is required. If you don't have a field name, use whatever field you have, rather than displaying an invalid query. - + Some examples: - \`| STATS doc_count = COUNT(emp_no)\` @@ -496,16 +496,16 @@ export function registerEsqlFunction({ - \`| STATS first_name = COUNT_DISTINCT(first_name)\` ### PERCENTILE - + \`PERCENTILE\` returns the percentile value for a specific field. Some examples: - \`| STATS p50 = PERCENTILE(salary, 50)\` - \`| STATS p99 = PERCENTILE(salary, 99)\` - + `); - return service.start({ signal }).then((client) => { - const source$ = client.chat({ + const source$ = streamIntoObservable( + await client.chat({ connectorId, messages: [ { @@ -514,46 +514,48 @@ export function registerEsqlFunction({ }, ...messages.slice(1), ], - }); + signal, + stream: true, + }) + ).pipe(processOpenAiStream()); - const pending$ = source$.pipe( - map((message) => { - const content = message.message.content || ''; - let next: string = ''; - - if (content.length <= 2) { - next = ''; - } else if (content.includes('--')) { - next = message.message.content?.split('--')[2] || ''; - } else { - next = content; - } + return new Observable((subscriber) => { + let cachedContent: string = ''; - return { - ...message, - message: { - ...message.message, - content: next, - }, - }; - }) - ); - const onComplete$ = source$.pipe( - last(), - map((message) => { - const [, , next] = message.message.content?.split('--') ?? []; - - return { - ...message, - message: { - ...message.message, - content: next || message.message.content, - }, - }; - }) - ); - - return concat(pending$, onComplete$); + function includesDivider() { + const firstDividerIndex = cachedContent.indexOf('--'); + return firstDividerIndex !== -1 && cachedContent.lastIndexOf('--') !== firstDividerIndex; + } + + source$.subscribe({ + next: (message) => { + if (includesDivider()) { + subscriber.next(message); + } + cachedContent += message.choices[0].delta.content || ''; + }, + complete: () => { + if (!includesDivider()) { + subscriber.next({ + created: 0, + id: '', + model: '', + object: 'chat.completion.chunk', + choices: [ + { + delta: { + content: cachedContent, + }, + }, + ], + }); + } + subscriber.complete(); + }, + error: (error) => { + subscriber.error(error); + }, + }); }); } ); diff --git a/x-pack/plugins/observability_ai_assistant/server/functions/get_dataset_info.ts b/x-pack/plugins/observability_ai_assistant/server/functions/get_dataset_info.ts new file mode 100644 index 0000000000000..bd48e1bda2f05 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/functions/get_dataset_info.ts @@ -0,0 +1,191 @@ +/* + * 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 { chunk, groupBy, uniq } from 'lodash'; +import { lastValueFrom } from 'rxjs'; +import { FunctionRegistrationParameters } from '.'; +import { FunctionVisibility, MessageRole } from '../../common/types'; +import { concatenateOpenAiChunks } from '../../common/utils/concatenate_openai_chunks'; +import { processOpenAiStream } from '../../common/utils/process_openai_stream'; +import { streamIntoObservable } from '../service/util/stream_into_observable'; + +export function registerGetDatasetInfoFunction({ + client, + resources, + registerFunction, +}: FunctionRegistrationParameters) { + registerFunction( + { + name: 'get_dataset_info', + contexts: ['core'], + visibility: FunctionVisibility.System, + description: `Use this function to get information about indices/datasets available and the fields available on them. + + providing empty string as index name will retrieve all indices + else list of all fields for the given index will be given. if no fields are returned this means no indices were matched by provided index pattern. + wildcards can be part of index name.`, + descriptionForUser: + 'This function allows the assistant to get information about available indices and their fields.', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + index: { + type: 'string', + description: + 'index pattern the user is interested in or empty string to get information about all available indices', + }, + }, + required: ['index'], + } as const, + }, + async ({ arguments: { index }, messages, connectorId }, signal) => { + const coreContext = await resources.context.core; + + const esClient = coreContext.elasticsearch.client.asCurrentUser; + const savedObjectsClient = coreContext.savedObjects.getClient(); + + let indices: string[] = []; + + try { + const body = await esClient.indices.resolveIndex({ + name: index === '' ? '*' : index, + expand_wildcards: 'open', + }); + indices = [...body.indices.map((i) => i.name), ...body.data_streams.map((d) => d.name)]; + } catch (e) { + indices = []; + } + + if (index === '') { + return { + indices, + fields: [], + }; + } + + if (indices.length === 0) { + return { + indices, + fields: [], + }; + } + + const fields = await resources.plugins.dataViews + .start() + .then((dataViewsStart) => + dataViewsStart.dataViewsServiceFactory(savedObjectsClient, esClient) + ) + .then((service) => + service.getFieldsForWildcard({ + pattern: index, + }) + ); + + // else get all the fields for the found dataview + const response = { + indices: [index], + fields: fields.flatMap((field) => { + return (field.esTypes ?? [field.type]).map((type) => { + return { + name: field.name, + description: field.customLabel || '', + type, + }; + }); + }), + }; + + const allFields = response.fields; + + const fieldNames = uniq(allFields.map((field) => field.name)); + + const groupedFields = groupBy(allFields, (field) => field.name); + + const relevantFields = await Promise.all( + chunk(fieldNames, 500).map(async (fieldsInChunk) => { + const chunkResponse$ = streamIntoObservable( + await client.chat({ + connectorId, + signal, + messages: [ + { + '@timestamp': new Date().toISOString(), + message: { + role: MessageRole.System, + content: `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.`, + }, + }, + ...messages.slice(1), + { + '@timestamp': new Date().toISOString(), + message: { + role: MessageRole.User, + content: `This is the list: + + ${fieldsInChunk.join('\n')}`, + }, + }, + ], + functions: [ + { + name: 'fields', + description: 'The fields you consider relevant to the conversation', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + fields: { + type: 'array', + additionalProperties: false, + items: { + type: 'string', + additionalProperties: false, + }, + }, + }, + required: ['fields'], + } as const, + }, + ], + functionCall: 'fields', + stream: true, + }) + ).pipe(processOpenAiStream(), concatenateOpenAiChunks()); + + const chunkResponse = await lastValueFrom(chunkResponse$); + + return chunkResponse.message?.function_call?.arguments + ? ( + JSON.parse(chunkResponse.message.function_call.arguments) as { + fields: string[]; + } + ).fields + .filter((field) => fieldsInChunk.includes(field)) + .map((field) => { + const fieldDescriptors = groupedFields[field]; + return `${field}:${fieldDescriptors + .map((descriptor) => descriptor.type) + .join(',')}`; + }) + : [chunkResponse.message?.content ?? '']; + }) + ); + + return { + content: { + indices: response.indices, + fields: relevantFields.flat(), + }, + }; + } + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/server/functions/index.ts b/x-pack/plugins/observability_ai_assistant/server/functions/index.ts new file mode 100644 index 0000000000000..6300852cbc064 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/functions/index.ts @@ -0,0 +1,89 @@ +/* + * 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 dedent from 'dedent'; +import { registerRecallFunction } from './recall'; +import { registerSummarizationFunction } from './summarize'; +import { ChatRegistrationFunction } from '../service/types'; +import { registerAlertsFunction } from './alerts'; +import { registerElasticsearchFunction } from './elasticsearch'; +import { registerEsqlFunction } from './esql'; +import { registerGetDatasetInfoFunction } from './get_dataset_info'; +import { registerLensFunction } from './lens'; +import { registerKibanaFunction } from './kibana'; + +export type FunctionRegistrationParameters = Omit< + Parameters[0], + 'registerContext' +>; + +export const registerFunctions: ChatRegistrationFunction = async ({ + client, + registerContext, + registerFunction, + resources, + signal, +}) => { + const registrationParameters: FunctionRegistrationParameters = { + client, + registerFunction, + resources, + signal, + }; + return client.getKnowledgeBaseStatus().then((response) => { + const isReady = response.ready; + + let description = dedent( + `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. + + It's very important to not assume what the user is meaning. Ask them for clarification if needed. + + If you are unsure about which function should be used and with what arguments, ask the user for clarification or confirmation. + + In KQL, 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! + + You can use Github-flavored Markdown in your responses. If a function returns an array, consider using a Markdown table to format the response. + + If multiple functions are suitable, use the most specific and easy one. E.g., when the user asks to visualise APM data, use the APM functions (if available) rather than Lens. + + If a function call fails, DO NOT UNDER ANY CIRCUMSTANCES execute it again. Ask the user for guidance and offer them options. + + Note that ES|QL (the Elasticsearch query language, which is NOT Elasticsearch SQL, but a new piped language) is the preferred query language. + + If the user asks about a query, or ES|QL, always call the "esql" function. DO NOT UNDER ANY CIRCUMSTANCES generate ES|QL queries yourself. Even if the "recall" function was used before that, follow it up with the "esql" function.` + ); + + if (isReady) { + description += `You can use the "summarize" functions to store new information you have learned in a knowledge database. Once you have established that you did not know the answer to a question, and the user gave you this information, it's important that you create a summarisation of what you have learned and store it in the knowledge database. Don't create a new summarization if you see a similar summarization in the conversation, instead, update the existing one by re-using its ID. + + Additionally, you can use the "recall" function to retrieve relevant information from the knowledge database. + `; + + description += `Here are principles you MUST adhere to, in order: + - DO NOT make any assumptions about where and how users have stored their data. ALWAYS first call get_dataset_info function with empty string to get information about available indices. Once you know about available indices you MUST use this function again to get a list of available fields for specific index. If user provides an index name make sure its a valid index first before using it to retrieve the field list by calling this function with an empty string! + `; + + registerSummarizationFunction(registrationParameters); + registerRecallFunction(registrationParameters); + registerLensFunction(registrationParameters); + } else { + description += `You do not have a working memory. Don't try to recall information via the "recall" function. If the user expects you to remember the previous conversations, tell them they can set up the knowledge base. A banner is available at the top of the conversation to set this up.`; + } + + registerElasticsearchFunction(registrationParameters); + registerKibanaFunction(registrationParameters); + registerEsqlFunction(registrationParameters); + registerAlertsFunction(registrationParameters); + registerGetDatasetInfoFunction(registrationParameters); + + registerContext({ + name: 'core', + description: dedent(description), + }); + }); +}; diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts b/x-pack/plugins/observability_ai_assistant/server/functions/kibana.ts similarity index 66% rename from x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts rename to x-pack/plugins/observability_ai_assistant/server/functions/kibana.ts index a47acdb02d433..49516e28c38e8 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/kibana.ts +++ b/x-pack/plugins/observability_ai_assistant/server/functions/kibana.ts @@ -5,19 +5,14 @@ * 2.0. */ -import type { CoreStart } from '@kbn/core/public'; -import type { RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; +import axios from 'axios'; +import { format } from 'url'; +import type { FunctionRegistrationParameters } from '.'; export function registerKibanaFunction({ - service, registerFunction, - coreStart, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; - coreStart: CoreStart; -}) { + resources, +}: FunctionRegistrationParameters) { registerFunction( { name: 'kibana', @@ -54,16 +49,36 @@ export function registerKibanaFunction({ }, }, ({ arguments: { method, pathname, body, query } }, signal) => { - return coreStart.http - .fetch(pathname, { - method, - body: body ? JSON.stringify(body) : undefined, - query, - signal, - }) - .then((response) => { - return { content: response }; - }); + const { request } = resources; + + const { + protocol, + host, + username, + password, + pathname: pathnameFromRequest, + } = request.rewrittenUrl!; + const nextUrl = { + host, + protocol, + username, + password, + pathname: pathnameFromRequest.replace( + '/internal/observability_ai_assistant/chat/complete', + pathname + ), + query, + }; + + return axios({ + method, + headers: request.headers, + url: format(nextUrl), + data: body ? JSON.stringify(body) : undefined, + signal, + }).then((response) => { + return { content: response.data }; + }); } ); } diff --git a/x-pack/plugins/observability_ai_assistant/server/functions/lens.ts b/x-pack/plugins/observability_ai_assistant/server/functions/lens.ts new file mode 100644 index 0000000000000..62e0f98c1b65d --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/functions/lens.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 { lensFunctionDefinition } from '../../common/functions/lens'; +import { RegisterFunction } from '../service/types'; + +export function registerLensFunction({ registerFunction }: { registerFunction: RegisterFunction }) { + registerFunction(lensFunctionDefinition, async () => { + return { + content: {}, + }; + }); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts b/x-pack/plugins/observability_ai_assistant/server/functions/recall.ts similarity index 85% rename from x-pack/plugins/observability_ai_assistant/public/functions/recall.ts rename to x-pack/plugins/observability_ai_assistant/server/functions/recall.ts index 4a9f417dd2021..5b6de5b0cc6f1 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/recall.ts +++ b/x-pack/plugins/observability_ai_assistant/server/functions/recall.ts @@ -5,21 +5,25 @@ * 2.0. */ +import { decodeOrThrow, jsonRt } from '@kbn/io-ts-utils'; import type { Serializable } from '@kbn/utility-types'; import dedent from 'dedent'; -import { last, omit } from 'lodash'; -import { CreateChatCompletionResponse } from 'openai'; import * as t from 'io-ts'; -import { decodeOrThrow, jsonRt } from '@kbn/io-ts-utils'; -import { Message, MessageRole, RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; +import { last, omit } from 'lodash'; +import { lastValueFrom } from 'rxjs'; +import { MessageRole, type Message } from '../../common/types'; +import { concatenateOpenAiChunks } from '../../common/utils/concatenate_openai_chunks'; +import { processOpenAiStream } from '../../common/utils/process_openai_stream'; +import type { ObservabilityAIAssistantClient } from '../service/client'; +import type { RegisterFunction } from '../service/types'; +import { streamIntoObservable } from '../service/util/stream_into_observable'; export function registerRecallFunction({ - service, + client, registerFunction, }: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; + client: ObservabilityAIAssistantClient; + registerFunction: RegisterFunction; }) { registerFunction( { @@ -89,7 +93,7 @@ export function registerRecallFunction({ const suggestions = await retrieveSuggestions({ userMessage, - service, + client, signal, contexts, queries, @@ -106,7 +110,7 @@ export function registerRecallFunction({ systemMessage, userMessage, queries, - service, + client, connectorId, signal, }); @@ -121,13 +125,13 @@ export function registerRecallFunction({ async function retrieveSuggestions({ userMessage, queries, - service, + client, contexts, signal, }: { userMessage?: Message; queries: string[]; - service: ObservabilityAIAssistantService; + client: ObservabilityAIAssistantClient; contexts: Array<'apm' | 'lens'>; signal: AbortSignal; }) { @@ -136,33 +140,21 @@ async function retrieveSuggestions({ ? [userMessage.message.content, ...queries] : queries; - const recallResponse = await service.callApi( - 'POST /internal/observability_ai_assistant/functions/recall', - { - params: { - body: { - queries: queriesWithUserPrompt, - contexts, - }, - }, - signal, - } - ); + const recallResponse = await client.recall({ + queries: queriesWithUserPrompt, + contexts, + }); return recallResponse.entries.map((entry) => omit(entry, 'labels', 'is_correction', 'score')); } const scoreFunctionRequestRt = t.type({ - choices: t.tuple([ - t.type({ - message: t.type({ - function_call: t.type({ - name: t.literal('score'), - arguments: t.string, - }), - }), + message: t.type({ + function_call: t.type({ + name: t.literal('score'), + arguments: t.string, }), - ]), + }), }); const scoreFunctionArgumentsRt = t.type({ @@ -179,7 +171,7 @@ async function scoreSuggestions({ systemMessage, userMessage, queries, - service, + client, connectorId, signal, }: { @@ -187,7 +179,7 @@ async function scoreSuggestions({ systemMessage: Message; userMessage?: Message; queries: string[]; - service: ObservabilityAIAssistantService; + client: ObservabilityAIAssistantClient; connectorId: string; signal: AbortSignal; }) { @@ -251,24 +243,21 @@ async function scoreSuggestions({ contexts: ['core'], }; - const response = (await service.callApi('POST /internal/observability_ai_assistant/chat', { - params: { - query: { - stream: false, - }, - body: { + const response = await lastValueFrom( + streamIntoObservable( + await client.chat({ connectorId, messages: [extendedSystemMessage, newUserMessage], functions: [scoreFunction], functionCall: 'score', - }, - }, - signal, - })) as CreateChatCompletionResponse; + signal, + }) + ).pipe(processOpenAiStream(), concatenateOpenAiChunks()) + ); const scoreFunctionRequest = decodeOrThrow(scoreFunctionRequestRt)(response); const { scores } = decodeOrThrow(jsonRt.pipe(scoreFunctionArgumentsRt))( - scoreFunctionRequest.choices[0].message.function_call.arguments + scoreFunctionRequest.message.function_call.arguments ); if (scores.length === 0) { diff --git a/x-pack/plugins/observability_ai_assistant/public/functions/summarize.ts b/x-pack/plugins/observability_ai_assistant/server/functions/summarize.ts similarity index 82% rename from x-pack/plugins/observability_ai_assistant/public/functions/summarize.ts rename to x-pack/plugins/observability_ai_assistant/server/functions/summarize.ts index 14f637591e613..8d15ecc033172 100644 --- a/x-pack/plugins/observability_ai_assistant/public/functions/summarize.ts +++ b/x-pack/plugins/observability_ai_assistant/server/functions/summarize.ts @@ -5,16 +5,13 @@ * 2.0. */ -import type { RegisterFunctionDefinition } from '../../common/types'; -import type { ObservabilityAIAssistantService } from '../types'; +import type { FunctionRegistrationParameters } from '.'; +import { KnowledgeBaseEntryRole } from '../../common'; export function registerSummarizationFunction({ - service, + client, registerFunction, -}: { - service: ObservabilityAIAssistantService; - registerFunction: RegisterFunctionDefinition; -}) { +}: FunctionRegistrationParameters) { registerFunction( { name: 'summarize', @@ -65,19 +62,19 @@ export function registerSummarizationFunction({ { arguments: { id, text, is_correction: isCorrection, confidence, public: isPublic } }, signal ) => { - return service - .callApi('POST /internal/observability_ai_assistant/functions/summarize', { - params: { - body: { - id, - text, - is_correction: isCorrection, - confidence, - public: isPublic, - labels: {}, - }, + return client + .createKnowledgeBaseEntry({ + entry: { + doc_id: id, + role: KnowledgeBaseEntryRole.AssistantSummarization, + id, + text, + is_correction: isCorrection, + confidence, + public: isPublic, + labels: {}, }, - signal, + // signal, }) .then(() => ({ content: { diff --git a/x-pack/plugins/observability_ai_assistant/server/index.ts b/x-pack/plugins/observability_ai_assistant/server/index.ts index 0869b0bb43519..d8ab28e944122 100644 --- a/x-pack/plugins/observability_ai_assistant/server/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/index.ts @@ -11,7 +11,10 @@ import type { ObservabilityAIAssistantConfig } from './config'; export type { ObservabilityAIAssistantServerRouteRepository } from './routes/get_global_observability_ai_assistant_route_repository'; import { config as configSchema } from './config'; -import { ObservabilityAIAssistantService } from './service'; +export type { + ObservabilityAIAssistantPluginStart, + ObservabilityAIAssistantPluginSetup, +} from './types'; export const config: PluginConfigDescriptor = { deprecations: ({ unusedFromRoot }) => [ @@ -38,20 +41,6 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export interface ObservabilityAIAssistantPluginSetup { - /** - * Returns a Observability AI Assistant service instance - */ - service: ObservabilityAIAssistantService; -} - -export interface ObservabilityAIAssistantPluginStart { - /** - * Returns a Observability AI Assistant service instance - */ - service: ObservabilityAIAssistantService; -} - export const plugin = async (ctx: PluginInitializerContext) => { const { ObservabilityAIAssistantPlugin } = await import('./plugin'); return new ObservabilityAIAssistantPlugin(ctx); diff --git a/x-pack/plugins/observability_ai_assistant/server/plugin.ts b/x-pack/plugins/observability_ai_assistant/server/plugin.ts index c793e28f40a86..577edfeb1da0c 100644 --- a/x-pack/plugins/observability_ai_assistant/server/plugin.ts +++ b/x-pack/plugins/observability_ai_assistant/server/plugin.ts @@ -31,6 +31,7 @@ import { ObservabilityAIAssistantPluginStartDependencies, } from './types'; import { addLensDocsToKb } from './service/knowledge_base_service/kb_docs/lens'; +import { registerFunctions } from './functions'; export class ObservabilityAIAssistantPlugin implements @@ -104,13 +105,15 @@ export class ObservabilityAIAssistantPlugin }; }) as ObservabilityAIAssistantRouteHandlerResources['plugins']; - this.service = new ObservabilityAIAssistantService({ + const service = (this.service = new ObservabilityAIAssistantService({ logger: this.logger.get('service'), core, taskManager: plugins.taskManager, - }); + })); + + service.register(registerFunctions); - addLensDocsToKb({ service: this.service, logger: this.logger.get('kb').get('lens') }); + addLensDocsToKb({ service, logger: this.logger.get('kb').get('lens') }); registerServerRoutes({ core, @@ -122,11 +125,13 @@ export class ObservabilityAIAssistantPlugin }); return { - service: this.service, + service, }; } public start(): ObservabilityAIAssistantPluginStart { - return {}; + return { + service: this.service!, + }; } } diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts index 90620156acf37..163b41135b518 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/chat/route.ts @@ -54,10 +54,17 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ const stream = query.stream; + const controller = new AbortController(); + + request.events.aborted$.subscribe(() => { + controller.abort(); + }); + return client.chat({ messages, connectorId, stream, + signal: controller.signal, ...(functions.length ? { functions, @@ -68,6 +75,62 @@ const chatRoute = createObservabilityAIAssistantServerRoute({ }, }); +const chatCompleteRoute = createObservabilityAIAssistantServerRoute({ + endpoint: 'POST /internal/observability_ai_assistant/chat/complete', + options: { + tags: ['access:ai_assistant'], + }, + params: t.type({ + body: t.intersection([ + t.type({ + messages: t.array(messageRt), + connectorId: t.string, + persist: toBooleanRt, + }), + t.partial({ + conversationId: t.string, + title: t.string, + }), + ]), + }), + handler: async (resources): Promise => { + const { request, params, service } = resources; + + const client = await service.getClient({ request }); + + if (!client) { + throw notImplemented(); + } + + const { + body: { messages, connectorId, conversationId, title, persist }, + } = params; + + const controller = new AbortController(); + + request.events.aborted$.subscribe(() => { + controller.abort(); + }); + + const functionClient = await service.getFunctionClient({ + signal: controller.signal, + resources, + client, + }); + + return client.complete({ + messages, + connectorId, + conversationId, + title, + persist, + signal: controller.signal, + functionClient, + }); + }, +}); + export const chatRoutes = { ...chatRoute, + ...chatCompleteRoute, }; diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/conversations/route.ts b/x-pack/plugins/observability_ai_assistant/server/routes/conversations/route.ts index 87aba7dc6757f..b39468c3e06c0 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/conversations/route.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/conversations/route.ts @@ -108,37 +108,6 @@ const updateConversationRoute = createObservabilityAIAssistantServerRoute({ }, }); -const updateConversationTitleBasedOnMessages = createObservabilityAIAssistantServerRoute({ - endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}/auto_title', - params: t.type({ - path: t.type({ - conversationId: t.string, - }), - body: t.type({ - connectorId: t.string, - }), - }), - options: { - tags: ['access:ai_assistant'], - }, - handler: async (resources): Promise => { - const { service, request, params } = resources; - - const client = await service.getClient({ request }); - - if (!client) { - throw notImplemented(); - } - - const conversation = await client.autoTitle({ - conversationId: params.path.conversationId, - connectorId: params.body.connectorId, - }); - - return Promise.resolve(conversation); - }, -}); - const updateConversationTitle = createObservabilityAIAssistantServerRoute({ endpoint: 'PUT /internal/observability_ai_assistant/conversation/{conversationId}/title', params: t.type({ @@ -198,7 +167,6 @@ export const conversationRoutes = { ...findConversationsRoute, ...createConversationRoute, ...updateConversationRoute, - ...updateConversationTitleBasedOnMessages, ...updateConversationTitle, ...deleteConversationRoute, }; diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts b/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts index 4567addfeb2d5..a7b6edf1aa97c 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/functions/route.ts @@ -4,153 +4,46 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import datemath from '@elastic/datemath'; import { notImplemented } from '@hapi/boom'; -import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { nonEmptyStringRt, toBooleanRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; -import { omit } from 'lodash'; -import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import { - ALERT_STATUS, - ALERT_STATUS_ACTIVE, -} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; -import { KnowledgeBaseEntryRole } from '../../../common/types'; -import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; + ContextDefinition, + FunctionDefinition, + KnowledgeBaseEntryRole, +} from '../../../common/types'; import type { RecalledEntry } from '../../service/knowledge_base_service'; +import { createObservabilityAIAssistantServerRoute } from '../create_observability_ai_assistant_server_route'; -const functionElasticsearchRoute = createObservabilityAIAssistantServerRoute({ - endpoint: 'POST /internal/observability_ai_assistant/functions/elasticsearch', - options: { - tags: ['access:ai_assistant'], - }, - params: t.type({ - body: t.intersection([ - t.type({ - method: t.union([ - t.literal('GET'), - t.literal('POST'), - t.literal('PATCH'), - t.literal('PUT'), - t.literal('DELETE'), - ]), - path: t.string, - }), - t.partial({ - body: t.any, - }), - ]), - }), - handler: async (resources): Promise => { - const { method, path, body } = resources.params.body; - - const response = await ( - await resources.context.core - ).elasticsearch.client.asCurrentUser.transport.request({ - method, - path, - body, - }); - - return response; - }, -}); - -const OMITTED_ALERT_FIELDS = [ - 'tags', - 'event.action', - 'event.kind', - 'kibana.alert.rule.execution.uuid', - 'kibana.alert.rule.revision', - 'kibana.alert.rule.tags', - 'kibana.alert.rule.uuid', - 'kibana.alert.workflow_status', - 'kibana.space_ids', - 'kibana.alert.time_range', - 'kibana.version', -] as const; - -const functionAlertsRoute = createObservabilityAIAssistantServerRoute({ - endpoint: 'POST /internal/observability_ai_assistant/functions/alerts', +const getFunctionsRoute = createObservabilityAIAssistantServerRoute({ + endpoint: 'GET /internal/observability_ai_assistant/functions', options: { tags: ['access:ai_assistant'], }, - params: t.type({ - body: t.intersection([ - t.type({ - featureIds: t.array(t.string), - start: t.string, - end: t.string, - }), - t.partial({ - filter: t.string, - includeRecovered: toBooleanRt, - }), - ]), - }), handler: async ( resources ): Promise<{ - content: { - total: number; - alerts: ParsedTechnicalFields[]; - }; + functionDefinitions: FunctionDefinition[]; + contextDefinitions: ContextDefinition[]; }> => { - const { - featureIds, - start: startAsDatemath, - end: endAsDatemath, - filter, - includeRecovered, - } = resources.params.body; - - const racContext = await resources.context.rac; - const alertsClient = await racContext.getAlertsClient(); + const { service, request } = resources; - const start = datemath.parse(startAsDatemath)!.valueOf(); - const end = datemath.parse(endAsDatemath)!.valueOf(); - - const kqlQuery = !filter ? [] : [toElasticsearchQuery(fromKueryExpression(filter))]; + const controller = new AbortController(); + request.events.aborted$.subscribe(() => { + controller.abort(); + }); - const response = await alertsClient.find({ - featureIds, + const client = await service.getClient({ request }); - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: start, - lte: end, - }, - }, - }, - ...kqlQuery, - ...(!includeRecovered - ? [ - { - term: { - [ALERT_STATUS]: ALERT_STATUS_ACTIVE, - }, - }, - ] - : []), - ], - }, - }, + const functionClient = await service.getFunctionClient({ + signal: controller.signal, + resources, + client, }); - // trim some fields - const alerts = response.hits.hits.map((hit) => - omit(hit._source, ...OMITTED_ALERT_FIELDS) - ) as unknown as ParsedTechnicalFields[]; - return { - content: { - total: (response.hits as { total: { value: number } }).total.value, - alerts, - }, + functionDefinitions: functionClient.getFunctions().map((fn) => fn.definition), + contextDefinitions: functionClient.getContexts(), }; }, }); @@ -235,82 +128,8 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({ }, }); -const functionGetDatasetInfoRoute = createObservabilityAIAssistantServerRoute({ - endpoint: 'POST /internal/observability_ai_assistant/functions/get_dataset_info', - params: t.type({ - body: t.type({ - index: t.string, - }), - }), - options: { - tags: ['access:ai_assistant'], - }, - handler: async ( - resources - ): Promise<{ - indices: string[]; - fields: Array<{ name: string; description: string; type: string }>; - }> => { - const esClient = (await resources.context.core).elasticsearch.client.asCurrentUser; - - const savedObjectsClient = (await resources.context.core).savedObjects.getClient(); - - const index = resources.params.body.index; - - let indices: string[] = []; - - try { - const body = await esClient.indices.resolveIndex({ - name: index === '' ? '*' : index, - expand_wildcards: 'open', - }); - indices = [...body.indices.map((i) => i.name), ...body.data_streams.map((d) => d.name)]; - } catch (e) { - indices = []; - } - - if (index === '') { - return { - indices, - fields: [], - }; - } - - if (indices.length === 0) { - return { - indices, - fields: [], - }; - } - - const dataViews = await ( - await resources.plugins.dataViews.start() - ).dataViewsServiceFactory(savedObjectsClient, esClient); - - const fields = await dataViews.getFieldsForWildcard({ - pattern: index, - }); - - // else get all the fields for the found dataview - return { - indices: [index], - fields: fields.flatMap((field) => { - return (field.esTypes ?? [field.type]).map((type) => { - return { - name: field.name, - description: field.customLabel || '', - type, - }; - }); - }), - }; - }, -}); - export const functionRoutes = { - ...functionElasticsearchRoute, + ...getFunctionsRoute, ...functionRecallRoute, ...functionSummariseRoute, - ...functionAlertsRoute, - ...functionGetDatasetInfoRoute, }; diff --git a/x-pack/plugins/observability_ai_assistant/server/routes/types.ts b/x-pack/plugins/observability_ai_assistant/server/routes/types.ts index 1766f5c2d5542..26753874d3224 100644 --- a/x-pack/plugins/observability_ai_assistant/server/routes/types.ts +++ b/x-pack/plugins/observability_ai_assistant/server/routes/types.ts @@ -8,6 +8,8 @@ import type { CustomRequestHandlerContext, KibanaRequest } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; import type { RacApiRequestHandlerContext } from '@kbn/rule-registry-plugin/server'; +import type { LicensingApiRequestHandlerContext } from '@kbn/licensing-plugin/server/types'; +import type { AlertingApiRequestHandlerContext } from '@kbn/alerting-plugin/server/types'; import type { ObservabilityAIAssistantService } from '../service'; import type { ObservabilityAIAssistantPluginSetupDependencies, @@ -16,6 +18,8 @@ import type { export type ObservabilityAIAssistantRequestHandlerContext = CustomRequestHandlerContext<{ rac: RacApiRequestHandlerContext; + licensing: LicensingApiRequestHandlerContext; + alerting: AlertingApiRequestHandlerContext; }>; export interface ObservabilityAIAssistantRouteHandlerResources { diff --git a/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.test.ts b/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.test.ts new file mode 100644 index 0000000000000..7d34404457d24 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import Ajv, { type ValidateFunction } from 'ajv'; +import { ChatFunctionClient } from '.'; +import type { ContextRegistry } from '../../../common/types'; +import type { FunctionHandlerRegistry } from '../types'; + +describe('chatFunctionClient', () => { + describe('when executing a function with invalid arguments', () => { + let client: ChatFunctionClient; + + let respondFn: jest.Mock; + + beforeEach(() => { + const contextRegistry: ContextRegistry = new Map(); + contextRegistry.set('core', { + description: '', + name: 'core', + }); + + respondFn = jest.fn().mockImplementationOnce(async () => { + return {}; + }); + + const functionRegistry: FunctionHandlerRegistry = new Map(); + functionRegistry.set('myFunction', { + respond: respondFn, + definition: { + contexts: ['core'], + description: '', + name: 'myFunction', + parameters: { + properties: { + foo: { + type: 'string', + }, + }, + required: ['foo'], + }, + }, + }); + + const validators = new Map(); + + validators.set( + 'myFunction', + new Ajv({ strict: false }).compile( + functionRegistry.get('myFunction')!.definition.parameters + ) + ); + + client = new ChatFunctionClient(contextRegistry, functionRegistry, validators); + }); + + it('throws an error', async () => { + await expect(async () => { + await client.executeFunction({ + name: 'myFunction', + args: JSON.stringify({ + foo: 0, + }), + messages: [], + signal: new AbortController().signal, + connectorId: '', + }); + }).rejects.toThrowError(`Function arguments are invalid`); + + expect(respondFn).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.ts new file mode 100644 index 0000000000000..e1d49696e5113 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/chat_function_client/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +/* eslint-disable max-classes-per-file*/ + +import type { ErrorObject, ValidateFunction } from 'ajv'; +import { keyBy } from 'lodash'; +import type { + ContextDefinition, + ContextRegistry, + FunctionResponse, + Message, +} from '../../../common/types'; +import { filterFunctionDefinitions } from '../../../common/utils/filter_function_definitions'; +import { FunctionHandler, FunctionHandlerRegistry } from '../types'; + +export class FunctionArgsValidationError extends Error { + constructor(public readonly errors: ErrorObject[]) { + super('Function arguments are invalid'); + } +} + +export class ChatFunctionClient { + constructor( + private readonly contextRegistry: ContextRegistry, + private readonly functionRegistry: FunctionHandlerRegistry, + private readonly validators: Map + ) {} + + private validate(name: string, parameters: unknown) { + const validator = this.validators.get(name)!; + const result = validator(parameters); + if (!result) { + throw new FunctionArgsValidationError(validator.errors!); + } + } + + getContexts(): ContextDefinition[] { + return Array.from(this.contextRegistry.values()); + } + + getFunctions({ + contexts, + filter, + }: { contexts?: string[]; filter?: string } = {}): FunctionHandler[] { + const allFunctions = Array.from(this.functionRegistry.values()); + + const functionsByName = keyBy(allFunctions, (definition) => definition.definition.name); + + const matchingDefinitions = filterFunctionDefinitions({ + contexts, + filter, + definitions: allFunctions.map((fn) => fn.definition), + }); + + return matchingDefinitions.map((definition) => functionsByName[definition.name]); + } + + hasFunction(name: string): boolean { + return this.functionRegistry.has(name); + } + + async executeFunction({ + name, + args, + messages, + signal, + connectorId, + }: { + name: string; + args: string | undefined; + messages: Message[]; + signal: AbortSignal; + connectorId: string; + }): Promise { + const fn = this.functionRegistry.get(name); + + if (!fn) { + throw new Error(`Function ${name} not found`); + } + + const parsedArguments = args ? JSON.parse(args) : {}; + + this.validate(name, parsedArguments); + + return await fn.respond({ arguments: parsedArguments, messages, connectorId }, signal); + } +} diff --git a/x-pack/plugins/observability_ai_assistant/server/service/client/handle_llm_response.ts b/x-pack/plugins/observability_ai_assistant/server/service/client/handle_llm_response.ts new file mode 100644 index 0000000000000..39d9b1a87c375 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/client/handle_llm_response.ts @@ -0,0 +1,71 @@ +/* + * 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 { Observable } from 'rxjs'; +import { v4 } from 'uuid'; +import { Message, MessageRole } from '../../../common'; +import { + StreamingChatResponseEvent, + StreamingChatResponseEventType, +} from '../../../common/conversation_complete'; +import type { CreateChatCompletionResponseChunk } from '../../../common/types'; + +export function handleLlmResponse({ + signal, + write, + source$, +}: { + signal: AbortSignal; + write: (event: StreamingChatResponseEvent) => Promise; + source$: Observable; +}): Promise<{ id: string; message: Message['message'] }> { + return new Promise<{ message: Message['message']; id: string }>((resolve, reject) => { + const message = { + content: '', + role: MessageRole.Assistant, + function_call: { name: '', arguments: '', trigger: MessageRole.Assistant as const }, + }; + + const id = v4(); + const subscription = source$.subscribe({ + next: (chunk) => { + const delta = chunk.choices[0].delta; + + message.content += delta.content || ''; + message.function_call.name += delta.function_call?.name || ''; + message.function_call.arguments += delta.function_call?.arguments || ''; + + write({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + message: delta, + id, + }); + }, + complete: () => { + resolve({ id, message }); + }, + error: (error) => { + reject(error); + }, + }); + + signal.addEventListener('abort', () => { + subscription.unsubscribe(); + reject(new Error('Request aborted')); + }); + }).then(async ({ id, message }) => { + await write({ + type: StreamingChatResponseEventType.MessageAdd, + message: { + '@timestamp': new Date().toISOString(), + message, + }, + id, + }); + return { id, message }; + }); +} diff --git a/x-pack/plugins/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/plugins/observability_ai_assistant/server/service/client/index.test.ts new file mode 100644 index 0000000000000..062377cda5112 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/client/index.test.ts @@ -0,0 +1,1133 @@ +/* + * 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 { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; +import type { ElasticsearchClient, Logger } from '@kbn/core/server'; +import type { DeeplyMockedKeys } from '@kbn/utility-types-jest'; +import { merge } from 'lodash'; +import { Subject } from 'rxjs'; +import { PassThrough, type Readable } from 'stream'; +import { finished } from 'stream/promises'; +import { ObservabilityAIAssistantClient } from '.'; +import { createResourceNamesMap } from '..'; +import { MessageRole, type Message } from '../../../common'; +import { StreamingChatResponseEventType } from '../../../common/conversation_complete'; +import type { CreateChatCompletionResponseChunk } from '../../../public/types'; +import type { ChatFunctionClient } from '../chat_function_client'; +import type { KnowledgeBaseService } from '../knowledge_base_service'; + +type ChunkDelta = CreateChatCompletionResponseChunk['choices'][number]['delta']; + +type LlmSimulator = ReturnType; + +const nextTick = () => { + return new Promise(process.nextTick); +}; + +const waitForNextWrite = async (stream: Readable): Promise => { + // this will fire before the client's internal write() promise is + // resolved + await new Promise((resolve) => stream.once('data', resolve)); + // so we wait another tick to let the client move to the next step + await nextTick(); +}; + +function createLlmSimulator() { + const stream = new PassThrough(); + + return { + stream, + next: async (msg: ChunkDelta) => { + const chunk: CreateChatCompletionResponseChunk = { + created: 0, + id: '', + model: 'gpt-4', + object: 'chat.completion.chunk', + choices: [ + { + delta: msg, + }, + ], + }; + await new Promise((resolve, reject) => { + stream.write(`data: ${JSON.stringify(chunk)}\n`, undefined, (err) => { + return err ? reject(err) : resolve(); + }); + }); + }, + complete: async () => { + if (stream.destroyed) { + throw new Error('Stream is already destroyed'); + } + await new Promise((resolve) => stream.write('data: [DONE]', () => stream.end(resolve))); + }, + error: (error: Error) => { + stream.destroy(error); + }, + }; +} + +describe('Observability AI Assistant service', () => { + let client: ObservabilityAIAssistantClient; + + const actionsClientMock: DeeplyMockedKeys = { + execute: jest.fn(), + } as any; + + const esClientMock: DeeplyMockedKeys = { + search: jest.fn(), + index: jest.fn(), + update: jest.fn(), + } as any; + + const knowledgeBaseServiceMock: DeeplyMockedKeys = { + recall: jest.fn(), + } as any; + + const loggerMock: DeeplyMockedKeys = { + log: jest.fn(), + error: jest.fn(), + } as any; + + const functionClientMock: DeeplyMockedKeys = { + executeFunction: jest.fn(), + getFunctions: jest.fn().mockReturnValue([]), + hasFunction: jest.fn().mockImplementation((name) => { + return name !== 'recall'; + }), + } as any; + + let llmSimulator: LlmSimulator; + + function createClient() { + jest.clearAllMocks(); + + return new ObservabilityAIAssistantClient({ + actionsClient: actionsClientMock, + esClient: esClientMock, + knowledgeBaseService: knowledgeBaseServiceMock, + logger: loggerMock, + namespace: 'default', + resources: createResourceNamesMap(), + user: { + name: 'johndoe', + }, + }); + } + + 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( + { + '@timestamp': new Date().toString(), + message: { + role: MessageRole.User, + }, + }, + typeof content === 'string' ? { message: { content } } : content + ); + } + + describe('when completing a conversation without an initial conversation id', () => { + let stream: Readable; + + let titleLlmPromiseResolve: (title: string) => void; + let titleLlmPromiseReject: Function; + + beforeEach(async () => { + client = createClient(); + actionsClientMock.execute + .mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }) + .mockImplementationOnce(() => { + return new Promise((resolve, reject) => { + titleLlmPromiseResolve = (title: string) => { + const titleLlmSimulator = createLlmSimulator(); + titleLlmSimulator.next({ content: title }); + titleLlmSimulator.complete(); + resolve({ + actionId: '', + status: 'ok', + data: titleLlmSimulator.stream, + }); + }; + titleLlmPromiseReject = reject; + }); + }); + + stream = await client.complete({ + connectorId: 'foo', + messages: [system('This is a system message'), user('How many alerts do I have?')], + functionClient: functionClientMock, + signal: new AbortController().signal, + persist: true, + }); + }); + + describe('when streaming the response from the LLM', () => { + let dataHandler: jest.Mock; + + beforeEach(async () => { + dataHandler = jest.fn(); + + stream.on('data', dataHandler); + + await llmSimulator.next({ content: 'Hello' }); + }); + + it('calls the actions client with the messages', () => { + expect(actionsClientMock.execute.mock.calls[0]).toEqual([ + { + actionId: 'foo', + params: { + subAction: 'stream', + subActionParams: { + body: expect.any(String), + stream: true, + }, + }, + }, + ]); + }); + + it('calls the llm again to generate a new title', () => { + expect(actionsClientMock.execute.mock.calls[1]).toEqual([ + { + actionId: 'foo', + params: { + subAction: 'stream', + subActionParams: { + body: expect.any(String), + stream: true, + }, + }, + }, + ]); + }); + + it('incrementally streams the response to the client', () => { + expect(dataHandler).toHaveBeenCalledTimes(1); + + expect(JSON.parse(dataHandler.mock.calls[0])).toEqual({ + id: expect.any(String), + message: { + content: 'Hello', + }, + type: StreamingChatResponseEventType.ChatCompletionChunk, + }); + }); + + describe('after the LLM errors out', () => { + beforeEach(async () => { + await llmSimulator.next({ content: ' again' }); + + llmSimulator.error(new Error('Unexpected error')); + + await finished(stream); + }); + + it('adds an error to the stream and closes it', () => { + expect(dataHandler).toHaveBeenCalledTimes(3); + + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + error: { + message: 'Unexpected error', + stack: expect.any(String), + }, + type: StreamingChatResponseEventType.ConversationCompletionError, + }); + }); + }); + + describe('when generating a title fails', () => { + beforeEach(async () => { + titleLlmPromiseReject(new Error('Failed generating title')); + + await nextTick(); + + await llmSimulator.complete(); + + await finished(stream); + }); + + it('falls back to the default title', () => { + expect(JSON.parse(dataHandler.mock.calls[2])).toEqual({ + conversation: { + title: 'New conversation', + id: expect.any(String), + last_updated: expect.any(String), + }, + type: StreamingChatResponseEventType.ConversationCreate, + }); + + expect(loggerMock.error).toHaveBeenCalled(); + }); + }); + + describe('after completing the response from the LLM', () => { + beforeEach(async () => { + await llmSimulator.next({ content: ' again' }); + + titleLlmPromiseResolve('An auto-generated title'); + + await nextTick(); + + await llmSimulator.complete(); + + await finished(stream); + }); + it('adds the completed message to the stream', () => { + expect(JSON.parse(dataHandler.mock.calls[1])).toEqual({ + id: expect.any(String), + message: { + content: ' again', + }, + type: StreamingChatResponseEventType.ChatCompletionChunk, + }); + + expect(JSON.parse(dataHandler.mock.calls[2])).toEqual({ + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + content: 'Hello again', + role: MessageRole.Assistant, + function_call: { + arguments: '', + name: '', + trigger: MessageRole.Assistant, + }, + }, + }, + type: StreamingChatResponseEventType.MessageAdd, + }); + }); + + it('creates a new conversation with the automatically generated title', () => { + expect(JSON.parse(dataHandler.mock.calls[3])).toEqual({ + conversation: { + title: 'An auto-generated title', + id: expect.any(String), + last_updated: expect.any(String), + }, + type: StreamingChatResponseEventType.ConversationCreate, + }); + + expect(esClientMock.index).toHaveBeenCalledWith({ + index: '.kibana-observability-ai-assistant-conversations', + refresh: true, + document: { + '@timestamp': expect.any(String), + conversation: { + id: expect.any(String), + last_updated: expect.any(String), + title: 'An auto-generated title', + }, + labels: {}, + numeric_labels: {}, + public: false, + namespace: 'default', + user: { + name: 'johndoe', + }, + messages: [ + { + '@timestamp': expect.any(String), + message: { + content: 'This is a system message', + role: MessageRole.System, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'How many alerts do I have?', + role: MessageRole.User, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'Hello again', + role: MessageRole.Assistant, + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + ], + }, + }); + }); + }); + }); + }); + + describe('when completig a conversation with an initial conversation id', () => { + let stream: Readable; + + let dataHandler: jest.Mock; + + beforeEach(async () => { + client = createClient(); + actionsClientMock.execute.mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }); + + esClientMock.search.mockImplementation(async () => { + return { + hits: { + hits: [ + { + _id: 'my-es-document-id', + _index: '.kibana-observability-ai-assistant-conversations', + _source: { + '@timestamp': new Date().toISOString(), + conversation: { + id: 'my-conversation-id', + title: 'My stored conversation', + last_updated: new Date().toISOString(), + }, + labels: {}, + numeric_labels: {}, + public: false, + messages: [ + system('This is a system message'), + user('How many alerts do I have?'), + ], + }, + }, + ], + }, + } as any; + }); + + esClientMock.update.mockImplementationOnce(async () => { + return {} as any; + }); + + stream = await client.complete({ + connectorId: 'foo', + messages: [system('This is a system message'), user('How many alerts do I have?')], + functionClient: functionClientMock, + signal: new AbortController().signal, + conversationId: 'my-conversation-id', + persist: true, + }); + + dataHandler = jest.fn(); + + stream.on('data', dataHandler); + + await llmSimulator.next({ content: 'Hello' }); + + await llmSimulator.complete(); + + await finished(stream); + }); + + it('updates the conversation', () => { + expect(JSON.parse(dataHandler.mock.calls[2])).toEqual({ + conversation: { + title: 'My stored conversation', + id: expect.any(String), + last_updated: expect.any(String), + }, + type: StreamingChatResponseEventType.ConversationUpdate, + }); + + expect(esClientMock.update).toHaveBeenCalledWith({ + refresh: true, + index: '.kibana-observability-ai-assistant-conversations', + id: 'my-es-document-id', + doc: { + '@timestamp': expect.any(String), + conversation: { + id: expect.any(String), + last_updated: expect.any(String), + title: 'My stored conversation', + }, + labels: {}, + numeric_labels: {}, + public: false, + namespace: 'default', + user: { + name: 'johndoe', + }, + messages: [ + { + '@timestamp': expect.any(String), + message: { + content: 'This is a system message', + role: MessageRole.System, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'How many alerts do I have?', + role: MessageRole.User, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'Hello', + role: MessageRole.Assistant, + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + ], + }, + }); + }); + }); + + describe('when the LLM response fails', () => { + let stream: Readable; + + let dataHandler: jest.Mock; + + beforeEach(async () => { + client = createClient(); + actionsClientMock.execute.mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }); + + stream = await client.complete({ + connectorId: 'foo', + messages: [system('This is a system message'), user('How many alerts do I have?')], + functionClient: functionClientMock, + signal: new AbortController().signal, + title: 'My predefined title', + persist: true, + }); + + dataHandler = jest.fn(); + + stream.on('data', dataHandler); + + await llmSimulator.next({ content: 'Hello' }); + + await new Promise((resolve) => + llmSimulator.stream.write( + `data: ${JSON.stringify({ + error: { + message: 'Connection unexpectedly closed', + }, + })}\n`, + resolve + ) + ); + + await llmSimulator.complete(); + + await finished(stream); + }); + + it('ends the stream and writes an error', async () => { + expect(JSON.parse(dataHandler.mock.calls[1])).toEqual({ + error: { + message: 'Connection unexpectedly closed', + stack: expect.any(String), + }, + type: StreamingChatResponseEventType.ConversationCompletionError, + }); + }); + + it('does not create or update the conversation', async () => { + expect(esClientMock.index).not.toHaveBeenCalled(); + expect(esClientMock.update).not.toHaveBeenCalled(); + }); + }); + + describe('when the assistant answers with a function request', () => { + let stream: Readable; + + let dataHandler: jest.Mock; + + let respondFn: jest.Mock; + + let fnResponseResolve: (data: unknown) => void; + + let fnResponseReject: (error: Error) => void; + + beforeEach(async () => { + client = createClient(); + actionsClientMock.execute.mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }); + + respondFn = jest.fn(); + + functionClientMock.getFunctions.mockImplementation(() => [ + { + definition: { + name: 'myFunction', + contexts: ['core'], + description: 'my-description', + descriptionForUser: '', + parameters: { + type: 'object', + additionalProperties: false, + properties: { + foo: { + type: 'string', + enum: ['bar'], + }, + }, + required: ['foo'], + }, + }, + respond: respondFn, + }, + ]); + + functionClientMock.executeFunction.mockImplementationOnce(() => { + return new Promise((resolve, reject) => { + fnResponseResolve = resolve; + fnResponseReject = reject; + }); + }); + + stream = await client.complete({ + connectorId: 'foo', + messages: [system('This is a system message'), user('How many alerts do I have?')], + functionClient: functionClientMock, + signal: new AbortController().signal, + title: 'My predefined title', + persist: true, + }); + + dataHandler = jest.fn(); + + stream.on('data', dataHandler); + + await llmSimulator.next({ + content: 'Hello', + function_call: { name: 'my-function', arguments: JSON.stringify({ foo: 'bar' }) }, + }); + + const prevLlmSimulator = llmSimulator; + + actionsClientMock.execute.mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }); + + await prevLlmSimulator.complete(); + + await waitForNextWrite(stream); + }); + + describe('while the function call is pending', () => { + it('appends the request message', async () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + content: 'Hello', + role: MessageRole.Assistant, + function_call: { + name: 'my-function', + arguments: JSON.stringify({ foo: 'bar' }), + trigger: MessageRole.Assistant, + }, + }, + }, + }); + }); + + it('executes the function', () => { + expect(functionClientMock.executeFunction).toHaveBeenCalledWith({ + connectorId: 'foo', + name: 'my-function', + args: JSON.stringify({ foo: 'bar' }), + signal: expect.any(AbortSignal), + messages: [ + { + '@timestamp': expect.any(String), + message: { + role: MessageRole.System, + content: 'This is a system message', + }, + }, + { + '@timestamp': expect.any(String), + message: { + role: MessageRole.User, + content: 'How many alerts do I have?', + }, + }, + { + '@timestamp': expect.any(String), + message: { + role: MessageRole.Assistant, + content: 'Hello', + function_call: { + name: 'my-function', + arguments: JSON.stringify({ foo: 'bar' }), + trigger: MessageRole.Assistant, + }, + }, + }, + ], + }); + }); + + afterEach(async () => { + fnResponseResolve({ content: { my: 'content' } }); + await waitForNextWrite(stream); + + await llmSimulator.complete(); + await finished(stream); + }); + }); + + describe('and the function succeeds', () => { + beforeEach(async () => { + fnResponseResolve({ content: { my: 'content' } }); + await waitForNextWrite(stream); + }); + + it('appends the function response', () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + role: MessageRole.User, + name: 'my-function', + content: JSON.stringify({ + my: 'content', + }), + }, + }, + }); + }); + + it('sends the function response back to the llm', () => { + expect(actionsClientMock.execute).toHaveBeenCalledTimes(2); + expect(actionsClientMock.execute.mock.lastCall!).toEqual([ + { + actionId: 'foo', + params: { + subAction: 'stream', + subActionParams: { + body: expect.any(String), + stream: true, + }, + }, + }, + ]); + }); + + describe('and the assistant replies without a function request', () => { + beforeEach(async () => { + await llmSimulator.next({ content: 'I am done here' }); + await llmSimulator.complete(); + await waitForNextWrite(stream); + + await finished(stream); + }); + + it('appends the assistant reply', () => { + expect(JSON.parse(dataHandler.mock.calls[3])).toEqual({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: expect.any(String), + message: { + content: 'I am done here', + }, + }); + expect(JSON.parse(dataHandler.mock.calls[4])).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + role: MessageRole.Assistant, + content: 'I am done here', + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + }); + }); + + it('stores the conversation', () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.ConversationCreate, + conversation: { + id: expect.any(String), + last_updated: expect.any(String), + title: 'My predefined title', + }, + }); + + expect(esClientMock.index).toHaveBeenCalled(); + + expect((esClientMock.index.mock.lastCall![0] as any).document.messages).toEqual([ + { + '@timestamp': expect.any(String), + message: { + content: 'This is a system message', + role: MessageRole.System, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'How many alerts do I have?', + role: MessageRole.User, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'Hello', + role: MessageRole.Assistant, + function_call: { + name: 'my-function', + arguments: JSON.stringify({ foo: 'bar' }), + trigger: MessageRole.Assistant, + }, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: JSON.stringify({ + my: 'content', + }), + name: 'my-function', + role: MessageRole.User, + }, + }, + { + '@timestamp': expect.any(String), + message: { + content: 'I am done here', + role: MessageRole.Assistant, + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + ]); + }); + }); + }); + + describe('and the function fails', () => { + beforeEach(async () => { + fnResponseReject(new Error('Function failed')); + await waitForNextWrite(stream); + }); + + it('appends the function response', () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + role: MessageRole.User, + name: 'my-function', + content: JSON.stringify({ + message: 'Error: Function failed', + error: {}, + }), + }, + }, + }); + }); + + it('sends the function response back to the llm', () => { + expect(actionsClientMock.execute).toHaveBeenCalledTimes(2); + expect(actionsClientMock.execute.mock.lastCall!).toEqual([ + { + actionId: 'foo', + params: { + subAction: 'stream', + subActionParams: { + body: expect.any(String), + stream: true, + }, + }, + }, + ]); + }); + }); + + describe('and the function responds with an observable', () => { + let response$: Subject; + beforeEach(async () => { + response$ = new Subject(); + fnResponseResolve(response$); + await waitForNextWrite(stream); + }); + + it('appends the function response', () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + role: MessageRole.User, + name: 'my-function', + content: '{}', + }, + }, + }); + }); + + describe('if the observable completes', () => { + beforeEach(async () => { + response$.next({ + created: 0, + id: '', + model: 'gpt-4', + object: 'chat.completion.chunk', + choices: [ + { + delta: { + content: 'Hello', + }, + }, + ], + }); + response$.complete(); + + await finished(stream); + }); + + it('emits a completion chunk', () => { + expect(JSON.parse(dataHandler.mock.calls[3])).toEqual({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: expect.any(String), + message: { + content: 'Hello', + }, + }); + }); + + it('appends the observable response', () => { + expect(JSON.parse(dataHandler.mock.calls[4])).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + role: MessageRole.Assistant, + content: 'Hello', + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + }); + }); + }); + + describe('if the observable errors out', () => { + beforeEach(async () => { + response$.next({ + created: 0, + id: '', + model: 'gpt-4', + object: 'chat.completion.chunk', + choices: [ + { + delta: { + content: 'Hello', + }, + }, + ], + }); + response$.error(new Error('Unexpected error')); + + await finished(stream); + }); + + it('appends an error', () => { + expect(JSON.parse(dataHandler.mock.lastCall!)).toEqual({ + type: StreamingChatResponseEventType.ConversationCompletionError, + error: { + message: 'Unexpected error', + stack: expect.any(String), + }, + }); + }); + }); + }); + }); + + describe('when recall is available', () => { + let stream: Readable; + + let dataHandler: jest.Mock; + beforeEach(async () => { + client = createClient(); + actionsClientMock.execute.mockImplementationOnce(async () => { + llmSimulator = createLlmSimulator(); + return { + actionId: '', + status: 'ok', + data: llmSimulator.stream, + }; + }); + + functionClientMock.hasFunction.mockReturnValue(true); + + functionClientMock.executeFunction.mockImplementationOnce(async () => { + return { + content: [ + { + id: 'my_document', + text: 'My document', + }, + ], + }; + }); + + stream = await client.complete({ + connectorId: 'foo', + messages: [system('This is a system message'), user('How many alerts do I have?')], + functionClient: functionClientMock, + signal: new AbortController().signal, + persist: false, + }); + + dataHandler = jest.fn(); + + stream.on('data', dataHandler); + + await waitForNextWrite(stream); + + await llmSimulator.next({ + content: 'Hello', + }); + + await llmSimulator.complete(); + + await finished(stream); + }); + + it('appends the recall request message', () => { + expect(JSON.parse(dataHandler.mock.calls[0]!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + content: '', + role: MessageRole.Assistant, + function_call: { + name: 'recall', + arguments: JSON.stringify({ queries: [], contexts: [] }), + trigger: MessageRole.Assistant, + }, + }, + }, + }); + }); + + it('appends the recall response', () => { + expect(JSON.parse(dataHandler.mock.calls[1]!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + content: JSON.stringify([{ id: 'my_document', text: 'My document' }]), + role: MessageRole.User, + name: 'recall', + }, + }, + }); + }); + + it('appends the response from the LLM', () => { + expect(JSON.parse(dataHandler.mock.calls[2]!)).toEqual({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + id: expect.any(String), + message: { + content: 'Hello', + }, + }); + + expect(JSON.parse(dataHandler.mock.calls[3]!)).toEqual({ + type: StreamingChatResponseEventType.MessageAdd, + id: expect.any(String), + message: { + '@timestamp': expect.any(String), + message: { + content: 'Hello', + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + role: MessageRole.Assistant, + }, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts index e31f213eeff02..c111af3d92d48 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/client/index.ts @@ -10,16 +10,23 @@ import type { ActionsClient } from '@kbn/actions-plugin/server'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; import type { PublicMethodsOf } from '@kbn/utility-types'; -import { compact, isEmpty, merge, omit } from 'lodash'; +import { compact, isEmpty, last, merge, omit, pick } from 'lodash'; import type { - ChatCompletionFunctions, ChatCompletionRequestMessage, CreateChatCompletionRequest, CreateChatCompletionResponse, } from 'openai'; +import { isObservable, lastValueFrom } from 'rxjs'; import { PassThrough, Readable } from 'stream'; import { v4 } from 'uuid'; import { + ConversationNotFoundError, + isChatCompletionError, + StreamingChatResponseEventType, + type StreamingChatResponseEvent, +} from '../../../common/conversation_complete'; +import { + FunctionResponse, MessageRole, type CompatibleJSONSchema, type Conversation, @@ -28,6 +35,9 @@ import { type KnowledgeBaseEntry, type Message, } from '../../../common/types'; +import { concatenateOpenAiChunks } from '../../../common/utils/concatenate_openai_chunks'; +import { processOpenAiStream } from '../../../common/utils/process_openai_stream'; +import type { ChatFunctionClient } from '../chat_function_client'; import { KnowledgeBaseEntryOperationType, KnowledgeBaseService, @@ -35,6 +45,8 @@ import { } from '../knowledge_base_service'; import type { ObservabilityAIAssistantResourceNames } from '../types'; import { getAccessQuery } from '../util/get_access_query'; +import { streamIntoObservable } from '../util/stream_into_observable'; +import { handleLlmResponse } from './handle_llm_response'; export class ObservabilityAIAssistantClient { constructor( @@ -108,18 +120,263 @@ export class ObservabilityAIAssistantClient { }); }; + complete = async ( + params: { + messages: Message[]; + connectorId: string; + signal: AbortSignal; + functionClient: ChatFunctionClient; + persist: boolean; + } & ({ conversationId: string } | { title?: string }) + ) => { + const stream = new PassThrough(); + + const { messages, connectorId, signal, functionClient, persist } = params; + + let conversationId: string = ''; + let title: string = ''; + if ('conversationId' in params) { + conversationId = params.conversationId; + } + + if ('title' in params) { + title = params.title || ''; + } + + function write(event: StreamingChatResponseEvent) { + if (stream.destroyed) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + stream.write(`${JSON.stringify(event)}\n`, 'utf-8', (err) => { + if (err) { + reject(err); + return; + } + resolve(); + }); + }); + } + + function fail(error: Error) { + const code = isChatCompletionError(error) ? error.code : undefined; + write({ + type: StreamingChatResponseEventType.ConversationCompletionError, + error: { + message: error.message, + stack: error.stack, + code, + }, + }).finally(() => { + stream.end(); + }); + } + + const next = async (nextMessages: Message[]): Promise => { + const lastMessage = last(nextMessages); + + const isUserMessage = lastMessage?.message.role === MessageRole.User; + + const isUserMessageWithoutFunctionResponse = isUserMessage && !lastMessage?.message.name; + + const recallFirst = + isUserMessageWithoutFunctionResponse && functionClient.hasFunction('recall'); + + const isAssistantMessageWithFunctionRequest = + lastMessage?.message.role === MessageRole.Assistant && + !!lastMessage?.message.function_call?.name; + + if (recallFirst) { + const addedMessage = { + '@timestamp': new Date().toISOString(), + message: { + role: MessageRole.Assistant, + content: '', + function_call: { + name: 'recall', + arguments: JSON.stringify({ + queries: [], + contexts: [], + }), + trigger: MessageRole.Assistant as const, + }, + }, + }; + await write({ + type: StreamingChatResponseEventType.MessageAdd, + id: v4(), + message: addedMessage, + }); + return await next(nextMessages.concat(addedMessage)); + } else if (isUserMessage) { + const { message } = await handleLlmResponse({ + signal, + write, + source$: streamIntoObservable( + await this.chat({ + messages: nextMessages, + connectorId, + stream: true, + signal, + functions: functionClient + .getFunctions() + .map((fn) => pick(fn.definition, 'name', 'description', 'parameters')), + }) + ).pipe(processOpenAiStream()), + }); + return await next(nextMessages.concat({ message, '@timestamp': new Date().toISOString() })); + } + + if (isAssistantMessageWithFunctionRequest) { + const functionResponse = await functionClient + .executeFunction({ + connectorId, + name: lastMessage.message.function_call!.name, + messages: nextMessages, + args: lastMessage.message.function_call!.arguments, + signal, + }) + .catch((error): FunctionResponse => { + return { + content: { + message: error.toString(), + error, + }, + }; + }); + + if (signal.aborted) { + return; + } + + const functionResponseIsObservable = isObservable(functionResponse); + + const functionResponseMessage = { + '@timestamp': new Date().toISOString(), + message: { + name: lastMessage.message.function_call!.name, + ...(functionResponseIsObservable + ? { content: '{}' } + : { + content: JSON.stringify(functionResponse.content || {}), + data: functionResponse.data ? JSON.stringify(functionResponse.data) : undefined, + }), + role: MessageRole.User, + }, + }; + + nextMessages = nextMessages.concat(functionResponseMessage); + await write({ + type: StreamingChatResponseEventType.MessageAdd, + message: functionResponseMessage, + id: v4(), + }); + + if (functionResponseIsObservable) { + const { message } = await handleLlmResponse({ + signal, + write, + source$: functionResponse, + }); + return await next( + nextMessages.concat({ '@timestamp': new Date().toISOString(), message }) + ); + } + return await next(nextMessages); + } + + if (!persist) { + stream.end(); + return; + } + + // store the updated conversation and close the stream + if (conversationId) { + const conversation = await this.getConversationWithMetaFields(conversationId); + if (!conversation) { + throw new ConversationNotFoundError(); + } + + if (signal.aborted) { + return; + } + + const updatedConversation = await this.update( + merge({}, omit(conversation._source, 'messages'), { messages: nextMessages }) + ); + await write({ + type: StreamingChatResponseEventType.ConversationUpdate, + conversation: updatedConversation.conversation, + }); + } else { + const generatedTitle = await titlePromise; + if (signal.aborted) { + return; + } + + const conversation = await this.create({ + '@timestamp': new Date().toISOString(), + conversation: { + title: generatedTitle || title || 'New conversation', + }, + messages: nextMessages, + labels: {}, + numeric_labels: {}, + public: false, + }); + await write({ + type: StreamingChatResponseEventType.ConversationCreate, + conversation: conversation.conversation, + }); + } + + stream.end(); + }; + + next(messages).catch((error) => { + if (!signal.aborted) { + this.dependencies.logger.error(error); + } + fail(error); + }); + + const titlePromise = + !conversationId && !title && persist + ? this.getGeneratedTitle({ + messages, + connectorId, + signal, + }).catch((error) => { + this.dependencies.logger.error( + 'Could not generate title, falling back to default title' + ); + this.dependencies.logger.error(error); + return Promise.resolve(undefined); + }) + : Promise.resolve(undefined); + + signal.addEventListener('abort', () => { + stream.end(); + }); + + return stream; + }; + chat = async ({ messages, connectorId, functions, functionCall, stream = true, + signal, }: { messages: Message[]; connectorId: string; functions?: Array<{ name: string; description: string; parameters: CompatibleJSONSchema }>; functionCall?: string; stream?: TStream; + signal: AbortSignal; }): Promise => { const messagesForOpenAI: ChatCompletionRequestMessage[] = compact( messages @@ -139,47 +396,12 @@ export class ObservabilityAIAssistantClient { }) ); - // add recalled information to system message, so the LLM considers it more important - - const recallMessages = messagesForOpenAI.filter((message) => message.name === 'recall'); - - const recalledDocuments: Map = new Map(); - - recallMessages.forEach((message) => { - const entries = message.content - ? (JSON.parse(message.content) as Array<{ id: string; text: string }>) - : []; - - const ids: string[] = []; - - entries.forEach((entry) => { - const id = entry.id; - if (!recalledDocuments.has(id)) { - recalledDocuments.set(id, entry); - } - ids.push(id); - }); - - message.content = `The following documents, present in the system message, were recalled: ${ids.join( - ', ' - )}`; - }); - - const systemMessage = messagesForOpenAI.find((message) => message.role === MessageRole.System); - - if (systemMessage && recalledDocuments.size > 0) { - systemMessage.content += `The "recall" function is not available. Do not attempt to execute it. Recalled documents: ${JSON.stringify( - Array.from(recalledDocuments.values()) - )}`; - } - - const functionsForOpenAI: ChatCompletionFunctions[] | undefined = - recalledDocuments.size > 0 ? functions?.filter((fn) => fn.name !== 'recall') : functions; + const functionsForOpenAI = functions; const request: Omit & { model?: string } = { messages: messagesForOpenAI, - stream: true, - functions: functionsForOpenAI, + ...(stream ? { stream: true } : {}), + ...(!!functions?.length ? { functions: functionsForOpenAI } : {}), temperature: 0, function_call: functionCall ? { name: functionCall } : undefined, }; @@ -200,9 +422,15 @@ export class ObservabilityAIAssistantClient { } const response = stream - ? ((executeResult.data as Readable).pipe(new PassThrough()) as Readable) + ? (executeResult.data as Readable) : (executeResult.data as CreateChatCompletionResponse); + if (response instanceof PassThrough) { + signal.addEventListener('abort', () => { + response.end(); + }); + } + return response as any; }; @@ -254,65 +482,47 @@ export class ObservabilityAIAssistantClient { return updatedConversation; }; - autoTitle = async ({ - conversationId, + getGeneratedTitle = async ({ + messages, connectorId, + signal, }: { - conversationId: string; + messages: Message[]; connectorId: string; + signal: AbortSignal; }) => { - const document = await this.getConversationWithMetaFields(conversationId); - if (!document) { - throw notFound(); - } - - const conversation = await this.get(conversationId); - - if (!conversation) { - throw notFound(); - } - - const response = await this.chat({ + const stream = await this.chat({ messages: [ { '@timestamp': new Date().toISOString(), message: { - role: MessageRole.Assistant, - content: conversation.messages.slice(1).reduce((acc, curr) => { + role: MessageRole.User, + content: messages.slice(1).reduce((acc, curr) => { return `${acc} ${curr.message.role}: ${curr.message.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 this 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. Here is the content:'), }, }, ], connectorId, - stream: false, + stream: true, + signal, }); - if ('object' in response && response.object === 'chat.completion') { - const input = - response.choices[0].message?.content || `Conversation on ${conversation['@timestamp']}`; - - // This regular expression captures a string enclosed in single or double quotes. - // It extracts the string content without the quotes. - // Example matches: - // - "Hello, World!" => Captures: Hello, World! - // - 'Another Example' => Captures: Another Example - // - JustTextWithoutQuotes => Captures: JustTextWithoutQuotes - const match = input.match(/^["']?([^"']+)["']?$/); - const title = match ? match[1] : input; - - const updatedConversation: Conversation = merge( - {}, - conversation, - { conversation: { title } }, - this.getConversationUpdateValues(new Date().toISOString()) - ); - - await this.setTitle({ conversationId, title }); - - return updatedConversation; - } - return conversation; + const response = await lastValueFrom( + streamIntoObservable(stream).pipe(processOpenAiStream(), concatenateOpenAiChunks()) + ); + + const input = response.message?.content || ''; + + // This regular expression captures a string enclosed in single or double quotes. + // It extracts the string content without the quotes. + // Example matches: + // - "Hello, World!" => Captures: Hello, World! + // - 'Another Example' => Captures: Another Example + // - JustTextWithoutQuotes => Captures: JustTextWithoutQuotes + const match = input.match(/^["']?([^"']+)["']?$/); + const title = match ? match[1] : input; + return title; }; setTitle = async ({ conversationId, title }: { conversationId: string; title: string }) => { diff --git a/x-pack/plugins/observability_ai_assistant/server/service/index.ts b/x-pack/plugins/observability_ai_assistant/server/service/index.ts index 00cb233364381..595217bc69e5c 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/index.ts @@ -12,41 +12,38 @@ import type { CoreSetup, CoreStart, KibanaRequest, Logger } from '@kbn/core/serv import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import { getSpaceIdFromPath } from '@kbn/spaces-plugin/common'; import type { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; +import Ajv, { type ValidateFunction } from 'ajv'; import { once } from 'lodash'; -import { KnowledgeBaseEntryRole } from '../../common/types'; +import { + ContextRegistry, + KnowledgeBaseEntryRole, + RegisterContextDefinition, +} from '../../common/types'; import type { ObservabilityAIAssistantPluginStartDependencies } from '../types'; +import { ChatFunctionClient } from './chat_function_client'; import { ObservabilityAIAssistantClient } from './client'; import { conversationComponentTemplate } from './conversation_component_template'; import { kbComponentTemplate } from './kb_component_template'; import { KnowledgeBaseEntryOperationType, KnowledgeBaseService } from './knowledge_base_service'; -import type { ObservabilityAIAssistantResourceNames } from './types'; +import type { + ChatRegistrationFunction, + FunctionHandlerRegistry, + ObservabilityAIAssistantResourceNames, + RegisterFunction, + RespondFunctionResources, +} from './types'; import { splitKbText } from './util/split_kb_text'; +const ajv = new Ajv({ + strict: false, +}); + function getResourceName(resource: string) { return `.kibana-observability-ai-assistant-${resource}`; } -export const ELSER_MODEL_ID = '.elser_model_2'; - -export const INDEX_QUEUED_DOCUMENTS_TASK_ID = 'observabilityAIAssistant:indexQueuedDocumentsTask'; - -export const INDEX_QUEUED_DOCUMENTS_TASK_TYPE = INDEX_QUEUED_DOCUMENTS_TASK_ID + 'Type'; - -type KnowledgeBaseEntryRequest = { id: string; labels?: Record } & ( - | { - text: string; - } - | { - texts: string[]; - } -); - -export class ObservabilityAIAssistantService { - private readonly core: CoreSetup; - private readonly logger: Logger; - private kbService?: KnowledgeBaseService; - - private readonly resourceNames: ObservabilityAIAssistantResourceNames = { +export function createResourceNamesMap() { + return { componentTemplate: { conversations: getResourceName('component-template-conversations'), kb: getResourceName('component-template-kb'), @@ -67,6 +64,31 @@ export class ObservabilityAIAssistantService { kb: getResourceName('kb-ingest-pipeline'), }, }; +} + +export const ELSER_MODEL_ID = '.elser_model_2'; + +export const INDEX_QUEUED_DOCUMENTS_TASK_ID = 'observabilityAIAssistant:indexQueuedDocumentsTask'; + +export const INDEX_QUEUED_DOCUMENTS_TASK_TYPE = INDEX_QUEUED_DOCUMENTS_TASK_ID + 'Type'; + +type KnowledgeBaseEntryRequest = { id: string; labels?: Record } & ( + | { + text: string; + } + | { + texts: string[]; + } +); + +export class ObservabilityAIAssistantService { + private readonly core: CoreSetup; + private readonly logger: Logger; + private kbService?: KnowledgeBaseService; + + private readonly resourceNames: ObservabilityAIAssistantResourceNames = createResourceNamesMap(); + + private readonly registrations: ChatRegistrationFunction[] = []; constructor({ logger, @@ -100,6 +122,12 @@ export class ObservabilityAIAssistantService { }); } + getKnowledgeBaseStatus() { + return this.init().then(() => { + return this.kbService!.status(); + }); + } + init = once(async () => { try { const [coreStart, pluginsStart] = await this.core.getStartServices(); @@ -224,13 +252,18 @@ export class ObservabilityAIAssistantService { }: { request: KibanaRequest; }): Promise { + const controller = new AbortController(); + + request.events.aborted$.subscribe(() => { + controller.abort(); + }); + const [_, [coreStart, plugins]] = await Promise.all([ this.init(), this.core.getStartServices() as Promise< [CoreStart, { security: SecurityPluginStart; actions: ActionsPluginStart }, unknown] >, ]); - const user = plugins.security.authc.getCurrentUser(request); if (!user) { @@ -255,6 +288,37 @@ export class ObservabilityAIAssistantService { }); } + async getFunctionClient({ + signal, + resources, + client, + }: { + signal: AbortSignal; + resources: RespondFunctionResources; + client: ObservabilityAIAssistantClient; + }): Promise { + const contextRegistry: ContextRegistry = new Map(); + const functionHandlerRegistry: FunctionHandlerRegistry = new Map(); + + const validators = new Map(); + + const registerContext: RegisterContextDefinition = (context) => { + contextRegistry.set(context.name, context); + }; + + const registerFunction: RegisterFunction = (definition, respond) => { + validators.set(definition.name, ajv.compile(definition.parameters)); + functionHandlerRegistry.set(definition.name, { definition, respond }); + }; + await Promise.all( + this.registrations.map((fn) => + fn({ signal, registerContext, registerFunction, resources, client }) + ) + ); + + return new ChatFunctionClient(contextRegistry, functionHandlerRegistry, validators); + } + addToKnowledgeBase(entries: KnowledgeBaseEntryRequest[]): void { this.init() .then(() => { @@ -308,4 +372,8 @@ export class ObservabilityAIAssistantService { }) ); } + + register(fn: ChatRegistrationFunction) { + this.registrations.push(fn); + } } diff --git a/x-pack/plugins/observability_ai_assistant/server/service/types.ts b/x-pack/plugins/observability_ai_assistant/server/service/types.ts index 39c2b29dbb026..d89bfd546c702 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/types.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/types.ts @@ -5,6 +5,54 @@ * 2.0. */ +import type { FromSchema } from 'json-schema-to-ts'; +import type { + CompatibleJSONSchema, + FunctionDefinition, + FunctionResponse, + Message, + RegisterContextDefinition, +} from '../../common/types'; +import type { ObservabilityAIAssistantRouteHandlerResources } from '../routes/types'; +import type { ObservabilityAIAssistantClient } from './client'; + +export type RespondFunctionResources = Pick< + ObservabilityAIAssistantRouteHandlerResources, + 'context' | 'logger' | 'plugins' | 'request' +>; + +type RespondFunction = ( + options: { + arguments: TArguments; + messages: Message[]; + connectorId: string; + }, + signal: AbortSignal +) => Promise; + +export interface FunctionHandler { + definition: FunctionDefinition; + respond: RespondFunction; +} + +export type RegisterFunction = < + TParameters extends CompatibleJSONSchema = any, + TResponse extends FunctionResponse = any, + TArguments = FromSchema +>( + definition: FunctionDefinition, + respond: RespondFunction +) => void; +export type FunctionHandlerRegistry = Map; + +export type ChatRegistrationFunction = ({}: { + signal: AbortSignal; + resources: RespondFunctionResources; + client: ObservabilityAIAssistantClient; + registerFunction: RegisterFunction; + registerContext: RegisterContextDefinition; +}) => Promise; + export interface ObservabilityAIAssistantResourceNames { componentTemplate: { conversations: string; diff --git a/x-pack/plugins/observability_ai_assistant/server/service/util/stream_into_observable.ts b/x-pack/plugins/observability_ai_assistant/server/service/util/stream_into_observable.ts new file mode 100644 index 0000000000000..764e39fdec152 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/server/service/util/stream_into_observable.ts @@ -0,0 +1,24 @@ +/* + * 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 { concatMap, filter, from, map, Observable } from 'rxjs'; +import type { Readable } from 'stream'; + +export function streamIntoObservable(readable: Readable): Observable { + let lineBuffer = ''; + + return from(readable).pipe( + map((chunk: Buffer) => chunk.toString('utf-8')), + map((part) => { + const lines = (lineBuffer + part).split('\n'); + lineBuffer = lines.pop() || ''; // Keep the last incomplete line for the next chunk + return lines; + }), + concatMap((lines) => lines), + filter((line) => line.trim() !== '') + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/server/types.ts b/x-pack/plugins/observability_ai_assistant/server/types.ts index bdb283b9a1df2..6e70663be3d8f 100644 --- a/x-pack/plugins/observability_ai_assistant/server/types.ts +++ b/x-pack/plugins/observability_ai_assistant/server/types.ts @@ -18,10 +18,22 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; +import { ObservabilityAIAssistantService } from './service'; + +export interface ObservabilityAIAssistantPluginSetup { + /** + * Returns a Observability AI Assistant service instance + */ + service: ObservabilityAIAssistantService; +} + +export interface ObservabilityAIAssistantPluginStart { + /** + * Returns a Observability AI Assistant service instance + */ + service: ObservabilityAIAssistantService; +} -/* eslint-disable @typescript-eslint/no-empty-interface*/ -export interface ObservabilityAIAssistantPluginStart {} -export interface ObservabilityAIAssistantPluginSetup {} export interface ObservabilityAIAssistantPluginSetupDependencies { actions: ActionsPluginSetup; security: SecurityPluginSetup; diff --git a/x-pack/plugins/observability_log_explorer/common/locators/locators.test.ts b/x-pack/plugins/observability_log_explorer/common/locators/locators.test.ts index fa4fea9baf7a8..d26ff4e133ea6 100644 --- a/x-pack/plugins/observability_log_explorer/common/locators/locators.test.ts +++ b/x-pack/plugins/observability_log_explorer/common/locators/locators.test.ts @@ -11,7 +11,7 @@ import { AllDatasetsLocatorParams, SingleDatasetLocatorParams, } from '@kbn/deeplinks-observability/locators'; -import { OBSERVABILITY_LOG_EXPLORER_APP_ID } from '../constants'; +import { OBSERVABILITY_LOG_EXPLORER } from '@kbn/deeplinks-observability'; import { AllDatasetsLocatorDefinition } from './all_datasets/all_datasets_locator'; import { SingleDatasetLocatorDefinition } from './single_dataset'; import { DatasetLocatorDependencies } from './types'; @@ -38,7 +38,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await allDatasetsLocator.getLocation({}); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: '/?_a=(index:BQZwpgNmDGAuCWB7AdgFQJ4AcwC4CGEEAlEA)', state: {}, }); @@ -53,7 +53,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await allDatasetsLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: '/?_g=(time:(from:now-30m,to:now))&_a=(index:BQZwpgNmDGAuCWB7AdgFQJ4AcwC4CGEEAlEA)', state: {}, }); @@ -70,7 +70,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await allDatasetsLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: '/?_a=(index:BQZwpgNmDGAuCWB7AdgFQJ4AcwC4CGEEAlEA,query:(language:kuery,query:foo))', state: {}, }); @@ -88,7 +88,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await allDatasetsLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: '/?_g=(refreshInterval:(pause:!f,value:666))&_a=(index:BQZwpgNmDGAuCWB7AdgFQJ4AcwC4CGEEAlEA)', state: {}, }); @@ -104,7 +104,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await allDatasetsLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_a=(columns:!(_source),index:BQZwpgNmDGAuCWB7AdgFQJ4AcwC4CGEEAlEA,sort:!(!('timestamp,%20asc')))`, state: {}, }); @@ -184,7 +184,7 @@ describe('Observability Logs Explorer Locators', () => { }); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_a=(index:BQZwpgNmDGAuCWB7AdgLmAEwIay%2BW6yWAtmKgOQSIDmIAtLGCLHQFRvkA0CsUqjzAJScipVABUmsYeChwkycQE8ADmQCuyAE5NEEAG5gMgoA)`, state: {}, }); @@ -201,7 +201,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await singleDatasetLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_g=(time:(from:now-30m,to:now))&_a=(index:BQZwpgNmDGAuCWB7AdgLmAEwIay%2BW6yWAtmKgOQSIDmIAtLGCLHQFRvkA0CsUqjzAJScipVABUmsYeChwkycQE8ADmQCuyAE5NEEAG5gMgoA)`, state: {}, }); @@ -221,7 +221,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await singleDatasetLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_a=(index:BQZwpgNmDGAuCWB7AdgLmAEwIay%2BW6yWAtmKgOQSIDmIAtLGCLHQFRvkA0CsUqjzAJScipVABUmsYeChwkycQE8ADmQCuyAE5NEEAG5gMgoA,query:(language:kuery,query:foo))`, state: {}, }); @@ -241,7 +241,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await singleDatasetLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_g=(refreshInterval:(pause:!f,value:666))&_a=(index:BQZwpgNmDGAuCWB7AdgLmAEwIay%2BW6yWAtmKgOQSIDmIAtLGCLHQFRvkA0CsUqjzAJScipVABUmsYeChwkycQE8ADmQCuyAE5NEEAG5gMgoA)`, state: {}, }); @@ -259,7 +259,7 @@ describe('Observability Logs Explorer Locators', () => { const location = await singleDatasetLocator.getLocation(params); expect(location).toMatchObject({ - app: OBSERVABILITY_LOG_EXPLORER_APP_ID, + app: OBSERVABILITY_LOG_EXPLORER, path: `/?_a=(columns:!(_source),index:BQZwpgNmDGAuCWB7AdgLmAEwIay%2BW6yWAtmKgOQSIDmIAtLGCLHQFRvkA0CsUqjzAJScipVABUmsYeChwkycQE8ADmQCuyAE5NEEAG5gMgoA,sort:!(!('timestamp,%20asc')))`, state: {}, }); diff --git a/x-pack/plugins/observability_log_explorer/common/translations.ts b/x-pack/plugins/observability_log_explorer/common/translations.ts index d5b1811f51955..d04c9942c9cbc 100644 --- a/x-pack/plugins/observability_log_explorer/common/translations.ts +++ b/x-pack/plugins/observability_log_explorer/common/translations.ts @@ -11,6 +11,17 @@ export const logExplorerAppTitle = i18n.translate('xpack.observabilityLogExplore defaultMessage: 'Log Explorer', }); +export const logsAppTitle = i18n.translate('xpack.observabilityLogExplorer.logsAppTitle', { + defaultMessage: 'Logs', +}); + +export const observabilityAppTitle = i18n.translate( + 'xpack.observabilityLogExplorer.observabilityAppTitle', + { + defaultMessage: 'Observability', + } +); + export const betaBadgeTitle = i18n.translate('xpack.observabilityLogExplorer.betaBadgeTitle', { defaultMessage: 'Beta', }); diff --git a/x-pack/plugins/observability_log_explorer/public/plugin.ts b/x-pack/plugins/observability_log_explorer/public/plugin.ts index f3b3cffaf9701..755072ad9786d 100644 --- a/x-pack/plugins/observability_log_explorer/public/plugin.ts +++ b/x-pack/plugins/observability_log_explorer/public/plugin.ts @@ -13,13 +13,13 @@ import { Plugin, PluginInitializerContext, } from '@kbn/core/public'; +import { OBSERVABILITY_LOG_EXPLORER } from '@kbn/deeplinks-observability'; import { ObservabilityLogExplorerLocators, SingleDatasetLocatorDefinition, AllDatasetsLocatorDefinition, } from '../common/locators'; import { type ObservabilityLogExplorerConfig } from '../common/plugin_config'; -import { OBSERVABILITY_LOG_EXPLORER_APP_ID } from '../common/constants'; import { logExplorerAppTitle } from '../common/translations'; import { renderObservabilityLogExplorer } from './applications/observability_log_explorer'; import type { @@ -48,7 +48,7 @@ export class ObservabilityLogExplorerPlugin const useHash = core.uiSettings.get('state:storeInSessionStorage'); core.application.register({ - id: OBSERVABILITY_LOG_EXPLORER_APP_ID, + id: OBSERVABILITY_LOG_EXPLORER, title: logExplorerAppTitle, category: DEFAULT_APP_CATEGORIES.observability, euiIconType: 'logoLogging', diff --git a/x-pack/plugins/observability_log_explorer/public/utils/breadcrumbs.tsx b/x-pack/plugins/observability_log_explorer/public/utils/breadcrumbs.tsx index c1eaca45b7855..55b4b9359fd0b 100644 --- a/x-pack/plugins/observability_log_explorer/public/utils/breadcrumbs.tsx +++ b/x-pack/plugins/observability_log_explorer/public/utils/breadcrumbs.tsx @@ -9,16 +9,50 @@ import { EuiBreadcrumb } from '@elastic/eui'; import type { ChromeStart } from '@kbn/core-chrome-browser'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; import { useEffect } from 'react'; -import { logExplorerAppTitle } from '../../common/translations'; +import { useLinkProps } from '@kbn/observability-shared-plugin/public'; +import { + LOGS_APP_ID, + OBSERVABILITY_LOG_EXPLORER, + OBSERVABILITY_OVERVIEW_APP_ID, +} from '@kbn/deeplinks-observability'; +import { + logExplorerAppTitle, + logsAppTitle, + observabilityAppTitle, +} from '../../common/translations'; export const useBreadcrumbs = ( breadcrumbs: EuiBreadcrumb[], chromeService: ChromeStart, serverlessService?: ServerlessPluginStart ) => { + const observabilityLinkProps = useLinkProps({ app: OBSERVABILITY_OVERVIEW_APP_ID }); + const logsLinkProps = useLinkProps({ app: LOGS_APP_ID }); + const logExplorerLinkProps = useLinkProps({ app: OBSERVABILITY_LOG_EXPLORER }); + useEffect(() => { - setBreadcrumbs(breadcrumbs, chromeService, serverlessService); - }, [breadcrumbs, chromeService, serverlessService]); + setBreadcrumbs( + serverlessService + ? breadcrumbs + : [ + { + text: observabilityAppTitle, + ...observabilityLinkProps, + }, + { + text: logsAppTitle, + ...logsLinkProps, + }, + { + text: logExplorerAppTitle, + ...logExplorerLinkProps, + }, + ...breadcrumbs, + ], + chromeService, + serverlessService + ); + }, [breadcrumbs, chromeService, serverlessService]); // eslint-disable-line react-hooks/exhaustive-deps }; export function setBreadcrumbs( @@ -26,16 +60,16 @@ export function setBreadcrumbs( chromeService: ChromeStart, serverlessService?: ServerlessPluginStart ) { + chromeService.docTitle.change(getDocTitle(breadcrumbs)); if (serverlessService) { serverlessService.setBreadcrumbs(breadcrumbs); } else if (chromeService) { - chromeService.setBreadcrumbs([ - { - text: logExplorerAppTitle, - }, - ...breadcrumbs, - ]); + chromeService.setBreadcrumbs(breadcrumbs); } } +export function getDocTitle(breadcrumbs: EuiBreadcrumb[]) { + return breadcrumbs.map(({ text }) => text as string).reverse(); +} + export const noBreadcrumbs: EuiBreadcrumb[] = []; diff --git a/x-pack/plugins/profiling/common/__fixtures__/base_flamegraph.ts b/x-pack/plugins/profiling/common/__fixtures__/base_flamegraph.ts index 1e1b2bd341b8f..f89080654c1b6 100644 --- a/x-pack/plugins/profiling/common/__fixtures__/base_flamegraph.ts +++ b/x-pack/plugins/profiling/common/__fixtures__/base_flamegraph.ts @@ -288,10 +288,6 @@ export const baseFlamegraph: BaseFlameGraph = { SamplingRate: 1, SelfCPU: 7, TotalCPU: 245, - SelfAnnualCO2Tons: 0.0013627551116480942, - TotalAnnualCO2Tons: 0.04769642890768329, - SelfAnnualCostsUSD: 61.30240940376492, - TotalAnnualCostsUSD: 2145.5843291317715, TotalSamples: 7, TotalSeconds: 4.980000019073486, }; diff --git a/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/differential_functions.cy.ts b/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/differential_functions.cy.ts index aaf42b56542f4..187a9a09d49c7 100644 --- a/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/differential_functions.cy.ts +++ b/x-pack/plugins/profiling/e2e/cypress/e2e/profiling_views/differential_functions.cy.ts @@ -31,8 +31,8 @@ describe('Differential Functions page', () => { cy.wait('@getTopNFunctions'); [ { id: 'overallPerformance', value: '0%' }, - { id: 'annualizedCo2', value: '2.5k lbs / 1.13k kg' }, - { id: 'annualizedCost', value: '$10.66k' }, + { id: 'annualizedCo2', value: '74.49 lbs / 33.79 kg' }, + { id: 'annualizedCost', value: '$318.32' }, { id: 'totalNumberOfSamples', value: '513' }, ].forEach((item) => { cy.get(`[data-test-subj="${item.id}_value"]`).contains(item.value); @@ -50,8 +50,8 @@ describe('Differential Functions page', () => { cy.wait('@getTopNFunctions'); [ { id: 'overallPerformance', value: '0%' }, - { id: 'annualizedCo2', value: '0 lbs / 0 kg', comparisonValue: '2.5k lbs / 1.13k kg' }, - { id: 'annualizedCost', value: '$0', comparisonValue: '$10.66k' }, + { id: 'annualizedCo2', value: '0 lbs / 0 kg', comparisonValue: '74.49 lbs / 33.79 kg' }, + { id: 'annualizedCost', value: '$0', comparisonValue: '$318.32' }, { id: 'totalNumberOfSamples', value: '0', comparisonValue: '15,390' }, ].forEach((item) => { cy.get(`[data-test-subj="${item.id}_value"]`).contains(item.value); @@ -76,14 +76,14 @@ describe('Differential Functions page', () => { { id: 'overallPerformance', value: '65.89%', icon: 'sortUp_success' }, { id: 'annualizedCo2', - value: '2.5k lbs / 1.13k kg', - comparisonValue: '548.84 lbs / 248.95 kg (78.01%', + value: '74.49 lbs / 33.79 kg', + comparisonValue: '25.41 lbs / 11.53 kg (65.89%)', icon: 'comparison_sortUp_success', }, { id: 'annualizedCost', - value: '$10.66k', - comparisonValue: '$2.35k (78.01%)', + value: '$318.32', + comparisonValue: '$108.59 (65.89%)', icon: 'comparison_sortUp_success', }, { @@ -116,14 +116,14 @@ describe('Differential Functions page', () => { { id: 'overallPerformance', value: '193.14%', icon: 'sortDown_danger' }, { id: 'annualizedCo2', - value: '548.84 lbs / 248.95 kg', - comparisonValue: '2.5k lbs / 1.13k kg (354.66%)', + value: '25.41 lbs / 11.53 kg', + comparisonValue: '74.49 lbs / 33.79 kg (193.14%)', icon: 'comparison_sortDown_danger', }, { id: 'annualizedCost', - value: '$2.35k', - comparisonValue: '$10.66k (354.66%)', + value: '$108.59', + comparisonValue: '$318.32 (193.14%)', icon: 'comparison_sortDown_danger', }, { diff --git a/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx b/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx index 7581d9a418618..82c7c0f92c071 100644 --- a/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx +++ b/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx @@ -131,8 +131,8 @@ export function DifferentialFlameGraphsView() { totalCPU: state.data.primaryFlamegraph.TotalCPU, totalCount: state.data.primaryFlamegraph.TotalSamples, scaleFactor: isNormalizedByTime ? baselineTime : baseline, - totalAnnualCO2Kgs: state.data.primaryFlamegraph.TotalAnnualCO2Kgs, - totalAnnualCostUSD: state.data.primaryFlamegraph.TotalAnnualCostsUSD, + totalAnnualCO2Kgs: state.data.primaryFlamegraph.TotalAnnualCO2KgsItems[0], + totalAnnualCostUSD: state.data.primaryFlamegraph.TotalAnnualCostsUSDItems[0], } : undefined } @@ -144,8 +144,8 @@ export function DifferentialFlameGraphsView() { totalCPU: state.data.comparisonFlamegraph.TotalCPU, totalCount: state.data.comparisonFlamegraph.TotalSamples, scaleFactor: isNormalizedByTime ? comparisonTime : comparison, - totalAnnualCO2Kgs: state.data.comparisonFlamegraph.TotalAnnualCO2Kgs, - totalAnnualCostUSD: state.data.comparisonFlamegraph.TotalAnnualCostsUSD, + totalAnnualCO2Kgs: state.data.comparisonFlamegraph.TotalAnnualCO2KgsItems[0], + totalAnnualCostUSD: state.data.comparisonFlamegraph.TotalAnnualCostsUSDItems[0], } : undefined } diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/managed_details/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/managed_details/index.ts index 3ab346fc7c697..49fd729c3a0d5 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/managed_details/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/managed_details/index.ts @@ -25,6 +25,6 @@ export interface ManagedUserHit { fields?: ManagedUserFields; } -export type ManagedUserHits = Record; +export type ManagedUserHits = Partial>; export type ManagedUserFields = Record; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts index ad3334e536793..f2470d197d562 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts @@ -6,7 +6,7 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import type { IEsError } from '@kbn/data-plugin/public'; +import type { IEsError } from '@kbn/search-errors'; import type { KibanaError, SecurityAppError } from '@kbn/securitysolution-t-grid'; import { useToasts } from '../lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts index 99500a42b8c35..7a810fa9247d2 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts @@ -10,8 +10,7 @@ import { isString } from 'lodash/fp'; import type { AppError } from '@kbn/securitysolution-t-grid'; import { isAppError, isKibanaError, isSecurityAppError } from '@kbn/securitysolution-t-grid'; -import type { IEsError } from '@kbn/data-plugin/public'; -import { isEsError } from '@kbn/data-plugin/public'; +import { type IEsError, isEsError } from '@kbn/search-errors'; import type { ErrorToastOptions, ToastsStart, Toast } from '@kbn/core/public'; import { useToasts } from '../lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.test.tsx index d502e8e2d06dd..2f1ada7447dd6 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/header.test.tsx @@ -75,7 +75,6 @@ describe('UserDetailsContent', () => { '@timestamp': [futureDay], }, }, - [ManagedUserDatasetKey.OKTA]: undefined, }, }, }} @@ -126,10 +125,7 @@ describe('UserDetailsContent', () => { ...mockProps, managedUser: { ...mockManagedUserData, - data: { - [ManagedUserDatasetKey.ENTRA]: undefined, - [ManagedUserDatasetKey.OKTA]: undefined, - }, + data: {}, }, }} /> diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts index 91b4751d745f1..1152caf76724a 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts @@ -66,6 +66,7 @@ export const getCypressBaseConfig = ( // grep related configs grepFilterSpecs: true, grepOmitFiltered: true, + IS_CI: process.env.CI, }, e2e: { diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/cases_response_console.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/cases_response_console.cy.ts index a33d325d5443a..573d3749c7391 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/cases_response_console.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/cases_response_console.cy.ts @@ -28,7 +28,8 @@ import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; import { APP_CASES_PATH } from '../../../../../common/constants'; -describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { +// TIMING OUT: https://github.com/elastic/kibana/issues/172720 +describe.skip('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { let indexedPolicy: IndexedFleetEndpointPolicyResponse; let policy: PolicyData; let createdHost: CreateAndEnrollEndpointHostResponse; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts index 9d378fde22f68..e76a0beb82dca 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts @@ -26,9 +26,8 @@ describe('Response console', { tags: ['@ess', '@serverless'] }, () => { login(); }); - // FLAKY: https://github.com/elastic/kibana/issues/170482 - describe.skip('File operations:', () => { - const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`; + describe('File operations:', () => { + const homeFilePath = Cypress.env('IS_CI') ? '/home/vagrant' : '/home/ubuntu'; const fileContent = 'This is a test file for the get-file command.'; const filePath = `${homeFilePath}/test_file.txt`; @@ -68,38 +67,52 @@ describe('Response console', { tags: ['@ess', '@serverless'] }, () => { }); it('"get-file --path" - should retrieve a file', () => { + const downloadsFolder = Cypress.config('downloadsFolder'); + waitForEndpointListPageToBeLoaded(createdHost.hostname); cy.task('createFileOnEndpoint', { hostname: createdHost.hostname, path: filePath, content: fileContent, }); + + // initiate get file action and wait for the API to complete + cy.intercept('api/endpoint/action/get_file').as('getFileAction'); openResponseConsoleFromEndpointList(); inputConsoleCommand(`get-file --path ${filePath}`); submitCommand(); - cy.getByTestSubj('getFileSuccess', { timeout: 60000 }).within(() => { + cy.wait('@getFileAction', { timeout: 60000 }); + + // verify that the file was retrieved + // and that the file download link is available + cy.getByTestSubj('getFileSuccess').within(() => { cy.contains('File retrieved from the host.'); cy.contains('(ZIP file passcode: elastic)'); cy.contains( 'Files are periodically deleted to clear storage space. Download and save file locally if needed.' ); - cy.contains('Click here to download').click(); - const downloadsFolder = Cypress.config('downloadsFolder'); - cy.readFile(`${downloadsFolder}/upload.zip`); - - cy.task('uploadFileToEndpoint', { - hostname: createdHost.hostname, - srcPath: `${downloadsFolder}/upload.zip`, - destPath: `${homeFilePath}/upload.zip`, - }); - - cy.task('readZippedFileContentOnEndpoint', { - hostname: createdHost.hostname, - path: `${homeFilePath}/upload.zip`, - password: 'elastic', - }).then((unzippedFileContent) => { - expect(unzippedFileContent).to.equal(fileContent); - }); + cy.contains('Click here to download').should('exist'); + }); + + cy.contains('Click here to download').click(); + + // wait for file to be downloaded + cy.readFile(`${downloadsFolder}/upload.zip`, { timeout: 120000 }).should('exist'); + + // move the zip file to VM + cy.task('uploadFileToEndpoint', { + hostname: createdHost.hostname, + srcPath: `${downloadsFolder}/upload.zip`, + destPath: `${homeFilePath}/upload.zip`, + }); + + // unzip the file and read its content + cy.task('readZippedFileContentOnEndpoint', { + hostname: createdHost.hostname, + path: `${homeFilePath}/upload.zip`, + password: 'elastic', + }).then((unzippedFileContent) => { + expect(unzippedFileContent).to.equal(fileContent); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts index 2bd47cd19f9ea..65c6bd974b83a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts @@ -113,7 +113,6 @@ export const managedUserDetails: ManagedUserHits = { _index: 'test-index', _id: '123-test', }, - [ManagedUserDatasetKey.OKTA]: undefined, }; export const mockManagedUserData: ManagedUserData = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx index 6fd22361c55cc..8c4f31ea12141 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx @@ -10,9 +10,7 @@ import React, { useCallback } from 'react'; import { head } from 'lodash/fp'; import { euiLightVars } from '@kbn/ui-theme'; import type { EuiBasicTableColumn } from '@elastic/eui'; -import { EuiToolTip } from '@elastic/eui'; import { useDispatch } from 'react-redux'; -import { EcsFlat } from '@kbn/ecs'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; import { DefaultFieldRenderer } from '../../field_renderers/field_renderers'; import type { @@ -36,16 +34,14 @@ const fieldColumn: EuiBasicTableColumn = { name: i18n.FIELD_COLUMN_TITLE, field: 'label', render: (label: string, { field }) => ( - - - {label ?? field} - - + + {label ?? field} + ), }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_managed_user.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_managed_user.ts index f8bfd378464c8..61e8b7e7e961c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_managed_user.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_managed_user.ts @@ -7,7 +7,6 @@ import { useEffect, useMemo } from 'react'; import { useInstalledIntegrations } from '../../../../../detections/components/rules/related_integrations/use_installed_integrations'; -import { ManagedUserDatasetKey } from '../../../../../../common/search_strategy/security_solution/users/managed_details'; import { UsersQueries } from '../../../../../../common/search_strategy'; import { useSpaceId } from '../../../../../common/hooks/use_space_id'; import { useSearchStrategy } from '../../../../../common/containers/use_search_strategy'; @@ -37,10 +36,7 @@ export const useManagedUser = (userName: string, observedUser: ObserverUser) => } = useSearchStrategy({ factoryQueryType: UsersQueries.managedDetails, initialResult: { - users: { - [ManagedUserDatasetKey.ENTRA]: undefined, - [ManagedUserDatasetKey.OKTA]: undefined, - }, + users: {}, }, errorMessage: i18n.FAIL_MANAGED_USER, }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.test.tsx index 02a7721d22246..70363853b9101 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.test.tsx @@ -108,7 +108,6 @@ describe('ManagedUser', () => { managedUser: { ...mockManagedUserData, data: { - [ManagedUserDatasetKey.ENTRA]: undefined, [ManagedUserDatasetKey.OKTA]: { fields: mockOktaUserFields, _index: '123', diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx index 42d059356081e..35a9a78011982 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx @@ -136,7 +136,7 @@ export const ManagedUser = ({ managedUser={oktaManagedUser.fields} indexName={oktaManagedUser._index} eventId={oktaManagedUser._id} - tableType={UserAssetTableType.assetEntra} + tableType={UserAssetTableType.assetOkta} > ; + latest_hit: SearchResponse; } export const managedUserDetails: SecuritySolutionFactory = { @@ -43,24 +42,10 @@ export const managedUserDetails: SecuritySolutionFactory { - acc[bucket.key] = bucket.latest_hit.hits.hits[0] as unknown as ManagedUserHit; - return acc; - }, - {} as ManagedUserHits - ); - - if (buckets.length === 0) { - return { - ...response, - inspect, - users: { - [ManagedUserDatasetKey.ENTRA]: undefined, - [ManagedUserDatasetKey.OKTA]: undefined, - }, - }; - } + const managedUsers = buckets.reduce((acc, bucket) => { + acc[bucket.key] = bucket.latest_hit.hits.hits[0]; + return acc; + }, {}); return { ...response, diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index f123d8d80ae56..4400f4b8c31e3 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -182,6 +182,7 @@ "@kbn/shared-ux-error-boundary", "@kbn/zod-helpers", "@kbn/core-http-common", + "@kbn/search-errors", "@kbn/stack-connectors-plugin" ] } diff --git a/x-pack/plugins/serverless_search/kibana.jsonc b/x-pack/plugins/serverless_search/kibana.jsonc index a9000e7542475..cc81622911a9a 100644 --- a/x-pack/plugins/serverless_search/kibana.jsonc +++ b/x-pack/plugins/serverless_search/kibana.jsonc @@ -28,6 +28,7 @@ ], "optionalPlugins": [ "indexManagement", + "usageCollection", ], "requiredBundles": [ "kibanaReact" diff --git a/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.test.ts b/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.test.ts new file mode 100644 index 0000000000000..7c3d693f428de --- /dev/null +++ b/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.test.ts @@ -0,0 +1,57 @@ +/* + * 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 { registerTelemetryUsageCollector } from './telemetry'; +import { createCollectorFetchContextMock } from '@kbn/usage-collection-plugin/server/mocks'; + +describe('Connectors Serverless Telemetry Usage Collector', () => { + const makeUsageCollectorStub = jest.fn(); + const registerStub = jest.fn(); + const usageCollectionMock = { + makeUsageCollector: makeUsageCollectorStub, + registerCollector: registerStub, + } as any; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('registerTelemetryUsageCollector', () => { + it('should make and register the usage collector', () => { + registerTelemetryUsageCollector(usageCollectionMock); + + expect(registerStub).toHaveBeenCalledTimes(1); + expect(makeUsageCollectorStub).toHaveBeenCalledTimes(1); + expect(makeUsageCollectorStub.mock.calls[0][0].type).toBe('connectors_serverless'); + expect(makeUsageCollectorStub.mock.calls[0][0].isReady()).toBe(true); + }); + }); + + describe('fetchTelemetryMetrics', () => { + it('should return telemetry data', async () => { + const fetchContextMock = createCollectorFetchContextMock(); + fetchContextMock.esClient.count = jest.fn().mockImplementation((query: any) => + Promise.resolve({ + count: query.query.bool.filter[0].term.is_native ? 5 : 2, + }) + ); + registerTelemetryUsageCollector(usageCollectionMock); + const telemetryMetrics = await makeUsageCollectorStub.mock.calls[0][0].fetch( + fetchContextMock + ); + + expect(telemetryMetrics).toEqual({ + native: { + total: 5, + }, + clients: { + total: 2, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.ts b/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.ts new file mode 100644 index 0000000000000..edf95fc197528 --- /dev/null +++ b/x-pack/plugins/serverless_search/server/collectors/connectors/telemetry.ts @@ -0,0 +1,98 @@ +/* + * 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/server'; + +import { CONNECTORS_INDEX } from '@kbn/search-connectors'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; + +interface Telemetry { + native: { + total: number; + }; + clients: { + total: number; + }; +} + +/** + * Register the telemetry collector + */ + +export const registerTelemetryUsageCollector = (usageCollection: UsageCollectionSetup) => { + const telemetryUsageCollector = usageCollection.makeUsageCollector({ + type: 'connectors_serverless', + isReady: () => true, + schema: { + native: { + total: { type: 'long' }, + }, + clients: { + total: { type: 'long' }, + }, + }, + async fetch({ esClient }) { + return await fetchTelemetryMetrics(esClient); + }, + }); + usageCollection.registerCollector(telemetryUsageCollector); +}; + +/** + * Fetch the aggregated telemetry metrics + */ + +export const fetchTelemetryMetrics = async (client: ElasticsearchClient): Promise => { + const [nativeCountResponse, clientsCountResponse] = await Promise.all([ + client.count({ + index: CONNECTORS_INDEX, + query: { + bool: { + filter: [ + { + term: { + is_native: true, + }, + }, + ], + must_not: [ + { + term: { + service_type: { + value: 'elastic-crawler', + }, + }, + }, + ], + }, + }, + }), + client.count({ + index: CONNECTORS_INDEX, + query: { + bool: { + filter: [ + { + term: { + is_native: false, + }, + }, + ], + }, + }, + }), + ]); + + return { + native: { + total: nativeCountResponse.count, + }, + clients: { + total: clientsCountResponse.count, + }, + } as Telemetry; +}; diff --git a/x-pack/plugins/serverless_search/server/plugin.ts b/x-pack/plugins/serverless_search/server/plugin.ts index 98f60c803972b..6e6a90735ee23 100644 --- a/x-pack/plugins/serverless_search/server/plugin.ts +++ b/x-pack/plugins/serverless_search/server/plugin.ts @@ -27,6 +27,7 @@ import type { StartDependencies, } from './types'; import { registerConnectorsRoutes } from './routes/connectors_routes'; +import { registerTelemetryUsageCollector } from './collectors/connectors/telemetry'; export interface RouteDependencies { http: CoreSetup['http']; @@ -77,7 +78,7 @@ export class ServerlessSearchPlugin public setup( { getStartServices, http }: CoreSetup, - pluginsSetup: SetupDependencies + { serverless, usageCollection }: SetupDependencies ) { const router = http.createRouter(); getStartServices().then(([, { security }]) => { @@ -94,7 +95,13 @@ export class ServerlessSearchPlugin registerIndicesRoutes(dependencies); }); - pluginsSetup.serverless.setupProjectSettings(SEARCH_PROJECT_SETTINGS); + if (usageCollection) { + getStartServices().then(() => { + registerTelemetryUsageCollector(usageCollection); + }); + } + + serverless.setupProjectSettings(SEARCH_PROJECT_SETTINGS); return {}; } diff --git a/x-pack/plugins/serverless_search/server/types.ts b/x-pack/plugins/serverless_search/server/types.ts index 3cbd26ad2dd5f..a78539c5b89e2 100644 --- a/x-pack/plugins/serverless_search/server/types.ts +++ b/x-pack/plugins/serverless_search/server/types.ts @@ -8,6 +8,7 @@ import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import type { ServerlessPluginSetup } from '@kbn/serverless/server'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ServerlessSearchPluginSetup {} @@ -20,4 +21,5 @@ export interface StartDependencies { } export interface SetupDependencies { serverless: ServerlessPluginSetup; + usageCollection?: UsageCollectionSetup; } diff --git a/x-pack/plugins/serverless_search/tsconfig.json b/x-pack/plugins/serverless_search/tsconfig.json index f58828f69569b..3f79fa5c9277a 100644 --- a/x-pack/plugins/serverless_search/tsconfig.json +++ b/x-pack/plugins/serverless_search/tsconfig.json @@ -38,5 +38,6 @@ "@kbn/data-views-plugin", "@kbn/kibana-utils-plugin", "@kbn/index-management-plugin", + "@kbn/usage-collection-plugin", ] } diff --git a/x-pack/plugins/stack_alerts/server/rule_types/constants.ts b/x-pack/plugins/stack_alerts/server/rule_types/constants.ts index a5cfb6dc5364a..97adeec198018 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/constants.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/constants.ts @@ -5,9 +5,9 @@ * 2.0. */ import { IRuleTypeAlerts } from '@kbn/alerting-plugin/server'; -import { StackAlert } from '@kbn/alerts-as-data-utils'; -import { ALERT_EVALUATION_VALUE } from '@kbn/rule-data-utils'; +import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE } from '@kbn/rule-data-utils'; import { ALERT_NAMESPACE } from '@kbn/rule-data-utils'; +import { StackAlertType } from './types'; export const STACK_AAD_INDEX_NAME = 'stack'; @@ -15,13 +15,18 @@ export const ALERT_TITLE = `${ALERT_NAMESPACE}.title` as const; // kibana.alert.evaluation.conditions - human readable string that shows the conditions set by the user export const ALERT_EVALUATION_CONDITIONS = `${ALERT_NAMESPACE}.evaluation.conditions` as const; -export const STACK_ALERTS_AAD_CONFIG: IRuleTypeAlerts = { +export const STACK_ALERTS_AAD_CONFIG: IRuleTypeAlerts = { context: STACK_AAD_INDEX_NAME, mappings: { fieldMap: { [ALERT_TITLE]: { type: 'keyword', array: false, required: false }, [ALERT_EVALUATION_CONDITIONS]: { type: 'keyword', array: false, required: false }, [ALERT_EVALUATION_VALUE]: { type: 'keyword', array: false, required: false }, + [ALERT_EVALUATION_THRESHOLD]: { + type: 'scaled_float', + scaling_factor: 100, + required: false, + }, }, }, shouldWrite: true, diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.test.ts index c5bafcc4851ac..02ddc658b021f 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.test.ts @@ -299,6 +299,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents is greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '491', 'kibana.alert.reason': 'Document count is 491 in the last 5m. Alert when greater than or equal to 200.', @@ -311,6 +312,64 @@ describe('es_query executor', () => { expect(mockSetLimitReached).toHaveBeenCalledWith(false); }); + it('should create alert if compare function returns true for ungrouped alert for multi threshold param', async () => { + mockFetchEsQuery.mockResolvedValueOnce({ + parsedResults: { + results: [ + { + group: 'all documents', + count: 491, + hits: [], + }, + ], + truncated: false, + }, + link: 'https://localhost:5601/app/management/insightsAndAlerting/triggersActions/rule/test-rule-id', + }); + await executor(coreMock, { + ...defaultExecutorOptions, + // @ts-expect-error + params: { + ...defaultProps, + threshold: [200, 500], + thresholdComparator: 'between' as Comparator, + }, + }); + + expect(mockReport).toHaveBeenCalledTimes(1); + expect(mockReport).toHaveBeenNthCalledWith(1, { + actionGroup: 'query matched', + context: { + conditions: 'Number of matching documents is between 200 and 500', + date: new Date(mockNow).toISOString(), + hits: [], + link: 'https://localhost:5601/app/management/insightsAndAlerting/triggersActions/rule/test-rule-id', + message: 'Document count is 491 in the last 5m. Alert when between 200 and 500.', + title: "rule 'test-rule-name' matched query", + value: 491, + }, + id: 'query matched', + state: { + dateEnd: new Date(mockNow).toISOString(), + dateStart: new Date(mockNow).toISOString(), + latestTimestamp: undefined, + }, + payload: { + 'kibana.alert.evaluation.conditions': + 'Number of matching documents is between 200 and 500', + 'kibana.alert.evaluation.threshold': null, + 'kibana.alert.evaluation.value': '491', + 'kibana.alert.reason': + 'Document count is 491 in the last 5m. Alert when between 200 and 500.', + 'kibana.alert.title': "rule 'test-rule-name' matched query", + 'kibana.alert.url': + 'https://localhost:5601/app/management/insightsAndAlerting/triggersActions/rule/test-rule-id', + }, + }); + expect(mockSetLimitReached).toHaveBeenCalledTimes(1); + expect(mockSetLimitReached).toHaveBeenCalledWith(false); + }); + it('should create as many alerts as number of results in parsedResults for grouped alert', async () => { mockFetchEsQuery.mockResolvedValueOnce({ parsedResults: { @@ -371,6 +430,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents for group "host-1" is greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '291', 'kibana.alert.reason': 'Document count is 291 in the last 5m for host-1. Alert when greater than or equal to 200.', @@ -401,6 +461,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents for group "host-2" is greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '477', 'kibana.alert.reason': 'Document count is 477 in the last 5m for host-2. Alert when greater than or equal to 200.', @@ -431,6 +492,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents for group "host-3" is greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '999', 'kibana.alert.reason': 'Document count is 999 in the last 5m for host-3. Alert when greater than or equal to 200.', @@ -482,6 +544,7 @@ describe('es_query executor', () => { id: 'query matched', payload: { 'kibana.alert.evaluation.conditions': 'Query matched documents', + 'kibana.alert.evaluation.threshold': 0, 'kibana.alert.evaluation.value': '198', 'kibana.alert.reason': 'Document count is 198 in the last 5m. Alert when greater than or equal to 0.', @@ -586,6 +649,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents is NOT greater than or equal to 500', + 'kibana.alert.evaluation.threshold': 500, 'kibana.alert.evaluation.value': '0', 'kibana.alert.reason': 'Document count is 0 in the last 5m. Alert when greater than or equal to 500.', @@ -645,6 +709,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents for group "host-1" is NOT greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '0', 'kibana.alert.reason': 'Document count is 0 in the last 5m for host-1. Alert when greater than or equal to 200.', @@ -668,6 +733,7 @@ describe('es_query executor', () => { payload: { 'kibana.alert.evaluation.conditions': 'Number of matching documents for group "host-2" is NOT greater than or equal to 200', + 'kibana.alert.evaluation.threshold': 200, 'kibana.alert.evaluation.value': '0', 'kibana.alert.reason': 'Document count is 0 in the last 5m for host-2. Alert when greater than or equal to 200.', @@ -720,6 +786,7 @@ describe('es_query executor', () => { }, payload: { 'kibana.alert.evaluation.conditions': 'Query did NOT match documents', + 'kibana.alert.evaluation.threshold': 0, 'kibana.alert.evaluation.value': '0', 'kibana.alert.reason': 'Document count is 0 in the last 5m. Alert when greater than 0.', 'kibana.alert.title': "rule 'test-rule-name' recovered", diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.ts index 282ab7357af6d..d0d440c769487 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/executor.ts @@ -8,7 +8,12 @@ import { sha256 } from 'js-sha256'; import { i18n } from '@kbn/i18n'; import { CoreSetup } from '@kbn/core/server'; import { isGroupAggregation, UngroupedGroupId } from '@kbn/triggers-actions-ui-plugin/common'; -import { ALERT_EVALUATION_VALUE, ALERT_REASON, ALERT_URL } from '@kbn/rule-data-utils'; +import { + ALERT_EVALUATION_THRESHOLD, + ALERT_EVALUATION_VALUE, + ALERT_REASON, + ALERT_URL, +} from '@kbn/rule-data-utils'; import { ComparatorFns } from '../../../common'; import { @@ -161,6 +166,7 @@ export async function executor(core: CoreSetup, options: ExecutorOptions { payload: expect.objectContaining({ 'kibana.alert.evaluation.conditions': 'Number of matching documents is greater than or equal to 3', + 'kibana.alert.evaluation.threshold': 3, 'kibana.alert.evaluation.value': '3', 'kibana.alert.reason': expect.any(String), 'kibana.alert.title': "rule 'rule-name' matched query", @@ -797,6 +798,7 @@ describe('ruleType', () => { id: 'query matched', payload: expect.objectContaining({ 'kibana.alert.evaluation.conditions': 'Query matched documents', + 'kibana.alert.evaluation.threshold': 0, 'kibana.alert.evaluation.value': '3', 'kibana.alert.reason': expect.any(String), 'kibana.alert.title': "rule 'rule-name' matched query", diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.ts index 832819e28772c..870f30ff2dfcb 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.ts @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { extractReferences, injectReferences } from '@kbn/data-plugin/common'; import { ES_QUERY_ID, STACK_ALERTS_FEATURE_ID } from '@kbn/rule-data-utils'; -import { StackAlert } from '@kbn/alerts-as-data-utils'; import { STACK_ALERTS_AAD_CONFIG } from '..'; import { RuleType } from '../../types'; import { ActionContext } from './action_context'; @@ -23,6 +22,7 @@ import { ExecutorOptions } from './types'; import { ActionGroupId } from './constants'; import { executor } from './executor'; import { isSearchSourceRule } from './util'; +import { StackAlertType } from '../types'; export function getRuleType( core: CoreSetup @@ -34,7 +34,7 @@ export function getRuleType( ActionContext, typeof ActionGroupId, never, - StackAlert + StackAlertType > { const ruleTypeName = i18n.translate('xpack.stackAlerts.esQuery.alertTypeTitle', { defaultMessage: 'Elasticsearch query', diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/types.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/types.ts index 5f3ec1ba5e240..ba84b4e56e26a 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/types.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/types.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { StackAlert } from '@kbn/alerts-as-data-utils'; import { RuleExecutorOptions, RuleTypeParams } from '../../types'; import { ActionContext } from './action_context'; import { EsQueryRuleParams, EsQueryRuleState } from './rule_type_params'; import { ActionGroupId } from './constants'; +import { StackAlertType } from '../types'; export type OnlyEsQueryRuleParams = Omit & { searchType: 'esQuery'; @@ -37,5 +37,5 @@ export type ExecutorOptions

= RuleExecutorOptions< {}, ActionContext, typeof ActionGroupId, - StackAlert + StackAlertType >; diff --git a/x-pack/plugins/stack_alerts/server/rule_types/index_threshold/rule_type.ts b/x-pack/plugins/stack_alerts/server/rule_types/index_threshold/rule_type.ts index 4bf1a2e2accd3..72c7539e6b726 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/index_threshold/rule_type.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/index_threshold/rule_type.ts @@ -12,7 +12,6 @@ import { TIME_SERIES_BUCKET_SELECTOR_FIELD, } from '@kbn/triggers-actions-ui-plugin/server'; import { isGroupAggregation } from '@kbn/triggers-actions-ui-plugin/common'; -import { StackAlert } from '@kbn/alerts-as-data-utils'; import { ALERT_EVALUATION_VALUE, ALERT_REASON, @@ -23,13 +22,14 @@ import { ComparatorFns, getComparatorScript, getHumanReadableComparator } from ' import { ActionContext, BaseActionContext, addMessages } from './action_context'; import { Params, ParamsSchema } from './rule_type_params'; import { RuleType, RuleExecutorOptions, StackAlertsStartDeps } from '../../types'; +import { StackAlertType } from '../types'; export const ID = '.index-threshold'; export const ActionGroupId = 'threshold met'; export function getRuleType( data: Promise -): RuleType { +): RuleType { const ruleTypeName = i18n.translate('xpack.stackAlerts.indexThreshold.alertTypeTitle', { defaultMessage: 'Index threshold', }); @@ -212,7 +212,14 @@ export function getRuleType( }; async function executor( - options: RuleExecutorOptions + options: RuleExecutorOptions< + Params, + {}, + {}, + ActionContext, + typeof ActionGroupId, + StackAlertType + > ) { const { rule: { id: ruleId, name }, diff --git a/x-pack/plugins/stack_alerts/server/rule_types/types.ts b/x-pack/plugins/stack_alerts/server/rule_types/types.ts index ea9352f281b84..e06553233e774 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/types.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/types.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { StackAlert } from '@kbn/alerts-as-data-utils'; import { CoreSetup, Logger } from '@kbn/core/server'; import { AlertingSetup, StackAlertsStartDeps } from '../types'; @@ -14,3 +15,8 @@ export interface RegisterRuleTypesParams { alerting: AlertingSetup; core: CoreSetup; } + +export type StackAlertType = Omit & { + // Defining a custom type for this because the schema generation script doesn't allow explicit null values + 'kibana.alert.evaluation.threshold'?: string | number | null; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx index bc3d1a19c2bd5..c3220ede642fc 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { Provider as ReduxProvider } from 'react-redux'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { CoreStart } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; @@ -26,18 +27,21 @@ interface Props { // eslint-disable-next-line import/no-default-export export default function MonitorStatusAlert({ core, plugins, params }: Props) { kibanaService.core = core; + const queryClient = new QueryClient(); return ( - - - - + + + + + - - + + + ); } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx index 2ce861c65be79..89bffbe6dfd73 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx @@ -15,7 +15,6 @@ import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { InspectorContextProvider } from '@kbn/observability-shared-plugin/public'; import { ObservabilityAIAssistantProvider } from '@kbn/observability-ai-assistant-plugin/public'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { SyntheticsDataViewContextProvider } from './contexts/synthetics_data_view_context'; import { SyntheticsAppProps } from './contexts'; @@ -69,8 +68,6 @@ const Application = (props: SyntheticsAppProps) => { store.dispatch(setBasePath(basePath)); - const queryClient = new QueryClient(); - return ( @@ -84,56 +81,54 @@ const Application = (props: SyntheticsAppProps) => { }} > - - - - - - - - - - -

- - - - - - - -
- - - - - - - - - - + + + + + + + + + +
+ + + + + + + +
+
+
+
+
+
+
+
+
+
diff --git a/x-pack/plugins/task_manager/server/integration_tests/task_state_validation.test.ts b/x-pack/plugins/task_manager/server/integration_tests/task_state_validation.test.ts index 3f0aafd563e9c..716e1f8dcb83f 100644 --- a/x-pack/plugins/task_manager/server/integration_tests/task_state_validation.test.ts +++ b/x-pack/plugins/task_manager/server/integration_tests/task_state_validation.test.ts @@ -307,7 +307,7 @@ describe('task state validation', () => { }); it('should fail the task run when setting allow_reading_invalid_state:false and reading an invalid state', async () => { - const errorLogSpy = jest.spyOn(pollingLifecycleOpts.logger, 'error'); + const logSpy = jest.spyOn(pollingLifecycleOpts.logger, 'warn'); const id = uuidV4(); await injectTask(kibanaServer.coreStart.elasticsearch.client.asInternalUser, { @@ -328,12 +328,13 @@ describe('task state validation', () => { taskIdsToRemove.push(id); await retry(async () => { - expect(errorLogSpy).toHaveBeenCalledWith( - `Failed to poll for work: Error: [foo]: expected value of type [string] but got [boolean]` + expect(logSpy.mock.calls[0][0]).toBe( + `Task (fooType/${id}) has a validation error: [foo]: expected value of type [string] but got [boolean]` + ); + expect(logSpy.mock.calls[1][0]).toBe( + `Task fooType \"${id}\" failed in attempt to run: [foo]: expected value of type [string] but got [boolean]` ); }); - - expect(mockCreateTaskRunner).not.toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/task_manager/server/lib/create_managed_configuration.test.ts b/x-pack/plugins/task_manager/server/lib/create_managed_configuration.test.ts index 84dd65cd3cf16..b1d6ce92c323a 100644 --- a/x-pack/plugins/task_manager/server/lib/create_managed_configuration.test.ts +++ b/x-pack/plugins/task_manager/server/lib/create_managed_configuration.test.ts @@ -184,6 +184,23 @@ describe('createManagedConfiguration()', () => { ); }); + test('should log a warning when an issue occurred in the calculating of the increased poll interval', async () => { + const { errors$ } = setupScenario(NaN); + errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); + clock.tick(ADJUST_THROUGHPUT_INTERVAL); + expect(logger.error).toHaveBeenCalledWith( + 'Poll interval configuration had an issue calculating the new poll interval: Math.min(Math.ceil(NaN * 1.2), Math.max(60000, NaN)) = NaN, will keep the poll interval unchanged (NaN)' + ); + }); + + test('should log a warning when an issue occurred in the calculating of the decreased poll interval', async () => { + setupScenario(NaN); + clock.tick(ADJUST_THROUGHPUT_INTERVAL); + expect(logger.error).toHaveBeenCalledWith( + 'Poll interval configuration had an issue calculating the new poll interval: Math.max(NaN, Math.floor(NaN * 0.95)) = NaN, will keep the poll interval unchanged (NaN)' + ); + }); + test('should decrease configuration back to normal incrementally after an error is emitted', async () => { const { subscription, errors$ } = setupScenario(100); errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); @@ -210,5 +227,40 @@ describe('createManagedConfiguration()', () => { // 172.8 -> 173 from Math.ceil expect(subscription).toHaveBeenNthCalledWith(4, 173); }); + + test('should limit the upper bound to 60s by default', async () => { + const { subscription, errors$ } = setupScenario(3000); + for (let i = 0; i < 18; i++) { + errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); + clock.tick(ADJUST_THROUGHPUT_INTERVAL); + } + expect(subscription).toHaveBeenNthCalledWith(2, 3600); + expect(subscription).toHaveBeenNthCalledWith(3, 4320); + expect(subscription).toHaveBeenNthCalledWith(4, 5184); + expect(subscription).toHaveBeenNthCalledWith(5, 6221); + expect(subscription).toHaveBeenNthCalledWith(6, 7466); + expect(subscription).toHaveBeenNthCalledWith(7, 8960); + expect(subscription).toHaveBeenNthCalledWith(8, 10752); + expect(subscription).toHaveBeenNthCalledWith(9, 12903); + expect(subscription).toHaveBeenNthCalledWith(10, 15484); + expect(subscription).toHaveBeenNthCalledWith(11, 18581); + expect(subscription).toHaveBeenNthCalledWith(12, 22298); + expect(subscription).toHaveBeenNthCalledWith(13, 26758); + expect(subscription).toHaveBeenNthCalledWith(14, 32110); + expect(subscription).toHaveBeenNthCalledWith(15, 38532); + expect(subscription).toHaveBeenNthCalledWith(16, 46239); + expect(subscription).toHaveBeenNthCalledWith(17, 55487); + expect(subscription).toHaveBeenNthCalledWith(18, 60000); + }); + + test('should not adjust poll interval dynamically if initial value is > 60s', async () => { + const { subscription, errors$ } = setupScenario(65000); + for (let i = 0; i < 5; i++) { + errors$.next(SavedObjectsErrorHelpers.createTooManyRequestsError('a', 'b')); + clock.tick(ADJUST_THROUGHPUT_INTERVAL); + } + expect(subscription).toHaveBeenCalledTimes(1); + expect(subscription).toHaveBeenNthCalledWith(1, 65000); + }); }); }); diff --git a/x-pack/plugins/task_manager/server/lib/create_managed_configuration.ts b/x-pack/plugins/task_manager/server/lib/create_managed_configuration.ts index baed33ef9d048..70c1e53ff6de1 100644 --- a/x-pack/plugins/task_manager/server/lib/create_managed_configuration.ts +++ b/x-pack/plugins/task_manager/server/lib/create_managed_configuration.ts @@ -13,6 +13,8 @@ import { isEsCannotExecuteScriptError } from './identify_es_error'; const FLUSH_MARKER = Symbol('flush'); export const ADJUST_THROUGHPUT_INTERVAL = 10 * 1000; +export const PREFERRED_MAX_POLL_INTERVAL = 60 * 1000; +export const MIN_WORKERS = 1; // When errors occur, reduce maxWorkers by MAX_WORKERS_DECREASE_PERCENTAGE // When errors no longer occur, start increasing maxWorkers by MAX_WORKERS_INCREASE_PERCENTAGE @@ -65,7 +67,10 @@ function createMaxWorkersScan(logger: Logger, startingMaxWorkers: number) { if (errorCount > 0) { // Decrease max workers by MAX_WORKERS_DECREASE_PERCENTAGE while making sure it doesn't go lower than 1. // Using Math.floor to make sure the number is different than previous while not being a decimal value. - newMaxWorkers = Math.max(Math.floor(previousMaxWorkers * MAX_WORKERS_DECREASE_PERCENTAGE), 1); + newMaxWorkers = Math.max( + Math.floor(previousMaxWorkers * MAX_WORKERS_DECREASE_PERCENTAGE), + MIN_WORKERS + ); } else { // Increase max workers by MAX_WORKERS_INCREASE_PERCENTAGE while making sure it doesn't go // higher than the starting value. Using Math.ceil to make sure the number is different than @@ -95,7 +100,18 @@ function createPollIntervalScan(logger: Logger, startingPollInterval: number) { if (errorCount > 0) { // Increase poll interval by POLL_INTERVAL_INCREASE_PERCENTAGE and use Math.ceil to // make sure the number is different than previous while not being a decimal value. - newPollInterval = Math.ceil(previousPollInterval * POLL_INTERVAL_INCREASE_PERCENTAGE); + // Also ensure we don't go over PREFERRED_MAX_POLL_INTERVAL or startingPollInterval, + // whichever is greater. + newPollInterval = Math.min( + Math.ceil(previousPollInterval * POLL_INTERVAL_INCREASE_PERCENTAGE), + Math.ceil(Math.max(PREFERRED_MAX_POLL_INTERVAL, startingPollInterval)) + ); + if (!Number.isSafeInteger(newPollInterval) || newPollInterval < 0) { + logger.error( + `Poll interval configuration had an issue calculating the new poll interval: Math.min(Math.ceil(${previousPollInterval} * ${POLL_INTERVAL_INCREASE_PERCENTAGE}), Math.max(${PREFERRED_MAX_POLL_INTERVAL}, ${startingPollInterval})) = ${newPollInterval}, will keep the poll interval unchanged (${previousPollInterval})` + ); + newPollInterval = previousPollInterval; + } } else { // Decrease poll interval by POLL_INTERVAL_DECREASE_PERCENTAGE and use Math.floor to // make sure the number is different than previous while not being a decimal value. @@ -103,6 +119,12 @@ function createPollIntervalScan(logger: Logger, startingPollInterval: number) { startingPollInterval, Math.floor(previousPollInterval * POLL_INTERVAL_DECREASE_PERCENTAGE) ); + if (!Number.isSafeInteger(newPollInterval) || newPollInterval < 0) { + logger.error( + `Poll interval configuration had an issue calculating the new poll interval: Math.max(${startingPollInterval}, Math.floor(${previousPollInterval} * ${POLL_INTERVAL_DECREASE_PERCENTAGE})) = ${newPollInterval}, will keep the poll interval unchanged (${previousPollInterval})` + ); + newPollInterval = previousPollInterval; + } } if (newPollInterval !== previousPollInterval) { logger.debug( diff --git a/x-pack/plugins/task_manager/server/polling/task_poller.test.ts b/x-pack/plugins/task_manager/server/polling/task_poller.test.ts index 7df438d4152e5..b878c25c36906 100644 --- a/x-pack/plugins/task_manager/server/polling/task_poller.test.ts +++ b/x-pack/plugins/task_manager/server/polling/task_poller.test.ts @@ -90,6 +90,57 @@ describe('TaskPoller', () => { expect(work).toHaveBeenCalledTimes(4); }); + test('poller ignores null pollInterval values', async () => { + const pollInterval = 100; + const pollInterval$ = new BehaviorSubject(pollInterval); + + const work = jest.fn(async () => true); + const logger = loggingSystemMock.create().get(); + createTaskPoller({ + initialPollInterval: pollInterval, + logger, + pollInterval$, + pollIntervalDelay$: of(0), + getCapacity: () => 1, + work, + }).start(); + + expect(work).toHaveBeenCalledTimes(1); + + // `work` is async, we have to force a node `tick` + await new Promise((resolve) => setImmediate(resolve)); + clock.tick(pollInterval); + expect(work).toHaveBeenCalledTimes(2); + + pollInterval$.next(pollInterval * 2); + + // `work` is async, we have to force a node `tick` + await new Promise((resolve) => setImmediate(resolve)); + clock.tick(pollInterval); + expect(work).toHaveBeenCalledTimes(2); + clock.tick(pollInterval); + expect(work).toHaveBeenCalledTimes(3); + + // Force null into the events + pollInterval$.next(null as unknown as number); + + // `work` is async, we have to force a node `tick` + await new Promise((resolve) => setImmediate(resolve)); + clock.tick(pollInterval); + expect(work).toHaveBeenCalledTimes(3); + + // `work` is async, we have to force a node `tick` + await new Promise((resolve) => setImmediate(resolve)); + clock.tick(pollInterval); + expect(work).toHaveBeenCalledTimes(4); + + expect(logger.error).toHaveBeenCalledWith( + new Error( + 'Expected the new interval to be a number > 0, received: null but poller will keep using: 200' + ) + ); + }); + test('filters interval polling on capacity', async () => { const pollInterval = 100; diff --git a/x-pack/plugins/task_manager/server/polling/task_poller.ts b/x-pack/plugins/task_manager/server/polling/task_poller.ts index 812f29d170e96..ff984a44f1aa0 100644 --- a/x-pack/plugins/task_manager/server/polling/task_poller.ts +++ b/x-pack/plugins/task_manager/server/polling/task_poller.ts @@ -85,6 +85,17 @@ export function createTaskPoller({ return; } pollInterval$.subscribe((interval) => { + if (!Number.isSafeInteger(interval) || interval < 0) { + // TODO: Investigate why we sometimes get null / NaN, causing the setTimeout logic to always schedule + // the next polling cycle to run immediately. If we don't see occurrences of this message by December 2024, + // we can remove the TODO and/or check because we now have a cap to how much we increase the poll interval. + logger.error( + new Error( + `Expected the new interval to be a number > 0, received: ${interval} but poller will keep using: ${pollInterval}` + ) + ); + return; + } pollInterval = interval; logger.debug(`Task poller now using interval of ${interval}ms`); }); diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.ts index 2024277ea94e0..20a63377b41e0 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.ts @@ -218,6 +218,7 @@ export class TaskPollingLifecycle implements ITaskEventEmitter { expect(instance.enabled).not.toBeDefined(); }); + test('throws error when the task has invalid state', async () => { + const mockTaskInstance: Partial = { + schedule: { interval: '10m' }, + status: TaskStatus.Idle, + startedAt: new Date(), + enabled: true, + runAt: new Date(), + params: { foo: true }, + state: { foo: true, bar: 'test', baz: 'test' }, + stateVersion: 4, + }; + + const { runner, logger } = await readyToRunStageSetup({ + instance: mockTaskInstance, + definitions: { + bar: { + title: 'Bar!', + createTaskRunner: () => ({ + async run() { + return { state: { foo: 'bar' } }; + }, + }), + stateSchemaByVersion: { + 1: { + up: (state: Record) => ({ foo: state.foo || '' }), + schema: schema.object({ + foo: schema.string(), + }), + }, + 2: { + up: (state: Record) => ({ ...state, bar: state.bar || '' }), + schema: schema.object({ + foo: schema.string(), + bar: schema.string(), + }), + }, + 3: { + up: (state: Record) => ({ ...state, baz: state.baz || '' }), + schema: schema.object({ + foo: schema.string(), + bar: schema.string(), + baz: schema.string(), + }), + }, + }, + }, + }, + requeueInvalidTasksConfig: { + enabled: true, + delay: 3000, + max_attempts: 20, + }, + }); + + expect(() => runner.run()).rejects.toMatchInlineSnapshot( + `[Error: [foo]: expected value of type [string] but got [boolean]]` + ); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + 'Task (bar/foo) has a validation error: [foo]: expected value of type [string] but got [boolean]' + ); + }); + + test('does not throw error and runs when the task has invalid state and allowReadingInvalidState = true', async () => { + const mockTaskInstance: Partial = { + schedule: { interval: '10m' }, + status: TaskStatus.Idle, + startedAt: new Date(), + enabled: true, + runAt: new Date(), + params: { foo: true }, + state: { foo: true, bar: 'test', baz: 'test' }, + stateVersion: 4, + }; + + const { runner, store, logger } = await readyToRunStageSetup({ + instance: mockTaskInstance, + definitions: { + bar: { + title: 'Bar!', + createTaskRunner: () => ({ + async run() { + return { state: { foo: 'bar' } }; + }, + }), + stateSchemaByVersion: { + 1: { + up: (state: Record) => ({ foo: state.foo || '' }), + schema: schema.object({ + foo: schema.string(), + }), + }, + 2: { + up: (state: Record) => ({ ...state, bar: state.bar || '' }), + schema: schema.object({ + foo: schema.string(), + bar: schema.string(), + }), + }, + 3: { + up: (state: Record) => ({ ...state, baz: state.baz || '' }), + schema: schema.object({ + foo: schema.string(), + bar: schema.string(), + baz: schema.string(), + }), + }, + }, + }, + }, + requeueInvalidTasksConfig: { + enabled: true, + delay: 3000, + max_attempts: 20, + }, + allowReadingInvalidState: true, + }); + + const result = await runner.run(); + + expect(store.update).toHaveBeenCalledTimes(1); + const instance = store.update.mock.calls[0][0]; + expect(instance.state).toEqual({ + foo: 'bar', + }); + expect(instance.attempts).toBe(0); + expect(logger.warn).not.toHaveBeenCalled(); + expect(result).toEqual(asOk({ state: { foo: 'bar' } })); + }); + describe('TaskEvents', () => { test('emits TaskEvent when a task is run successfully', async () => { const id = _.random(1, 20).toString(); @@ -2418,6 +2548,7 @@ describe('TaskManagerRunner', () => { definitions?: TaskDefinitionRegistry; onTaskEvent?: jest.Mock<(event: TaskEvent) => void>; requeueInvalidTasksConfig?: RequeueInvalidTasksConfig; + allowReadingInvalidState?: boolean; } function withAnyTiming(taskRun: TaskRun) { @@ -2494,6 +2625,7 @@ describe('TaskManagerRunner', () => { warn_threshold: 5000, }, requeueInvalidTasksConfig: opts.requeueInvalidTasksConfig || mockRequeueInvalidTasksConfig, + allowReadingInvalidState: opts.allowReadingInvalidState || false, }); if (stage === TaskRunningStage.READY_TO_RUN) { diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.ts index 62cb733980e57..191401b33b429 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.ts @@ -57,6 +57,7 @@ import { import { TaskTypeDictionary } from '../task_type_dictionary'; import { createSkipError, isRetryableError, isSkipError, isUnrecoverableError } from './errors'; import type { EventLoopDelayConfig, RequeueInvalidTasksConfig } from '../config'; +import { TaskValidator } from '../task_validator'; export const EMPTY_RUN_RESULT: SuccessfulRunResult = { state: {} }; @@ -109,6 +110,7 @@ type Opts = { usageCounter?: UsageCounter; eventLoopDelayConfig: EventLoopDelayConfig; requeueInvalidTasksConfig: RequeueInvalidTasksConfig; + allowReadingInvalidState: boolean; } & Pick; export enum TaskRunResult { @@ -158,6 +160,7 @@ export class TaskManagerRunner implements TaskRunner { private usageCounter?: UsageCounter; private eventLoopDelayConfig: EventLoopDelayConfig; private readonly requeueInvalidTasksConfig: RequeueInvalidTasksConfig; + private readonly taskValidator: TaskValidator; /** * Creates an instance of TaskManagerRunner. @@ -182,6 +185,7 @@ export class TaskManagerRunner implements TaskRunner { usageCounter, eventLoopDelayConfig, requeueInvalidTasksConfig, + allowReadingInvalidState, }: Opts) { this.instance = asPending(sanitizeInstance(instance)); this.definitions = definitions; @@ -196,6 +200,11 @@ export class TaskManagerRunner implements TaskRunner { this.uuid = uuidv4(); this.eventLoopDelayConfig = eventLoopDelayConfig; this.requeueInvalidTasksConfig = requeueInvalidTasksConfig; + this.taskValidator = new TaskValidator({ + logger: this.logger, + definitions: this.definitions, + allowReadingInvalidState, + }); } /** @@ -306,8 +315,11 @@ export class TaskManagerRunner implements TaskRunner { childOf: this.instance.task.traceparent, }); + // Validate state + const validatedTaskInstance = this.validateTaskState(this.instance.task); + const modifiedContext = await this.beforeRun({ - taskInstance: this.instance.task, + taskInstance: validatedTaskInstance, }); const stopTaskTimer = startTaskTimerWithEventLoopMonitoring(this.eventLoopDelayConfig); @@ -393,6 +405,17 @@ export class TaskManagerRunner implements TaskRunner { return { ...(error ? { error } : {}), state }; } + private validateTaskState(taskInstance: ConcreteTaskInstance) { + const { taskType, id } = taskInstance; + try { + const validatedTask = this.taskValidator.getValidatedTaskInstanceFromReading(taskInstance); + return validatedTask; + } catch (error) { + this.logger.warn(`Task (${taskType}/${id}) has a validation error: ${error.message}`); + throw error; + } + } + private async validateIndirectTaskParams({ taskInstance }: RunContext) { let error; const { state, taskType, id, numSkippedRuns = 0 } = taskInstance; diff --git a/x-pack/plugins/task_manager/server/task_store.ts b/x-pack/plugins/task_manager/server/task_store.ts index acc12b39ec0b2..dc3ce1459f760 100644 --- a/x-pack/plugins/task_manager/server/task_store.ts +++ b/x-pack/plugins/task_manager/server/task_store.ts @@ -383,7 +383,7 @@ export class TaskStore { throw e; } const taskInstance = savedObjectToConcreteTaskInstance(result); - return this.taskValidator.getValidatedTaskInstanceFromReading(taskInstance); + return taskInstance; } /** @@ -407,9 +407,7 @@ export class TaskStore { return asErr({ id: task.id, type: task.type, error: task.error }); } const taskInstance = savedObjectToConcreteTaskInstance(task); - const validatedTaskInstance = - this.taskValidator.getValidatedTaskInstanceFromReading(taskInstance); - return asOk(validatedTaskInstance); + return asOk(taskInstance); }); } @@ -454,7 +452,6 @@ export class TaskStore { .map((doc) => this.serializer.rawToSavedObject(doc)) .map((doc) => omit(doc, 'namespace') as SavedObject) .map((doc) => savedObjectToConcreteTaskInstance(doc)) - .map((doc) => this.taskValidator.getValidatedTaskInstanceFromReading(doc)) .filter((doc): doc is ConcreteTaskInstance => !!doc), }; } catch (e) { diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 743e19137ff19..777d78acb192f 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -7713,6 +7713,42 @@ } } }, + "connectors": { + "properties": { + "native": { + "properties": { + "total": { + "type": "long" + } + } + }, + "clients": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, + "connectors_serverless": { + "properties": { + "native": { + "properties": { + "total": { + "type": "long" + } + } + }, + "clients": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, "discoverEnhanced": { "properties": { "exploreDataInChartActionEnabled": { diff --git a/x-pack/plugins/timelines/public/hooks/use_app_toasts.ts b/x-pack/plugins/timelines/public/hooks/use_app_toasts.ts index a33ee86e0a31a..decce2d6cec9e 100644 --- a/x-pack/plugins/timelines/public/hooks/use_app_toasts.ts +++ b/x-pack/plugins/timelines/public/hooks/use_app_toasts.ts @@ -12,7 +12,7 @@ import type { AppError } from '@kbn/securitysolution-t-grid'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { ErrorToastOptions, ToastsStart, Toast, NotificationsStart } from '@kbn/core/public'; -import { IEsError, isEsError } from '@kbn/data-plugin/public'; +import { IEsError, isEsError } from '@kbn/search-errors'; export type UseAppToasts = Pick & { api: ToastsStart; diff --git a/x-pack/plugins/timelines/tsconfig.json b/x-pack/plugins/timelines/tsconfig.json index 91fb476e1f983..5697cae6120d1 100644 --- a/x-pack/plugins/timelines/tsconfig.json +++ b/x-pack/plugins/timelines/tsconfig.json @@ -34,6 +34,7 @@ "@kbn/safer-lodash-set", "@kbn/alerts-as-data-utils", "@kbn/logging", + "@kbn/search-errors", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 4149395492ce6..00aa8b30278db 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -147,12 +147,12 @@ "autocomplete.loadingDescription": "Chargement...", "autocomplete.seeDocumentation": "Consultez la documentation", "autocomplete.selectField": "Veuillez d'abord sélectionner un champ...", - "bfetch.networkErrorWithStatus": "Vérifiez votre connexion réseau et réessayez. Code {code}", "bfetch.disableBfetch": "Désactiver la mise en lots de requêtes", "bfetch.disableBfetchCompression": "Désactiver la compression par lots", "bfetch.disableBfetchCompressionDesc": "Vous pouvez désactiver la compression par lots. Cela permet de déboguer des requêtes individuelles, mais augmente la taille des réponses.", "bfetch.disableBfetchDesc": "Désactive la mise en lot des requêtes. Cette option augmente le nombre de requêtes HTTP depuis Kibana, mais permet de les déboguer individuellement.", - "bfetch.networkError": "Vérifiez votre connexion réseau et réessayez.", + "bfetchError.networkError": "Vérifiez votre connexion réseau et réessayez.", + "bfetchError.networkErrorWithStatus": "Vérifiez votre connexion réseau et réessayez. Code {code}", "cellActions.youAreInADialogContainingOptionsScreenReaderOnly": "Vous êtes dans une boîte de dialogue contenant des options pour le champ {fieldName}. Appuyez sur Tab pour naviguer entre les options. Appuyez sur Échap pour quitter.", "cellActions.actions.copyToClipboard.displayName": "Copier dans le Presse-papiers", "cellActions.actions.copyToClipboard.successMessage": "Copié dans le presse-papiers", @@ -1349,7 +1349,6 @@ "data.mgmt.searchSessions.status.expiresSoonInHoursTooltip": "{numHours} heures", "data.mgmt.searchSessions.status.message.createdOn": "Expire le {expireDate}", "data.mgmt.searchSessions.status.message.expiredOn": "Expiré le {expireDate}", - "data.painlessError.painlessScriptedFieldErrorMessage": "Erreur d'exécution du champ d'exécution ou du champ scripté sur le modèle d'indexation {indexPatternName}", "data.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "Intervalle de calendrier non valide : {interval}, la valeur doit être 1", "data.parseEsInterval.invalidEsIntervalFormatErrorMessage": "Format d'intervalle non valide : {interval}", "data.search.aggs.aggTypesLabel": "Plages {fieldName}", @@ -1461,8 +1460,6 @@ "data.advancedSettings.timepicker.thisWeek": "Cette semaine", "data.advancedSettings.timepicker.timeDefaultsTitle": "Filtre temporel par défaut", "data.advancedSettings.timepicker.today": "Aujourd'hui", - "data.errors.fetchError": "Vérifiez votre connexion réseau et réessayez.", - "data.esError.unknownRootCause": "inconnue", "data.functions.esaggs.help": "Exécuter l'agrégation AggConfig", "data.functions.esaggs.inspector.dataRequest.description": "Cette requête interroge Elasticsearch pour récupérer les données pour la visualisation.", "data.functions.esaggs.inspector.dataRequest.title": "Données", @@ -1531,7 +1528,6 @@ "data.mgmt.searchSessions.table.notRestorableWarning": "La session de recherche va être de nouveau exécutée. Vous pouvez ensuite l'enregistrer pour une utilisation ultérieure.", "data.mgmt.searchSessions.table.numSearches": "# recherches", "data.mgmt.searchSessions.table.versionIncompatibleWarning": "Cette session de recherche a été créée dans une instance Kibana exécutant une version différente. Il se peut qu'elle ne soit pas correctement restaurée.", - "data.painlessError.buttonTxt": "Modifier le script", "data.search.aggs.aggGroups.bucketsText": "Compartiments", "data.search.aggs.aggGroups.metricsText": "Indicateurs", "data.search.aggs.aggGroups.noneText": "Aucun", @@ -2048,7 +2044,6 @@ "data.search.esdsl.index.help": "Index Elasticsearch à interroger", "data.search.esdsl.q.help": "Requête DSL", "data.search.esdsl.size.help": "Paramètre de taille de l’API de recherche d’Elasticsearch", - "data.search.esErrorTitle": "Impossible d’extraire les résultats de recherche", "data.search.esql.help": "Interroge Elasticsearch avec ES|QL.", "data.search.esql.query.help": "Une recherche ES|QL.", "data.search.essql.count.help": "Nombre de documents à récupérer. Pour de meilleures performances, utilisez un ensemble de données plus petit.", @@ -2141,7 +2136,6 @@ "data.search.functions.timerange.help": "Créer une plage temporelle Kibana", "data.search.functions.timerange.mode.help": "Spécifier le mode (absolu ou relatif)", "data.search.functions.timerange.to.help": "Spécifier la date de fin", - "data.search.httpErrorTitle": "Impossible de se connecter au serveur Kibana", "data.search.searchSource.dataViewDescription": "La vue de données qui a été interrogée.", "data.search.searchSource.dataViewIdLabel": "ID de vue de données", "data.search.searchSource.dataViewLabel": "Vue de données", @@ -4951,129 +4945,6 @@ "management.settings.offLabel": "Désactivé", "management.settings.onLabel": "Activé", "management.settings.resetToDefaultLinkText": "Réinitialiser à la valeur par défaut", - "monaco.esql.autocomplete.matchingFieldDefinition": "Utiliser pour correspondance avec {matchingField} de la politique", - "monaco.esql.autocomplete.policyDefinition": "Politique définie selon {count, plural, one {index} many {index système non migrés} other {des index}} : {indices}", - "monaco.esql.autocomplete.absDoc": "Renvoie la valeur absolue.", - "monaco.esql.autocomplete.acosDoc": "Fonction trigonométrique cosinus inverse", - "monaco.esql.autocomplete.addDoc": "Ajouter (+)", - "monaco.esql.autocomplete.andDoc": "et", - "monaco.esql.autocomplete.ascDoc": "Ordre croissant", - "monaco.esql.autocomplete.asDoc": "En tant que", - "monaco.esql.autocomplete.asinDoc": "Fonction trigonométrique sinus inverse", - "monaco.esql.autocomplete.assignDoc": "Affecter (=)", - "monaco.esql.autocomplete.atan2Doc": "L'angle entre l'axe positif des x et le rayon allant de l'origine au point (x , y) dans le plan cartésien", - "monaco.esql.autocomplete.atanDoc": "Fonction trigonométrique tangente inverse", - "monaco.esql.autocomplete.autoBucketDoc": "Groupement automatique des dates en fonction d'une plage et d'un compartiment cible donnés.", - "monaco.esql.autocomplete.avgDoc": "Renvoie la moyenne des valeurs dans un champ", - "monaco.esql.autocomplete.byDoc": "Par", - "monaco.esql.autocomplete.caseDoc": "Accepte les paires de conditions et de valeurs. La fonction renvoie la valeur correspondant à la première condition évaluée à \"True\" (Vraie). Si le nombre d'arguments est impair, le dernier argument est la valeur par défaut qui est renvoyée si aucune condition ne correspond.", - "monaco.esql.autocomplete.cidrMatchDoc": "La fonction utilise un premier paramètre de type adresse IP, puis un ou plusieurs paramètres évalués en fonction d'une spécification CIDR.", - "monaco.esql.autocomplete.closeBracketDoc": "Parenthèse fermante )", - "monaco.esql.autocomplete.coalesceDoc": "Renvoie la première valeur non nulle.", - "monaco.esql.autocomplete.concatDoc": "Concatène deux ou plusieurs chaînes.", - "monaco.esql.autocomplete.constantDefinition": "Variable définie par l'utilisateur", - "monaco.esql.autocomplete.cosDoc": "Fonction trigonométrique cosinus", - "monaco.esql.autocomplete.coshDoc": "Fonction hyperbolique cosinus", - "monaco.esql.autocomplete.countDistinctDoc": "Renvoie le décompte des valeurs distinctes dans un champ.", - "monaco.esql.autocomplete.countDoc": "Renvoie le décompte des valeurs dans un champ.", - "monaco.esql.autocomplete.createNewPolicy": "Cliquez pour créer", - "monaco.esql.autocomplete.dateDurationDefinition.day": "Jour", - "monaco.esql.autocomplete.dateDurationDefinition.days": "Jours (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "Heure", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "Heures (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "Milliseconde", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "Millisecondes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "Minute", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "Minutes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "Mois", - "monaco.esql.autocomplete.dateDurationDefinition.months": "Mois (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "Seconde", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "Secondes (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "Semaine", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "Semaines (pluriel)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "An", - "monaco.esql.autocomplete.dateDurationDefinition.years": "Ans (pluriel)", - "monaco.esql.autocomplete.dateExtractDoc": "Extrait des parties d'une date, telles que l'année, le mois, le jour, l'heure. Les types de champs pris en charge sont ceux fournis par la fonction \"java.time.temporal.ChronoField\"", - "monaco.esql.autocomplete.dateFormatDoc": "Renvoie une représentation sous forme de chaîne d'une date dans le format fourni. Si aucun format n'est indiqué, le format \"yyyy-MM-dd'T'HH:mm:ss.SSSZ\" est utilisé.", - "monaco.esql.autocomplete.dateParseDoc": "Analyser les dates à partir de chaînes.", - "monaco.esql.autocomplete.dateTruncDoc": "Arrondit une date à l'intervalle le plus proche. Les intervalles peuvent être exprimés à l'aide de la syntaxe littérale timespan.", - "monaco.esql.autocomplete.declarationLabel": "Déclaration :", - "monaco.esql.autocomplete.descDoc": "Ordre décroissant", - "monaco.esql.autocomplete.dissectDoc": "Extrait de multiples valeurs de chaîne à partir d'une entrée de chaîne unique, suivant un modèle", - "monaco.esql.autocomplete.divideDoc": "Diviser (/)", - "monaco.esql.autocomplete.dropDoc": "Supprime les colonnes", - "monaco.esql.autocomplete.enrichDoc": "Enrichir le tableau à l'aide d'un autre tableau", - "monaco.esql.autocomplete.equalToDoc": "Égal à", - "monaco.esql.autocomplete.evalDoc": "Calcule une expression et place la valeur résultante dans un champ de résultats de recherche.", - "monaco.esql.autocomplete.examplesLabel": "Exemples :", - "monaco.esql.autocomplete.fieldDefinition": "Champ spécifié par le tableau d'entrée", - "monaco.esql.autocomplete.floorDoc": "Arrondir un nombre à l'entier inférieur.", - "monaco.esql.autocomplete.fromDoc": "Récupère les données d'un ou de plusieurs ensembles de données. Un ensemble de données est une collection de données dans laquelle vous souhaitez effectuer une recherche. Le seul ensemble de données pris en charge est un index. Dans une requête ou une sous-requête, vous devez utiliser d'abord la commande from, et cette dernière ne nécessite pas de barre verticale au début. Par exemple, pour récupérer des données d'un index :", - "monaco.esql.autocomplete.greaterThanDoc": "Supérieur à", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "Supérieur ou égal à", - "monaco.esql.autocomplete.greatestDoc": "Renvoie la valeur maximale de plusieurs colonnes.", - "monaco.esql.autocomplete.grokDoc": "Extrait de multiples valeurs de chaîne à partir d'une entrée de chaîne unique, suivant un modèle", - "monaco.esql.autocomplete.inDoc": "Teste si la valeur d'une expression est contenue dans une liste d'autres expressions", - "monaco.esql.autocomplete.isFiniteDoc": "Renvoie un booléen qui indique si son entrée est un nombre fini.", - "monaco.esql.autocomplete.isInfiniteDoc": "Renvoie un booléen qui indique si son entrée est infinie.", - "monaco.esql.autocomplete.keepDoc": "Réarrange les champs dans le tableau d'entrée en appliquant les clauses \"KEEP\" dans les champs", - "monaco.esql.autocomplete.leftDoc": "Renvoyer la sous-chaîne qui extrait la longueur des caractères de la chaîne en partant de la gauche.", - "monaco.esql.autocomplete.lengthDoc": "Renvoie la longueur des caractères d'une chaîne.", - "monaco.esql.autocomplete.lessThanDoc": "Inférieur à", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "Inférieur ou égal à", - "monaco.esql.autocomplete.likeDoc": "Filtrer les données en fonction des modèles de chaînes", - "monaco.esql.autocomplete.limitDoc": "Renvoie les premiers résultats de recherche, dans l'ordre de recherche, en fonction de la \"limite\" spécifiée.", - "monaco.esql.autocomplete.log10Doc": "Renvoie le log de base 10.", - "monaco.esql.autocomplete.ltrimDoc": "Supprime les espaces blancs au début des chaînes.", - "monaco.esql.autocomplete.maxDoc": "Renvoie la valeur maximale dans un champ.", - "monaco.esql.autocomplete.medianDeviationDoc": "Renvoie la médiane de chaque écart de point de données par rapport à la médiane de l'ensemble de l'échantillon.", - "monaco.esql.autocomplete.medianDoc": "Renvoie le 50centile.", - "monaco.esql.autocomplete.minDoc": "Renvoie la valeur minimale dans un champ.", - "monaco.esql.autocomplete.multiplyDoc": "Multiplier (*)", - "monaco.esql.autocomplete.mvExpandDoc": "Développe des champs comportant des valeurs multiples en indiquant une valeur par ligne et en dupliquant les autres champs", - "monaco.esql.autocomplete.newVarDoc": "Définir une nouvelle variable", - "monaco.esql.autocomplete.noPoliciesLabel": "Pas de stratégie disponible", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "Cliquez pour créer", - "monaco.esql.autocomplete.notEqualToDoc": "Différent de", - "monaco.esql.autocomplete.nowDoc": "Renvoie la date et l'heure actuelles.", - "monaco.esql.autocomplete.onDoc": "Activé", - "monaco.esql.autocomplete.openBracketDoc": "Parenthèse ouvrante (", - "monaco.esql.autocomplete.orDoc": "ou", - "monaco.esql.autocomplete.percentiletDoc": "Renvoie le n-ième centile d'un champ.", - "monaco.esql.autocomplete.pipeDoc": "Barre verticale (|)", - "monaco.esql.autocomplete.powDoc": "Renvoie la valeur d'une base (premier argument) élevée à une puissance (deuxième argument).", - "monaco.esql.autocomplete.renameDoc": "Attribue un nouveau nom à une ancienne colonne", - "monaco.esql.autocomplete.rightDoc": "Renvoyer la sous-chaîne qui extrait la longueur des caractères de la chaîne en partant de la droite.", - "monaco.esql.autocomplete.rlikeDoc": "Filtrer les données en fonction des expressions régulières des chaînes", - "monaco.esql.autocomplete.roundDoc": "Renvoie un nombre arrondi à la décimale, spécifié par la valeur entière la plus proche. La valeur par défaut est arrondie à un entier.", - "monaco.esql.autocomplete.rtrimDoc": "Supprime les espaces blancs à la fin des chaînes.", - "monaco.esql.autocomplete.sinDoc": "Fonction trigonométrique sinus.", - "monaco.esql.autocomplete.sinhDoc": "Fonction hyperbolique sinus.", - "monaco.esql.autocomplete.sortDoc": "Trie tous les résultats en fonction des champs spécifiés. Lorsqu'ils sont en ordre décroissant, les résultats pour lesquels un champ est manquant sont considérés comme la plus petite valeur possible du champ, ou la plus grande valeur possible du champ lorsqu'ils sont en ordre croissant.", - "monaco.esql.autocomplete.sourceDefinition": "Tableau d'entrée", - "monaco.esql.autocomplete.splitDoc": "Divise une chaîne de valeur unique en plusieurs chaînes.", - "monaco.esql.autocomplete.sqrtDoc": "Renvoie la racine carrée d'un nombre. ", - "monaco.esql.autocomplete.startsWithDoc": "Renvoie un booléen qui indique si une chaîne de mot-clés débute par une autre chaîne.", - "monaco.esql.autocomplete.statsDoc": "Calcule les statistiques agrégées, telles que la moyenne, le décompte et la somme, sur l'ensemble des résultats de recherche entrants. Comme pour l'agrégation SQL, si la commande stats est utilisée sans clause BY, une seule ligne est renvoyée, qui est l'agrégation de tout l'ensemble des résultats de recherche entrants. Lorsque vous utilisez une clause BY, une ligne est renvoyée pour chaque valeur distincte dans le champ spécifié dans la clause BY. La commande stats renvoie uniquement les champs dans l'agrégation, et vous pouvez utiliser un large éventail de fonctions statistiques avec la commande stats. Lorsque vous effectuez plusieurs agrégations, séparez chacune d'entre elle par une virgule.", - "monaco.esql.autocomplete.substringDoc": "Renvoie la sous-chaîne d'une chaîne, délimitée en fonction d'une position de départ et d'une longueur optionnelle. Cet exemple renvoie les trois premières lettres de chaque nom de famille.", - "monaco.esql.autocomplete.subtractDoc": "Subtract (-)", - "monaco.esql.autocomplete.sumDoc": "Renvoie la somme des valeurs dans un champ.", - "monaco.esql.autocomplete.tanDoc": "Fonction trigonométrique tangente.", - "monaco.esql.autocomplete.tanhDoc": "Fonction hyperbolique tangente.", - "monaco.esql.autocomplete.toBooleanDoc": "Convertit en booléen.", - "monaco.esql.autocomplete.toDateTimeDoc": "Convertit en date.", - "monaco.esql.autocomplete.toDegreesDoc": "Convertit en degrés", - "monaco.esql.autocomplete.toDoubleDoc": "Convertit en double.", - "monaco.esql.autocomplete.toIntegerDoc": "Convertit en nombre entier.", - "monaco.esql.autocomplete.toIpDoc": "Convertit en ip.", - "monaco.esql.autocomplete.toLongDoc": "Convertit en long.", - "monaco.esql.autocomplete.toRadiansDoc": "Convertit en radians", - "monaco.esql.autocomplete.toStringDoc": "Convertit en chaîne.", - "monaco.esql.autocomplete.toUnsignedLongDoc": "Convertit en long non signé.", - "monaco.esql.autocomplete.toVersionDoc": "Convertit en version.", - "monaco.esql.autocomplete.trimDoc": "Supprime les espaces de début et de fin d'une chaîne.", - "monaco.esql.autocomplete.whereDoc": "Utilise \"predicate-expressions\" pour filtrer les résultats de recherche. Une expression predicate, lorsqu'elle est évaluée, renvoie TRUE ou FALSE. La commande where renvoie uniquement les résultats qui donnent la valeur TRUE. Par exemple, pour filtrer les résultats pour une valeur de champ spécifique", - "monaco.esql.autocomplete.withDoc": "Avec", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "Accéder à une valeur de champ dans un script au moyen de la syntaxe doc['field_name']", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "Émettre une valeur sans rien renvoyer", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "Récupérer la valeur du champ \"{fieldName}\"", @@ -5327,6 +5198,12 @@ "searchApiPanels.welcomeBanner.selectClient.heading": "Choisissez-en un", "searchApiPanels.welcomeBanner.selectClient.title": "Sélectionner votre client", "searchApiPanels.welcomeBanner.tryInConsoleButton": "Essayer dans la console", + "searchErrors.painlessError.painlessScriptedFieldErrorMessage": "Erreur d'exécution du champ d'exécution ou du champ scripté sur le modèle d'indexation {indexPatternName}", + "searchErrors.errors.fetchError": "Vérifiez votre connexion réseau et réessayez.", + "searchErrors.esError.unknownRootCause": "inconnue", + "searchErrors.painlessError.buttonTxt": "Modifier le script", + "searchErrors.search.esErrorTitle": "Impossible d’extraire les résultats de recherche", + "searchErrors.search.httpErrorTitle": "Impossible de se connecter au serveur Kibana", "searchResponseWarnings.badgeButtonLabel": "{warningCount} {warningCount, plural, one {avertissement} many {avertissements} other {avertissements}}", "searchResponseWarnings.noResultsTitle": "Résultat introuvable", "securitySolutionPackages.dataTable.eventsTab.unit": "{totalCount, plural, =1 {alerte} one {alertes} many {alertes} other {alertes}}", @@ -12129,7 +12006,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "Le modèle ARM n'est pas compatible avec la version actuelle de l'intégration. Veuillez passer à la version la plus récente de votre intégration pour utiliser le modèle ARM", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "Cliquez sur le bouton \"Enregistrer et continuer\" en bas à droite de cette page.", "xpack.csp.azureIntegration.azureNotSupportedMessage": "CIS Azure n'est pas compatible avec la version actuelle de l'intégration. Veuillez passer à la version la plus récente de votre intégration pour utiliser CIS Azure", - "xpack.csp.azureIntegration.credentialType.manualLabel": "Manuel", "xpack.csp.azureIntegration.documentationLinkText": "documentation", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "Guide de premiers pas", "xpack.csp.azureIntegration.setupFormatOptions.manual": "Manuel", @@ -23599,7 +23475,6 @@ "xpack.maps.inspector.mapDetailsTitle": "Détails de la carte", "xpack.maps.inspector.mapDetailsViewHelpText": "Voir l'état de la carte", "xpack.maps.inspector.mapDetailsViewTitle": "Détails de la carte", - "xpack.maps.inspector.vectorTile.layerSelectPrepend": "Calque", "xpack.maps.inspector.vectorTile.noRequestsLoggedDescription.mapHasNotLoggedAnyRequestsText": "Cette carte ne comporte aucun résultat de recherche de tuiles vectorielles.", "xpack.maps.inspector.vectorTile.noRequestsLoggedTitle": "Aucune requête consignée dans un log pour les tuiles vectorielles", "xpack.maps.inspector.vectorTile.requestsView": "Vous visualisez les requêtes de recherche de tuiles vectorielles. Pour afficher les requêtes envoyées à l'API de recherche, définissez Afficher sur Requêtes.", @@ -29673,7 +29548,6 @@ "xpack.observabilityAiAssistant.conversationStartTitle": "a démarré une conversation", "xpack.observabilityAiAssistant.couldNotFindConversationTitle": "Conversation introuvable", "xpack.observabilityAiAssistant.emptyConversationTitle": "Nouvelle conversation", - "xpack.observabilityAiAssistant.errorCreatingConversation": "Impossible de créer une conversation", "xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase": "Impossible de configurer la base de connaissances", "xpack.observabilityAiAssistant.errorUpdatingConversation": "Impossible de mettre à jour la conversation", "xpack.observabilityAiAssistant.experimentalTitle": "Version d'évaluation technique", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 107a0c7e929b6..36660d0392e6b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -147,12 +147,12 @@ "autocomplete.loadingDescription": "読み込み中...", "autocomplete.seeDocumentation": "ドキュメントを参照", "autocomplete.selectField": "最初にフィールドを選択してください...", - "bfetch.networkErrorWithStatus": "ネットワーク接続を確認して再試行してください。コード{code}", "bfetch.disableBfetch": "リクエストバッチを無効にする", "bfetch.disableBfetchCompression": "バッチ圧縮を無効にする", "bfetch.disableBfetchCompressionDesc": "バッチ圧縮を無効にします。個別の要求をデバッグできますが、応答サイズが大きくなります。", "bfetch.disableBfetchDesc": "リクエストバッチを無効にします。これにより、KibanaからのHTTPリクエスト数は減りますが、個別にリクエストをデバッグできます。", - "bfetch.networkError": "ネットワーク接続を確認して再試行してください。", + "bfetchError.networkError": "ネットワーク接続を確認して再試行してください。", + "bfetchError.networkErrorWithStatus": "ネットワーク接続を確認して再試行してください。コード{code}", "cellActions.youAreInADialogContainingOptionsScreenReaderOnly": "フィールド{fieldName}のオプションを含むダイアログを表示しています。Tabを押すと、オプションを操作します。Escapeを押すと、終了します。", "cellActions.actions.copyToClipboard.displayName": "クリップボードにコピー", "cellActions.actions.copyToClipboard.successMessage": "クリップボードにコピーしました", @@ -1363,7 +1363,6 @@ "data.mgmt.searchSessions.status.expiresSoonInHoursTooltip": "{numHours}時間", "data.mgmt.searchSessions.status.message.createdOn": "{expireDate}に有効期限", "data.mgmt.searchSessions.status.message.expiredOn": "{expireDate}に有効期限切れ", - "data.painlessError.painlessScriptedFieldErrorMessage": "インデックスパターン{indexPatternName}でのランタイムフィールドまたはスクリプトフィールドの実行エラー", "data.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "無効なカレンダー間隔:{interval}、1よりも大きな値が必要です", "data.parseEsInterval.invalidEsIntervalFormatErrorMessage": "無効な間隔フォーマット:{interval}", "data.search.aggs.aggTypesLabel": "{fieldName}範囲", @@ -1475,8 +1474,6 @@ "data.advancedSettings.timepicker.thisWeek": "今週", "data.advancedSettings.timepicker.timeDefaultsTitle": "デフォルトのタイムピッカー", "data.advancedSettings.timepicker.today": "今日", - "data.errors.fetchError": "ネットワーク接続を確認して再試行してください。", - "data.esError.unknownRootCause": "不明", "data.functions.esaggs.help": "AggConfig 集約を実行します", "data.functions.esaggs.inspector.dataRequest.description": "このリクエストはElasticsearchにクエリし、ビジュアライゼーション用のデータを取得します。", "data.functions.esaggs.inspector.dataRequest.title": "データ", @@ -1545,7 +1542,6 @@ "data.mgmt.searchSessions.table.notRestorableWarning": "検索セッションはもう一度実行されます。今後使用するために保存できます。", "data.mgmt.searchSessions.table.numSearches": "# 検索", "data.mgmt.searchSessions.table.versionIncompatibleWarning": "この検索は別のバージョンを実行しているKibanaインスタンスで作成されました。正常に復元されない可能性があります。", - "data.painlessError.buttonTxt": "スクリプトを編集", "data.search.aggs.aggGroups.bucketsText": "バケット", "data.search.aggs.aggGroups.metricsText": "メトリック", "data.search.aggs.aggGroups.noneText": "なし", @@ -2062,7 +2058,6 @@ "data.search.esdsl.index.help": "クエリするElasticsearchインデックス", "data.search.esdsl.q.help": "クエリDSL", "data.search.esdsl.size.help": "Elasticsearch 検索 API サイズパラメーター", - "data.search.esErrorTitle": "検索結果を取得できません", "data.search.esql.help": "ES|QLを使用してElasticsearchを照会します。", "data.search.esql.query.help": "ES|QLクエリ。", "data.search.essql.count.help": "取得するドキュメント数です。パフォーマンスを向上させるには、小さなデータセットを使用します。", @@ -2155,7 +2150,6 @@ "data.search.functions.timerange.help": "Kibana timerangeを作成", "data.search.functions.timerange.mode.help": "モードを指定(絶対または相対)", "data.search.functions.timerange.to.help": "終了日を指定", - "data.search.httpErrorTitle": "Kibanaサーバーに接続できません", "data.search.searchSource.dataViewDescription": "照会されたデータビュー。", "data.search.searchSource.dataViewIdLabel": "データビューID", "data.search.searchSource.dataViewLabel": "データビュー", @@ -4966,129 +4960,6 @@ "management.settings.offLabel": "オフ", "management.settings.onLabel": "オン", "management.settings.resetToDefaultLinkText": "デフォルトにリセット", - "monaco.esql.autocomplete.matchingFieldDefinition": "ポリシーで{matchingField}で照合するために使用", - "monaco.esql.autocomplete.policyDefinition": "{count, plural, other {インデックス}}で定義されたポリシー:{indices}", - "monaco.esql.autocomplete.absDoc": "絶対値を返します。", - "monaco.esql.autocomplete.acosDoc": "逆余弦三角関数", - "monaco.esql.autocomplete.addDoc": "加算(+)", - "monaco.esql.autocomplete.andDoc": "AND", - "monaco.esql.autocomplete.ascDoc": "昇順", - "monaco.esql.autocomplete.asDoc": "として", - "monaco.esql.autocomplete.asinDoc": "逆正弦三角関数", - "monaco.esql.autocomplete.assignDoc": "割り当て(=)", - "monaco.esql.autocomplete.atan2Doc": "直交平面上の原点から点(x , y)に向かう光線と正のx軸のなす角", - "monaco.esql.autocomplete.atanDoc": "逆正接三角関数", - "monaco.esql.autocomplete.autoBucketDoc": "指定された範囲とバケット目標に基づいて、日付を自動的にバケット化します。", - "monaco.esql.autocomplete.avgDoc": "フィールドの値の平均を返します", - "monaco.esql.autocomplete.byDoc": "グループ基準", - "monaco.esql.autocomplete.caseDoc": "条件と値のペアを指定できます。この関数は、最初にtrueと評価された条件に属する値を返します。引数の数が奇数の場合、最後の引数は条件に一致しない場合に返されるデフォルト値になります。", - "monaco.esql.autocomplete.cidrMatchDoc": "この関数は、IP型の最初のパラメーターを取り、その後にCIDR指定に対して評価された1つ以上のパラメーターを取ります。", - "monaco.esql.autocomplete.closeBracketDoc": "閉じ括弧 )", - "monaco.esql.autocomplete.coalesceDoc": "最初のNULL以外の値を返します。", - "monaco.esql.autocomplete.concatDoc": "2つ以上の文字列を連結します。", - "monaco.esql.autocomplete.constantDefinition": "ユーザー定義変数", - "monaco.esql.autocomplete.cosDoc": "余弦三角関数", - "monaco.esql.autocomplete.coshDoc": "余弦双曲線関数", - "monaco.esql.autocomplete.countDistinctDoc": "フィールド内の異なる値の数を返します。", - "monaco.esql.autocomplete.countDoc": "フィールドの値の数を返します。", - "monaco.esql.autocomplete.createNewPolicy": "クリックして作成", - "monaco.esql.autocomplete.dateDurationDefinition.day": "日", - "monaco.esql.autocomplete.dateDurationDefinition.days": "日(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "時間", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "時間(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "ミリ秒", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "ミリ秒(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "分", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "分(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "月", - "monaco.esql.autocomplete.dateDurationDefinition.months": "月(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "秒", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "秒(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "週", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "週(複数)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "年", - "monaco.esql.autocomplete.dateDurationDefinition.years": "年(複数)", - "monaco.esql.autocomplete.dateExtractDoc": "年、月、日、時間など、日付の一部を抽出します。サポートされているフィールド型はjava.time.temporal.ChronoFieldで提供されている型です。", - "monaco.esql.autocomplete.dateFormatDoc": "指定した書式の日付の文字列表現を返します。書式が指定されていない場合は、yyyy-MM-dd'T'HH:mm:ss.SSSZの書式が使用されます。", - "monaco.esql.autocomplete.dateParseDoc": "文字列から日付を解析します。", - "monaco.esql.autocomplete.dateTruncDoc": "最も近い区間まで日付を切り捨てます。区間はtimespanリテラル構文を使って表現できます。", - "monaco.esql.autocomplete.declarationLabel": "宣言:", - "monaco.esql.autocomplete.descDoc": "降順", - "monaco.esql.autocomplete.dissectDoc": "単一の文字列入力から、パターンに基づいて複数の文字列値を抽出", - "monaco.esql.autocomplete.divideDoc": "除算(/)", - "monaco.esql.autocomplete.dropDoc": "列を削除", - "monaco.esql.autocomplete.enrichDoc": "別のテーブルでテーブルをエンリッチ", - "monaco.esql.autocomplete.equalToDoc": "等しい", - "monaco.esql.autocomplete.evalDoc": "式を計算し、結果の値を検索結果フィールドに入力します。", - "monaco.esql.autocomplete.examplesLabel": "例:", - "monaco.esql.autocomplete.fieldDefinition": "入力テーブルで指定されたフィールド", - "monaco.esql.autocomplete.floorDoc": "最も近い整数に数値を切り捨てます。", - "monaco.esql.autocomplete.fromDoc": "1つ以上のデータセットからデータを取得します。データセットは検索するデータの集合です。唯一のサポートされているデータセットはインデックスです。クエリまたはサブクエリでは、最初にコマンドから使用する必要があります。先頭のパイプは不要です。たとえば、インデックスからデータを取得します。", - "monaco.esql.autocomplete.greaterThanDoc": "より大きい", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "よりも大きいまたは等しい", - "monaco.esql.autocomplete.greatestDoc": "多数の列から最大値を返します。", - "monaco.esql.autocomplete.grokDoc": "単一の文字列入力から、パターンに基づいて複数の文字列値を抽出", - "monaco.esql.autocomplete.inDoc": "ある式が取る値が、他の式のリストに含まれているかどうかをテストします", - "monaco.esql.autocomplete.isFiniteDoc": "入力が有限数であるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.isInfiniteDoc": "入力が無限数であるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.keepDoc": "フィールドでkeep句を適用して、入力テーブルのフィールドを並べ替えます", - "monaco.esql.autocomplete.leftDoc": "stringから左から順にlength文字を抜き出したサブ文字列を返します。", - "monaco.esql.autocomplete.lengthDoc": "文字列の文字数を返します。", - "monaco.esql.autocomplete.lessThanDoc": "より小さい", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "以下", - "monaco.esql.autocomplete.likeDoc": "文字列パターンに基づいてデータをフィルター", - "monaco.esql.autocomplete.limitDoc": "指定された「制限」に基づき、検索順序で、最初の検索結果を返します。", - "monaco.esql.autocomplete.log10Doc": "底が10の対数を返します。", - "monaco.esql.autocomplete.ltrimDoc": "文字列から先頭の空白を取り除きます。", - "monaco.esql.autocomplete.maxDoc": "フィールドの最大値を返します。", - "monaco.esql.autocomplete.medianDeviationDoc": "サンプル全体の中央値からの各データポイントの偏差の中央値を返します。", - "monaco.esql.autocomplete.medianDoc": "50%パーセンタイルを返します。", - "monaco.esql.autocomplete.minDoc": "フィールドの最小値を返します。", - "monaco.esql.autocomplete.multiplyDoc": "乗算(*)", - "monaco.esql.autocomplete.mvExpandDoc": "複数値フィールドを値ごとに1行に展開し、他のフィールドを複製します", - "monaco.esql.autocomplete.newVarDoc": "新しい変数を定義", - "monaco.esql.autocomplete.noPoliciesLabel": "ポリシーがありません", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "クリックして作成", - "monaco.esql.autocomplete.notEqualToDoc": "Not equal to", - "monaco.esql.autocomplete.nowDoc": "現在の日付と時刻を返します。", - "monaco.esql.autocomplete.onDoc": "オン", - "monaco.esql.autocomplete.openBracketDoc": "開き括弧 (", - "monaco.esql.autocomplete.orDoc": "または", - "monaco.esql.autocomplete.percentiletDoc": "フィールドのnパーセンタイルを返します。", - "monaco.esql.autocomplete.pipeDoc": "パイプ(|)", - "monaco.esql.autocomplete.powDoc": "底(第1引数)を累乗(第2引数)した値を返します。", - "monaco.esql.autocomplete.renameDoc": "古い列の名前を新しい列に変更", - "monaco.esql.autocomplete.rightDoc": "stringのうち右から数えてlength文字までのサブ文字列を返します。", - "monaco.esql.autocomplete.rlikeDoc": "文字列の正規表現に基づいてデータをフィルター", - "monaco.esql.autocomplete.roundDoc": "最も近い整数値で指定された数字まで端数処理された数値を返します。デフォルトは整数になるように四捨五入されます。", - "monaco.esql.autocomplete.rtrimDoc": "文字列から末尾の空白を取り除きます。", - "monaco.esql.autocomplete.sinDoc": "正弦三角関数。", - "monaco.esql.autocomplete.sinhDoc": "正弦双曲線関数。", - "monaco.esql.autocomplete.sortDoc": "すべての結果を指定されたフィールドで並べ替えます。降順では、フィールドが見つからない結果は、フィールドの最も小さい可能な値と見なされます。昇順では、フィールドの最も大きい可能な値と見なされます。", - "monaco.esql.autocomplete.sourceDefinition": "入力テーブル", - "monaco.esql.autocomplete.splitDoc": "単一の値の文字列を複数の文字列に分割します。", - "monaco.esql.autocomplete.sqrtDoc": "数値の平方根を返します。", - "monaco.esql.autocomplete.startsWithDoc": "キーワード文字列が他の文字列で始まるかどうかを示すブール値を返します。", - "monaco.esql.autocomplete.statsDoc": "受信検索結果セットで、平均、カウント、合計などの集約統計情報を計算します。SQL集約と同様に、statsコマンドをBY句なしで使用した場合は、1行のみが返されます。これは、受信検索結果セット全体に対する集約です。BY句を使用すると、BY句で指定したフィールドの1つの値ごとに1行が返されます。statsコマンドは集約のフィールドのみを返します。statsコマンドではさまざまな統計関数を使用できます。複数の集約を実行するときには、各集約をカンマで区切ります。", - "monaco.esql.autocomplete.substringDoc": "文字列のサブ文字列を、開始位置とオプションの長さで指定して返します。この例では、それぞれの姓の最初の3文字を返します。", - "monaco.esql.autocomplete.subtractDoc": "減算(-)", - "monaco.esql.autocomplete.sumDoc": "フィールドの値の合計を返します。", - "monaco.esql.autocomplete.tanDoc": "正接三角関数。", - "monaco.esql.autocomplete.tanhDoc": "正接双曲線関数。", - "monaco.esql.autocomplete.toBooleanDoc": "ブール値に変換します。", - "monaco.esql.autocomplete.toDateTimeDoc": "日付に変換します。", - "monaco.esql.autocomplete.toDegreesDoc": "度に変換します", - "monaco.esql.autocomplete.toDoubleDoc": "doubleに変換します。", - "monaco.esql.autocomplete.toIntegerDoc": "整数に変換します。", - "monaco.esql.autocomplete.toIpDoc": "IPに変換します。", - "monaco.esql.autocomplete.toLongDoc": "longに変換します。", - "monaco.esql.autocomplete.toRadiansDoc": "ラジアンに変換します", - "monaco.esql.autocomplete.toStringDoc": "文字列に変換します。", - "monaco.esql.autocomplete.toUnsignedLongDoc": "符号なしlongに変換します。", - "monaco.esql.autocomplete.toVersionDoc": "バージョンに変換します。", - "monaco.esql.autocomplete.trimDoc": "文字列から先頭と末尾の空白を削除します。", - "monaco.esql.autocomplete.whereDoc": "「predicate-expressions」を使用して、検索結果をフィルターします。予測式は評価時にTRUEまたはFALSEを返します。whereコマンドはTRUEに評価される結果のみを返します。たとえば、特定のフィールド値の結果をフィルターします", - "monaco.esql.autocomplete.withDoc": "を使用して", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "doc['field_name'] 構文を使用して、スクリプトからフィールド値にアクセスします", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "戻らずに値を発行します。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "フィールド「{fieldName}」の値を取得します", @@ -5342,6 +5213,12 @@ "searchApiPanels.welcomeBanner.selectClient.heading": "1つ選択", "searchApiPanels.welcomeBanner.selectClient.title": "クライアントを選択", "searchApiPanels.welcomeBanner.tryInConsoleButton": "コンソールで試す", + "searchErrors.painlessError.painlessScriptedFieldErrorMessage": "インデックスパターン{indexPatternName}でのランタイムフィールドまたはスクリプトフィールドの実行エラー", + "searchErrors.errors.fetchError": "ネットワーク接続を確認して再試行してください。", + "searchErrors.esError.unknownRootCause": "不明", + "searchErrors.painlessError.buttonTxt": "スクリプトを編集", + "searchErrors.search.esErrorTitle": "検索結果を取得できません", + "searchErrors.search.httpErrorTitle": "Kibanaサーバーに接続できません", "searchResponseWarnings.badgeButtonLabel": "{warningCount} {warningCount, plural, other {警告}}", "searchResponseWarnings.noResultsTitle": "結果が見つかりませんでした", "securitySolutionPackages.dataTable.eventsTab.unit": "{totalCount, plural, =1 {アラート} other {アラート}}", @@ -12143,7 +12020,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "ARMテンプレートは現在の統合バージョンではサポートされていません。ARMテンプレートを使用するには、統合を最新バージョンにアップグレードしてください", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "このページの右下にある\"保存して続行\"ボタンをクリックしてください。", "xpack.csp.azureIntegration.azureNotSupportedMessage": "CIS Azureは現在の統合バージョンではサポートされていません。CIS Azureを使用するには、統合を最新バージョンにアップグレードしてください", - "xpack.csp.azureIntegration.credentialType.manualLabel": "手動", "xpack.csp.azureIntegration.documentationLinkText": "ドキュメンテーション", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "入門ガイド", "xpack.csp.azureIntegration.setupFormatOptions.manual": "手動", @@ -23614,7 +23490,6 @@ "xpack.maps.inspector.mapDetailsTitle": "マップの詳細", "xpack.maps.inspector.mapDetailsViewHelpText": "マップステータスを表示します", "xpack.maps.inspector.mapDetailsViewTitle": "マップの詳細", - "xpack.maps.inspector.vectorTile.layerSelectPrepend": "レイヤー", "xpack.maps.inspector.vectorTile.noRequestsLoggedDescription.mapHasNotLoggedAnyRequestsText": "このマップにはベクトルタイル検索結果がありません。", "xpack.maps.inspector.vectorTile.noRequestsLoggedTitle": "ベクトルタイルの要求はログに記録されません", "xpack.maps.inspector.vectorTile.requestsView": "ベクトルタイル検索要求を表示しています。検索APIに送信された要求を表示するには、[表示]を[要求]に設定します。", @@ -29673,7 +29548,6 @@ "xpack.observabilityAiAssistant.conversationStartTitle": "会話を開始しました", "xpack.observabilityAiAssistant.couldNotFindConversationTitle": "会話が見つかりません", "xpack.observabilityAiAssistant.emptyConversationTitle": "新しい会話", - "xpack.observabilityAiAssistant.errorCreatingConversation": "会話を作成できませんでした", "xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase": "ナレッジベースをセットアップできませんでした", "xpack.observabilityAiAssistant.errorUpdatingConversation": "会話を更新できませんでした", "xpack.observabilityAiAssistant.experimentalTitle": "テクニカルプレビュー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0ed4a01b5d034..84bf8c04333b5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -147,12 +147,12 @@ "autocomplete.loadingDescription": "正在加载……", "autocomplete.seeDocumentation": "参阅文档", "autocomplete.selectField": "请首先选择字段......", - "bfetch.networkErrorWithStatus": "检查您的网络连接,然后重试。代码 {code}", "bfetch.disableBfetch": "禁用请求批处理", "bfetch.disableBfetchCompression": "禁用批量压缩", "bfetch.disableBfetchCompressionDesc": "禁用批量压缩。这允许您对单个请求进行故障排查,但会增加响应大小。", "bfetch.disableBfetchDesc": "禁用请求批处理。这会增加来自 Kibana 的 HTTP 请求数,但允许对单个请求进行故障排查。", - "bfetch.networkError": "检查您的网络连接,然后重试。", + "bfetchError.networkError": "检查您的网络连接,然后重试。", + "bfetchError.networkErrorWithStatus": "检查您的网络连接,然后重试。代码 {code}", "cellActions.youAreInADialogContainingOptionsScreenReaderOnly": "您在对话框中,其中包含 {fieldName} 字段的选项。按 tab 键导航选项。按 escape 退出。", "cellActions.actions.copyToClipboard.displayName": "复制到剪贴板", "cellActions.actions.copyToClipboard.successMessage": "已复制到剪贴板", @@ -1363,7 +1363,6 @@ "data.mgmt.searchSessions.status.expiresSoonInHoursTooltip": "{numHours} 小时", "data.mgmt.searchSessions.status.message.createdOn": "于 {expireDate}过期", "data.mgmt.searchSessions.status.message.expiredOn": "已于 {expireDate}过期", - "data.painlessError.painlessScriptedFieldErrorMessage": "在索引模式 {indexPatternName} 上执行运行时字段或脚本字段时出错", "data.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "无效的日历时间间隔:{interval},值必须为 1", "data.parseEsInterval.invalidEsIntervalFormatErrorMessage": "时间间隔格式无效:{interval}", "data.search.aggs.aggTypesLabel": "{fieldName} 范围", @@ -1475,8 +1474,6 @@ "data.advancedSettings.timepicker.thisWeek": "本周", "data.advancedSettings.timepicker.timeDefaultsTitle": "时间筛选默认值", "data.advancedSettings.timepicker.today": "今日", - "data.errors.fetchError": "检查您的网络连接,然后重试。", - "data.esError.unknownRootCause": "未知", "data.functions.esaggs.help": "运行 AggConfig 聚合", "data.functions.esaggs.inspector.dataRequest.description": "此请求查询 Elasticsearch,以获取可视化的数据。", "data.functions.esaggs.inspector.dataRequest.title": "数据", @@ -1545,7 +1542,6 @@ "data.mgmt.searchSessions.table.notRestorableWarning": "搜索会话将重新执行。然后,您可以将其保存,供未来使用。", "data.mgmt.searchSessions.table.numSearches": "搜索数", "data.mgmt.searchSessions.table.versionIncompatibleWarning": "此搜索会话在运行不同版本的 Kibana 实例中已创建。其可能不会正确还原。", - "data.painlessError.buttonTxt": "编辑脚本", "data.search.aggs.aggGroups.bucketsText": "存储桶", "data.search.aggs.aggGroups.metricsText": "指标", "data.search.aggs.aggGroups.noneText": "无", @@ -2062,7 +2058,6 @@ "data.search.esdsl.index.help": "要查询的 ElasticSearch 索引", "data.search.esdsl.q.help": "查询 DSL", "data.search.esdsl.size.help": "ElasticSearch searchAPI 大小参数", - "data.search.esErrorTitle": "无法检索搜索结果", "data.search.esql.help": "使用 ES|QL 查询 Elasticsearch。", "data.search.esql.query.help": "ES|QL 查询。", "data.search.essql.count.help": "要检索的文档数目。要获取更佳的性能,请使用较小的数据集。", @@ -2155,7 +2150,6 @@ "data.search.functions.timerange.help": "创建 kibana 时间戳", "data.search.functions.timerange.mode.help": "指定模式(绝对或相对)", "data.search.functions.timerange.to.help": "指定结束日期", - "data.search.httpErrorTitle": "无法连接到 Kibana 服务器", "data.search.searchSource.dataViewDescription": "被查询的数据视图。", "data.search.searchSource.dataViewIdLabel": "数据视图 ID", "data.search.searchSource.dataViewLabel": "数据视图", @@ -4965,129 +4959,6 @@ "management.settings.offLabel": "关闭", "management.settings.onLabel": "开启", "management.settings.resetToDefaultLinkText": "重置为默认值", - "monaco.esql.autocomplete.matchingFieldDefinition": "用于匹配策略上的{matchingField}", - "monaco.esql.autocomplete.policyDefinition": "策略在{count, plural, other {索引}}上定义:{indices}", - "monaco.esql.autocomplete.absDoc": "返回绝对值。", - "monaco.esql.autocomplete.acosDoc": "反余弦三角函数", - "monaco.esql.autocomplete.addDoc": "添加 (+)", - "monaco.esql.autocomplete.andDoc": "且", - "monaco.esql.autocomplete.ascDoc": "升序", - "monaco.esql.autocomplete.asDoc": "作为", - "monaco.esql.autocomplete.asinDoc": "反正弦三角函数", - "monaco.esql.autocomplete.assignDoc": "分配 (=)", - "monaco.esql.autocomplete.atan2Doc": "笛卡儿平面中正 x 轴与从原点到点 (x , y) 构成的射线之间的角度", - "monaco.esql.autocomplete.atanDoc": "反正切三角函数", - "monaco.esql.autocomplete.autoBucketDoc": "根据给定范围和存储桶目标自动收集存储桶日期。", - "monaco.esql.autocomplete.avgDoc": "返回字段中的值的平均值", - "monaco.esql.autocomplete.byDoc": "依据", - "monaco.esql.autocomplete.caseDoc": "接受成对的条件和值。此函数返回属于第一个评估为 `true` 的条件的值。如果参数数量为奇数,则最后一个参数为在无条件匹配时返回的默认值。", - "monaco.esql.autocomplete.cidrMatchDoc": "此函数接受的第一个参数应为 IP 类型,后接一个或多个评估为 CIDR 规范的参数。", - "monaco.esql.autocomplete.closeBracketDoc": "右括号 )", - "monaco.esql.autocomplete.coalesceDoc": "返回第一个非 null 值。", - "monaco.esql.autocomplete.concatDoc": "串联两个或多个字符串。", - "monaco.esql.autocomplete.constantDefinition": "用户定义的变量", - "monaco.esql.autocomplete.cosDoc": "余弦三角函数", - "monaco.esql.autocomplete.coshDoc": "余弦双曲函数", - "monaco.esql.autocomplete.countDistinctDoc": "返回字段中不同值的计数。", - "monaco.esql.autocomplete.countDoc": "返回字段中的值的计数。", - "monaco.esql.autocomplete.createNewPolicy": "单击以创建", - "monaco.esql.autocomplete.dateDurationDefinition.day": "天", - "monaco.esql.autocomplete.dateDurationDefinition.days": "天(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.hour": "小时", - "monaco.esql.autocomplete.dateDurationDefinition.hours": "小时(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.millisecond": "毫秒", - "monaco.esql.autocomplete.dateDurationDefinition.milliseconds": "毫秒(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.minute": "分钟", - "monaco.esql.autocomplete.dateDurationDefinition.minutes": "分钟(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.month": "月", - "monaco.esql.autocomplete.dateDurationDefinition.months": "月(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.second": "秒", - "monaco.esql.autocomplete.dateDurationDefinition.seconds": "秒(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.week": "周", - "monaco.esql.autocomplete.dateDurationDefinition.weeks": "周(复数)", - "monaco.esql.autocomplete.dateDurationDefinition.year": "年", - "monaco.esql.autocomplete.dateDurationDefinition.years": "年(复数)", - "monaco.esql.autocomplete.dateExtractDoc": "提取日期的某些部分,如年、月、日、小时。支持的字段类型为 java.time.temporal.ChronoField 提供的那些类型", - "monaco.esql.autocomplete.dateFormatDoc": "以提供的格式返回日期的字符串表示形式。如果未指定格式,则使用“yyyy-MM-dd'T'HH:mm:ss.SSSZ”格式。", - "monaco.esql.autocomplete.dateParseDoc": "解析字符串中的日期。", - "monaco.esql.autocomplete.dateTruncDoc": "将日期向下舍入到最近的时间间隔。时间间隔可以用时间跨度文本语法表示。", - "monaco.esql.autocomplete.declarationLabel": "声明:", - "monaco.esql.autocomplete.descDoc": "降序", - "monaco.esql.autocomplete.dissectDoc": "根据模式从单个字符串输入中提取多个字符串值", - "monaco.esql.autocomplete.divideDoc": "除 (/)", - "monaco.esql.autocomplete.dropDoc": "丢弃列", - "monaco.esql.autocomplete.enrichDoc": "用其他表来扩充表", - "monaco.esql.autocomplete.equalToDoc": "等于", - "monaco.esql.autocomplete.evalDoc": "计算表达式并将生成的值置入搜索结果字段。", - "monaco.esql.autocomplete.examplesLabel": "示例:", - "monaco.esql.autocomplete.fieldDefinition": "由输入表指定的字段", - "monaco.esql.autocomplete.floorDoc": "将数字向下舍入到最近的整数。", - "monaco.esql.autocomplete.fromDoc": "从一个或多个数据集中检索数据。数据集是您希望搜索的数据的集合。索引是唯一受支持的数据集。在查询或子查询中,必须先使用 from 命令,并且它不需要前导管道符。例如,要从索引中检索数据:", - "monaco.esql.autocomplete.greaterThanDoc": "大于", - "monaco.esql.autocomplete.greaterThanOrEqualToDoc": "大于或等于", - "monaco.esql.autocomplete.greatestDoc": "返回许多列中的最大值。", - "monaco.esql.autocomplete.grokDoc": "根据模式从单个字符串输入中提取多个字符串值", - "monaco.esql.autocomplete.inDoc": "测试某表达式接受的值是否包含在其他表达式列表中", - "monaco.esql.autocomplete.isFiniteDoc": "返回指示其输入是否为有限数字的布尔值。", - "monaco.esql.autocomplete.isInfiniteDoc": "返回指示其输入是否无限的布尔值。", - "monaco.esql.autocomplete.keepDoc": "通过在字段中应用 keep 子句重新安排输入表中的字段", - "monaco.esql.autocomplete.leftDoc": "返回从字符串中提取长度字符的子字符串,从左侧开始。", - "monaco.esql.autocomplete.lengthDoc": "返回字符串的字符长度。", - "monaco.esql.autocomplete.lessThanDoc": "小于", - "monaco.esql.autocomplete.lessThanOrEqualToDoc": "小于或等于", - "monaco.esql.autocomplete.likeDoc": "根据字符串模式筛选数据", - "monaco.esql.autocomplete.limitDoc": "根据指定的“限制”按搜索顺序返回第一个搜索结果。", - "monaco.esql.autocomplete.log10Doc": "返回对数底数 10。", - "monaco.esql.autocomplete.ltrimDoc": "从字符串中移除前导空格。", - "monaco.esql.autocomplete.maxDoc": "返回字段中的最大值。", - "monaco.esql.autocomplete.medianDeviationDoc": "返回每个数据点的中位数与整个样例的中位数的偏差。", - "monaco.esql.autocomplete.medianDoc": "返回 50% 百分位数。", - "monaco.esql.autocomplete.minDoc": "返回字段中的最小值。", - "monaco.esql.autocomplete.multiplyDoc": "乘 (*)", - "monaco.esql.autocomplete.mvExpandDoc": "将多值字段扩展成每个值一行,从而复制其他字段", - "monaco.esql.autocomplete.newVarDoc": "定义新变量", - "monaco.esql.autocomplete.noPoliciesLabel": "没有可用策略", - "monaco.esql.autocomplete.noPoliciesLabelsFound": "单击以创建", - "monaco.esql.autocomplete.notEqualToDoc": "不等于", - "monaco.esql.autocomplete.nowDoc": "返回当前日期和时间。", - "monaco.esql.autocomplete.onDoc": "开启", - "monaco.esql.autocomplete.openBracketDoc": "左括号 (", - "monaco.esql.autocomplete.orDoc": "或", - "monaco.esql.autocomplete.percentiletDoc": "返回字段的第 n 个百分位。", - "monaco.esql.autocomplete.pipeDoc": "管道符 (|)", - "monaco.esql.autocomplete.powDoc": "返回提升为幂(第二个参数)的底数(第一个参数)的值。", - "monaco.esql.autocomplete.renameDoc": "将旧列重命名为新列", - "monaco.esql.autocomplete.rightDoc": "返回从字符串中提取长度字符的子字符串,从右侧开始。", - "monaco.esql.autocomplete.rlikeDoc": "根据字符串正则表达式筛选数据", - "monaco.esql.autocomplete.roundDoc": "返回四舍五入到小数(由最近的整数值指定)的数字。默认做法是四舍五入到整数。", - "monaco.esql.autocomplete.rtrimDoc": "从字符串中移除尾随空格。", - "monaco.esql.autocomplete.sinDoc": "正弦三角函数。", - "monaco.esql.autocomplete.sinhDoc": "正弦双曲函数。", - "monaco.esql.autocomplete.sortDoc": "按指定字段对所有结果排序。采用降序时,会将缺少字段的结果视为字段的最小可能值,或者,在采用升序时,会将其视为字段的最大可能值。", - "monaco.esql.autocomplete.sourceDefinition": "输入表", - "monaco.esql.autocomplete.splitDoc": "将单值字符串拆分成多个字符串。", - "monaco.esql.autocomplete.sqrtDoc": "返回数字的平方根。", - "monaco.esql.autocomplete.startsWithDoc": "返回指示关键字字符串是否以另一个字符串开头的布尔值。", - "monaco.esql.autocomplete.statsDoc": "对传入的搜索结果集计算汇总统计信息,如平均值、计数和总和。与 SQL 聚合类似,如果使用不含 BY 子句的 stats 命令,则只返回一行内容,即聚合传入的整个搜索结果集。使用 BY 子句时,将为在 BY 子句中指定的字段中的每个不同值返回一行内容。stats 命令仅返回聚合中的字段,并且您可以将一系列统计函数与 stats 命令搭配在一起使用。执行多个聚合时,请用逗号分隔每个聚合。", - "monaco.esql.autocomplete.substringDoc": "返回字符串的子字符串,用起始位置和可选长度指定。此示例返回每个姓氏的前三个字符。", - "monaco.esql.autocomplete.subtractDoc": "减 (-)", - "monaco.esql.autocomplete.sumDoc": "返回字段中的值的总和。", - "monaco.esql.autocomplete.tanDoc": "正切三角函数。", - "monaco.esql.autocomplete.tanhDoc": "正切双曲函数。", - "monaco.esql.autocomplete.toBooleanDoc": "转换为布尔值。", - "monaco.esql.autocomplete.toDateTimeDoc": "转换为日期。", - "monaco.esql.autocomplete.toDegreesDoc": "转换为度", - "monaco.esql.autocomplete.toDoubleDoc": "转换为双精度值。", - "monaco.esql.autocomplete.toIntegerDoc": "转换为整数。", - "monaco.esql.autocomplete.toIpDoc": "转换为 IP。", - "monaco.esql.autocomplete.toLongDoc": "转换为长整型。", - "monaco.esql.autocomplete.toRadiansDoc": "转换为弧度", - "monaco.esql.autocomplete.toStringDoc": "转换为字符串。", - "monaco.esql.autocomplete.toUnsignedLongDoc": "转换为无符号长整型。", - "monaco.esql.autocomplete.toVersionDoc": "转换为版本。", - "monaco.esql.autocomplete.trimDoc": "从字符串中移除前导和尾随空格。", - "monaco.esql.autocomplete.whereDoc": "使用“predicate-expressions”可筛选搜索结果。进行计算时,谓词表达式将返回 TRUE 或 FALSE。where 命令仅返回计算结果为 TRUE 的结果。例如,筛选特定字段值的结果", - "monaco.esql.autocomplete.withDoc": "具有", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "使用 doc['field_name'] 语法,从脚本中访问字段值", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "发出值,而不返回值。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "检索字段“{fieldName}”的值", @@ -5341,6 +5212,12 @@ "searchApiPanels.welcomeBanner.selectClient.heading": "选择一个", "searchApiPanels.welcomeBanner.selectClient.title": "选择客户端", "searchApiPanels.welcomeBanner.tryInConsoleButton": "在 Console 中试用", + "searchErrors.painlessError.painlessScriptedFieldErrorMessage": "在索引模式 {indexPatternName} 上执行运行时字段或脚本字段时出错", + "searchErrors.errors.fetchError": "检查您的网络连接,然后重试。", + "searchErrors.esError.unknownRootCause": "未知", + "searchErrors.painlessError.buttonTxt": "编辑脚本", + "searchErrors.search.esErrorTitle": "无法检索搜索结果", + "searchErrors.search.httpErrorTitle": "无法连接到 Kibana 服务器", "searchResponseWarnings.badgeButtonLabel": "{warningCount} {warningCount, plural, other {警告}}", "searchResponseWarnings.noResultsTitle": "找不到结果", "securitySolutionPackages.dataTable.eventsTab.unit": "{totalCount, plural, =1 {告警} other {告警}}", @@ -12143,7 +12020,6 @@ "xpack.csp.azureIntegration.armTemplateSetupStep.notSupported": "当前版本的集成不支持 ARM 模板,请将集成升级到最新版本以使用 ARM 模板", "xpack.csp.azureIntegration.armTemplateSetupStep.save": "单击此页面底部右侧的“保存并继续”按钮。", "xpack.csp.azureIntegration.azureNotSupportedMessage": "当前版本的集成不支持 CIS Azure,请将集成升级到最新版本以使用 CIS Azure", - "xpack.csp.azureIntegration.credentialType.manualLabel": "手动", "xpack.csp.azureIntegration.documentationLinkText": "文档", "xpack.csp.azureIntegration.gettingStarted.setupInfoContentLink": "入门指南", "xpack.csp.azureIntegration.setupFormatOptions.manual": "手动", @@ -23613,7 +23489,6 @@ "xpack.maps.inspector.mapDetailsTitle": "地图详情", "xpack.maps.inspector.mapDetailsViewHelpText": "查看地图状态", "xpack.maps.inspector.mapDetailsViewTitle": "地图详情", - "xpack.maps.inspector.vectorTile.layerSelectPrepend": "图层", "xpack.maps.inspector.vectorTile.noRequestsLoggedDescription.mapHasNotLoggedAnyRequestsText": "此地图没有任何矢量磁贴搜索结果。", "xpack.maps.inspector.vectorTile.noRequestsLoggedTitle": "未为矢量磁贴记录任何请求", "xpack.maps.inspector.vectorTile.requestsView": "您正查看矢量磁贴搜索请求。要查看提交到搜索 API 的请求,请将视图设置为“请求”。", @@ -29670,7 +29545,6 @@ "xpack.observabilityAiAssistant.conversationStartTitle": "已开始对话", "xpack.observabilityAiAssistant.couldNotFindConversationTitle": "未找到对话", "xpack.observabilityAiAssistant.emptyConversationTitle": "新对话", - "xpack.observabilityAiAssistant.errorCreatingConversation": "无法创建对话", "xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase": "无法设置知识库", "xpack.observabilityAiAssistant.errorUpdatingConversation": "无法更新对话", "xpack.observabilityAiAssistant.experimentalTitle": "技术预览", diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_edit_rule_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_edit_rule_flyout.tsx index 9ff225c15bf57..2d99e3911a168 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_edit_rule_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_edit_rule_flyout.tsx @@ -6,16 +6,20 @@ */ import React from 'react'; +import { QueryClientProvider } from '@tanstack/react-query'; import { ConnectorProvider } from '../application/context/connector_context'; import { RuleEdit } from '../application/sections/rule_form'; import type { ConnectorServices, RuleEditProps as AlertEditProps } from '../types'; +import { queryClient } from '../application/query_client'; export const getEditRuleFlyoutLazy = ( props: AlertEditProps & { connectorServices: ConnectorServices } ) => { return ( - + + + ); }; diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 7fdd7668135a4..4a5c665911495 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -195,7 +195,6 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) '--xpack.alerting.healthCheck.interval="1s"', '--xpack.alerting.rules.minimumScheduleInterval.value="1s"', '--xpack.alerting.rules.run.alerts.max=20', - '--xpack.observability.unsafe.thresholdRule.enabled=true', `--xpack.alerting.rules.run.actions.connectorTypeOverrides=${JSON.stringify([ { id: 'test.capped', max: '1' }, ])}`, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts index 4c555aba0e2dc..4f23a5ff3a727 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/migrations.ts @@ -15,8 +15,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - // FLAKY: https://github.com/elastic/kibana/issues/169159 - describe.skip('migrations', () => { + describe('migrations', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/actions'); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts index 18f451bbabd9e..b5b2d41e9a404 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts @@ -99,6 +99,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { expect(alertDoc[ALERT_REASON]).to.match(messagePattern); expect(alertDoc['kibana.alert.title']).to.be("rule 'always fire' matched query"); expect(alertDoc['kibana.alert.evaluation.conditions']).to.be('Query matched documents'); + expect(alertDoc['kibana.alert.evaluation.threshold']).to.eql(0); const value = parseInt(alertDoc['kibana.alert.evaluation.value'], 10); expect(value).greaterThan(0); expect(alertDoc[ALERT_URL]).to.contain('/s/space1/app/'); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/rule.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/rule.ts index 10f49d7742dca..948eccc893e18 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/rule.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/rule.ts @@ -169,6 +169,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { expect(alertDoc['kibana.alert.evaluation.conditions']).to.be( 'Number of matching documents is greater than -1' ); + expect(alertDoc['kibana.alert.evaluation.threshold']).to.eql(-1); const value = parseInt(alertDoc['kibana.alert.evaluation.value'], 10); expect(value).greaterThan(0); expect(alertDoc[ALERT_URL]).to.contain('/s/space1/app/'); diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts b/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts index dc140d3cea763..936750f860c48 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts @@ -15,7 +15,8 @@ export default function ({ getService }: FtrProviderContext) { const synthtraceApm = getService('apmSynthtraceEsClient'); const synthtraceInfra = getService('infraSynthtraceEsClient'); - describe('GET /assets', () => { + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172765 + describe.skip('GET /assets', () => { const from = new Date(Date.now() - 1000 * 60 * 2).toISOString(); const to = new Date().toISOString(); diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts b/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts index 9948244e48fe2..d71f7a1c7f951 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts @@ -72,7 +72,7 @@ export default function ({ getService }: FtrProviderContext) { expect(response.body).to.have.property('containers'); expect(response.body.containers.length).to.equal(6); - const ids = response.body.containers.map((result: Asset) => result['asset.id'][0]); + const ids = response.body.containers.map((result: Asset) => result['asset.id']); expect(ids).to.eql([ 'container-id-1', diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts b/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts index ac5d3302c9e4c..8ce5e4dea8592 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts @@ -74,7 +74,7 @@ export default function ({ getService }: FtrProviderContext) { expect(response.body).to.have.property('hosts'); expect(response.body.hosts.length).to.equal(6); - const ids = response.body.hosts.map((result: Asset) => result['asset.id'][0]); + const ids = response.body.hosts.map((result: Asset) => result['asset.id']); expect(ids).to.eql([ 'my-host-1', diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/pods.ts b/x-pack/test/api_integration/apis/asset_manager/tests/pods.ts index eb88049b6511f..e77f10c084d18 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/pods.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/pods.ts @@ -72,7 +72,7 @@ export default function ({ getService }: FtrProviderContext) { expect(response.body).to.have.property('pods'); expect(response.body.pods.length).to.equal(6); - const ids = response.body.pods.map((result: Asset) => result['asset.id'][0]); + const ids = response.body.pods.map((result: Asset) => result['asset.id']); expect(ids).to.eql([ 'pod-uid-1', diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/services.ts b/x-pack/test/api_integration/apis/asset_manager/tests/services.ts index ae92a646b3b2a..608551a20d280 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/services.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/services.ts @@ -17,7 +17,8 @@ export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const synthtrace = getService('apmSynthtraceEsClient'); - describe('GET /assets/services', () => { + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172755 + describe.skip('GET /assets/services', () => { beforeEach(async () => { await synthtrace.clean(); }); diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/benchmark.ts b/x-pack/test/api_integration/apis/cloud_security_posture/benchmark.ts index f8735da12c9e4..ccaa3940258ec 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/benchmark.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/benchmark.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createPackagePolicy } from './helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/get_csp_rule_template.ts b/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts similarity index 90% rename from x-pack/test/api_integration/apis/cloud_security_posture/get_csp_rule_template.ts rename to x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts index 485e36d5ff67e..f3b02be244462 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/get_csp_rule_template.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/find_csp_benchmark_rule.ts @@ -6,8 +6,10 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { GetCspRuleTemplateResponse } from '@kbn/cloud-security-posture-plugin/common/types'; -import { CspRuleTemplate } from '@kbn/cloud-security-posture-plugin/common/schemas'; +import type { + CspBenchmarkRule, + FindCspBenchmarkRuleResponse, +} from '@kbn/cloud-security-posture-plugin/common/types/latest'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createPackagePolicy } from './helper'; @@ -118,7 +120,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set('kbn-xsrf', 'xxxx') @@ -130,7 +132,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); const allRulesHaveCorrectBenchmarkId = body.items.every( - (rule: CspRuleTemplate) => rule.metadata.benchmark.id === 'cis_k8s' + (rule: CspBenchmarkRule) => rule.metadata.benchmark.id === 'cis_k8s' ); expect(allRulesHaveCorrectBenchmarkId).to.eql( @@ -149,7 +151,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set('kbn-xsrf', 'xxxx') @@ -162,7 +164,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); const allowedFields = ['name', 'section', 'id']; - const fieldsMatched = body.items.every((rule: CspRuleTemplate) => { + const fieldsMatched = body.items.every((rule: CspBenchmarkRule) => { const keys = Object.keys(rule.metadata); return ( keys.length === allowedFields.length && keys.every((key) => allowedFields.includes(key)) @@ -182,7 +184,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set('kbn-xsrf', 'xxxx') @@ -196,7 +198,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); // check if the items are sorted by metadata.section field - const sections = body.items.map((rule: CspRuleTemplate) => rule.metadata.section); + const sections = body.items.map((rule: CspBenchmarkRule) => rule.metadata.section); const isSorted = sections.every( (section, index) => index === 0 || section >= sections[index - 1] ); @@ -216,7 +218,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set('kbn-xsrf', 'xxxx') diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts index 434d3fd308974..de9fdfe9952ea 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts @@ -9,7 +9,7 @@ import type { SuperTest, Test } from 'supertest'; import { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { IndexDetails } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { IndexDetails } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { SecurityService } from '../../../../../test/common/services/security/security'; export const deleteIndex = (es: Client, indexToBeDeleted: string[]) => { diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/index.ts b/x-pack/test/api_integration/apis/cloud_security_posture/index.ts index 9ba1111514a8b..c1a64ff01397e 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/index.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/index.ts @@ -17,7 +17,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./status/status_unprivileged')); loadTestFile(require.resolve('./status/status_indexing')); loadTestFile(require.resolve('./benchmark')); - loadTestFile(require.resolve('./get_csp_rule_template')); + loadTestFile(require.resolve('./find_csp_benchmark_rule')); // Place your tests files under this directory and add the following here: // loadTestFile(require.resolve('./your test name')); diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts index 46cd700c7964c..3eda0f6a7b01a 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_index_timeout.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts index 0ba63bd6d436e..6ba3fbe5c31ef 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexed.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts index 216f5aee17627..f55f5533718ed 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_indexing.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts index c991311922758..f67e2d5a0814b 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../helper'; diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts index 06f80adf46034..e80e80c322568 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_unprivileged.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts index dce7e655c0e67..a148f160bfd81 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/status/status_waiting_for_results.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { setupFleetAndAgents } from '../../../../fleet_api_integration/apis/agents/services'; import { generateAgent } from '../../../../fleet_api_integration/helpers'; import { FtrProviderContext } from '../../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts index d67cd7051860c..b82e7a5343746 100644 --- a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts +++ b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts @@ -55,7 +55,7 @@ export default function ({ getService }: FtrProviderContext) { basemaps: {}, joins: { term: { min: 1, max: 1, total: 4, avg: 0.14814814814814814 } }, layerTypes: { - es_docs: { min: 1, max: 2, total: 19, avg: 0.7037037037037037 }, + es_docs: { min: 1, max: 3, total: 20, avg: 0.7407407407407407 }, es_agg_grids: { min: 1, max: 1, total: 6, avg: 0.2222222222222222 }, es_point_to_point: { min: 1, max: 1, total: 1, avg: 0.037037037037037035 }, es_top_hits: { min: 1, max: 1, total: 2, avg: 0.07407407407407407 }, @@ -69,7 +69,7 @@ export default function ({ getService }: FtrProviderContext) { super_fine: { min: 1, max: 1, total: 3, avg: 0.1111111111111111 }, }, scalingOptions: { - limit: { min: 1, max: 2, total: 14, avg: 0.5185185185185185 }, + limit: { min: 1, max: 3, total: 15, avg: 0.5555555555555556 }, clusters: { min: 1, max: 1, total: 1, avg: 0.037037037037037035 }, mvt: { min: 1, max: 1, total: 4, avg: 0.14814814814814814 }, }, @@ -80,8 +80,8 @@ export default function ({ getService }: FtrProviderContext) { min: 0, }, dataSourcesCount: { - avg: 1.1481481481481481, - max: 5, + avg: 1.1851851851851851, + max: 6, min: 1, }, emsVectorLayersCount: { @@ -103,8 +103,8 @@ export default function ({ getService }: FtrProviderContext) { min: 1, }, GEOJSON_VECTOR: { - avg: 0.7777777777777778, - max: 4, + avg: 0.8148148148148148, + max: 5, min: 1, }, HEATMAP: { @@ -124,8 +124,8 @@ export default function ({ getService }: FtrProviderContext) { }, }, layersCount: { - avg: 1.1851851851851851, - max: 6, + avg: 1.2222222222222223, + max: 7, min: 1, }, }, diff --git a/x-pack/test/apm_api_integration/tests/agent_explorer/agent_explorer.spec.ts b/x-pack/test/apm_api_integration/tests/agent_explorer/agent_explorer.spec.ts index 7fea0939d41ee..157c1ef77065c 100644 --- a/x-pack/test/apm_api_integration/tests/agent_explorer/agent_explorer.spec.ts +++ b/x-pack/test/apm_api_integration/tests/agent_explorer/agent_explorer.spec.ts @@ -52,7 +52,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); registry.when('Agent explorer', { config: 'basic', archives: [] }, () => { - describe('when data is loaded', () => { + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172753 + describe.skip('when data is loaded', () => { before(async () => { const serviceOtelJava = apm .service({ diff --git a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts index e7e29c34c6634..bf7d78aaae5dc 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts @@ -25,7 +25,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const logger = getService('log'); const synthtraceEsClient = getService('synthtraceEsClient'); - registry.when( + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172754 + registry.when.skip( 'fetching service anomalies with a trial license', { config: 'trial', archives: [] }, () => { diff --git a/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts index 239cff2e98af5..12a492bda7cf1 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts @@ -33,7 +33,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); const synthtraceEsClient = getService('synthtraceEsClient'); - registry.when('error count threshold alert', { config: 'basic', archives: [] }, () => { + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172764 + registry.when.skip('error count threshold alert', { config: 'basic', archives: [] }, () => { const javaErrorMessage = 'a java error'; const phpErrorMessage = 'a php error'; diff --git a/x-pack/test/apm_api_integration/tests/alerts/preview_chart_error_count.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/preview_chart_error_count.spec.ts index 519440746864d..acc7a406ebe40 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/preview_chart_error_count.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/preview_chart_error_count.spec.ts @@ -68,7 +68,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); - registry.when(`with data loaded`, { config: 'basic', archives: [] }, () => { + // FLAKY: https://github.com/elastic/kibana/issues/172769 + registry.when.skip(`with data loaded`, { config: 'basic', archives: [] }, () => { describe('error_count', () => { before(async () => { await generateErrorData({ serviceName: 'synth-go', start, end, synthtraceEsClient }); diff --git a/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts b/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts index 05d7da0e2ca30..f20ddd3dea311 100644 --- a/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts @@ -87,7 +87,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { } ); - registry.when( + // FAILING VERSION BUMP: https://github.com/elastic/kibana/issues/172766 + registry.when.skip( 'fetching service anomalies with a trial license', { config: 'trial', archives: [] }, () => { diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index 7b4ab43aaaeae..10913f7bdac22 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -26,7 +26,8 @@ function getGlobPattern() { export default function apmApiIntegrationTests({ getService, loadTestFile }: FtrProviderContext) { const registry = getService('registry'); - describe('APM API tests', function () { + // FLAKY: https://github.com/elastic/kibana/issues/172772 + describe.skip('APM API tests', function () { const filePattern = getGlobPattern(); const tests = globby.sync(filePattern, { cwd }); diff --git a/x-pack/test/cloud_security_posture_api/routes/stats.ts b/x-pack/test/cloud_security_posture_api/routes/stats.ts index 92dac0d6b0277..f558a0f6e7137 100644 --- a/x-pack/test/cloud_security_posture_api/routes/stats.ts +++ b/x-pack/test/cloud_security_posture_api/routes/stats.ts @@ -15,7 +15,7 @@ import { ComplianceDashboardData, ComplianceDashboardDataV2, PostureTrend, -} from '@kbn/cloud-security-posture-plugin/common/types'; +} from '@kbn/cloud-security-posture-plugin/common/types_old'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; import { diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings_onboarding.ts b/x-pack/test/cloud_security_posture_functional/pages/findings_onboarding.ts index 59f2f33ba3976..4919e4102df87 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings_onboarding.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings_onboarding.ts @@ -12,7 +12,8 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default ({ getPageObjects }: FtrProviderContext) => { const PageObjects = getPageObjects(['common', 'findings', 'header']); - describe('Findings Page onboarding', function () { + // FLAKY: https://github.com/elastic/kibana/issues/163950 + describe.skip('Findings Page onboarding', function () { this.tags(['cloud_security_posture_findings_onboarding']); let findings: typeof PageObjects.findings; let notInstalledVulnerabilities: typeof findings.notInstalledVulnerabilities; diff --git a/x-pack/test/functional/apps/aiops/log_pattern_analysis.ts b/x-pack/test/functional/apps/aiops/log_pattern_analysis.ts index 6ea8a1d4abc36..2fa19f348dcab 100644 --- a/x-pack/test/functional/apps/aiops/log_pattern_analysis.ts +++ b/x-pack/test/functional/apps/aiops/log_pattern_analysis.ts @@ -23,7 +23,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); } - describe('log pattern analysis', async function () { + // FLAKY: https://github.com/elastic/kibana/issues/172739 + describe.skip('log pattern analysis', async function () { let tabsCount = 1; afterEach(async () => { diff --git a/x-pack/test/functional/apps/aiops/log_pattern_analysis_in_discover.ts b/x-pack/test/functional/apps/aiops/log_pattern_analysis_in_discover.ts index 403bbe6382f6c..8d089155aa8b6 100644 --- a/x-pack/test/functional/apps/aiops/log_pattern_analysis_in_discover.ts +++ b/x-pack/test/functional/apps/aiops/log_pattern_analysis_in_discover.ts @@ -23,7 +23,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); } - describe('log pattern analysis', async function () { + // FLAKY: https://github.com/elastic/kibana/issues/172770 + describe.skip('log pattern analysis', async function () { let tabsCount = 1; afterEach(async () => { diff --git a/x-pack/test/functional/apps/maps/group4/layer_errors.js b/x-pack/test/functional/apps/maps/group4/layer_errors.js index b3d20b9509d1e..e597f1bb0fe52 100644 --- a/x-pack/test/functional/apps/maps/group4/layer_errors.js +++ b/x-pack/test/functional/apps/maps/group4/layer_errors.js @@ -7,14 +7,37 @@ import expect from '@kbn/expect'; -export default function ({ getPageObjects }) { +export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps', 'header']); + const inspector = getService('inspector'); + const testSubjects = getService('testSubjects'); describe('layer errors', () => { before(async () => { await PageObjects.maps.loadSavedMap('layer with errors'); }); + describe('Layer with EsError', () => { + after(async () => { + await inspector.close(); + }); + + it('should diplay error icon in legend', async () => { + await PageObjects.maps.hasErrorIconExistsOrFail('connections'); + }); + + it('should display "View details" button', async () => { + await testSubjects.existOrFail('viewEsErrorButton'); + }); + + it('should open request in inspector', async () => { + await testSubjects.click('viewEsErrorButton'); + + const selectedRequest = await testSubjects.getVisibleText('euiComboBoxPill'); + expect(selectedRequest).to.equal('load layer features (connections)'); + }); + }); + describe('ESSearchSource with missing index pattern id', () => { const LAYER_NAME = 'idThatDoesNotExitForESSearchSource'; diff --git a/x-pack/test/functional/apps/painless_lab/config.ts b/x-pack/test/functional/apps/painless_lab/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/painless_lab/config.ts @@ -0,0 +1,17 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/painless_lab/index.ts b/x-pack/test/functional/apps/painless_lab/index.ts new file mode 100644 index 0000000000000..70aca9309243e --- /dev/null +++ b/x-pack/test/functional/apps/painless_lab/index.ts @@ -0,0 +1,14 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ loadTestFile }: FtrProviderContext) => { + describe('Painless lab app', function () { + loadTestFile(require.resolve('./painless_lab')); + }); +}; diff --git a/x-pack/test/functional/apps/painless_lab/painless_lab.ts b/x-pack/test/functional/apps/painless_lab/painless_lab.ts new file mode 100644 index 0000000000000..015263d6edec5 --- /dev/null +++ b/x-pack/test/functional/apps/painless_lab/painless_lab.ts @@ -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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const TEST_SCRIPT_RESULT = 45; +const TEST_SCRIPT = ` +int total = 0; + +for (int i = 0; i < 10; ++i) { + total += i; +} + +return total; +`.trim(); + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + const testSubjects = getService('testSubjects'); + const monacoEditor = getService('monacoEditor'); + + describe('Painless lab', function describeIndexTests() { + before(async () => { + await PageObjects.common.navigateToApp('dev_tools', { hash: '/painless_lab' }); + await retry.waitFor('Wait for editor to be visible', async () => { + return testSubjects.isDisplayed('painless_lab'); + }); + }); + + it('should show the editor and preview panels', async () => { + const editor = await testSubjects.find('kibanaCodeEditor'); + const preview = await testSubjects.find('painlessTabs'); + + expect(await editor.isDisplayed()).to.be(true); + expect(await preview.isDisplayed()).to.be(true); + }); + + it('executes the script and shows the right result', async () => { + await monacoEditor.setCodeEditorValue(TEST_SCRIPT); + + await retry.try(async () => { + const result = await testSubjects.find('painlessTabs'); + expect(await result.getVisibleText()).to.contain(TEST_SCRIPT_RESULT.toString()); + }); + }); + }); +} diff --git a/x-pack/test/functional/fixtures/kbn_archiver/maps.json b/x-pack/test/functional/fixtures/kbn_archiver/maps.json index 318cb3c445186..832edf4cb705b 100644 --- a/x-pack/test/functional/fixtures/kbn_archiver/maps.json +++ b/x-pack/test/functional/fixtures/kbn_archiver/maps.json @@ -737,42 +737,51 @@ } { + "id": "745c98b0-23e1-11e9-a048-6fef5a3e0d1e", + "type": "map", + "namespaces": [ + "default" + ], + "updated_at": "2023-11-29T18:49:52.695Z", + "created_at": "2023-11-29T18:47:39.446Z", + "version": "WzU1LDFd", "attributes": { "description": "", - "layerListJSON": "[{\"sourceDescriptor\":{\"type\":\"KIBANA_TILEMAP\"},\"id\":\"ap0ys\",\"label\":\"Custom_TMS\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"idThatDoesNotExitForEMSTile\"},\"temporary\":false,\"id\":\"plw9l\",\"label\":\"EMS_tiles\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"VECTOR_TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"idThatDoesNotExitForEMSFileSource\"},\"temporary\":false,\"id\":\"2gro0\",\"label\":\"EMS_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"f67fe707-95dd-46d6-89b8-82617b251b61\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"resolution\":\"COARSE\",\"indexPatternRefName\":\"layer_4_source_index_pattern\",\"applyGlobalQuery\":true},\"temporary\":false,\"id\":\"pl5qd\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"sourceDescriptor\":{\"id\":\"a07072bb-3a92-4320-bd37-250ef6d04db7\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[],\"indexPatternRefName\":\"layer_5_source_index_pattern\",\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\"},\"temporary\":false,\"id\":\"9bw8h\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[],\"indexPatternRefName\":\"layer_6_source_index_pattern\",\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"origin\":\"join\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"indexPatternRefName\":\"layer_6_join_0_index_pattern\",\"applyGlobalQuery\":true,\"type\":\"ES_TERM_SOURCE\"}}]}]", - "mapStateJSON": "{\"zoom\":0.71,\"center\":{\"lon\":0.10268,\"lat\":0},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"settings\":{\"autoFitToDataBounds\":false}}", + "layerListJSON": "[{\"sourceDescriptor\":{\"type\":\"KIBANA_TILEMAP\"},\"id\":\"ap0ys\",\"label\":\"Custom_TMS\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"RASTER_TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"idThatDoesNotExitForEMSTile\",\"lightModeDefault\":\"road_map\"},\"temporary\":false,\"id\":\"plw9l\",\"label\":\"EMS_tiles\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\",\"properties\":{},\"previousStyle\":null},\"type\":\"EMS_VECTOR_TILE\"},{\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"idThatDoesNotExitForEMSFileSource\"},\"temporary\":false,\"id\":\"2gro0\",\"label\":\"EMS_vector_shapes\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"GEOJSON_VECTOR\"},{\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"id\":\"f67fe707-95dd-46d6-89b8-82617b251b61\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"resolution\":\"COARSE\",\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_3_source_index_pattern\"},\"temporary\":false,\"id\":\"pl5qd\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"GEOJSON_VECTOR\"},{\"sourceDescriptor\":{\"id\":\"a07072bb-3a92-4320-bd37-250ef6d04db7\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[],\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\",\"indexPatternRefName\":\"layer_4_source_index_pattern\"},\"temporary\":false,\"id\":\"9bw8h\",\"label\":\"\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"previousStyle\":null},\"type\":\"GEOJSON_VECTOR\"},{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[],\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\",\"indexPatternRefName\":\"layer_5_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"origin\":\"join\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"applyGlobalQuery\":true,\"type\":\"ES_TERM_SOURCE\",\"indexPatternRefName\":\"layer_5_join_0_index_pattern\"}}]},{\"sourceDescriptor\":{\"geoField\":\"destination\",\"scalingType\":\"LIMIT\",\"id\":\"ed01aac3-c0be-491e-98c9-f1cb6e37f185\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"applyForceRefresh\":true,\"filterByMapBounds\":true,\"tooltipProperties\":[],\"sortField\":\"\",\"sortOrder\":\"desc\",\"topHitsGroupByTimeseries\":false,\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"indexPatternRefName\":\"layer_6_source_index_pattern\"},\"id\":\"1cfaa7fa-dc73-419d-b362-7238e2270a1c\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#54B399\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#41937c\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":0}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelZoomRange\":{\"options\":{\"useLayerZoomRange\":true,\"minZoom\":0,\"maxZoom\":24}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}},\"labelPosition\":{\"options\":{\"position\":\"CENTER\"}}},\"isTimeAware\":true},\"includeInFitToBounds\":true,\"type\":\"GEOJSON_VECTOR\",\"joins\":[],\"disableTooltips\":false}]", + "mapStateJSON": "{\"adHocDataViews\":[],\"zoom\":3.38,\"center\":{\"lon\":76.34937,\"lat\":-77.25604},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"561253e0-f731-11e8-8487-11b9dd924f96\",\"type\":\"custom\",\"disabled\":false,\"negate\":false,\"alias\":\"connections shard failure\",\"key\":\"query\",\"value\":\"{\\\"error_query\\\":{\\\"indices\\\":[{\\\"error_type\\\":\\\"exception\\\",\\\"message\\\":\\\"simulated shard failure\\\",\\\"name\\\":\\\"connections\\\"}]}}\"},\"$state\":{\"store\":\"appState\"},\"query\":{\"error_query\":{\"indices\":[{\"error_type\":\"exception\",\"message\":\"simulated shard failure\",\"name\":\"connections\"}]}}}],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"customIcons\":[],\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"keydownScrollZoom\":false,\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"showTimesliderToggleButton\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}", "title": "layer with errors", - "uiStateJSON": "{}" - }, - "coreMigrationVersion": "8.0.0", - "id": "745c98b0-23e1-11e9-a048-6fef5a3e0d1e", - "migrationVersion": { - "map": "7.14.0" + "uiStateJSON": "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[\"1cfaa7fa-dc73-419d-b362-7238e2270a1c\"]}" }, "references": [ { - "id": "idThatDoesNotExitForESGeoGridSource", + "name": "layer_3_source_index_pattern", + "type": "index-pattern", + "id": "idThatDoesNotExitForESGeoGridSource" + }, + { "name": "layer_4_source_index_pattern", - "type": "index-pattern" + "type": "index-pattern", + "id": "idThatDoesNotExitForESSearchSource" }, { - "id": "idThatDoesNotExitForESSearchSource", "name": "layer_5_source_index_pattern", - "type": "index-pattern" + "type": "index-pattern", + "id": "561253e0-f731-11e8-8487-11b9dd924f96" }, { - "id": "561253e0-f731-11e8-8487-11b9dd924f96", - "name": "layer_6_source_index_pattern", - "type": "index-pattern" + "name": "layer_5_join_0_index_pattern", + "type": "index-pattern", + "id": "idThatDoesNotExitForESJoinSource" }, { - "id": "idThatDoesNotExitForESJoinSource", - "name": "layer_6_join_0_index_pattern", - "type": "index-pattern" + "name": "layer_6_source_index_pattern", + "type": "index-pattern", + "id": "dedd3180-c8d8-11e9-b36c-81f9f9da524f" } ], - "type": "map", - "version": "WzU4LDJd" + "managed": false, + "coreMigrationVersion": "8.8.0", + "typeMigrationVersion": "8.4.0" } { diff --git a/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts b/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts new file mode 100644 index 0000000000000..51beb1b3671a5 --- /dev/null +++ b/x-pack/test/observability_ai_assistant_api_integration/common/create_llm_proxy.ts @@ -0,0 +1,147 @@ +/* + * 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 getPort from 'get-port'; +import http, { type Server } from 'http'; +import { once, pull } from 'lodash'; +import { createOpenAiChunk } from './create_openai_chunk'; + +type Request = http.IncomingMessage; +type Response = http.ServerResponse & { req: http.IncomingMessage }; + +type RequestHandler = (request: Request, response: Response) => void; + +interface RequestInterceptor { + name: string; + when: (body: string) => boolean; +} + +export interface LlmResponseSimulator { + status: (code: number) => Promise; + next: ( + msg: + | string + | { + content?: string; + function_call?: { name: string; arguments: string }; + } + ) => Promise; + error: (error: Error) => Promise; + complete: () => Promise; + write: (chunk: string) => Promise; +} + +export class LlmProxy { + server: Server; + + interceptors: Array = []; + + constructor(private readonly port: number) { + this.server = http + .createServer(async (request, response) => { + const interceptors = this.interceptors.concat(); + + const body = await new Promise((resolve, reject) => { + let concatenated = ''; + request.on('data', (chunk) => { + concatenated += chunk.toString(); + }); + request.on('close', () => { + resolve(concatenated); + }); + }); + + while (interceptors.length) { + const interceptor = interceptors.shift()!; + if (interceptor.when(body)) { + pull(this.interceptors, interceptor); + interceptor.handle(request, response); + return; + } + } + + throw new Error('No interceptors found to handle request'); + }) + .listen(port); + } + + getPort() { + return this.port; + } + + clear() { + this.interceptors.length = 0; + } + + close() { + this.server.close(); + } + + intercept( + name: string, + when: RequestInterceptor['when'] + ): { + waitForIntercept: () => Promise; + } { + const waitForInterceptPromise = Promise.race([ + new Promise((outerResolve, outerReject) => { + this.interceptors.push({ + name, + when, + handle: (request, response) => { + function write(chunk: string) { + return new Promise((resolve) => response.write(chunk, () => resolve())); + } + function end() { + return new Promise((resolve) => response.end(resolve)); + } + + const simulator: LlmResponseSimulator = { + status: once(async (status: number) => { + response.writeHead(status, { + 'Content-Type': 'text/event-stream', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + }); + }), + next: (msg) => { + const chunk = createOpenAiChunk(msg); + return write(`data: ${JSON.stringify(chunk)}\n`); + }, + write: (chunk: string) => { + return write(chunk); + }, + complete: async () => { + await write('data: [DONE]'); + await end(); + }, + error: async (error) => { + await write(`data: ${JSON.stringify({ error })}`); + await end(); + }, + }; + + outerResolve(simulator); + }, + }); + }), + new Promise((_, reject) => { + setTimeout(() => reject(new Error('Operation timed out')), 5000); + }), + ]); + + return { + waitForIntercept: () => waitForInterceptPromise, + }; + } +} + +export async function createLlmProxy() { + const port = await getPort({ port: getPort.makeRange(9000, 9100) }); + + return new LlmProxy(port); +} diff --git a/x-pack/test/observability_ai_assistant_api_integration/common/create_openai_chunk.ts b/x-pack/test/observability_ai_assistant_api_integration/common/create_openai_chunk.ts new file mode 100644 index 0000000000000..7e39a7d73ce8b --- /dev/null +++ b/x-pack/test/observability_ai_assistant_api_integration/common/create_openai_chunk.ts @@ -0,0 +1,27 @@ +/* + * 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 { CreateChatCompletionResponseChunk } from '@kbn/observability-ai-assistant-plugin/common/types'; +import { v4 } from 'uuid'; + +export function createOpenAiChunk( + msg: string | { content?: string; function_call?: { name: string; arguments?: string } } +): CreateChatCompletionResponseChunk { + msg = typeof msg === 'string' ? { content: msg } : msg; + + return { + id: v4(), + object: 'chat.completion.chunk', + created: 0, + model: 'gpt-4', + choices: [ + { + delta: msg, + }, + ], + }; +} diff --git a/x-pack/test/observability_ai_assistant_api_integration/tests/complete/complete.spec.ts b/x-pack/test/observability_ai_assistant_api_integration/tests/complete/complete.spec.ts new file mode 100644 index 0000000000000..6601dbc213ab4 --- /dev/null +++ b/x-pack/test/observability_ai_assistant_api_integration/tests/complete/complete.spec.ts @@ -0,0 +1,256 @@ +/* + * 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 { Response } from 'supertest'; +import { MessageRole, type Message } from '@kbn/observability-ai-assistant-plugin/common'; +import { omit } from 'lodash'; +import { PassThrough } from 'stream'; +import expect from '@kbn/expect'; +import { + ConversationCreateEvent, + StreamingChatResponseEvent, + StreamingChatResponseEventType, +} from '@kbn/observability-ai-assistant-plugin/common/conversation_complete'; +import { CreateChatCompletionRequest } from 'openai'; +import { createLlmProxy, LlmProxy } from '../../common/create_llm_proxy'; +import { createOpenAiChunk } from '../../common/create_openai_chunk'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient'); + + const COMPLETE_API_URL = `/internal/observability_ai_assistant/chat/complete`; + + const messages: Message[] = [ + { + '@timestamp': new Date().toISOString(), + message: { + role: MessageRole.System, + content: 'You are a helpful assistant', + }, + }, + { + '@timestamp': new Date().toISOString(), + message: { + role: MessageRole.User, + content: 'Good morning!', + }, + }, + ]; + + describe('Complete', () => { + let proxy: LlmProxy; + let connectorId: string; + + before(async () => { + proxy = await createLlmProxy(); + + const response = await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'OpenAI', + connector_type_id: '.gen-ai', + config: { + apiProvider: 'OpenAI', + apiUrl: `http://localhost:${proxy.getPort()}`, + }, + secrets: { + apiKey: 'my-api-key', + }, + }) + .expect(200); + + connectorId = response.body.id; + }); + + after(async () => { + await supertest + .delete(`/api/actions/connector/${connectorId}`) + .set('kbn-xsrf', 'foo') + .expect(204); + + proxy.close(); + }); + + it('returns a streaming response from the server', async () => { + const interceptor = proxy.intercept('conversation', () => true); + + const receivedChunks: any[] = []; + + const passThrough = new PassThrough(); + + supertest + .post(COMPLETE_API_URL) + .set('kbn-xsrf', 'foo') + .send({ + messages, + connectorId, + persist: false, + }) + .pipe(passThrough); + + passThrough.on('data', (chunk) => { + receivedChunks.push(chunk.toString()); + }); + + const simulator = await interceptor.waitForIntercept(); + + await simulator.status(200); + const chunk = JSON.stringify(createOpenAiChunk('Hello')); + + await simulator.write(`data: ${chunk.substring(0, 10)}`); + await simulator.write(`${chunk.substring(10)}\n`); + await simulator.complete(); + + await new Promise((resolve) => passThrough.on('end', () => resolve())); + + const parsedChunks = receivedChunks + .join('') + .split('\n') + .map((line) => line.trim()) + .filter(Boolean) + .map((line) => JSON.parse(line) as StreamingChatResponseEvent); + + expect(parsedChunks.length).to.be(2); + expect(omit(parsedChunks[0], 'id')).to.eql({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + message: { + content: 'Hello', + }, + }); + + expect(omit(parsedChunks[1], 'id', 'message.@timestamp')).to.eql({ + type: StreamingChatResponseEventType.MessageAdd, + message: { + message: { + content: 'Hello', + role: MessageRole.Assistant, + function_call: { + name: '', + arguments: '', + trigger: MessageRole.Assistant, + }, + }, + }, + }); + }); + + describe('when creating a new conversation', async () => { + let lines: StreamingChatResponseEvent[]; + before(async () => { + const titleInterceptor = proxy.intercept( + 'title', + (body) => (JSON.parse(body) as CreateChatCompletionRequest).messages.length === 1 + ); + + const conversationInterceptor = proxy.intercept( + 'conversation', + (body) => (JSON.parse(body) as CreateChatCompletionRequest).messages.length !== 1 + ); + + const responsePromise = new Promise((resolve, reject) => { + supertest + .post(COMPLETE_API_URL) + .set('kbn-xsrf', 'foo') + .send({ + messages, + connectorId, + persist: true, + }) + .end((err, response) => { + if (err) { + return reject(err); + } + return resolve(response); + }); + }); + + const [conversationSimulator, titleSimulator] = await Promise.all([ + conversationInterceptor.waitForIntercept(), + titleInterceptor.waitForIntercept(), + ]); + + await titleSimulator.status(200); + await titleSimulator.next('My generated title'); + await titleSimulator.complete(); + + await conversationSimulator.status(200); + await conversationSimulator.next('Hello'); + await conversationSimulator.next(' again'); + await conversationSimulator.complete(); + + const response = await responsePromise; + + lines = String(response.body) + .split('\n') + .map((line) => line.trim()) + .filter(Boolean) + .map((line) => JSON.parse(line) as StreamingChatResponseEvent); + }); + + it('creates a new conversation', async () => { + expect(omit(lines[0], 'id')).to.eql({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + message: { + content: 'Hello', + }, + }); + expect(omit(lines[1], 'id')).to.eql({ + type: StreamingChatResponseEventType.ChatCompletionChunk, + message: { + content: ' again', + }, + }); + expect(omit(lines[2], 'id', 'message.@timestamp')).to.eql({ + type: StreamingChatResponseEventType.MessageAdd, + message: { + message: { + content: 'Hello again', + function_call: { + arguments: '', + name: '', + trigger: MessageRole.Assistant, + }, + role: MessageRole.Assistant, + }, + }, + }); + expect(omit(lines[3], 'conversation.id', 'conversation.last_updated')).to.eql({ + type: StreamingChatResponseEventType.ConversationCreate, + conversation: { + title: 'My generated title', + }, + }); + }); + + after(async () => { + const createdConversationId = lines.filter( + (line): line is ConversationCreateEvent => + line.type === StreamingChatResponseEventType.ConversationCreate + )[0]?.conversation.id; + + await observabilityAIAssistantAPIClient + .writeUser({ + endpoint: 'DELETE /internal/observability_ai_assistant/conversation/{conversationId}', + params: { + path: { + conversationId: createdConversationId, + }, + }, + }) + .expect(200); + }); + }); + + // todo + it.skip('updates an existing conversation', async () => {}); + + // todo + it.skip('executes a function', async () => {}); + }); +} diff --git a/x-pack/test/observability_ai_assistant_api_integration/tests/functions/elasticsearch.spec.ts b/x-pack/test/observability_ai_assistant_api_integration/tests/functions/elasticsearch.spec.ts deleted file mode 100644 index 919085369cc70..0000000000000 --- a/x-pack/test/observability_ai_assistant_api_integration/tests/functions/elasticsearch.spec.ts +++ /dev/null @@ -1,46 +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 expect from '@kbn/expect'; -import type { FtrProviderContext } from '../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient'); - - describe('Functions: elasticsearch', () => { - it('executes a search request', async () => { - const response = await observabilityAIAssistantAPIClient - .readUser({ - endpoint: 'POST /internal/observability_ai_assistant/functions/elasticsearch', - params: { - body: { - method: 'GET', - path: '_all/_search', - body: { - query: { - bool: { - filter: [ - { - term: { - matches_no_docs: 'true', - }, - }, - ], - }, - }, - track_total_hits: false, - }, - }, - }, - }) - .expect(200); - - expect((response.body as any).hits.hits).to.eql([]); - expect((response.body as any).hits.total).to.eql(undefined); - }); - }); -} diff --git a/x-pack/test/reporting_functional/reporting_and_deprecated_security/security_roles_privileges.ts b/x-pack/test/reporting_functional/reporting_and_deprecated_security/security_roles_privileges.ts index f9b84469c1eee..acd8b0da9e4c5 100644 --- a/x-pack/test/reporting_functional/reporting_and_deprecated_security/security_roles_privileges.ts +++ b/x-pack/test/reporting_functional/reporting_and_deprecated_security/security_roles_privileges.ts @@ -16,7 +16,8 @@ const CANVAS_TITLE = 'The Very Cool Workpad for PDF Tests'; export default function ({ getService }: FtrProviderContext) { const reportingFunctional = getService('reportingFunctional'); - describe('Security with `reporting_user` built-in role', () => { + // FLAKY: https://github.com/elastic/kibana/issues/172599 + describe.skip('Security with `reporting_user` built-in role', () => { before(async () => { await reportingFunctional.initEcommerce(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/esql_rule_ess.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/esql_rule_ess.cy.ts index 33cdeb5403120..dc52a7269faf1 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/esql_rule_ess.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/esql_rule_ess.cy.ts @@ -86,8 +86,7 @@ describe('Detection ES|QL rules, creation', { tags: ['@ess'] }, () => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/172074 - describe.skip('ES|QL query validation', () => { + describe('ES|QL query validation', () => { beforeEach(() => { login(); visit(CREATE_RULE_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_analyzer_graph_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_analyzer_graph_tab.cy.ts index 3868625e9b339..0ea48827b6fe7 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_analyzer_graph_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_analyzer_graph_tab.cy.ts @@ -14,6 +14,7 @@ import { openGraphAnalyzerTab } from '../../../../tasks/expandable_flyout/alert_ import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../tasks/expandable_flyout/alert_details_right_panel'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; import { ANALYZER_NODE } from '../../../../screens/alerts'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -27,6 +28,7 @@ describe.skip( { tags: ['@ess', '@brokenInServerless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_correlations_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_correlations_tab.cy.ts index a5ac102c11c9c..9fb3b9a763a95 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_correlations_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_correlations_tab.cy.ts @@ -29,87 +29,81 @@ import { expandFirstAlertExpandableFlyout, } from '../../../../tasks/expandable_flyout/common'; import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { ALERTS_URL } from '../../../../urls/navigation'; -// FLAKY: https://github.com/elastic/kibana/issues/170822 -describe.skip( - 'Expandable flyout left panel correlations', - { tags: ['@ess', '@serverless'] }, - () => { - beforeEach(() => { - login(); - createRule(getNewRule()); - visit(ALERTS_URL); - waitForAlertsToPopulate(); - expandFirstAlertExpandableFlyout(); - expandDocumentDetailsExpandableFlyoutLeftSection(); - createNewCaseFromExpandableFlyout(); - openInsightsTab(); - openCorrelationsTab(); - }); +describe('Expandable flyout left panel correlations', { tags: ['@ess', '@serverless'] }, () => { + beforeEach(() => { + deleteAlertsAndRules(); + login(); + createRule(getNewRule()); + visit(ALERTS_URL); + waitForAlertsToPopulate(); + expandFirstAlertExpandableFlyout(); + expandDocumentDetailsExpandableFlyoutLeftSection(); + createNewCaseFromExpandableFlyout(); + openInsightsTab(); + openCorrelationsTab(); + }); - it('should render correlations details correctly', () => { - cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB) - .should('have.text', 'Insights') - .and('have.class', 'euiTab-isSelected'); + it('should render correlations details correctly', () => { + cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB) + .should('have.text', 'Insights') + .and('have.class', 'euiTab-isSelected'); - cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_CORRELATIONS_BUTTON) - .should('have.text', 'Correlations') - .and('have.class', 'euiButtonGroupButton-isSelected'); + cy.get(DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_CORRELATIONS_BUTTON) + .should('have.text', 'Correlations') + .and('have.class', 'euiButtonGroupButton-isSelected'); - // cy.log('suppressed alerts'); + // cy.log('suppressed alerts'); - // TODO get proper data to test suppressed alerts - // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_TITLE).scrollIntoView(); - // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_TITLE) - // .should('be.visible') - // .and('contain.text', '1 suppressed alert'); - // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_INVESTIGATE_IN_TIMELINE_BUTTON).should('be.visible'); + // TODO get proper data to test suppressed alerts + // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_TITLE).scrollIntoView(); + // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_TITLE) + // .should('be.visible') + // .and('contain.text', '1 suppressed alert'); + // cy.get(CORRELATIONS_SUPPRESSED_ALERTS_INVESTIGATE_IN_TIMELINE_BUTTON).should('be.visible'); - cy.log('related cases'); + cy.log('related cases'); - cy.get(CORRELATIONS_CASES_SECTION_TITLE).should('contain.text', '1 related case'); - cy.get(CORRELATIONS_CASES_SECTION_TABLE) - .should('contain.text', 'case') - .and('contain.text', 'open'); + cy.get(CORRELATIONS_CASES_SECTION_TITLE).should('contain.text', '1 related case'); + cy.get(CORRELATIONS_CASES_SECTION_TABLE) + .should('contain.text', 'case') + .and('contain.text', 'open'); - cy.log('related alerts by source event'); + cy.log('related alerts by source event'); - cy.get(CORRELATIONS_SOURCE_SECTION_TITLE).should( - 'contain.text', - '1 alert related by source event' - ); - cy.get(CORRELATIONS_SOURCE_SECTION_TABLE).should('exist'); - cy.get(CORRELATIONS_SOURCE_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( - 'contain.text', - 'Investigate in timeline' - ); + cy.get(CORRELATIONS_SOURCE_SECTION_TITLE).should( + 'contain.text', + '1 alert related by source event' + ); + cy.get(CORRELATIONS_SOURCE_SECTION_TABLE).should('exist'); + cy.get(CORRELATIONS_SOURCE_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( + 'contain.text', + 'Investigate in timeline' + ); - cy.log('related alerts by session'); + cy.log('related alerts by session'); - cy.get(CORRELATIONS_SESSION_SECTION_TITLE).should( - 'contain.text', - '1 alert related by session' - ); - cy.get(CORRELATIONS_SESSION_SECTION_TABLE).should('exist'); - cy.get(CORRELATIONS_SESSION_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( - 'contain.text', - 'Investigate in timeline' - ); + cy.get(CORRELATIONS_SESSION_SECTION_TITLE).should('contain.text', '1 alert related by session'); + cy.get(CORRELATIONS_SESSION_SECTION_TABLE).should('exist'); + cy.get(CORRELATIONS_SESSION_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( + 'contain.text', + 'Investigate in timeline' + ); - cy.log('related alerts by ancestry'); + cy.log('related alerts by ancestry'); - cy.get(CORRELATIONS_ANCESTRY_SECTION_TITLE).should( - 'contain.text', - '1 alert related by ancestry' - ); - cy.get(CORRELATIONS_ANCESTRY_SECTION_TABLE).should('exist'); - cy.get(CORRELATIONS_ANCESTRY_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( - 'contain.text', - 'Investigate in timeline' - ); - }); - } -); + cy.get(CORRELATIONS_ANCESTRY_SECTION_TITLE).should( + 'contain.text', + '1 alert related by ancestry' + ); + cy.get(CORRELATIONS_ANCESTRY_SECTION_TABLE).should('exist'); + cy.get(CORRELATIONS_ANCESTRY_SECTION_INVESTIGATE_IN_TIMELINE_BUTTON).should( + 'contain.text', + 'Investigate in timeline' + ); + }); +}); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_entities_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_entities_tab.cy.ts index 567a60752398c..a22ee1284e46d 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_entities_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_entities_tab.cy.ts @@ -19,6 +19,7 @@ import { openEntitiesTab } from '../../../../tasks/expandable_flyout/alert_detai import { openInsightsTab } from '../../../../tasks/expandable_flyout/alert_details_left_panel'; import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../tasks/expandable_flyout/alert_details_right_panel'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -31,6 +32,7 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_investigation_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_investigation_tab.cy.ts index c4e4cf5535352..43a2d14fe4f17 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_investigation_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_investigation_tab.cy.ts @@ -12,6 +12,7 @@ import { import { openInvestigationTab } from '../../../../tasks/expandable_flyout/alert_details_left_panel_investigation_tab'; import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../tasks/expandable_flyout/alert_details_right_panel'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -24,6 +25,7 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts index f862bb8ea6127..998793f5be776 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_prevalence_tab.cy.ts @@ -20,6 +20,7 @@ import { DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_PREVALENCE_TABLE_USER_PREVALENCE_CELL, DOCUMENT_DETAILS_FLYOUT_INSIGHTS_TAB_PREVALENCE_DATE_PICKER, } from '../../../../screens/expandable_flyout/alert_details_left_panel_prevalence_tab'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -27,12 +28,12 @@ import { getNewRule } from '../../../../objects/rule'; import { ALERTS_URL } from '../../../../urls/navigation'; import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule'; -// FLAKY: https://github.com/elastic/kibana/issues/170751 -describe.skip( +describe( 'Alert details expandable flyout left panel prevalence', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule({ ...getNewRule(), investigation_fields: { field_names: ['host.os.name'] } }); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_response_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_response_tab.cy.ts index e4c2baba4e87e..0517e86ac9359 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_response_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_response_tab.cy.ts @@ -12,6 +12,7 @@ import { import { openResponseTab } from '../../../../tasks/expandable_flyout/alert_details_left_panel_response_tab'; import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../tasks/expandable_flyout/alert_details_right_panel'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -25,6 +26,7 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_session_view_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_session_view_tab.cy.ts index 0c37aa9b835bb..d6f8965df95cc 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_session_view_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_session_view_tab.cy.ts @@ -9,6 +9,7 @@ import { DOCUMENT_DETAILS_FLYOUT_VISUALIZE_TAB_SESSION_VIEW_BUTTON } from '../.. import { DOCUMENT_DETAILS_FLYOUT_VISUALIZE_TAB } from '../../../../screens/expandable_flyout/alert_details_left_panel'; import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../tasks/expandable_flyout/alert_details_right_panel'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -22,6 +23,7 @@ describe.skip( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_threat_intelligence_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_threat_intelligence_tab.cy.ts index 17080cbd32ae8..6ba280581b9bd 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_threat_intelligence_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_left_panel_threat_intelligence_tab.cy.ts @@ -11,6 +11,7 @@ import { expandDocumentDetailsExpandableFlyoutLeftSection } from '../../../../ta import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; import { INDICATOR_MATCH_ENRICHMENT_SECTION } from '../../../../screens/alerts_details'; import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { ALERTS_URL } from '../../../../urls/navigation'; @@ -24,6 +25,7 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_alert_reason_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_alert_reason_preview.cy.ts index 89596877fb3e8..39dc469507977 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_alert_reason_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_alert_reason_preview.cy.ts @@ -8,6 +8,7 @@ import { DOCUMENT_DETAILS_FLYOUT_ALERT_REASON_PREVIEW_CONTAINER } from '../../../../screens/expandable_flyout/alert_details_preview_panel_alert_reason_preview'; import { expandFirstAlertExpandableFlyout } from '../../../../tasks/expandable_flyout/common'; import { clickAlertReasonButton } from '../../../../tasks/expandable_flyout/alert_details_right_panel_overview_tab'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -22,6 +23,7 @@ describe( const rule = getNewRule(); beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(rule); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_rule_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_rule_preview.cy.ts index 82ce990292901..eab7f9508e343 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_rule_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_preview_panel_rule_preview.cy.ts @@ -25,6 +25,7 @@ import { toggleRulePreviewScheduleSection, } from '../../../../tasks/expandable_flyout/alert_details_preview_panel_rule_preview'; import { clickRuleSummaryButton } from '../../../../tasks/expandable_flyout/alert_details_right_panel_overview_tab'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -39,6 +40,7 @@ describe( const rule = getNewRule(); beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(rule); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_json_tab.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_json_tab.cy.ts index f41dba6dd1006..bb6a72707772c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_json_tab.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel_json_tab.cy.ts @@ -11,6 +11,7 @@ import { DOCUMENT_DETAILS_FLYOUT_JSON_TAB_CONTENT, DOCUMENT_DETAILS_FLYOUT_JSON_TAB_COPY_TO_CLIPBOARD_BUTTON, } from '../../../../screens/expandable_flyout/alert_details_right_panel_json_tab'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { createRule } from '../../../../tasks/api_calls/rules'; @@ -23,6 +24,7 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + deleteAlertsAndRules(); login(); createRule(getNewRule()); visit(ALERTS_URL); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/url_state.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/url_state.cy.ts index e3c77be733312..abf0ad51f1ded 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/url_state.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/url_state.cy.ts @@ -22,6 +22,7 @@ import { visit, visitWithTimeRange } from '../../../tasks/navigation'; import { TIMELINES_URL } from '../../../urls/navigation'; +// FLAKY: https://github.com/elastic/kibana/issues/172503 describe.skip('Open timeline', { tags: ['@serverless', '@ess'] }, () => { let timelineSavedObjectId: string | null = null; before(function () { diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts index feddf08dc39b1..e8ee1743dc94e 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts @@ -141,6 +141,7 @@ export default function ({ getService }: FtrProviderContext) { [SPACE_IDS]: ['default'], ['kibana.alert.title']: "rule 'always fire' matched query", ['kibana.alert.evaluation.conditions']: 'Number of matching documents is greater than -1', + ['kibana.alert.evaluation.threshold']: -1, ['kibana.alert.evaluation.value']: '0', [ALERT_ACTION_GROUP]: 'query matched', [ALERT_FLAPPING]: false, diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts index 9b130040e2340..fcda3e0c62cb8 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts @@ -167,6 +167,7 @@ export default function ({ getService }: FtrProviderContext) { [EVENT_KIND]: 'signal', ['kibana.alert.title']: "rule 'always fire' matched query", ['kibana.alert.evaluation.conditions']: 'Number of matching documents is greater than -1', + ['kibana.alert.evaluation.threshold']: -1, ['kibana.alert.evaluation.value']: '0', [ALERT_ACTION_GROUP]: 'query matched', [ALERT_FLAPPING]: false, @@ -291,6 +292,7 @@ export default function ({ getService }: FtrProviderContext) { [EVENT_KIND]: 'signal', ['kibana.alert.title']: "rule 'always fire' matched query", ['kibana.alert.evaluation.conditions']: 'Number of matching documents is greater than -1', + ['kibana.alert.evaluation.threshold']: -1, ['kibana.alert.evaluation.value']: '0', [ALERT_ACTION_GROUP]: 'query matched', [ALERT_FLAPPING]: false, @@ -507,6 +509,7 @@ export default function ({ getService }: FtrProviderContext) { [EVENT_KIND]: 'signal', ['kibana.alert.title']: "rule 'always fire' matched query", ['kibana.alert.evaluation.conditions']: 'Number of matching documents is greater than -1', + ['kibana.alert.evaluation.threshold']: -1, ['kibana.alert.evaluation.value']: '0', [ALERT_ACTION_GROUP]: 'query matched', [ALERT_FLAPPING]: false, diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/config.feature_flags.ts b/x-pack/test_serverless/api_integration/test_suites/observability/config.feature_flags.ts index 06fb7e5682ea3..09340543ad7a8 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/config.feature_flags.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/config.feature_flags.ts @@ -20,10 +20,7 @@ export default createTestConfig({ suiteTags: { exclude: ['skipSvlOblt'] }, services, // add feature flags - kbnServerArgs: [ - '--xpack.observability.unsafe.thresholdRule.enabled=true', - '--xpack.infra.enabled=true', - ], + kbnServerArgs: ['--xpack.infra.enabled=true'], // load tests in the index file testFiles: [require.resolve('./index.feature_flags.ts')], diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/benchmark.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/benchmark.ts index 53802db8caf3d..f67febd8e4a13 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/benchmark.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/benchmark.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/get_csp_rule_template.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts similarity index 91% rename from x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/get_csp_rule_template.ts rename to x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts index 19208865deb5c..8209e9965a9a2 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/get_csp_rule_template.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/find_csp_benchmark_rule.ts @@ -9,8 +9,11 @@ import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; -import type { GetCspRuleTemplateResponse } from '@kbn/cloud-security-posture-plugin/common/types'; -import { CspRuleTemplate } from '@kbn/cloud-security-posture-plugin/common/schemas'; +import type { + CspBenchmarkRule, + FindCspBenchmarkRuleResponse, +} from '@kbn/cloud-security-posture-plugin/common/types/latest'; + import { FtrProviderContext } from '../../../ftr_provider_context'; import { createPackagePolicy } from '../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing @@ -19,6 +22,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + // find csp benchmark rule tests describe('GET internal/cloud_security_posture/rules/_find', function () { // security_exception: action [indices:admin/create] is unauthorized for user [elastic] with effective roles [superuser] on restricted indices [.fleet-actions-7], this action is granted by the index privileges [create_index,manage,all] this.tags(['failsOnMKI']); @@ -126,7 +130,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx') @@ -139,7 +143,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); const allRulesHaveCorrectBenchmarkId = body.items.every( - (rule: CspRuleTemplate) => rule.metadata.benchmark.id === 'cis_k8s' + (rule: CspBenchmarkRule) => rule.metadata.benchmark.id === 'cis_k8s' ); expect(allRulesHaveCorrectBenchmarkId).to.eql( @@ -158,7 +162,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx') @@ -172,7 +176,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); const allowedFields = ['name', 'section', 'id']; - const fieldsMatched = body.items.every((rule: CspRuleTemplate) => { + const fieldsMatched = body.items.every((rule: CspBenchmarkRule) => { const keys = Object.keys(rule.metadata); return ( keys.length === allowedFields.length && keys.every((key) => allowedFields.includes(key)) @@ -192,7 +196,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx') @@ -207,7 +211,7 @@ export default function ({ getService }: FtrProviderContext) { expect(body.items.length).greaterThan(0); // check if the items are sorted by metadata.section field - const sections = body.items.map((rule: CspRuleTemplate) => rule.metadata.section); + const sections = body.items.map((rule: CspBenchmarkRule) => rule.metadata.section); const isSorted = sections.every( (section, index) => index === 0 || section >= sections[index - 1] ); @@ -227,7 +231,7 @@ export default function ({ getService }: FtrProviderContext) { 'kspm' ); - const { body }: { body: GetCspRuleTemplateResponse } = await supertest + const { body }: { body: FindCspBenchmarkRuleResponse } = await supertest .get(`/internal/cloud_security_posture/rules/_find`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') .set('kbn-xsrf', 'xxxx') diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/index.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/index.ts index 2e0281d1ab43f..9a4a40ab4add9 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/index.ts @@ -14,7 +14,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./status/status_indexed')); loadTestFile(require.resolve('./status/status_indexing')); loadTestFile(require.resolve('./benchmark')); - loadTestFile(require.resolve('./get_csp_rule_template')); + loadTestFile(require.resolve('./find_csp_benchmark_rule')); loadTestFile(require.resolve('./telemetry')); // TODO: migrate status_unprivileged tests from stateful, if it feasible in serverless with the new security model diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts index ace5eef6a5499..ec3216971ec35 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexed.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts index 316fb54f829c6..17e1e6458edaa 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_indexing.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { FINDINGS_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts index ac516bc68434c..9dc25ca4a1133 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/status/status_not_deployed_not_installed.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types'; +import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types_old'; import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, diff --git a/x-pack/test_serverless/functional/test_suites/common/console/console.ts b/x-pack/test_serverless/functional/test_suites/common/console/console.ts index e91f7e47d291f..d754abdf340bb 100644 --- a/x-pack/test_serverless/functional/test_suites/common/console/console.ts +++ b/x-pack/test_serverless/functional/test_suites/common/console/console.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import { asyncForEach } from '@kbn/std'; import { FtrProviderContext } from '../../../ftr_provider_context'; const DEFAULT_REQUEST = ` @@ -24,21 +23,24 @@ GET \${exampleVariable1} // _search export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); - const browser = getService('browser'); - const PageObjects = getPageObjects(['common', 'console', 'header']); - const security = getService('security'); - const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['svlCommonPage', 'common', 'console', 'header']); describe('console app', function describeIndexTests() { this.tags('includeFirefox'); before(async () => { + await PageObjects.svlCommonPage.login(); log.debug('navigateTo console'); await PageObjects.common.navigateToApp('dev_tools', { hash: '/console' }); }); + beforeEach(async () => { await PageObjects.console.closeHelpIfExists(); }); + after(async () => { + await PageObjects.svlCommonPage.forceLogout(); + }); + it('should show the default request', async () => { await retry.try(async () => { const actualRequest = await PageObjects.console.getRequest(); @@ -57,161 +59,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(actualResponse).to.contain(expectedResponseContains); }); }); - - it('should resize the editor', async () => { - const editor = await PageObjects.console.getEditor(); - await browser.setWindowSize(1300, 1100); - const initialSize = await editor.getSize(); - await browser.setWindowSize(1000, 1100); - const afterSize = await editor.getSize(); - expect(initialSize.width).to.be.greaterThan(afterSize.width); - }); - - it('should return statusCode 400 to unsupported HTTP verbs', async () => { - const expectedResponseContains = '"statusCode": 400'; - await PageObjects.console.enterRequest('\n OPTIONS /'); - await PageObjects.console.clickPlay(); - await retry.try(async () => { - const actualResponse = await PageObjects.console.getResponse(); - log.debug(actualResponse); - expect(actualResponse).to.contain(expectedResponseContains); - - expect(await PageObjects.console.hasSuccessBadge()).to.be(false); - }); - }); - - describe('with kbn: prefix in request', () => { - before(async () => { - await PageObjects.console.clearTextArea(); - }); - it('it should send successful request to Kibana API', async () => { - const expectedResponseContains = 'default space'; - await PageObjects.console.enterRequest('\n GET kbn:/api/spaces/space'); - await PageObjects.console.clickPlay(); - await retry.try(async () => { - const actualResponse = await PageObjects.console.getResponse(); - log.debug(actualResponse); - expect(actualResponse).to.contain(expectedResponseContains); - }); - }); - }); - - describe('with query params', () => { - it('should issue a successful request', async () => { - await PageObjects.console.clearTextArea(); - await PageObjects.console.enterRequest( - '\n GET _cat/aliases?format=json&v=true&pretty=true' - ); - await PageObjects.console.clickPlay(); - await PageObjects.header.waitUntilLoadingHasFinished(); - - await retry.try(async () => { - const status = await PageObjects.console.getResponseStatus(); - expect(status).to.eql(200); - }); - }); - }); - - describe('multiple requests output', function () { - const sendMultipleRequests = async (requests: string[]) => { - await asyncForEach(requests, async (request) => { - await PageObjects.console.enterRequest(request); - }); - await PageObjects.console.selectAllRequests(); - await PageObjects.console.clickPlay(); - }; - - before(async () => { - await security.testUser.setRoles(['kibana_admin', 'test_index']); - }); - - after(async () => { - await security.testUser.restoreDefaults(); - }); - - beforeEach(async () => { - // Welcome fly out exists sometimes - const flyOutExists = await testSubjects.exists('euiFlyoutCloseButton'); - if (flyOutExists) { - await testSubjects.click('euiFlyoutCloseButton'); - } - await PageObjects.console.clearTextArea(); - }); - - it('should contain comments starting with # symbol', async () => { - await sendMultipleRequests(['\n PUT test-index', '\n DELETE test-index']); - await retry.try(async () => { - const response = await PageObjects.console.getResponse(); - log.debug(response); - expect(response).to.contain('# PUT test-index 200'); - expect(response).to.contain('# DELETE test-index 200'); - }); - }); - - it('should display status badges', async () => { - await sendMultipleRequests(['\n GET _search/test', '\n GET _search']); - await PageObjects.header.waitUntilLoadingHasFinished(); - expect(await PageObjects.console.hasWarningBadge()).to.be(true); - expect(await PageObjects.console.hasSuccessBadge()).to.be(true); - }); - }); - - describe('with folded/unfolded lines in request body', () => { - const enterRequest = async () => { - await PageObjects.console.enterRequest('\nGET test/doc/1 \n{\n\t\t"_source": []'); - await PageObjects.console.clickPlay(); - }; - - beforeEach(async () => { - await PageObjects.console.clearTextArea(); - }); - - it('should restore the state of folding/unfolding when navigating back to Console', async () => { - await enterRequest(); - await PageObjects.console.clickFoldWidget(); - await PageObjects.common.navigateToApp('home'); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.common.navigateToApp('dev_tools', { hash: '/console' }); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.console.closeHelpIfExists(); - expect(await PageObjects.console.hasFolds()).to.be(true); - }); - - it('should restore the state of folding/unfolding when the page reloads', async () => { - await enterRequest(); - await PageObjects.console.clickFoldWidget(); - await browser.refresh(); - await PageObjects.header.waitUntilLoadingHasFinished(); - expect(await PageObjects.console.hasFolds()).to.be(true); - }); - - it('should not have folds by default', async () => { - await enterRequest(); - await browser.refresh(); - await PageObjects.header.waitUntilLoadingHasFinished(); - expect(await PageObjects.console.hasFolds()).to.be(false); - }); - - it(`doesn't fail if a fold fails`, async () => { - // for more details, see https://github.com/elastic/kibana/issues/151563 - await browser.clearLocalStorage(); - await browser.setLocalStorageItem( - 'sense:folds', - '[{"start":{"row":1,"column":1},"end":{"row":82,"column":4}}]' - ); - await browser.setLocalStorageItem( - 'sense:console_local_text-object_95a511b6-b6e1-4ea6-9344-428bf5183d88', - '{"id":"95a511b6-b6e1-4ea6-9344-428bf5183d88","createdAt":1677592109975,"updatedAt":1677592148666,"text":"GET _cat/indices"}' - ); - await browser.refresh(); - - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.console.closeHelpIfExists(); - const request = await PageObjects.console.getRequest(); - // the request is restored from the local storage value - expect(request).to.eql('GET _cat/indices'); - await browser.clearLocalStorage(); - }); - }); }); } diff --git a/x-pack/test_serverless/functional/test_suites/common/grok_debugger/grok_debugger.ts b/x-pack/test_serverless/functional/test_suites/common/grok_debugger/grok_debugger.ts index 6c4be69abbf18..c3547fe790303 100644 --- a/x-pack/test_serverless/functional/test_suites/common/grok_debugger/grok_debugger.ts +++ b/x-pack/test_serverless/functional/test_suites/common/grok_debugger/grok_debugger.ts @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { - const PageObjects = getPageObjects(['common', 'grokDebugger']); + const PageObjects = getPageObjects(['svlCommonPage', 'common', 'grokDebugger']); const browser = getService('browser'); const security = getService('security'); const testSubjects = getService('testSubjects'); @@ -22,6 +22,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // fold. Otherwise it can't be clicked by the browser driver. await browser.setWindowSize(1600, 1000); await security.testUser.setRoles(['global_devtools_read', 'ingest_pipelines_user']); + await PageObjects.svlCommonPage.login(); await PageObjects.common.navigateToApp('dev_tools', { hash: '/grokdebugger' }); await retry.waitFor('Grok Debugger Header to be visible', async () => { return testSubjects.isDisplayed('grokDebuggerContainer'); @@ -29,6 +30,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); after(async () => { + await PageObjects.svlCommonPage.forceLogout(); await security.testUser.restoreDefaults(); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts b/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts index 904ea9ed4b4f6..7ff25a8387f3c 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts @@ -88,7 +88,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { } }); - describe('updating settings', () => { + describe.skip('updating settings', () => { it('allows to update a setting', async () => { const fieldTestSubj = 'management-settings-editField-' + settings.CSV_QUOTE_VALUES_ID; expect(await testSubjects.isEuiSwitchChecked(fieldTestSubj)).to.be(true); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts index d615087f476ef..5910713892fe0 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts @@ -19,7 +19,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const TEST_TEMPLATE = 'a_test_template'; - describe('Index Templates', function () { + // FLAKY: https://github.com/elastic/kibana/issues/172703 + // FLAKY: https://github.com/elastic/kibana/issues/172704 + describe.skip('Index Templates', function () { before(async () => { await security.testUser.setRoles(['index_management_user']); // Navigate to the index management page diff --git a/x-pack/test_serverless/functional/test_suites/common/painless_lab/index.ts b/x-pack/test_serverless/functional/test_suites/common/painless_lab/index.ts new file mode 100644 index 0000000000000..0a0b9c0ab022d --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/painless_lab/index.ts @@ -0,0 +1,14 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Serverless Common UI - Painless lab', function () { + loadTestFile(require.resolve('./painless_lab')); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/common/painless_lab/painless_lab.ts b/x-pack/test_serverless/functional/test_suites/common/painless_lab/painless_lab.ts new file mode 100644 index 0000000000000..e781808189100 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/painless_lab/painless_lab.ts @@ -0,0 +1,58 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +const TEST_SCRIPT_RESULT = 45; +const TEST_SCRIPT = ` +int total = 0; + +for (int i = 0; i < 10; ++i) { + total += i; +} + +return total; +`.trim(); + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const PageObjects = getPageObjects(['common', 'console', 'header', 'svlCommonPage']); + const testSubjects = getService('testSubjects'); + const monacoEditor = getService('monacoEditor'); + + describe('Painless lab', function describeIndexTests() { + before(async () => { + await PageObjects.svlCommonPage.login(); + await PageObjects.common.navigateToApp('dev_tools', { hash: '/painless_lab' }); + await retry.waitFor('Wait for editor to be visible', async () => { + return testSubjects.isDisplayed('painless_lab'); + }); + }); + + after(async () => { + await PageObjects.svlCommonPage.forceLogout(); + }); + + it('should show the editor and preview panels', async () => { + const editor = await testSubjects.find('kibanaCodeEditor'); + const preview = await testSubjects.find('painlessTabs'); + + expect(await editor.isDisplayed()).to.be(true); + expect(await preview.isDisplayed()).to.be(true); + }); + + it('executes the script and shows the right result', async () => { + await monacoEditor.setCodeEditorValue(TEST_SCRIPT); + + await retry.try(async () => { + const result = await testSubjects.find('painlessTabs'); + expect(await result.getVisibleText()).to.contain(TEST_SCRIPT_RESULT.toString()); + }); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group1.ts b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group1.ts index 7207a857f692f..79ace54bdc6ac 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group1.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/common_configs/config.group1.ts @@ -19,6 +19,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../common/reporting'), require.resolve('../../common/grok_debugger'), require.resolve('../../common/console'), + require.resolve('../../common/painless_lab'), ], junit: { reportName: 'Serverless Observability Functional Tests - Common Group 1', diff --git a/x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts b/x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts index 157593d38100b..2fd50316f8679 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts @@ -21,7 +21,6 @@ export default createTestConfig({ kbnServerArgs: [ '--xpack.infra.enabled=true', '--xpack.infra.featureFlags.customThresholdAlertsEnabled=true', - '--xpack.observability.unsafe.thresholdRule.enabled=true', ], // load tests in the index file testFiles: [require.resolve('./index.feature_flags.ts')], diff --git a/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts index 9f96ca3b0c263..c7771a0bf9c2d 100644 --- a/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts +++ b/x-pack/test_serverless/functional/test_suites/security/common_configs/config.group1.ts @@ -19,6 +19,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../common/reporting'), require.resolve('../../common/grok_debugger'), require.resolve('../../common/console'), + require.resolve('../../common/painless_lab'), ], junit: { reportName: 'Serverless Security Functional Tests - Common Group 1', diff --git a/yarn.lock b/yarn.lock index dd4e1988b5727..fc25c7f6f2fe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3147,6 +3147,10 @@ version "0.0.0" uid "" +"@kbn/bfetch-error@link:packages/kbn-bfetch-error": + version "0.0.0" + uid "" + "@kbn/bfetch-explorer-plugin@link:examples/bfetch_explorer": version "0.0.0" uid "" @@ -5523,6 +5527,10 @@ version "0.0.0" uid "" +"@kbn/search-errors@link:packages/kbn-search-errors": + version "0.0.0" + uid "" + "@kbn/search-examples-plugin@link:examples/search_examples": version "0.0.0" uid ""