diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 2cdc6d1c297cdd..025836a90204c5 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -37,22 +37,31 @@ pipeline { deleteDir() gitCheckout(basedir: "${BASE_DIR}", githubNotifyFirstTimeContributor: false, shallow: false, reference: "/var/lib/jenkins/.git-references/kibana.git") + + // Filter when to run based on the below reasons: + // - On a PRs when: + // - There are changes related to the APM UI project + // - only when the owners of those changes are members of the given GitHub teams + // - On merges to branches when: + // - There are changes related to the APM UI project + // - FORCE parameter is set to true. script { + def apm_updated = false dir("${BASE_DIR}"){ - def regexps =[ "^x-pack/plugins/apm/.*" ] - env.APM_UPDATED = isGitRegionMatch(patterns: regexps) + apm_updated = isGitRegionMatch(patterns: [ "^x-pack/plugins/apm/.*" ]) + } + if (isPR()) { + def isMember = isMemberOf(user: env.CHANGE_AUTHOR, team: ['apm-ui', 'uptime']) + setEnvVar('RUN_APM_E2E', params.FORCE || (apm_updated && isMember)) + } else { + setEnvVar('RUN_APM_E2E', params.FORCE || apm_updated) } } } } stage('Prepare Kibana') { options { skipDefaultCheckout() } - when { - anyOf { - expression { return params.FORCE } - expression { return env.APM_UPDATED != "false" } - } - } + when { expression { return env.RUN_APM_E2E != "false" } } environment { JENKINS_NODE_COOKIE = 'dontKillMe' } @@ -70,12 +79,7 @@ pipeline { } stage('Smoke Tests'){ options { skipDefaultCheckout() } - when { - anyOf { - expression { return params.FORCE } - expression { return env.APM_UPDATED != "false" } - } - } + when { expression { return env.RUN_APM_E2E != "false" } } steps{ notifyTestStatus('Running smoke tests', 'PENDING') dir("${BASE_DIR}"){ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bcb47744758497..d81f6af4cec28f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -64,11 +64,12 @@ /src/apm.js @watson @vigneshshanmugam # Client Side Monitoring (lives in APM directories but owned by Uptime) -/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum @elastic/uptime +/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm @elastic/uptime /x-pack/plugins/apm/public/application/csmApp.tsx @elastic/uptime /x-pack/plugins/apm/public/components/app/RumDashboard @elastic/uptime /x-pack/plugins/apm/server/lib/rum_client @elastic/uptime /x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime +/x-pack/plugins/apm/server/projections/rum_overview.ts @elastic/uptime # Beats /x-pack/legacy/plugins/beats_management/ @elastic/beats @@ -85,6 +86,7 @@ # Exclude tutorial resources folder for now because they are not owned by Kibana app and most will move out soon /src/legacy/core_plugins/kibana/public/home/*.ts @elastic/kibana-core-ui /src/legacy/core_plugins/kibana/public/home/np_ready/ @elastic/kibana-core-ui +/x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui # Observability UIs /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui @@ -128,6 +130,7 @@ /packages/kbn-test/ @elastic/kibana-operations /packages/kbn-ui-shared-deps/ @elastic/kibana-operations /packages/kbn-es-archiver/ @elastic/kibana-operations +/packages/kbn-utils/ @elastic/kibana-operations /src/legacy/server/keystore/ @elastic/kibana-operations /src/legacy/server/pid/ @elastic/kibana-operations /src/legacy/server/sass/ @elastic/kibana-operations @@ -152,6 +155,7 @@ /x-pack/plugins/cloud/ @elastic/kibana-platform /x-pack/test/saved_objects_field_count/ @elastic/kibana-platform /packages/kbn-config-schema/ @elastic/kibana-platform +/packages/kbn-std/ @elastic/kibana-platform /src/legacy/server/config/ @elastic/kibana-platform /src/legacy/server/http/ @elastic/kibana-platform /src/legacy/server/logging/ @elastic/kibana-platform @@ -169,6 +173,7 @@ /x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security /x-pack/plugins/security/ @elastic/kibana-security /x-pack/test/api_integration/apis/security/ @elastic/kibana-security +/x-pack/test/ui_capabilities/ @elastic/kibana-security /x-pack/test/encrypted_saved_objects_api_integration/ @elastic/kibana-security /x-pack/test/functional/apps/security/ @elastic/kibana-security /x-pack/test/kerberos_api_integration/ @elastic/kibana-security @@ -292,6 +297,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/plugins/infra/**/*.scss @elastic/observability-design /x-pack/plugins/ingest_manager/**/*.scss @elastic/observability-design /x-pack/plugins/observability/**/*.scss @elastic/observability-design +/x-pack/plugins/monitoring/**/*.scss @elastic/observability-design # Ent. Search design /x-pack/plugins/enterprise_search/**/*.scss @elastic/ent-search-design diff --git a/.github/ISSUE_TEMPLATE/APM.md b/.github/ISSUE_TEMPLATE/APM.md index 983806f70bc3fa..c3abbdd67269de 100644 --- a/.github/ISSUE_TEMPLATE/APM.md +++ b/.github/ISSUE_TEMPLATE/APM.md @@ -2,7 +2,7 @@ name: APM Issue about: Issues related to the APM solution in Kibana labels: Team:apm -title: [APM] +title: "[APM]" --- **Versions** diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc new file mode 100644 index 00000000000000..4a390336da34fc --- /dev/null +++ b/docs/developer/architecture/code-exploration.asciidoc @@ -0,0 +1,598 @@ +//// + +NOTE: + This is an automatically generated file. Please do not edit directly. Instead, run the + following from within the kibana repository: + + node scripts/build_plugin_list_docs + + You can update the template within packages/kbn-dev-utils/target/plugin_list/generate_plugin_list.js + +//// + +[[code-exploration]] +== Exploring Kibana code + +The goals of our folder heirarchy are: + +- Easy for developers to know where to add new services, plugins and applications. +- Easy for developers to know where to find the code from services, plugins and applications. +- Easy to browse and understand our folder structure. + +To that aim, we strive to: + +- Avoid too many files in any given folder. +- Choose clear, unambigious folder names. +- Organize by domain. +- Every folder should contain a README that describes the contents of that folder. + +[discrete] +[[kibana-services-applications]] +=== Services and Applications + +[discrete] +==== src/plugins + +- {kib-repo}blob/{branch}/src/plugins/advanced_settings[advancedSettings] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/apm_oss[apmOss] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/bfetch/README.md[bfetch] + +bfetch allows to batch HTTP requests and streams responses back. + + +- {kib-repo}blob/{branch}/src/plugins/charts/README.md[charts] + +The Charts plugin is a way to create easier integration of shared colors, themes, types and other utilities across all Kibana charts and visualizations. + + +- {kib-repo}blob/{branch}/src/plugins/console[console] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/dashboard/README.md[dashboard] + +Contains the dashboard application. + + +- {kib-repo}blob/{branch}/src/plugins/data/README.md[data] + +data plugin provides common data access services. + + +- {kib-repo}blob/{branch}/src/plugins/dev_tools/README.md[devTools] + +The ui/registry/dev_tools is removed in favor of the devTools plugin which exposes a register method in the setup contract. +Registering app works mostly the same as registering apps in core.application.register. +Routing will be handled by the id of the dev tool - your dev tool will be mounted when the URL matches /app/dev_tools#/. +This API doesn't support angular, for registering angular dev tools, bootstrap a local module on mount into the given HTML element. + + +- {kib-repo}blob/{branch}/src/plugins/discover/README.md[discover] + +Contains the Discover application and the saved search embeddable. + + +- {kib-repo}blob/{branch}/src/plugins/embeddable/README.md[embeddable] + +Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable containers. + + +- {kib-repo}blob/{branch}/src/plugins/es_ui_shared/README.md[esUiShared] + +This plugin contains reusable code in the form of self-contained modules (or libraries). Each of these modules exports a set of functionality relevant to the domain of the module. + + +- {kib-repo}blob/{branch}/src/plugins/expressions/README.md[expressions] + +This plugin provides methods which will parse & execute an expression pipeline +string for you, as well as a series of registries for advanced users who might +want to incorporate their own functions, types, and renderers into the service +for use in their own application. + + +- {kib-repo}blob/{branch}/src/plugins/home/README.md[home] + +Moves the legacy ui/registry/feature_catalogue module for registering "features" that should be shown in the home page's feature catalogue to a service within a "home" plugin. The feature catalogue refered to here should not be confused with the "feature" plugin for registering features used to derive UI capabilities for feature controls. + + +- {kib-repo}blob/{branch}/src/plugins/index_pattern_management[indexPatternManagement] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/input_control_vis/README.md[inputControlVis] + +Contains the input control visualization allowing to place custom filter controls on a dashboard. + + +- {kib-repo}blob/{branch}/src/plugins/inspector/README.md[inspector] + +The inspector is a contextual tool to gain insights into different elements +in Kibana, e.g. visualizations. It has the form of a flyout panel. + + +- {kib-repo}blob/{branch}/src/plugins/kibana_legacy/README.md[kibanaLegacy] + +This plugin will contain several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform. + + +- {kib-repo}blob/{branch}/src/plugins/kibana_react/README.md[kibanaReact] + +Tools for building React applications in Kibana. + + +- {kib-repo}blob/{branch}/src/plugins/kibana_usage_collection/README.md[kibanaUsageCollection] + +This plugin registers the basic usage collectors from Kibana: + + +- {kib-repo}blob/{branch}/src/plugins/kibana_utils/README.md[kibanaUtils] + +Utilities for building Kibana plugins. + + +- {kib-repo}blob/{branch}/src/plugins/legacy_export[legacyExport] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/management[management] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/maps_legacy[mapsLegacy] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/navigation/README.md[navigation] + +The navigation plugins exports the TopNavMenu component. +It also provides a stateful version of it on the start contract. + + +- {kib-repo}blob/{branch}/src/plugins/newsfeed[newsfeed] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/region_map[regionMap] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/saved_objects[savedObjects] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/saved_objects_management[savedObjectsManagement] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/share/README.md[share] + +Replaces the legacy ui/share module for registering share context menus. + + +- {kib-repo}blob/{branch}/src/plugins/telemetry/README.md[telemetry] + +Telemetry allows Kibana features to have usage tracked in the wild. The general term "telemetry" refers to multiple things: + + +- {kib-repo}blob/{branch}/src/plugins/telemetry_collection_manager/README.md[telemetryCollectionManager] + +Telemetry's collection manager to go through all the telemetry sources when fetching it before reporting. + + +- {kib-repo}blob/{branch}/src/plugins/telemetry_management_section/README.md[telemetryManagementSection] + +This plugin adds the Advanced Settings section for the Usage Data collection (aka Telemetry). + + +- {kib-repo}blob/{branch}/src/plugins/tile_map[tileMap] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/src/plugins/timelion/README.md[timelion] + +Contains the deprecated timelion application. For the timelion visualization, +which also contains the timelion APIs and backend, look at the vis_type_timelion plugin. + + +- {kib-repo}blob/{branch}/src/plugins/ui_actions/README.md[uiActions] + +An API for: + + +- {kib-repo}blob/{branch}/src/plugins/usage_collection/README.md[usageCollection] + +Usage Collection allows collecting usage data for other services to consume (telemetry and monitoring). +To integrate with the telemetry services for usage collection of your feature, there are 2 steps: + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_markdown/README.md[visTypeMarkdown] + +The markdown visualization that can be used to place text panels on dashboards. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_metric/README.md[visTypeMetric] + +Contains the metric visualization. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_table/README.md[visTypeTable] + +Contains the data table visualization, that allows presenting data in a simple table format. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_tagcloud/README.md[visTypeTagcloud] + +Contains the tagcloud visualization. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_timelion/README.md[visTypeTimelion] + +Contains the timelion visualization and the timelion backend. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_timeseries/README.md[visTypeTimeseries] + +Contains everything around TSVB (the editor, visualizatin implementations and backends). + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_vega/README.md[visTypeVega] + +Contains the Vega visualization. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_vislib/README.md[visTypeVislib] + +Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and +heatmap charts. + + +- {kib-repo}blob/{branch}/src/plugins/vis_type_xy/README.md[visTypeXy] + +Contains the new xy-axis chart using the elastic-charts library, which will eventually +replace the vislib xy-axis (bar, area, line) charts. + + +- {kib-repo}blob/{branch}/src/plugins/visualizations/README.md[visualizations] + +Contains most of the visualization infrastructure, e.g. the visualization type registry or the +visualization embeddable. + + +- {kib-repo}blob/{branch}/src/plugins/visualize/README.md[visualize] + +Contains the visualize application which includes the listing page and the app frame, +which will load the visualization's editor. + + +[discrete] +==== x-pack/plugins + +- {kib-repo}blob/{branch}/x-pack/plugins/actions/README.md[actions] + +The Kibana actions plugin provides a framework to create executable actions. You can: + + +- {kib-repo}blob/{branch}/x-pack/plugins/alerting_builtins/README.md[alertingBuiltins] + +This plugin provides alertTypes shipped with Kibana for use with the +the alerts plugin. When enabled, it will register +the built-in alertTypes with the alerting plugin, register associated HTTP +routes, etc. + + +- {kib-repo}blob/{branch}/x-pack/plugins/alerts/README.md[alerts] + +The Kibana alerting plugin provides a common place to set up alerts. You can: + + +- {kib-repo}blob/{branch}/x-pack/plugins/apm/readme.md[apm] + +To access an elasticsearch instance that has live data you have two options: + + +- {kib-repo}blob/{branch}/x-pack/plugins/audit_trail[auditTrail] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/beats_management/readme.md[beatsManagement] + +Notes: +Failure to have auth enabled in Kibana will make for a broken UI. UI-based errors not yet in place + + +- {kib-repo}blob/{branch}/x-pack/plugins/canvas/README.md[canvas] + +"Never look back. The past is done. The future is a blank canvas." ― Suzy Kassem, Rise Up and Salute the Sun + + +- {kib-repo}blob/{branch}/x-pack/plugins/case/README.md[case] + +Experimental Feature + + +- {kib-repo}blob/{branch}/x-pack/plugins/cloud[cloud] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/code[code] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/console_extensions[consoleExtensions] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/cross_cluster_replication/README.md[crossClusterReplication] + +You can run a local cluster and simulate a remote cluster within a single Kibana directory. + + +- {kib-repo}blob/{branch}/x-pack/plugins/dashboard_enhanced/README.md[dashboardEnhanced] + +Contains the enhancements to the OSS dashboard app. + + +- {kib-repo}blob/{branch}/x-pack/plugins/dashboard_mode/README.md[dashboardMode] + +The deprecated dashboard only mode. + + +- {kib-repo}blob/{branch}/x-pack/plugins/data_enhanced[dataEnhanced] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/discover_enhanced/README.md[discoverEnhanced] + +Contains the enhancements to the OSS discover app. + + +- {kib-repo}blob/{branch}/x-pack/plugins/embeddable_enhanced[embeddableEnhanced] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/encrypted_saved_objects/README.md[encryptedSavedObjects] + +The purpose of this plugin is to provide a way to encrypt/decrypt attributes on the custom Saved Objects that works with +security and spaces filtering as well as performing audit logging. + + +- {kib-repo}blob/{branch}/x-pack/plugins/enterprise_search/README.md[enterpriseSearch] + +This plugin's goal is to provide a Kibana user interface to the Enterprise Search solution's products (App Search and Workplace Search). In it's current MVP state, the plugin provides the following with the goal of gathering user feedback and raising product awareness: + + +- {kib-repo}blob/{branch}/x-pack/plugins/event_log/README.md[eventLog] + +The purpose of this plugin is to provide a way to persist a history of events +occuring in Kibana, initially just for the Make It Action project - alerts +and actions. + + +- {kib-repo}blob/{branch}/x-pack/plugins/features[features] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/file_upload[fileUpload] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/global_search/README.md[globalSearch] + +The GlobalSearch plugin provides an easy way to search for various objects, such as applications +or dashboards from the Kibana instance, from both server and client-side plugins + + +- {kib-repo}blob/{branch}/x-pack/plugins/global_search_bar/README.md[globalSearchBar] + +The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) + + +- {kib-repo}blob/{branch}/x-pack/plugins/global_search_providers[globalSearchProviders] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/graph/README.md[graph] + +This is the main source folder of the Graph plugin. It contains all of the Kibana server and client source code. x-pack/test/functional/apps/graph contains additional functional tests. + + +- {kib-repo}blob/{branch}/x-pack/plugins/grokdebugger/README.md[grokdebugger] + +- {kib-repo}blob/{branch}/x-pack/plugins/index_lifecycle_management/README.md[indexLifecycleManagement] + +You can test that the Frozen badge, phase filtering, and lifecycle information is surfaced in +Index Management by running this series of requests in Console: + + +- {kib-repo}blob/{branch}/x-pack/plugins/index_management[indexManagement] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/infra/README.md[infra] + +This is the home of the infra plugin, which aims to provide a solution for +the infrastructure monitoring use-case within Kibana. + + +- {kib-repo}blob/{branch}/x-pack/plugins/ingest_manager/README.md[ingestManager] + +Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.ingestManager.fleet.tlsCheckDisabled=false) + + +- {kib-repo}blob/{branch}/x-pack/plugins/ingest_pipelines/README.md[ingestPipelines] + +The ingest_pipelines plugin provides Kibana support for Elasticsearch's ingest nodes. Please refer to the Elasticsearch documentation for more details. + + +- {kib-repo}blob/{branch}/x-pack/plugins/lens/readme.md[lens] + +Run all tests from the x-pack root directory + + +- {kib-repo}blob/{branch}/x-pack/plugins/license_management[licenseManagement] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/licensing/README.md[licensing] + +The licensing plugin retrieves license data from Elasticsearch at regular configurable intervals. + + +- {kib-repo}blob/{branch}/x-pack/plugins/lists/README.md[lists] + +README.md for developers working on the backend lists on how to get started +using the CURL scripts in the scripts folder. + + +- {kib-repo}blob/{branch}/x-pack/plugins/logstash[logstash] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/maps/README.md[maps] + +Visualize geo data from Elasticsearch or 3rd party geo-services. + + +- {kib-repo}blob/{branch}/x-pack/plugins/maps_legacy_licensing/README.md[mapsLegacyLicensing] + +This plugin provides access to the detailed tile map services from Elastic. + + +- {kib-repo}blob/{branch}/x-pack/plugins/ml[ml] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/monitoring[monitoring] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/observability/README.md[observability] + +This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. + + +- {kib-repo}blob/{branch}/x-pack/plugins/oss_telemetry[ossTelemetry] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/painless_lab[painlessLab] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/remote_clusters[remoteClusters] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/reporting/README.md[reporting] + +An awesome Kibana reporting plugin + + +- {kib-repo}blob/{branch}/x-pack/plugins/rollup/README.md[rollup] + +Welcome to the Kibana rollup plugin! This plugin provides Kibana support for Elasticsearch's rollup feature. Please refer to the Elasticsearch documentation to understand rollup indices and how to create rollup jobs. + + +- {kib-repo}blob/{branch}/x-pack/plugins/searchprofiler[searchprofiler] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/security/README.md[security] + +See Configuring security in Kibana. + + +- {kib-repo}blob/{branch}/x-pack/plugins/security_solution/README.md[securitySolution] + +Welcome to the Kibana Security Solution plugin! This README will go over getting started with development and testing. + + +- {kib-repo}blob/{branch}/x-pack/plugins/snapshot_restore/README.md[snapshotRestore] + +or + + +- {kib-repo}blob/{branch}/x-pack/plugins/spaces[spaces] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/task_manager[taskManager] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/telemetry_collection_xpack/README.md[telemetryCollectionXpack] + +Gathers all usage collection, retrieving them from both: OSS and X-Pack plugins. + + +- {kib-repo}blob/{branch}/x-pack/plugins/transform[transform] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/translations[translations] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/triggers_actions_ui/README.md[triggers_actions_ui] + +The Kibana alerts and actions UI plugin provides a user interface for managing alerts and actions. +As a developer you can reuse and extend built-in alerts and actions UI functionality: + + +- {kib-repo}blob/{branch}/x-pack/plugins/ui_actions_enhanced/README.md[uiActionsEnhanced] + +- {kib-repo}blob/{branch}/x-pack/plugins/upgrade_assistant[upgradeAssistant] + +WARNING: Missing README. + + +- {kib-repo}blob/{branch}/x-pack/plugins/uptime/README.md[uptime] + +The purpose of this plugin is to provide users of Heartbeat more visibility of what's happening +in their infrastructure. + + +- {kib-repo}blob/{branch}/x-pack/plugins/watcher/README.md[watcher] + +This plugins adopts some conventions in addition to or in place of conventions in Kibana (at the time of the plugin's creation): + diff --git a/docs/developer/architecture/security/feature-registration.asciidoc b/docs/developer/architecture/security/feature-registration.asciidoc index 3724624dbb9170..3ff83e9db8c43f 100644 --- a/docs/developer/architecture/security/feature-registration.asciidoc +++ b/docs/developer/architecture/security/feature-registration.asciidoc @@ -9,13 +9,12 @@ Registering features also gives your plugin access to “UI Capabilities”. The === Registering a feature -Feature registration is controlled via the built-in `xpack_main` plugin. To register a feature, call `xpack_main`'s `registerFeature` function from your plugin's `init` function, and provide the appropriate details: +Feature registration is controlled via the built-in `features` plugin. To register a feature, call `features`'s `registerKibanaFeature` function from your plugin's `setup` lifecycle function, and provide the appropriate details: ["source","javascript"] ----------- -init(server) { - const xpackMainPlugin = server.plugins.xpack_main; - xpackMainPlugin.registerFeature({ +setup(core, { features }) { + features.registerKibanaFeature({ // feature details here. }); } @@ -45,12 +44,12 @@ Registering a feature consists of the following fields. For more information, co |An array of applications this feature enables. Typically, all of your plugin's apps (from `uiExports`) will be included here. |`privileges` (required) -|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`FeatureConfig`]. +|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`]. |See <> and <> |The set of privileges this feature requires to function. |`subFeatures` (optional) -|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`FeatureConfig`]. +|{kib-repo}blob/{branch}/x-pack/plugins/features/common/feature.ts[`KibanaFeatureConfig`]. |See <> |The set of subfeatures that enables finer access control than the `all` and `read` feature privileges. These options are only available in the Gold subscription level and higher. @@ -73,15 +72,17 @@ For a full explanation of fields and options, consult the {kib-repo}blob/{branch === Using UI Capabilities UI Capabilities are available to your public (client) plugin code. These capabilities are read-only, and are used to inform the UI. This object is namespaced by feature id. For example, if your feature id is “foo”, then your UI Capabilities are stored at `uiCapabilities.foo`. -To access capabilities, import them from `ui/capabilities`: +Capabilities can be accessed from your plugin's `start` lifecycle from the `core.application` service: ["source","javascript"] ----------- -import { uiCapabilities } from 'ui/capabilities'; +public start(core) { + const { capabilities } = core.application; -const canUserSave = uiCapabilities.foo.save; -if (canUserSave) { - // show save button + const canUserSave = capabilities.foo.save; + if (canUserSave) { + // show save button + } } ----------- @@ -89,9 +90,8 @@ if (canUserSave) { === Example 1: Canvas Application ["source","javascript"] ----------- -init(server) { - const xpackMainPlugin = server.plugins.xpack_main; - xpackMainPlugin.registerFeature({ +public setup(core, { features }) { + features.registerKibanaFeature({ id: 'canvas', name: 'Canvas', icon: 'canvasApp', @@ -130,11 +130,13 @@ The `all` privilege defines a single “save” UI Capability. To access this in ["source","javascript"] ----------- -import { uiCapabilities } from 'ui/capabilities'; +public start(core) { + const { capabilities } = core.application; -const canUserSave = uiCapabilities.canvas.save; -if (canUserSave) { - // show save button + const canUserSave = capabilities.canvas.save; + if (canUserSave) { + // show save button + } } ----------- @@ -145,9 +147,8 @@ Because the `read` privilege does not define the `save` capability, users with r ["source","javascript"] ----------- -init(server) { - const xpackMainPlugin = server.plugins.xpack_main; - xpackMainPlugin.registerFeature({ +public setup(core, { features }) { + features.registerKibanaFeature({ id: 'dev_tools', name: i18n.translate('xpack.features.devToolsFeatureName', { defaultMessage: 'Dev Tools', @@ -206,9 +207,8 @@ a single "Create Short URLs" subfeature privilege is defined, which allows users ["source","javascript"] ----------- -init(server) { - const xpackMainPlugin = server.plugins.xpack_main; - xpackMainPlugin.registerFeature({ +public setup(core, { features }) { + features.registerKibanaFeature({ { id: 'discover', name: i18n.translate('xpack.features.discoverFeatureName', { diff --git a/docs/developer/best-practices/images/state_inside_the_link.png b/docs/developer/best-practices/images/state_inside_the_link.png new file mode 100644 index 00000000000000..833478ccbda687 Binary files /dev/null and b/docs/developer/best-practices/images/state_inside_the_link.png differ diff --git a/docs/developer/best-practices/index.asciidoc b/docs/developer/best-practices/index.asciidoc index 42cee6ef0e58a7..13ea010d0aa96a 100644 --- a/docs/developer/best-practices/index.asciidoc +++ b/docs/developer/best-practices/index.asciidoc @@ -122,6 +122,14 @@ In addition, if users are relying on state stored in your app’s URL as part of your public contract, keep in mind that you may also need to provide backwards compatibility for bookmarked URLs. +[discrete] +=== Routing, Navigation and URL + +The {kib} platform provides a set of tools to help developers build consistent experience around routing and browser navigation. +Some of that tooling is inside `core`, some is available as part of various plugins. + +<> to get an idea of available tools and common approaches for handling routing and browser navigation. + [discrete] === Testing & stability @@ -131,6 +139,8 @@ Review: * <> * <> +include::navigation.asciidoc[leveloffset=+1] + include::stability.asciidoc[leveloffset=+1] include::security.asciidoc[leveloffset=+1] diff --git a/docs/developer/best-practices/navigation.asciidoc b/docs/developer/best-practices/navigation.asciidoc new file mode 100644 index 00000000000000..d01f2c2aa0f950 --- /dev/null +++ b/docs/developer/best-practices/navigation.asciidoc @@ -0,0 +1,226 @@ +[[kibana-navigation]] +== Routing, Navigation and URL + +The {kib} platform provides a set of tools to help developers build consistent experience around routing and browser navigation. +Some of that tooling is inside `core`, some is available as part of various plugins. + +The purpose of this guide is to give a high-level overview of available tools and to explain common approaches for handling routing and browser navigation. + +This guide covers following topics: + +* <> +* <> +* <> +* <> +* <> +* <> + +[[deep-linking]] +=== Deep-linking into {kib} apps + +Assuming you want to link from your app to *Discover*. When building such URL there are two things to consider: + +1. Prepending a proper `basePath`. +2. Specifying *Discover* state. + +==== Prepending a proper `basePath` + +To prepend {kib}'s `basePath` use {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.ibasepath.prepend.md[core.http.basePath.prepend] helper: + +[source,typescript jsx] +---- +const discoverUrl = core.http.basePath.prepend(`/discover`); + +console.log(discoverUrl); // http://localhost:5601/bpr/s/space/app/discover +---- + +==== Specifying state + +**Consider a {kib} app URL a part of app's plugin contract:** + +. Avoid hardcoding other app's URL in your app's code. +. Avoid generating other app's state and serializing it into URL query params. + +[source,typescript jsx] +---- +// Avoid relying on other app's state structure in your app's code: +const discoverUrlWithSomeState = core.http.basePath.prepend(`/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2020-09-10T11:39:50.203Z',to:'2020-09-10T11:40:20.249Z'))&_a=(columns:!(_source),filters:!(),index:'90943e30-9a47-11e8-b64d-95841ca0b247',interval:auto,query:(language:kuery,query:''),sort:!())`); +---- + +Instead, each app should expose {kib-repo}tree/{branch}/src/plugins/share/public/url_generators/README.md[a URL generator]. +Other apps should use those URL generators for creating URLs. + +[source,typescript jsx] +---- +// Properly generated URL to *Discover* app. Generator code is owned by *Discover* app and available on *Discover*'s plugin contract. +const discoverUrl = discoverUrlGenerator.createUrl({filters, timeRange}); +---- + +To get a better idea, take a look at *Discover* URL generator {kib-repo}tree/{branch}/src/plugins/discover/public/url_generator.ts[implementation]. +It allows specifying various **Discover** app state pieces like: index pattern, filters, query, time range and more. + +There are two ways to access other's app URL generator in your code: + +1. From a plugin contract of a destination app *(preferred)*. +2. Using URL generator service instance on `share` plugin contract (in case an explicit plugin dependency is not possible). + +In case you want other apps to link to your app, then you should create a URL generator and expose it on your plugin's contract. + + +[[navigating-between-kibana-apps]] +=== Navigating between {kib} apps + +{kib} is a single page application and there is a set of simple rules developers should follow +to make sure there is no page reload when navigating from one place in {kib} to another. + +For example, navigation using native browser APIs would cause a full page reload. + +[source,js] +---- +const urlToADashboard = core.http.basePath.prepend(`/dashboard/my-dashboard`); + +// this would cause a full page reload: +window.location.href = urlToADashboard; +---- + +To navigate between different {kib} apps without a page reload there are APIs in `core`: + +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetoapp.md[core.application.navigateToApp] +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md[core.application.navigateToUrl] + +*Rendering a link to a different {kib} app on its own would also cause a full page reload:* + +[source,typescript jsx] +---- +const myLink = () => + Go to Dashboard; +---- + +A workaround could be to handle a click, prevent browser navigation and use `core.application.navigateToApp` API: + +[source,typescript jsx] +---- +const MySPALink = () => + { + e.preventDefault(); + core.application.navigateToApp('dashboard', { path: '/my-dashboard' }); + }} + > + Go to Dashboard + ; +---- + +As it would be too much boilerplate to do this for each {kib} link in your app, there is a handy wrapper that helps with it: +{kib-repo}tree/{branch}/src/plugins/kibana_react/public/app_links/redirect_app_link.tsx#L49[RedirectAppLinks]. + +[source,typescript jsx] +---- +const MyApp = () => + + {/*...*/} + {/* navigations using this link will happen in SPA friendly way */} + Go to Dashboard + {/*...*/} + +---- + +[[routing]] +=== Setting up internal app routing + +It is very common for {kib} apps to use React and React Router. +Common rules to follow in this scenario: + +* Set up `BrowserRouter` and not `HashRouter`. +* *Initialize your router with `history` instance provided by the `core`.* + +This is required to make sure `core` is aware of navigations triggered inside your app, so it could act accordingly when needed. + +* `Core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] instance. +* {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.appmountparameters.history.md[Example usage] +* {kib-repo}tree/{branch}/test/plugin_functional/plugins/core_plugin_a/public/application.tsx#L120[Example plugin] + +Relative links will be resolved relative to your app's route (e.g.: `http://localhost5601/app/{your-app-id}`) +and setting up internal links in your app in SPA friendly way would look something like: + +[source,typescript jsx] +---- +import {Link} from 'react-router-dom'; + +const MyInternalLink = () => +---- + +[[history-and-location]] +=== Using history and browser location + +Try to avoid using `window.location` and `window.history` directly. + +Instead, consider using {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] +instance provided by `core`. + +* This way `core` will know about location changes triggered within your app, and it would act accordingly. +* Some plugins are listening to location changes. Triggering location change manually could lead to unpredictable and hard-to-catch bugs. + +Common use-case for using +`core`'s {kib-repo}tree/{branch}/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md[ScopedHistory] directly: + +* Reading/writing query params or hash. +* Imperatively triggering internal navigations within your app. +* Listening to browser location changes. + + +[[state-sync]] +=== Syncing state with URL + +Historically {kib} apps store _a lot_ of application state in the URL. +The most common pattern that {kib} apps follow today is storing state in `_a` and `_g` query params in https://github.com/w33ble/rison-node#readme[rison] format. +[[query-params]] +Those query params follow the convention: + +* `_g` (*global*) - global UI state that should be shared and synced across multiple apps. common example from Analyze group apps: time range, refresh interval, *pinned* filters. +* `_a` (*application*) - UI state scoped to current app. + +NOTE: After migrating to KP platform we got navigations without page reloads. Since then there is no real need to follow `_g` and `_a` separation anymore. It's up you to decide if you want to follow this pattern or if you prefer a single query param or something else. The need for this separation earlier is explained in <>. + +There are utils to help you to implement such kind of state syncing. + +**When you should consider using state syncing utils:** + +* You want to sync your application state with URL in similar manner Analyze group applications do. +* You want to follow platform's <> out of the box. +* You want to support `state:storeInSessionStore` escape hatch for URL overflowing out of the box. +* You should also consider using them if you'd like to serialize state to different (not `rison`) format. Utils are composable, and you can implement your own `storage`. +* In case you want to sync part of your state with URL, but other part of it with browser storage. + +**When you shouldn't use state syncing utils:** + +* Adding a query param flag or simple key/value to the URL. + +Follow {kib-repo}tree/{branch}/src/plugins/kibana_utils/docs/state_sync#state-syncing-utilities[these] docs to learn more. + + +[[preserve-state]] +=== Preserving state between navigations + +Consider the scenario: + +1. You are in *Dashboard* app looking at a dashboard with some filters applied; +2. Navigate to *Discover* using in-app navigation; +3. Change the time filter' +4. Navigate to *Dashboard* using in-app navigation. + +You'd notice that you were navigated to *Dashboard* app with the *same state* that you left it with, +except that the time filter has changed to the one you applied on *Discover* app. + +Historically {kib} Analyze groups apps achieve that behavior relying on state in the URL. +If you'd have a closer look on a link in the navigation, +you'd notice that state is stored inside that link, and it also gets updated whenever relevant state changes happen: + +[role="screenshot"] +image:images/state_inside_the_link.png[State is stored inside the navigation link] + +This is where <> into `_a` and `_g` query params comes into play. What is considered a *global* state gets constantly updated in those navigation links. In the example above it was a time filter. +This is backed by {kib-repo}tree/{branch}/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts#L57[KbnUrlTracker] util. You can use it to achieve similar behavior. + +NOTE: After migrating to KP navigation works without page reloads and all plugins are loaded simultaneously. +Hence, likely there are simpler ways to preserve state of your application, unless you want to do it through URL. diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 88f29fa7e3cbe9..7727cd322181fa 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -341,6 +341,10 @@ and actions. or dashboards from the Kibana instance, from both server and client-side plugins +|{kib-repo}blob/{branch}/x-pack/plugins/global_search_bar/README.md[globalSearchBar] +|The GlobalSearchBar plugin provides a search interface for navigating Kibana. (It is the UI to the GlobalSearch plugin.) + + |{kib-repo}blob/{branch}/x-pack/plugins/global_search_providers[globalSearchProviders] |WARNING: Missing README. @@ -416,10 +420,6 @@ using the CURL scripts in the scripts folder. |This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. -|{kib-repo}blob/{branch}/x-pack/plugins/oss_telemetry[ossTelemetry] -|WARNING: Missing README. - - |{kib-repo}blob/{branch}/x-pack/plugins/painless_lab[painlessLab] |WARNING: Missing README. diff --git a/docs/developer/plugin/external-plugin-functional-tests.asciidoc b/docs/developer/plugin/external-plugin-functional-tests.asciidoc index 7e5b5b79d06e9c..b39d576d852685 100644 --- a/docs/developer/plugin/external-plugin-functional-tests.asciidoc +++ b/docs/developer/plugin/external-plugin-functional-tests.asciidoc @@ -13,7 +13,7 @@ To get started copy and paste this example to `test/functional/config.js`: ["source","js"] ----------- import { resolve } from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { MyServiceProvider } from './services/my_service'; import { MyAppPageProvider } from './services/my_app_page'; diff --git a/docs/development/core/public/kibana-plugin-core-public.assertnever.md b/docs/development/core/public/kibana-plugin-core-public.assertnever.md deleted file mode 100644 index 8fefd4450d49b1..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [assertNever](./kibana-plugin-core-public.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md index bca69adeef66b0..47365782599eda 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.md @@ -30,6 +30,7 @@ chrome.navControls.registerLeft({ | Method | Description | | --- | --- | -| [registerLeft(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the left side of the chrome header. | -| [registerRight(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the right side of the chrome header. | +| [registerCenter(navControl)](./kibana-plugin-core-public.chromenavcontrols.registercenter.md) | Register a nav control to be presented on the top-center side of the chrome header. | +| [registerLeft(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerleft.md) | Register a nav control to be presented on the bottom-left side of the chrome header. | +| [registerRight(navControl)](./kibana-plugin-core-public.chromenavcontrols.registerright.md) | Register a nav control to be presented on the top-right side of the chrome header. | diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md new file mode 100644 index 00000000000000..2f921050e58dd3 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registercenter.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeNavControls](./kibana-plugin-core-public.chromenavcontrols.md) > [registerCenter](./kibana-plugin-core-public.chromenavcontrols.registercenter.md) + +## ChromeNavControls.registerCenter() method + +Register a nav control to be presented on the top-center side of the chrome header. + +Signature: + +```typescript +registerCenter(navControl: ChromeNavControl): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| navControl | ChromeNavControl | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md index c5c78bf9fb1da9..514c44bd9d7102 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerleft.md @@ -4,7 +4,7 @@ ## ChromeNavControls.registerLeft() method -Register a nav control to be presented on the left side of the chrome header. +Register a nav control to be presented on the bottom-left side of the chrome header. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md index 12058f1d16ab98..eb56e0e38c6c9e 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavcontrols.registerright.md @@ -4,7 +4,7 @@ ## ChromeNavControls.registerRight() method -Register a nav control to be presented on the right side of the chrome header. +Register a nav control to be presented on the top-right side of the chrome header. Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md deleted file mode 100644 index 09864be43996da..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md +++ /dev/null @@ -1,17 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeStart](./kibana-plugin-core-public.chromestart.md) > [getNavType$](./kibana-plugin-core-public.chromestart.getnavtype_.md) - -## ChromeStart.getNavType$() method - -Get the navigation type TODO \#64541 Can delete - -Signature: - -```typescript -getNavType$(): Observable; -``` -Returns: - -`Observable` - diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.md index e983ad50d2afe5..2594848ef0847f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromestart.md @@ -59,7 +59,6 @@ core.chrome.setHelpExtension(elem => { | [getHelpExtension$()](./kibana-plugin-core-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent | | [getIsNavDrawerLocked$()](./kibana-plugin-core-public.chromestart.getisnavdrawerlocked_.md) | Get an observable of the current locked state of the nav drawer. | | [getIsVisible$()](./kibana-plugin-core-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. | -| [getNavType$()](./kibana-plugin-core-public.chromestart.getnavtype_.md) | Get the navigation type TODO \#64541 Can delete | | [removeApplicationClass(className)](./kibana-plugin-core-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass(). If className is unknown it is ignored. | | [setAppTitle(appTitle)](./kibana-plugin-core-public.chromestart.setapptitle.md) | Sets the current app's title | | [setBadge(badge)](./kibana-plugin-core-public.chromestart.setbadge.md) | Override the current badge | diff --git a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md b/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md deleted file mode 100644 index 7c879b659a8524..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [deepFreeze](./kibana-plugin-core-public.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 85e1da08b00afe..f7b55b0650d8b8 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -10,6 +10,9 @@ readonly links: { readonly dashboard: { readonly drilldowns: string; + readonly drilldownsTriggerPicker: string; + readonly urlDrilldownTemplateSyntax: string; + readonly urlDrilldownVariables: string; }; readonly filebeat: { readonly base: string; diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index 4644dc432bc9a9..3f58cf08ee6b6c 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly drilldowns: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly visualize: Record<string, string>;
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly dashboard: {
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly date_histogram: string;
readonly date_range: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessSyntax: string;
readonly luceneExpressions: string;
};
readonly indexPatterns: {
readonly loadingData: string;
readonly introduction: string;
};
readonly addData: string;
readonly kibana: string;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly luceneQuerySyntax: string;
readonly queryDsl: string;
readonly kueryQuerySyntax: string;
};
readonly date: {
readonly dateMath: string;
};
readonly management: Record<string, string>;
readonly visualize: Record<string, string>;
} | | diff --git a/docs/development/core/public/kibana-plugin-core-public.environmentmode.dev.md b/docs/development/core/public/kibana-plugin-core-public.environmentmode.dev.md deleted file mode 100644 index 68ea11c62cf96d..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.environmentmode.dev.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) > [dev](./kibana-plugin-core-public.environmentmode.dev.md) - -## EnvironmentMode.dev property - -Signature: - -```typescript -dev: boolean; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.environmentmode.md b/docs/development/core/public/kibana-plugin-core-public.environmentmode.md deleted file mode 100644 index 34ca3a00005638..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.environmentmode.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) - -## EnvironmentMode interface - - -Signature: - -```typescript -export interface EnvironmentMode -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [dev](./kibana-plugin-core-public.environmentmode.dev.md) | boolean | | -| [name](./kibana-plugin-core-public.environmentmode.name.md) | 'development' | 'production' | | -| [prod](./kibana-plugin-core-public.environmentmode.prod.md) | boolean | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.environmentmode.name.md b/docs/development/core/public/kibana-plugin-core-public.environmentmode.name.md deleted file mode 100644 index 2d1722a82417c0..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.environmentmode.name.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) > [name](./kibana-plugin-core-public.environmentmode.name.md) - -## EnvironmentMode.name property - -Signature: - -```typescript -name: 'development' | 'production'; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.environmentmode.prod.md b/docs/development/core/public/kibana-plugin-core-public.environmentmode.prod.md deleted file mode 100644 index 5145f8f6887e50..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.environmentmode.prod.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) > [prod](./kibana-plugin-core-public.environmentmode.prod.md) - -## EnvironmentMode.prod property - -Signature: - -```typescript -prod: boolean; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.freezable.md b/docs/development/core/public/kibana-plugin-core-public.freezable.md deleted file mode 100644 index fee87dde25c287..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [Freezable](./kibana-plugin-core-public.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md b/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md deleted file mode 100644 index 3ef9b6bf703eb9..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [getFlattenedObject](./kibana-plugin-core-public.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md b/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md deleted file mode 100644 index 3c2ffa6340a977..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [isRelativeUrl](./kibana-plugin-core-public.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index 08b12190ef6383..85ef00d2714159 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -27,16 +27,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | Status of the application's navLink. | | [AppStatus](./kibana-plugin-core-public.appstatus.md) | Accessibility status of an application. | -## Functions - -| Function | Description | -| --- | --- | -| [assertNever(x)](./kibana-plugin-core-public.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-public.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-public.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-public.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-public.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | - ## Interfaces | Interface | Description | @@ -65,7 +55,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | | [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | -| [EnvironmentMode](./kibana-plugin-core-public.environmentmode.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | | [FatalErrorInfo](./kibana-plugin-core-public.fatalerrorinfo.md) | Represents the message and stack of a fatal Error | | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | @@ -95,7 +84,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [OverlayBannersStart](./kibana-plugin-core-public.overlaybannersstart.md) | | | [OverlayRef](./kibana-plugin-core-public.overlayref.md) | Returned by [OverlayStart](./kibana-plugin-core-public.overlaystart.md) methods for closing a mounted overlay. | | [OverlayStart](./kibana-plugin-core-public.overlaystart.md) | | -| [PackageInfo](./kibana-plugin-core-public.packageinfo.md) | | | [Plugin](./kibana-plugin-core-public.plugin.md) | The interface that should be returned by a PluginInitializer. | | [PluginInitializerContext](./kibana-plugin-core-public.plugininitializercontext.md) | The available core services passed to a PluginInitializer | | [SavedObject](./kibana-plugin-core-public.savedobject.md) | | @@ -128,7 +116,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ToastOptions](./kibana-plugin-core-public.toastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | | [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-public.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -156,7 +143,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | -| [Freezable](./kibana-plugin-core-public.freezable.md) | | | [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | | [HandlerParameters](./kibana-plugin-core-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md b/docs/development/core/public/kibana-plugin-core-public.modifyurl.md deleted file mode 100644 index b174f733a5c646..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [modifyUrl](./kibana-plugin-core-public.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.branch.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.branch.md deleted file mode 100644 index 24fd8a74c84f11..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.branch.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) > [branch](./kibana-plugin-core-public.packageinfo.branch.md) - -## PackageInfo.branch property - -Signature: - -```typescript -branch: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildnum.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildnum.md deleted file mode 100644 index b849b7bdc2a54e..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildnum.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) > [buildNum](./kibana-plugin-core-public.packageinfo.buildnum.md) - -## PackageInfo.buildNum property - -Signature: - -```typescript -buildNum: number; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildsha.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildsha.md deleted file mode 100644 index 42e5a21ab2f540..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.buildsha.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) > [buildSha](./kibana-plugin-core-public.packageinfo.buildsha.md) - -## PackageInfo.buildSha property - -Signature: - -```typescript -buildSha: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.dist.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.dist.md deleted file mode 100644 index ac6e39e07172b4..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.dist.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) > [dist](./kibana-plugin-core-public.packageinfo.dist.md) - -## PackageInfo.dist property - -Signature: - -```typescript -dist: boolean; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.md deleted file mode 100644 index e819fb7990e5d0..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.md +++ /dev/null @@ -1,23 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) - -## PackageInfo interface - - -Signature: - -```typescript -export interface PackageInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [branch](./kibana-plugin-core-public.packageinfo.branch.md) | string | | -| [buildNum](./kibana-plugin-core-public.packageinfo.buildnum.md) | number | | -| [buildSha](./kibana-plugin-core-public.packageinfo.buildsha.md) | string | | -| [dist](./kibana-plugin-core-public.packageinfo.dist.md) | boolean | | -| [version](./kibana-plugin-core-public.packageinfo.version.md) | string | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.packageinfo.version.md b/docs/development/core/public/kibana-plugin-core-public.packageinfo.version.md deleted file mode 100644 index 5a7649a1445f6c..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.packageinfo.version.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [PackageInfo](./kibana-plugin-core-public.packageinfo.md) > [version](./kibana-plugin-core-public.packageinfo.version.md) - -## PackageInfo.version property - -Signature: - -```typescript -version: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md deleted file mode 100644 index 238dd668858969..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md deleted file mode 100644 index 161e7dc7ebfae9..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md deleted file mode 100644 index f1884718337b5f..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md deleted file mode 100644 index 2816d4c7df5413..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md deleted file mode 100644 index 5ad21f004481ce..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md deleted file mode 100644 index 2e70da2f17421c..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md deleted file mode 100644 index cedc7f0b878e37..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md deleted file mode 100644 index a9541efe0882aa..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md deleted file mode 100644 index cb28a25f9e1625..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.assertnever.md b/docs/development/core/server/kibana-plugin-core-server.assertnever.md deleted file mode 100644 index c13c88df9b9bf2..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.assertnever.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [assertNever](./kibana-plugin-core-server.assertnever.md) - -## assertNever() function - -Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking - -Signature: - -```typescript -export declare function assertNever(x: never): never; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| x | never | | - -Returns: - -`never` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecation.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecation.md deleted file mode 100644 index 6fa74bccb4fc54..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecation.md +++ /dev/null @@ -1,18 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) - -## ConfigDeprecation type - -Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. - -Signature: - -```typescript -export declare type ConfigDeprecation = (config: Record, fromPath: string, logger: ConfigDeprecationLogger) => Record; -``` - -## Remarks - -This should only be manually implemented if [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) does not provide the proper helpers for a specific deprecation need. - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.md deleted file mode 100644 index 8b34b379af67e9..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.md +++ /dev/null @@ -1,36 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) - -## ConfigDeprecationFactory interface - -Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md). - -See methods documentation for more detailed examples. - -Signature: - -```typescript -export interface ConfigDeprecationFactory -``` - -## Example - - -```typescript -const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ - rename('oldKey', 'newKey'), - unused('deprecatedKey'), -] - -``` - -## Methods - -| Method | Description | -| --- | --- | -| [rename(oldKey, newKey)](./kibana-plugin-core-server.configdeprecationfactory.rename.md) | Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. | -| [renameFromRoot(oldKey, newKey, silent)](./kibana-plugin-core-server.configdeprecationfactory.renamefromroot.md) | Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied.This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. | -| [unused(unusedKey)](./kibana-plugin-core-server.configdeprecationfactory.unused.md) | Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. | -| [unusedFromRoot(unusedKey)](./kibana-plugin-core-server.configdeprecationfactory.unusedfromroot.md) | Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied.This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.rename.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.rename.md deleted file mode 100644 index 91bf1b86fe52ec..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.rename.md +++ /dev/null @@ -1,36 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) > [rename](./kibana-plugin-core-server.configdeprecationfactory.rename.md) - -## ConfigDeprecationFactory.rename() method - -Rename a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the oldKey was found and deprecation applied. - -Signature: - -```typescript -rename(oldKey: string, newKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| oldKey | string | | -| newKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Rename 'myplugin.oldKey' to 'myplugin.newKey' - -```typescript -const provider: ConfigDeprecationProvider = ({ rename }) => [ - rename('oldKey', 'newKey'), -] - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.renamefromroot.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.renamefromroot.md deleted file mode 100644 index cc8cde9a5ed79f..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.renamefromroot.md +++ /dev/null @@ -1,39 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) > [renameFromRoot](./kibana-plugin-core-server.configdeprecationfactory.renamefromroot.md) - -## ConfigDeprecationFactory.renameFromRoot() method - -Rename a configuration property from the root configuration. Will log a deprecation warning if the oldKey was found and deprecation applied. - -This should be only used when renaming properties from different configuration's path. To rename properties from inside a plugin's configuration, use 'rename' instead. - -Signature: - -```typescript -renameFromRoot(oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| oldKey | string | | -| newKey | string | | -| silent | boolean | | - -Returns: - -`ConfigDeprecation` - -## Example - -Rename 'oldplugin.key' to 'newplugin.key' - -```typescript -const provider: ConfigDeprecationProvider = ({ renameFromRoot }) => [ - renameFromRoot('oldplugin.key', 'newplugin.key'), -] - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unused.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unused.md deleted file mode 100644 index e7443b135984fc..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unused.md +++ /dev/null @@ -1,35 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) > [unused](./kibana-plugin-core-server.configdeprecationfactory.unused.md) - -## ConfigDeprecationFactory.unused() method - -Remove a configuration property from inside a plugin's configuration path. Will log a deprecation warning if the unused key was found and deprecation applied. - -Signature: - -```typescript -unused(unusedKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| unusedKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Flags 'myplugin.deprecatedKey' as unused - -```typescript -const provider: ConfigDeprecationProvider = ({ unused }) => [ - unused('deprecatedKey'), -] - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unusedfromroot.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unusedfromroot.md deleted file mode 100644 index 8d5ed349e60e96..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationfactory.unusedfromroot.md +++ /dev/null @@ -1,37 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) > [unusedFromRoot](./kibana-plugin-core-server.configdeprecationfactory.unusedfromroot.md) - -## ConfigDeprecationFactory.unusedFromRoot() method - -Remove a configuration property from the root configuration. Will log a deprecation warning if the unused key was found and deprecation applied. - -This should be only used when removing properties from outside of a plugin's configuration. To remove properties from inside a plugin's configuration, use 'unused' instead. - -Signature: - -```typescript -unusedFromRoot(unusedKey: string): ConfigDeprecation; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| unusedKey | string | | - -Returns: - -`ConfigDeprecation` - -## Example - -Flags 'somepath.deprecatedProperty' as unused - -```typescript -const provider: ConfigDeprecationProvider = ({ unusedFromRoot }) => [ - unusedFromRoot('somepath.deprecatedProperty'), -] - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationlogger.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationlogger.md deleted file mode 100644 index 15da7d24b4a7ca..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationlogger.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationLogger](./kibana-plugin-core-server.configdeprecationlogger.md) - -## ConfigDeprecationLogger type - -Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) - -Signature: - -```typescript -export declare type ConfigDeprecationLogger = (message: string) => void; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.configdeprecationprovider.md b/docs/development/core/server/kibana-plugin-core-server.configdeprecationprovider.md deleted file mode 100644 index 64351cbdb4a71c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configdeprecationprovider.md +++ /dev/null @@ -1,28 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) - -## ConfigDeprecationProvider type - -A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md). - -See [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) for more usage examples. - -Signature: - -```typescript -export declare type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => ConfigDeprecation[]; -``` - -## Example - - -```typescript -const provider: ConfigDeprecationProvider = ({ rename, unused }) => [ - rename('oldKey', 'newKey'), - unused('deprecatedKey'), - myCustomDeprecation, -] - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.configpath.md b/docs/development/core/server/kibana-plugin-core-server.configpath.md deleted file mode 100644 index 0b15d3ca727f2c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.configpath.md +++ /dev/null @@ -1,12 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ConfigPath](./kibana-plugin-core-server.configpath.md) - -## ConfigPath type - - -Signature: - -```typescript -export declare type ConfigPath = string | string[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md b/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md deleted file mode 100644 index 946050bff0585c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [deepFreeze](./kibana-plugin-core-server.deepfreeze.md) - -## deepFreeze() function - -Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively - -Signature: - -```typescript -export declare function deepFreeze(object: T): RecursiveReadonly; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| object | T | | - -Returns: - -`RecursiveReadonly` - diff --git a/docs/development/core/server/kibana-plugin-core-server.environmentmode.dev.md b/docs/development/core/server/kibana-plugin-core-server.environmentmode.dev.md deleted file mode 100644 index c1b9d5b7e19b1b..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.environmentmode.dev.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) > [dev](./kibana-plugin-core-server.environmentmode.dev.md) - -## EnvironmentMode.dev property - -Signature: - -```typescript -dev: boolean; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.environmentmode.md b/docs/development/core/server/kibana-plugin-core-server.environmentmode.md deleted file mode 100644 index 94795754739abf..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.environmentmode.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) - -## EnvironmentMode interface - - -Signature: - -```typescript -export interface EnvironmentMode -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [dev](./kibana-plugin-core-server.environmentmode.dev.md) | boolean | | -| [name](./kibana-plugin-core-server.environmentmode.name.md) | 'development' | 'production' | | -| [prod](./kibana-plugin-core-server.environmentmode.prod.md) | boolean | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.environmentmode.name.md b/docs/development/core/server/kibana-plugin-core-server.environmentmode.name.md deleted file mode 100644 index 5627deab9e83ec..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.environmentmode.name.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) > [name](./kibana-plugin-core-server.environmentmode.name.md) - -## EnvironmentMode.name property - -Signature: - -```typescript -name: 'development' | 'production'; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.environmentmode.prod.md b/docs/development/core/server/kibana-plugin-core-server.environmentmode.prod.md deleted file mode 100644 index 1ed3fa33b89979..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.environmentmode.prod.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) > [prod](./kibana-plugin-core-server.environmentmode.prod.md) - -## EnvironmentMode.prod property - -Signature: - -```typescript -prod: boolean; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.freezable.md b/docs/development/core/server/kibana-plugin-core-server.freezable.md deleted file mode 100644 index 32ba89e8370c1e..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.freezable.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Freezable](./kibana-plugin-core-server.freezable.md) - -## Freezable type - - -Signature: - -```typescript -export declare type Freezable = { - [k: string]: any; -} | any[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md b/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md deleted file mode 100644 index 2e7850ca579f6b..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [getFlattenedObject](./kibana-plugin-core-server.getflattenedobject.md) - -## getFlattenedObject() function - -Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. - -example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } - -Signature: - -```typescript -export declare function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| rootValue | Record<string, any> | | - -Returns: - -`{ - [key: string]: any; -}` - diff --git a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md b/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md deleted file mode 100644 index bff9eb05419bec..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [isRelativeUrl](./kibana-plugin-core-server.isrelativeurl.md) - -## isRelativeUrl() function - -Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* - -Signature: - -```typescript -export declare function isRelativeUrl(candidatePath: string): boolean; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| candidatePath | string | | - -Returns: - -`boolean` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.debug.md b/docs/development/core/server/kibana-plugin-core-server.logger.debug.md deleted file mode 100644 index c2b95d92b21d14..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.debug.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [debug](./kibana-plugin-core-server.logger.debug.md) - -## Logger.debug() method - -Log messages useful for debugging and interactive investigation - -Signature: - -```typescript -debug(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.error.md b/docs/development/core/server/kibana-plugin-core-server.logger.error.md deleted file mode 100644 index 68e7499fabc320..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.error.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [error](./kibana-plugin-core-server.logger.error.md) - -## Logger.error() method - -Logs abnormal or unexpected errors or messages that caused a failure in the application flow - -Signature: - -```typescript -error(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.fatal.md b/docs/development/core/server/kibana-plugin-core-server.logger.fatal.md deleted file mode 100644 index d39194d2126b73..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.fatal.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [fatal](./kibana-plugin-core-server.logger.fatal.md) - -## Logger.fatal() method - -Logs abnormal or unexpected errors or messages that caused an unrecoverable failure - -Signature: - -```typescript -fatal(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.get.md b/docs/development/core/server/kibana-plugin-core-server.logger.get.md deleted file mode 100644 index 5f69831a738082..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.get.md +++ /dev/null @@ -1,33 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [get](./kibana-plugin-core-server.logger.get.md) - -## Logger.get() method - -Returns a new [Logger](./kibana-plugin-core-server.logger.md) instance extending the current logger context. - -Signature: - -```typescript -get(...childContextPaths: string[]): Logger; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| childContextPaths | string[] | | - -Returns: - -`Logger` - -## Example - - -```typescript -const logger = loggerFactory.get('plugin', 'service'); // 'plugin.service' context -const subLogger = logger.get('feature'); // 'plugin.service.feature' context - -``` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.info.md b/docs/development/core/server/kibana-plugin-core-server.logger.info.md deleted file mode 100644 index 7e786ed0e3f9b9..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.info.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [info](./kibana-plugin-core-server.logger.info.md) - -## Logger.info() method - -Logs messages related to general application flow - -Signature: - -```typescript -info(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.md b/docs/development/core/server/kibana-plugin-core-server.logger.md deleted file mode 100644 index 7012358524c359..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.md +++ /dev/null @@ -1,26 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) - -## Logger interface - -Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. - -Signature: - -```typescript -export interface Logger -``` - -## Methods - -| Method | Description | -| --- | --- | -| [debug(message, meta)](./kibana-plugin-core-server.logger.debug.md) | Log messages useful for debugging and interactive investigation | -| [error(errorOrMessage, meta)](./kibana-plugin-core-server.logger.error.md) | Logs abnormal or unexpected errors or messages that caused a failure in the application flow | -| [fatal(errorOrMessage, meta)](./kibana-plugin-core-server.logger.fatal.md) | Logs abnormal or unexpected errors or messages that caused an unrecoverable failure | -| [get(childContextPaths)](./kibana-plugin-core-server.logger.get.md) | Returns a new [Logger](./kibana-plugin-core-server.logger.md) instance extending the current logger context. | -| [info(message, meta)](./kibana-plugin-core-server.logger.info.md) | Logs messages related to general application flow | -| [trace(message, meta)](./kibana-plugin-core-server.logger.trace.md) | Log messages at the most detailed log level | -| [warn(errorOrMessage, meta)](./kibana-plugin-core-server.logger.warn.md) | Logs abnormal or unexpected errors or messages | - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.trace.md b/docs/development/core/server/kibana-plugin-core-server.logger.trace.md deleted file mode 100644 index b8d761f69541e3..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.trace.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [trace](./kibana-plugin-core-server.logger.trace.md) - -## Logger.trace() method - -Log messages at the most detailed log level - -Signature: - -```typescript -trace(message: string, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| message | string | The log message | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.logger.warn.md b/docs/development/core/server/kibana-plugin-core-server.logger.warn.md deleted file mode 100644 index 21cefe4f748dd5..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logger.warn.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Logger](./kibana-plugin-core-server.logger.md) > [warn](./kibana-plugin-core-server.logger.warn.md) - -## Logger.warn() method - -Logs abnormal or unexpected errors or messages - -Signature: - -```typescript -warn(errorOrMessage: string | Error, meta?: LogMeta): void; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| errorOrMessage | string | Error | An Error object or message string to log | -| meta | LogMeta | | - -Returns: - -`void` - diff --git a/docs/development/core/server/kibana-plugin-core-server.loggerfactory.get.md b/docs/development/core/server/kibana-plugin-core-server.loggerfactory.get.md deleted file mode 100644 index d081d359b94809..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.loggerfactory.get.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) > [get](./kibana-plugin-core-server.loggerfactory.get.md) - -## LoggerFactory.get() method - -Returns a `Logger` instance for the specified context. - -Signature: - -```typescript -get(...contextParts: string[]): Logger; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| contextParts | string[] | Parts of the context to return logger for. For example get('plugins', 'pid') will return a logger for the plugins.pid context. | - -Returns: - -`Logger` - diff --git a/docs/development/core/server/kibana-plugin-core-server.loggerfactory.md b/docs/development/core/server/kibana-plugin-core-server.loggerfactory.md deleted file mode 100644 index 8795413bf675a2..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.loggerfactory.md +++ /dev/null @@ -1,20 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) - -## LoggerFactory interface - -The single purpose of `LoggerFactory` interface is to define a way to retrieve a context-based logger instance. - -Signature: - -```typescript -export interface LoggerFactory -``` - -## Methods - -| Method | Description | -| --- | --- | -| [get(contextParts)](./kibana-plugin-core-server.loggerfactory.get.md) | Returns a Logger instance for the specified context. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.logmeta.md b/docs/development/core/server/kibana-plugin-core-server.logmeta.md deleted file mode 100644 index 56a2af7e826c65..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.logmeta.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LogMeta](./kibana-plugin-core-server.logmeta.md) - -## LogMeta interface - -Contextual metadata - -Signature: - -```typescript -export interface LogMeta -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index c16600d1d0492f..69f2cf0338a01d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -42,13 +42,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | Function | Description | | --- | --- | -| [assertNever(x)](./kibana-plugin-core-server.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | -| [deepFreeze(object)](./kibana-plugin-core-server.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | | [exportSavedObjectsToStream({ types, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | -| [getFlattenedObject(rootValue)](./kibana-plugin-core-server.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | | [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | -| [isRelativeUrl(candidatePath)](./kibana-plugin-core-server.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | -| [modifyUrl(url, urlModifier)](./kibana-plugin-core-server.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | | [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | ## Interfaces @@ -70,7 +65,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [Capabilities](./kibana-plugin-core-server.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | APIs to manage the [Capabilities](./kibana-plugin-core-server.capabilities.md) that will be used by the application.Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the registerProvider method.Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the registerSwitcher method.Refers to the methods documentation for complete description and examples. | | [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md) | APIs to access the application [Capabilities](./kibana-plugin-core-server.capabilities.md). | -| [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) | Provides helpers to generates the most commonly used [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) when invoking a [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md).See methods documentation for more detailed examples. | | [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | | [CoreSetup](./kibana-plugin-core-server.coresetup.md) | Context passed to the plugins setup method. | | [CoreStart](./kibana-plugin-core-server.corestart.md) | Context passed to the plugins start method. | @@ -86,7 +80,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | | [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | | -| [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) | | | [ErrorHttpResponseOptions](./kibana-plugin-core-server.errorhttpresponseoptions.md) | HTTP response parameters | | [Explanation](./kibana-plugin-core-server.explanation.md) | | | [FakeRequest](./kibana-plugin-core-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | @@ -119,11 +112,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [LegacyRequest](./kibana-plugin-core-server.legacyrequest.md) | | | [LegacyServiceSetupDeps](./kibana-plugin-core-server.legacyservicesetupdeps.md) | | | [LegacyServiceStartDeps](./kibana-plugin-core-server.legacyservicestartdeps.md) | | -| [Logger](./kibana-plugin-core-server.logger.md) | Logger exposes all the necessary methods to log any type of information and this is the interface used by the logging consumers including plugins. | | [LoggerContextConfigInput](./kibana-plugin-core-server.loggercontextconfiginput.md) | | -| [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) | The single purpose of LoggerFactory interface is to define a way to retrieve a context-based logger instance. | | [LoggingServiceSetup](./kibana-plugin-core-server.loggingservicesetup.md) | Provides APIs to plugins for customizing the plugin's logger. | -| [LogMeta](./kibana-plugin-core-server.logmeta.md) | Contextual metadata | | [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) | APIs to retrieves metrics gathered and exposed by the core platform. | | [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) | | | [OnPostAuthToolkit](./kibana-plugin-core-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. | @@ -136,7 +126,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [OpsOsMetrics](./kibana-plugin-core-server.opsosmetrics.md) | OS related metrics | | [OpsProcessMetrics](./kibana-plugin-core-server.opsprocessmetrics.md) | Process related metrics | | [OpsServerMetrics](./kibana-plugin-core-server.opsservermetrics.md) | server related metrics | -| [PackageInfo](./kibana-plugin-core-server.packageinfo.md) | | | [Plugin](./kibana-plugin-core-server.plugin.md) | The interface that should be returned by a PluginInitializer. | | [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | | [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | @@ -217,7 +206,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) | | | [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | | -| [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Variables @@ -239,14 +227,9 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AuthResult](./kibana-plugin-core-server.authresult.md) | | | [CapabilitiesProvider](./kibana-plugin-core-server.capabilitiesprovider.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | | [CapabilitiesSwitcher](./kibana-plugin-core-server.capabilitiesswitcher.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | -| [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) | Configuration deprecation returned from [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) that handles a single deprecation from the configuration. | -| [ConfigDeprecationLogger](./kibana-plugin-core-server.configdeprecationlogger.md) | Logger interface used when invoking a [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) | -| [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) | A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md).See [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) for more usage examples. | -| [ConfigPath](./kibana-plugin-core-server.configpath.md) | | | [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | | [ElasticsearchClient](./kibana-plugin-core-server.elasticsearchclient.md) | Client used to query the elasticsearch cluster. | | [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | Configuration options to be used to create a [cluster client](./kibana-plugin-core-server.iclusterclient.md) using the [createClient API](./kibana-plugin-core-server.elasticsearchservicestart.createclient.md) | -| [Freezable](./kibana-plugin-core-server.freezable.md) | | | [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | | [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) to represent the type of the context. | diff --git a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md b/docs/development/core/server/kibana-plugin-core-server.modifyurl.md deleted file mode 100644 index fc0bc354a3ca37..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md +++ /dev/null @@ -1,31 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [modifyUrl](./kibana-plugin-core-server.modifyurl.md) - -## modifyUrl() function - -Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. - -Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash - -Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints - -Signature: - -```typescript -export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| url | string | | -| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | - -Returns: - -`string` - -The modified and reformatted url - diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.branch.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.branch.md deleted file mode 100644 index 34fbd56045921a..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.branch.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) > [branch](./kibana-plugin-core-server.packageinfo.branch.md) - -## PackageInfo.branch property - -Signature: - -```typescript -branch: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildnum.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildnum.md deleted file mode 100644 index acc33fae18fbcd..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildnum.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) > [buildNum](./kibana-plugin-core-server.packageinfo.buildnum.md) - -## PackageInfo.buildNum property - -Signature: - -```typescript -buildNum: number; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildsha.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildsha.md deleted file mode 100644 index 14ad75168fd859..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.buildsha.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) > [buildSha](./kibana-plugin-core-server.packageinfo.buildsha.md) - -## PackageInfo.buildSha property - -Signature: - -```typescript -buildSha: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.dist.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.dist.md deleted file mode 100644 index d7567010ddd53f..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.dist.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) > [dist](./kibana-plugin-core-server.packageinfo.dist.md) - -## PackageInfo.dist property - -Signature: - -```typescript -dist: boolean; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.md deleted file mode 100644 index 3e1789d8df896c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.md +++ /dev/null @@ -1,23 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) - -## PackageInfo interface - - -Signature: - -```typescript -export interface PackageInfo -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [branch](./kibana-plugin-core-server.packageinfo.branch.md) | string | | -| [buildNum](./kibana-plugin-core-server.packageinfo.buildnum.md) | number | | -| [buildSha](./kibana-plugin-core-server.packageinfo.buildsha.md) | string | | -| [dist](./kibana-plugin-core-server.packageinfo.dist.md) | boolean | | -| [version](./kibana-plugin-core-server.packageinfo.version.md) | string | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.packageinfo.version.md b/docs/development/core/server/kibana-plugin-core-server.packageinfo.version.md deleted file mode 100644 index 1606ab5901941b..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.packageinfo.version.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [PackageInfo](./kibana-plugin-core-server.packageinfo.md) > [version](./kibana-plugin-core-server.packageinfo.version.md) - -## PackageInfo.version property - -Signature: - -```typescript -version: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md b/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md index d539b5a0501c15..d06b3cb9fa64ae 100644 --- a/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md +++ b/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md @@ -4,7 +4,7 @@ ## PluginConfigDescriptor.deprecations property -Provider for the [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) to apply to the plugin configuration. +Provider for the to apply to the plugin configuration. Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md b/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md index 964d45f155948e..5708c4f9a3f88a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md +++ b/docs/development/core/server/kibana-plugin-core-server.pluginconfigdescriptor.md @@ -44,7 +44,7 @@ export const config: PluginConfigDescriptor = { | Property | Type | Description | | --- | --- | --- | -| [deprecations](./kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md) | ConfigDeprecationProvider | Provider for the [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md) to apply to the plugin configuration. | +| [deprecations](./kibana-plugin-core-server.pluginconfigdescriptor.deprecations.md) | ConfigDeprecationProvider | Provider for the to apply to the plugin configuration. | | [exposeToBrowser](./kibana-plugin-core-server.pluginconfigdescriptor.exposetobrowser.md) | {
[P in keyof T]?: boolean;
} | List of configuration properties that will be available on the client-side plugin. | | [schema](./kibana-plugin-core-server.pluginconfigdescriptor.schema.md) | PluginConfigSchema<T> | Schema to use to validate the plugin configuration.[PluginConfigSchema](./kibana-plugin-core-server.pluginconfigschema.md) | diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.configpath.md b/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.configpath.md index c391431e12b1cf..8aa603242df8e1 100644 --- a/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.configpath.md +++ b/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.configpath.md @@ -4,7 +4,7 @@ ## PluginManifest.configPath property -Root [configuration path](./kibana-plugin-core-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. +Root used by the plugin, defaults to "id" in snake\_case format. Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md b/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md index 6db2f89590149f..b0182a7c48e16c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md +++ b/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md @@ -20,7 +20,7 @@ Should never be used in code outside of Core but is exported for documentation p | Property | Type | Description | | --- | --- | --- | -| [configPath](./kibana-plugin-core-server.pluginmanifest.configpath.md) | ConfigPath | Root [configuration path](./kibana-plugin-core-server.configpath.md) used by the plugin, defaults to "id" in snake\_case format. | +| [configPath](./kibana-plugin-core-server.pluginmanifest.configpath.md) | ConfigPath | Root used by the plugin, defaults to "id" in snake\_case format. | | [extraPublicDirs](./kibana-plugin-core-server.pluginmanifest.extrapublicdirs.md) | string[] | Specifies directory names that can be imported by other ui-plugins built using the same instance of the @kbn/optimizer. A temporary measure we plan to replace with better mechanisms for sharing static code between plugins | | [id](./kibana-plugin-core-server.pluginmanifest.id.md) | PluginName | Identifier of the plugin. Must be a string in camelCase. Part of a plugin public contract. Other plugins leverage it to access plugin API, navigate to the plugin, etc. | | [kibanaVersion](./kibana-plugin-core-server.pluginmanifest.kibanaversion.md) | string | The version of Kibana the plugin is compatible with, defaults to "version". | diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md deleted file mode 100644 index 0422738669a708..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) - -## URLMeaningfulParts.auth property - -Signature: - -```typescript -auth?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md deleted file mode 100644 index 13a3f4a9c95c80..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) - -## URLMeaningfulParts.hash property - -Signature: - -```typescript -hash?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md deleted file mode 100644 index 6631f6f6744c5d..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) - -## URLMeaningfulParts.hostname property - -Signature: - -```typescript -hostname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md deleted file mode 100644 index 257f7b4b634ab3..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md +++ /dev/null @@ -1,27 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) - -## URLMeaningfulParts interface - -We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". - -Signature: - -```typescript -export interface URLMeaningfulParts -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) | string | null | | -| [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) | string | null | | -| [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) | string | null | | -| [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) | string | null | | -| [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) | string | null | | -| [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) | string | null | | -| [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) | ParsedQuery | | -| [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) | boolean | null | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md deleted file mode 100644 index 8fee8c8e146ca3..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) - -## URLMeaningfulParts.pathname property - -Signature: - -```typescript -pathname?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md deleted file mode 100644 index dcf3517d92ba20..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) - -## URLMeaningfulParts.port property - -Signature: - -```typescript -port?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md deleted file mode 100644 index 914dcd4e8a8a55..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) - -## URLMeaningfulParts.protocol property - -Signature: - -```typescript -protocol?: string | null; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md deleted file mode 100644 index 358adcfd3d1800..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) - -## URLMeaningfulParts.query property - -Signature: - -```typescript -query: ParsedQuery; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md deleted file mode 100644 index d5b598167f2f29..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) - -## URLMeaningfulParts.slashes property - -Signature: - -```typescript -slashes?: boolean | null; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index cf171d9ee9f374..e85747b8cc3d7d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md index 73ba8eb66040ba..496e1ae9677d80 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md @@ -15,13 +15,13 @@ Using `createSearchSource`, the instance can be re-created. ```typescript serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; ``` Returns: `{ searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }` diff --git a/docs/management/index-lifecycle-policies/manage-policy.asciidoc b/docs/management/index-lifecycle-policies/manage-policy.asciidoc index a57af8a33494b5..8e2dc96de4b99d 100644 --- a/docs/management/index-lifecycle-policies/manage-policy.asciidoc +++ b/docs/management/index-lifecycle-policies/manage-policy.asciidoc @@ -25,4 +25,10 @@ created index. For more information, see {ref}/indices-templates.html[Index temp * *Delete a policy.* You can’t delete a policy that is currently in use or recover a deleted index. +[float] +=== Required permissions + +The `manage_ilm` cluster privilege is required to access *Index lifecycle policies*. + +You can add these privileges in *Stack Management > Security > Roles*. diff --git a/docs/management/managing-ccr.asciidoc b/docs/management/managing-ccr.asciidoc index 67193b3b5a037c..9c06e479e28b21 100644 --- a/docs/management/managing-ccr.asciidoc +++ b/docs/management/managing-ccr.asciidoc @@ -20,6 +20,13 @@ image::images/cross-cluster-replication-list-view.png[][Cross-cluster replicatio * The Elasticsearch version of the local cluster must be the same as or newer than the remote cluster. Refer to {ref}/ccr-overview.html[this document] for more information. +[float] +=== Required permissions + +The `manage` and `manage_ccr` cluster privileges are required to access *Cross-Cluster Replication*. + +You can add these privileges in *Stack Management > Security > Roles*. + [float] [[configure-replication]] === Configure replication diff --git a/docs/management/managing-licenses.asciidoc b/docs/management/managing-licenses.asciidoc index 25ae29036f6561..b53bda95466dc3 100644 --- a/docs/management/managing-licenses.asciidoc +++ b/docs/management/managing-licenses.asciidoc @@ -29,6 +29,13 @@ See {ref}/encrypting-communications.html[Encrypting communications]. {kib} and the {ref}/start-basic.html[start basic API] provide a list of all of the features that will no longer be supported if you revert to a basic license. +[float] +=== Required permissions + +The `manage` cluster privilege is required to access *License Management*. + +You can add this privilege in *Stack Management > Security > Roles*. + [discrete] [[update-license]] === Update your license diff --git a/docs/management/managing-remote-clusters.asciidoc b/docs/management/managing-remote-clusters.asciidoc index 83895838efec60..92e0fa822b0567 100644 --- a/docs/management/managing-remote-clusters.asciidoc +++ b/docs/management/managing-remote-clusters.asciidoc @@ -11,6 +11,13 @@ To get started, open the menu, then go to *Stack Management > Data > Remote Clus [role="screenshot"] image::images/remote-clusters-list-view.png[Remote Clusters list view, including Add a remote cluster button] +[float] +=== Required permissions + +The `manage` cluster privilege is required to access *Remote Clusters*. + +You can add this privilege in *Stack Management > Security > Roles*. + [float] [[managing-remote-clusters]] === Add a remote cluster diff --git a/docs/management/rollups/create_and_manage_rollups.asciidoc b/docs/management/rollups/create_and_manage_rollups.asciidoc index 8aa57f50fe94bf..e20f384b5ed181 100644 --- a/docs/management/rollups/create_and_manage_rollups.asciidoc +++ b/docs/management/rollups/create_and_manage_rollups.asciidoc @@ -20,6 +20,13 @@ image::images/management_rollup_list.png[][List of currently active rollup jobs] Before using this feature, you should be familiar with how rollups work. {ref}/xpack-rollup.html[Rolling up historical data] is a good source for more detailed information. +[float] +=== Required permissions + +The `manage_rollup` cluster privilege is required to access *Rollup jobs*. + +You can add this privilege in *Stack Management > Security > Roles*. + [float] [[create-and-manage-rollup-job]] === Create a rollup job diff --git a/docs/management/upgrade-assistant/index.asciidoc b/docs/management/upgrade-assistant/index.asciidoc index c5fd6a3a555a1d..2b8c2da2ef5772 100644 --- a/docs/management/upgrade-assistant/index.asciidoc +++ b/docs/management/upgrade-assistant/index.asciidoc @@ -13,6 +13,14 @@ Before you upgrade, make sure that you are using the latest released minor version of {es} to see the most up-to-date deprecation issues. For example, if you want to upgrade to to 7.0, make sure that you are using 6.8. +[float] +=== Required permissions + +The `manage` cluster privilege is required to access the *Upgrade assistant*. +Additional privileges may be needed to perform certain actions. + +You can add this privilege in *Stack Management > Security > Roles*. + [float] === Reindexing diff --git a/docs/migration/migrate_8_0.asciidoc b/docs/migration/migrate_8_0.asciidoc index b80503750a26e9..0cb28ce0fb6e78 100644 --- a/docs/migration/migrate_8_0.asciidoc +++ b/docs/migration/migrate_8_0.asciidoc @@ -115,7 +115,7 @@ URL that it derived from the actual server address and `xpack.security.public` s *Impact:* Any workflow that involved manually clearing generated bundles will have to be updated with the new path. -[float]] +[float] === kibana.keystore has moved from the `data` folder to the `config` folder *Details:* By default, kibana.keystore has moved from the configured `path.data` folder to `/config` for archive distributions and `/etc/kibana` for package distributions. If a pre-existing keystore exists in the data directory that path will continue to be used. @@ -136,6 +136,18 @@ custom roles with {kibana-ref}/kibana-privileges.html[{kib} privileges]. instead be assigned the `kibana_admin` role to maintain their current access level. +[float] +=== `kibana_dashboard_only_user` role has been removed. + +*Details:* The `kibana_dashboard_only_user` role has been removed. +If you wish to restrict access to just the Dashboard feature, create +custom roles with {kibana-ref}/kibana-privileges.html[{kib} privileges]. + +*Impact:* Any users currently assigned the `kibana_dashboard_only_user` role will need to be assigned a custom role which only grants access to the Dashboard feature. + +Granting additional cluster or index privileges may enable certain +**Stack Monitoring** features. + [float] [[breaking_80_reporting_changes]] === Reporting changes diff --git a/examples/alerting_example/server/plugin.ts b/examples/alerting_example/server/plugin.ts index e74cad28f77f4a..8e246960937ec3 100644 --- a/examples/alerting_example/server/plugin.ts +++ b/examples/alerting_example/server/plugin.ts @@ -38,7 +38,7 @@ export class AlertingExamplePlugin implements Plugin obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +jest.mock('../../../package.json', () => mockPackage); export const mockApplyDeprecations = jest.fn((config, deprecations, log) => config); jest.mock('./deprecation/apply_deprecations', () => ({ diff --git a/src/core/server/config/config_service.test.ts b/packages/kbn-config/src/config_service.test.ts similarity index 95% rename from src/core/server/config/config_service.test.ts rename to packages/kbn-config/src/config_service.test.ts index 95153447bd4a90..b32b4054557001 100644 --- a/src/core/server/config/config_service.test.ts +++ b/packages/kbn-config/src/config_service.test.ts @@ -20,22 +20,36 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { first, take } from 'rxjs/operators'; -import { mockPackage, mockApplyDeprecations } from './config_service.test.mocks'; -import { rawConfigServiceMock } from './raw_config_service.mock'; +import { mockApplyDeprecations } from './config_service.test.mocks'; +import { rawConfigServiceMock } from './raw/raw_config_service.mock'; import { schema } from '@kbn/config-schema'; +import { MockedLogger, loggerMock } from '@kbn/logging/target/mocks'; + +import { ConfigService, Env, RawPackageInfo } from '.'; -import { ConfigService, Env } from '.'; -import { loggingSystemMock } from '../logging/logging_system.mock'; import { getEnvOptions } from './__mocks__/env'; +const packageInfos: RawPackageInfo = { + branch: 'master', + version: '8.0.0', + build: { + number: 42, + sha: 'one', + }, +}; const emptyArgv = getEnvOptions(); -const defaultEnv = new Env('/kibana', emptyArgv); -const logger = loggingSystemMock.create(); +const defaultEnv = new Env('/kibana', packageInfos, emptyArgv); + +let logger: MockedLogger; const getRawConfigProvider = (rawConfig: Record) => rawConfigServiceMock.create({ rawConfig }); +beforeEach(() => { + logger = loggerMock.create(); +}); + test('returns config at path as observable', async () => { const rawConfig = getRawConfigProvider({ key: 'foo' }); const configService = new ConfigService(rawConfig, defaultEnv, logger); @@ -237,7 +251,7 @@ test('tracks unhandled paths', async () => { }); test('correctly passes context', async () => { - mockPackage.raw = { + const mockPackage = { branch: 'feature-v1', version: 'v1', build: { @@ -247,7 +261,7 @@ test('correctly passes context', async () => { }, }; - const env = new Env('/kibana', getEnvOptions()); + const env = new Env('/kibana', mockPackage, getEnvOptions()); const rawConfigProvider = rawConfigServiceMock.create({ rawConfig: { foo: {} } }); const schemaDefinition = schema.object({ @@ -441,9 +455,9 @@ test('logs deprecation warning during validation', async () => { return config; }); - loggingSystemMock.clear(logger); + loggerMock.clear(logger); await configService.validate(); - expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(` + expect(loggerMock.collect(logger).warn).toMatchInlineSnapshot(` Array [ Array [ "some deprecation message", diff --git a/src/core/server/config/config_service.ts b/packages/kbn-config/src/config_service.ts similarity index 97% rename from src/core/server/config/config_service.ts rename to packages/kbn-config/src/config_service.ts index bceba420bb6ce3..faa8397cd6d6ef 100644 --- a/src/core/server/config/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -17,22 +17,23 @@ * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Type } from '@kbn/config-schema'; import { isEqual } from 'lodash'; import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; import { distinctUntilChanged, first, map, shareReplay, take } from 'rxjs/operators'; +import { Logger, LoggerFactory } from '@kbn/logging'; import { Config, ConfigPath, Env } from '.'; -import { Logger, LoggerFactory } from '../logging'; import { hasConfigPathIntersection } from './config'; -import { RawConfigurationProvider } from './raw_config_service'; +import { RawConfigurationProvider } from './raw/raw_config_service'; import { applyDeprecations, ConfigDeprecationWithContext, ConfigDeprecationProvider, configDeprecationFactory, } from './deprecation'; -import { LegacyObjectToConfigAdapter } from '../legacy/config'; +import { LegacyObjectToConfigAdapter } from './legacy'; /** @internal */ export type IConfigService = PublicMethodsOf; diff --git a/src/core/server/config/deprecation/apply_deprecations.test.ts b/packages/kbn-config/src/deprecation/apply_deprecations.test.ts similarity index 100% rename from src/core/server/config/deprecation/apply_deprecations.test.ts rename to packages/kbn-config/src/deprecation/apply_deprecations.test.ts diff --git a/src/core/server/config/deprecation/apply_deprecations.ts b/packages/kbn-config/src/deprecation/apply_deprecations.ts similarity index 100% rename from src/core/server/config/deprecation/apply_deprecations.ts rename to packages/kbn-config/src/deprecation/apply_deprecations.ts diff --git a/src/core/server/config/deprecation/deprecation_factory.test.ts b/packages/kbn-config/src/deprecation/deprecation_factory.test.ts similarity index 100% rename from src/core/server/config/deprecation/deprecation_factory.test.ts rename to packages/kbn-config/src/deprecation/deprecation_factory.test.ts diff --git a/src/core/server/config/deprecation/deprecation_factory.ts b/packages/kbn-config/src/deprecation/deprecation_factory.ts similarity index 98% rename from src/core/server/config/deprecation/deprecation_factory.ts rename to packages/kbn-config/src/deprecation/deprecation_factory.ts index cbc9984924c5dd..0598347d2cffcc 100644 --- a/src/core/server/config/deprecation/deprecation_factory.ts +++ b/packages/kbn-config/src/deprecation/deprecation_factory.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { unset } from '@kbn/std'; import { ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationFactory } from './types'; -import { unset } from '../../../utils'; const _rename = ( config: Record, diff --git a/packages/kbn-config/src/deprecation/index.ts b/packages/kbn-config/src/deprecation/index.ts new file mode 100644 index 00000000000000..504dbfeeb001a4 --- /dev/null +++ b/packages/kbn-config/src/deprecation/index.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + ConfigDeprecation, + ConfigDeprecationWithContext, + ConfigDeprecationLogger, + ConfigDeprecationFactory, + ConfigDeprecationProvider, +} from './types'; +export { configDeprecationFactory } from './deprecation_factory'; +export { applyDeprecations } from './apply_deprecations'; diff --git a/src/core/server/config/deprecation/types.ts b/packages/kbn-config/src/deprecation/types.ts similarity index 100% rename from src/core/server/config/deprecation/types.ts rename to packages/kbn-config/src/deprecation/types.ts diff --git a/src/core/server/config/env.test.mocks.ts b/packages/kbn-config/src/env.test.mocks.ts similarity index 81% rename from src/core/server/config/env.test.mocks.ts rename to packages/kbn-config/src/env.test.mocks.ts index d35afdf0b66e52..3976b1c2016fbb 100644 --- a/src/core/server/config/env.test.mocks.ts +++ b/packages/kbn-config/src/env.test.mocks.ts @@ -17,7 +17,10 @@ * under the License. */ -jest.mock('path', () => ({ +const realPath = jest.requireActual('path'); + +jest.doMock('path', () => ({ + ...realPath, resolve(...pathSegments: string[]) { return pathSegments.join('/'); }, @@ -26,5 +29,10 @@ jest.mock('path', () => ({ }, })); -export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../package.json', () => mockPackage); +export const mockPackage = { + raw: {}, +}; + +jest.doMock('load-json-file', () => ({ + sync: () => mockPackage.raw, +})); diff --git a/src/core/server/config/env.test.ts b/packages/kbn-config/src/env.test.ts similarity index 89% rename from src/core/server/config/env.test.ts rename to packages/kbn-config/src/env.test.ts index 0fffcc44781d9c..f3d51a021246e5 100644 --- a/src/core/server/config/env.test.ts +++ b/packages/kbn-config/src/env.test.ts @@ -19,9 +19,24 @@ import { mockPackage } from './env.test.mocks'; -import { Env } from '.'; +import { Env, RawPackageInfo } from './env'; import { getEnvOptions } from './__mocks__/env'; +const REPO_ROOT = '/test/kibanaRoot'; + +const packageInfos: RawPackageInfo = { + branch: 'master', + version: '8.0.0', + build: { + number: 42, + sha: 'one', + }, +}; + +beforeEach(() => { + mockPackage.raw = {}; +}); + test('correctly creates default environment in dev mode.', () => { mockPackage.raw = { branch: 'some-branch', @@ -29,6 +44,7 @@ test('correctly creates default environment in dev mode.', () => { }; const defaultEnv = Env.createDefault( + REPO_ROOT, getEnvOptions({ configs: ['/test/cwd/config/kibana.yml'], isDevClusterMaster: true, @@ -50,6 +66,7 @@ test('correctly creates default environment in prod distributable mode.', () => }; const defaultEnv = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { dev: false }, configs: ['/some/other/path/some-kibana.yml'], @@ -71,6 +88,7 @@ test('correctly creates default environment in prod non-distributable mode.', () }; const defaultEnv = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { dev: false }, configs: ['/some/other/path/some-kibana.yml'], @@ -92,6 +110,7 @@ test('correctly creates default environment if `--env.name` is supplied.', () => }; const defaultDevEnv = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { envName: 'development' }, configs: ['/some/other/path/some-kibana.yml'], @@ -99,6 +118,7 @@ test('correctly creates default environment if `--env.name` is supplied.', () => ); const defaultProdEnv = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { dev: false, envName: 'production' }, configs: ['/some/other/path/some-kibana.yml'], @@ -110,18 +130,17 @@ test('correctly creates default environment if `--env.name` is supplied.', () => }); test('correctly creates environment with constructor.', () => { - mockPackage.raw = { - branch: 'feature-v1', - version: 'v1', - build: { - distributable: true, - number: 100, - sha: 'feature-v1-build-sha', - }, - }; - const env = new Env( '/some/home/dir', + { + branch: 'feature-v1', + version: 'v1', + build: { + distributable: true, + number: 100, + sha: 'feature-v1-build-sha', + }, + }, getEnvOptions({ cliArgs: { dev: false }, configs: ['/some/other/path/some-kibana.yml'], @@ -134,6 +153,7 @@ test('correctly creates environment with constructor.', () => { test('pluginSearchPaths contains x-pack plugins path if --oss flag is false', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { oss: false }, }) @@ -145,6 +165,7 @@ test('pluginSearchPaths contains x-pack plugins path if --oss flag is false', () test('pluginSearchPaths does not contains x-pack plugins path if --oss flag is true', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { oss: true }, }) @@ -156,6 +177,7 @@ test('pluginSearchPaths does not contains x-pack plugins path if --oss flag is t test('pluginSearchPaths contains examples plugins path if --run-examples flag is true', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { runExamples: true }, }) @@ -167,6 +189,7 @@ test('pluginSearchPaths contains examples plugins path if --run-examples flag is test('pluginSearchPaths contains x-pack/examples plugins path if --run-examples flag is true', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { runExamples: true }, }) @@ -178,6 +201,7 @@ test('pluginSearchPaths contains x-pack/examples plugins path if --run-examples test('pluginSearchPaths does not contains examples plugins path if --run-examples flag is false', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { runExamples: false }, }) @@ -189,6 +213,7 @@ test('pluginSearchPaths does not contains examples plugins path if --run-example test('pluginSearchPaths does not contains x-pack/examples plugins path if --run-examples flag is false', () => { const env = new Env( '/some/home/dir', + packageInfos, getEnvOptions({ cliArgs: { runExamples: false }, }) diff --git a/src/core/server/config/env.ts b/packages/kbn-config/src/env.ts similarity index 87% rename from src/core/server/config/env.ts rename to packages/kbn-config/src/env.ts index d8b056996315b8..250c7b72d47a9c 100644 --- a/src/core/server/config/env.ts +++ b/packages/kbn-config/src/env.ts @@ -17,13 +17,10 @@ * under the License. */ -import { resolve, dirname } from 'path'; +import { resolve, join } from 'path'; +import loadJsonFile from 'load-json-file'; import { PackageInfo, EnvironmentMode } from './types'; -// `require` is necessary for this to work inside x-pack code as well -// eslint-disable-next-line @typescript-eslint/no-var-requires -const pkg = require('../../../../package.json'); - /** @internal */ export interface EnvOptions { configs: string[]; @@ -50,13 +47,26 @@ export interface CliArgs { dist: boolean; } +/** @internal */ +export interface RawPackageInfo { + branch: string; + version: string; + build: { + distributable?: boolean; + number: number; + sha: string; + }; +} + export class Env { /** * @internal */ - public static createDefault(options: EnvOptions): Env { - const repoRoot = dirname(require.resolve('../../../../package.json')); - return new Env(repoRoot, options); + public static createDefault(repoRoot: string, options: EnvOptions, pkg?: RawPackageInfo): Env { + if (!pkg) { + pkg = loadJsonFile.sync(join(repoRoot, 'package.json')) as RawPackageInfo; + } + return new Env(repoRoot, pkg, options); } /** @internal */ @@ -99,7 +109,7 @@ export class Env { /** * @internal */ - constructor(public readonly homeDir: string, options: EnvOptions) { + constructor(public readonly homeDir: string, pkg: RawPackageInfo, options: EnvOptions) { this.configDir = resolve(this.homeDir, 'config'); this.binDir = resolve(this.homeDir, 'bin'); this.logDir = resolve(this.homeDir, 'log'); diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts new file mode 100644 index 00000000000000..f02514a92e606e --- /dev/null +++ b/packages/kbn-config/src/index.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + applyDeprecations, + ConfigDeprecation, + ConfigDeprecationFactory, + configDeprecationFactory, + ConfigDeprecationLogger, + ConfigDeprecationProvider, + ConfigDeprecationWithContext, +} from './deprecation'; + +export { RawConfigurationProvider, RawConfigService, getConfigFromFiles } from './raw'; + +export { ConfigService, IConfigService } from './config_service'; +export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './config'; +export { ObjectToConfigAdapter } from './object_to_config_adapter'; +export { CliArgs, Env, RawPackageInfo } from './env'; +export { EnvironmentMode, PackageInfo } from './types'; +export { LegacyObjectToConfigAdapter, LegacyLoggingConfig } from './legacy'; diff --git a/src/core/server/legacy/config/__snapshots__/legacy_object_to_config_adapter.test.ts.snap b/packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap similarity index 100% rename from src/core/server/legacy/config/__snapshots__/legacy_object_to_config_adapter.test.ts.snap rename to packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap diff --git a/packages/kbn-config/src/legacy/index.ts b/packages/kbn-config/src/legacy/index.ts new file mode 100644 index 00000000000000..cad6b754e956cf --- /dev/null +++ b/packages/kbn-config/src/legacy/index.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + LegacyObjectToConfigAdapter, + LegacyLoggingConfig, +} from './legacy_object_to_config_adapter'; diff --git a/src/core/server/legacy/config/legacy_object_to_config_adapter.test.ts b/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts similarity index 100% rename from src/core/server/legacy/config/legacy_object_to_config_adapter.test.ts rename to packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts diff --git a/src/core/server/legacy/config/legacy_object_to_config_adapter.ts b/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts similarity index 92% rename from src/core/server/legacy/config/legacy_object_to_config_adapter.ts rename to packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts index 3e496648c3af90..e8fca8735a6d93 100644 --- a/src/core/server/legacy/config/legacy_object_to_config_adapter.ts +++ b/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts @@ -17,10 +17,17 @@ * under the License. */ -import { ConfigPath } from '../../config'; -import { ObjectToConfigAdapter } from '../../config/object_to_config_adapter'; -import { LoggingConfigType } from '../../logging/logging_config'; -import { LegacyVars } from '../types'; +import { ConfigPath } from '../config'; +import { ObjectToConfigAdapter } from '../object_to_config_adapter'; + +// TODO: fix once core schemas are moved to this package +type LoggingConfigType = any; + +/** + * @internal + * @deprecated + */ +export type LegacyVars = Record; /** * Represents logging config supported by the legacy platform. diff --git a/packages/kbn-config/src/mocks.ts b/packages/kbn-config/src/mocks.ts new file mode 100644 index 00000000000000..5ca5de3a328a2b --- /dev/null +++ b/packages/kbn-config/src/mocks.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// these CANT be exported by the main entrypoint, as it cause ts check failures +// in `src/test` and `src/xpack/test` projects due to definition conflicts between +// mocha and jest declaring the same globals such as `it` or `beforeAll`, as the test +// files imports types from `core` that is importing the main `@kbn/config` entrypoint. +// For now, these should be imported using `import {} from '@kbn/config/target/mocks'` +export { configMock } from './config.mock'; +export { configServiceMock } from './config_service.mock'; +export { rawConfigServiceMock } from './raw/raw_config_service.mock'; +export { getEnvOptions } from './__mocks__/env'; diff --git a/src/core/server/config/object_to_config_adapter.test.ts b/packages/kbn-config/src/object_to_config_adapter.test.ts similarity index 100% rename from src/core/server/config/object_to_config_adapter.test.ts rename to packages/kbn-config/src/object_to_config_adapter.test.ts diff --git a/src/core/server/config/object_to_config_adapter.ts b/packages/kbn-config/src/object_to_config_adapter.ts similarity index 96% rename from src/core/server/config/object_to_config_adapter.ts rename to packages/kbn-config/src/object_to_config_adapter.ts index 50b31722dceeb2..c4d6ac02ccf052 100644 --- a/src/core/server/config/object_to_config_adapter.ts +++ b/packages/kbn-config/src/object_to_config_adapter.ts @@ -17,10 +17,10 @@ * under the License. */ -import { set } from '@elastic/safer-lodash-set'; import { cloneDeep, get, has } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { getFlattenedObject } from '@kbn/std'; -import { getFlattenedObject } from '../../utils'; import { Config, ConfigPath } from './'; /** diff --git a/src/core/server/config/__snapshots__/read_config.test.ts.snap b/packages/kbn-config/src/raw/__snapshots__/read_config.test.ts.snap similarity index 100% rename from src/core/server/config/__snapshots__/read_config.test.ts.snap rename to packages/kbn-config/src/raw/__snapshots__/read_config.test.ts.snap diff --git a/src/core/server/config/ensure_deep_object.test.ts b/packages/kbn-config/src/raw/ensure_deep_object.test.ts similarity index 100% rename from src/core/server/config/ensure_deep_object.test.ts rename to packages/kbn-config/src/raw/ensure_deep_object.test.ts diff --git a/src/core/server/config/ensure_deep_object.ts b/packages/kbn-config/src/raw/ensure_deep_object.ts similarity index 100% rename from src/core/server/config/ensure_deep_object.ts rename to packages/kbn-config/src/raw/ensure_deep_object.ts diff --git a/packages/kbn-config/src/raw/index.ts b/packages/kbn-config/src/raw/index.ts new file mode 100644 index 00000000000000..e32920fe64d672 --- /dev/null +++ b/packages/kbn-config/src/raw/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { RawConfigService, RawConfigurationProvider } from './raw_config_service'; +export { getConfigFromFiles } from './read_config'; diff --git a/src/core/server/config/raw_config_service.mock.ts b/packages/kbn-config/src/raw/raw_config_service.mock.ts similarity index 95% rename from src/core/server/config/raw_config_service.mock.ts rename to packages/kbn-config/src/raw/raw_config_service.mock.ts index fdcb17395aaadd..53ea797dac9e51 100644 --- a/src/core/server/config/raw_config_service.mock.ts +++ b/packages/kbn-config/src/raw/raw_config_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RawConfigService } from './raw_config_service'; import { Observable, of } from 'rxjs'; diff --git a/src/core/server/config/raw_config_service.test.mocks.ts b/packages/kbn-config/src/raw/raw_config_service.test.mocks.ts similarity index 100% rename from src/core/server/config/raw_config_service.test.mocks.ts rename to packages/kbn-config/src/raw/raw_config_service.test.mocks.ts diff --git a/src/core/server/config/raw_config_service.test.ts b/packages/kbn-config/src/raw/raw_config_service.test.ts similarity index 98% rename from src/core/server/config/raw_config_service.test.ts rename to packages/kbn-config/src/raw/raw_config_service.test.ts index 8846ea3847f799..444d67985250bc 100644 --- a/src/core/server/config/raw_config_service.test.ts +++ b/packages/kbn-config/src/raw/raw_config_service.test.ts @@ -20,7 +20,7 @@ import { mockGetConfigFromFiles } from './raw_config_service.test.mocks'; import { first } from 'rxjs/operators'; -import { RawConfigService } from '.'; +import { RawConfigService } from './raw_config_service'; const configFile = '/config/kibana.yml'; const anotherConfigFile = '/config/kibana.dev.yml'; diff --git a/src/core/server/config/raw_config_service.ts b/packages/kbn-config/src/raw/raw_config_service.ts similarity index 100% rename from src/core/server/config/raw_config_service.ts rename to packages/kbn-config/src/raw/raw_config_service.ts diff --git a/src/core/server/config/read_config.test.ts b/packages/kbn-config/src/raw/read_config.test.ts similarity index 96% rename from src/core/server/config/read_config.test.ts rename to packages/kbn-config/src/raw/read_config.test.ts index 46b75f28eb987b..89b73c5d4e26ae 100644 --- a/src/core/server/config/read_config.test.ts +++ b/packages/kbn-config/src/raw/read_config.test.ts @@ -20,7 +20,7 @@ import { relative, resolve } from 'path'; import { getConfigFromFiles } from './read_config'; -const fixtureFile = (name: string) => `${__dirname}/__fixtures__/${name}`; +const fixtureFile = (name: string) => resolve(`${__dirname}/../../__fixtures__/${name}`); test('reads single yaml from file system and parses to json', () => { const config = getConfigFromFiles([fixtureFile('config.yml')]); diff --git a/src/core/server/config/read_config.ts b/packages/kbn-config/src/raw/read_config.ts similarity index 100% rename from src/core/server/config/read_config.ts rename to packages/kbn-config/src/raw/read_config.ts diff --git a/src/core/server/config/types.ts b/packages/kbn-config/src/types.ts similarity index 100% rename from src/core/server/config/types.ts rename to packages/kbn-config/src/types.ts diff --git a/packages/kbn-config/tsconfig.json b/packages/kbn-config/tsconfig.json new file mode 100644 index 00000000000000..ba00ddfa6adb6f --- /dev/null +++ b/packages/kbn-config/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "outDir": "./target", + "stripInternal": false, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": ["./src/**/*.ts"], + "exclude": ["target"] +} diff --git a/packages/kbn-config/yarn.lock b/packages/kbn-config/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-config/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index 4f6f995f38f31b..a3fe8178822aa5 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@babel/core": "^7.11.1", + "@kbn/utils": "1.0.0", "axios": "^0.19.0", "chalk": "^4.1.0", "cheerio": "0.22.0", diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts index 2871fe2ffcf4a0..8217999b01128a 100644 --- a/packages/kbn-dev-utils/src/index.ts +++ b/packages/kbn-dev-utils/src/index.ts @@ -17,6 +17,7 @@ * under the License. */ +export { REPO_ROOT } from '@kbn/utils'; export { withProcRunner, ProcRunner } from './proc_runner'; export * from './tooling_log'; export * from './serializers'; @@ -33,7 +34,6 @@ export { KBN_P12_PATH, KBN_P12_PASSWORD, } from './certs'; -export { REPO_ROOT } from './repo_root'; export { KbnClient } from './kbn_client'; export * from './run'; export * from './axios'; diff --git a/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts b/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts index 783d584656b177..5d92ddb600aa9e 100644 --- a/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts +++ b/packages/kbn-dev-utils/src/plugin_list/discover_plugins.ts @@ -22,8 +22,8 @@ import Fs from 'fs'; import MarkdownIt from 'markdown-it'; import cheerio from 'cheerio'; +import { REPO_ROOT } from '@kbn/utils'; -import { REPO_ROOT } from '../repo_root'; import { simpleKibanaPlatformPluginDiscovery } from '../simple_kibana_platform_plugin_discovery'; import { extractAsciidocInfo } from './extract_asciidoc_info'; diff --git a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts index 43dac1cb7d418d..e1a1323553113a 100644 --- a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts +++ b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts @@ -20,8 +20,8 @@ import Path from 'path'; import normalizePath from 'normalize-path'; +import { REPO_ROOT } from '@kbn/utils'; -import { REPO_ROOT } from '../repo_root'; import { Plugins } from './discover_plugins'; function* printPlugins(plugins: Plugins, includes: string[]) { diff --git a/packages/kbn-dev-utils/src/plugin_list/run_plugin_list_cli.ts b/packages/kbn-dev-utils/src/plugin_list/run_plugin_list_cli.ts index 553eb1dd8afa07..613f9c9c264116 100644 --- a/packages/kbn-dev-utils/src/plugin_list/run_plugin_list_cli.ts +++ b/packages/kbn-dev-utils/src/plugin_list/run_plugin_list_cli.ts @@ -19,10 +19,9 @@ import Path from 'path'; import Fs from 'fs'; +import { REPO_ROOT } from '@kbn/utils'; import { run } from '../run'; -import { REPO_ROOT } from '../repo_root'; - import { discoverPlugins } from './discover_plugins'; import { generatePluginList } from './generate_plugin_list'; diff --git a/packages/kbn-dev-utils/src/precommit_hook/cli.ts b/packages/kbn-dev-utils/src/precommit_hook/cli.ts index a83e8c2b193d9e..28347f379150f6 100644 --- a/packages/kbn-dev-utils/src/precommit_hook/cli.ts +++ b/packages/kbn-dev-utils/src/precommit_hook/cli.ts @@ -20,9 +20,9 @@ import Path from 'path'; import { chmod, writeFile } from 'fs'; import { promisify } from 'util'; +import { REPO_ROOT } from '@kbn/utils'; import { run } from '../run'; -import { REPO_ROOT } from '../repo_root'; import { SCRIPT_SOURCE } from './script_source'; import { getGitDir } from './get_git_dir'; diff --git a/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts b/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts index 5ca7d67d0d4ead..f75c86f5100952 100644 --- a/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts +++ b/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts @@ -19,7 +19,7 @@ import execa from 'execa'; -import { REPO_ROOT } from '../repo_root'; +import { REPO_ROOT } from '@kbn/utils'; // Retrieves the correct location for the .git dir for // every git setup (including git worktree) diff --git a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts index 4008cf852c3a81..cc6b8334d76cff 100644 --- a/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts +++ b/packages/kbn-dev-utils/src/serializers/absolute_path_serializer.ts @@ -17,7 +17,7 @@ * under the License. */ -import { REPO_ROOT } from '../repo_root'; +import { REPO_ROOT } from '@kbn/utils'; export function createAbsolutePathSerializer( rootPath: string = REPO_ROOT, diff --git a/packages/kbn-logging/README.md b/packages/kbn-logging/README.md new file mode 100644 index 00000000000000..8bde73722deb00 --- /dev/null +++ b/packages/kbn-logging/README.md @@ -0,0 +1,61 @@ +# kbn-logging + +Base types for the kibana platform logging system. + +Note that this package currently only contains logging types. The only concrete implementation +is still in `core` for now. + +- [Loggers, Appenders and Layouts](#loggers-appenders-and-layouts) +- [Logger hierarchy](#logger-hierarchy) +- [Log level](#log-level) +- [Layouts](#layouts) + +The way logging works in Kibana is inspired by `log4j 2` logging framework used by [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html#logging). +The main idea is to have consistent logging behaviour (configuration, log format etc.) across the entire Elastic Stack +where possible. + +## Loggers, Appenders and Layouts + +Kibana logging system has three main components: _loggers_, _appenders_ and _layouts_. These components allow us to log +messages according to message type and level, and to control how these messages are formatted and where the final logs +will be displayed or stored. + +__Loggers__ define what logging settings should be applied at the particular context. + +__Appenders__ define where log messages are displayed (eg. stdout or console) and stored (eg. file on the disk). + +__Layouts__ define how log messages are formatted and what type of information they include. + + +## Logger hierarchy + +Every logger has its unique name or context that follows hierarchical naming rule. The logger is considered to be an +ancestor of another logger if its name followed by a `.` is a prefix of the descendant logger name. For example logger +with `a.b` context is an ancestor of logger with `a.b.c` context. All top-level loggers are descendants of special +logger with `root` context that resides at the top of the logger hierarchy. This logger always exists and +fully configured. + +Developer can configure _log level_ and _appenders_ that should be used within particular context. If logger configuration +specifies only _log level_ then _appenders_ configuration will be inherited from the ancestor logger. + +__Note:__ in the current implementation log messages are only forwarded to appenders configured for a particular logger +context or to appenders of the closest ancestor if current logger doesn't have any appenders configured. That means that +we __don't support__ so called _appender additivity_ when log messages are forwarded to _every_ distinct appender within +ancestor chain including `root`. + +## Log level + +Currently we support the following log levels: _all_, _fatal_, _error_, _warn_, _info_, _debug_, _trace_, _off_. +Levels are ordered, so _all_ > _fatal_ > _error_ > _warn_ > _info_ > _debug_ > _trace_ > _off_. +A log record is being logged by the logger if its level is higher than or equal to the level of its logger. Otherwise, +the log record is ignored. + +The _all_ and _off_ levels can be used only in configuration and are just handy shortcuts that allow developer to log every +log record or disable logging entirely for the specific context. + +## Layouts + +Every appender should know exactly how to format log messages before they are written to the console or file on the disk. +This behaviour is controlled by the layouts and configured through `appender.layout` configuration property for every +custom appender. Currently we don't define any default layout for the custom appenders, so one should always make the choice +explicitly. diff --git a/packages/kbn-logging/package.json b/packages/kbn-logging/package.json new file mode 100644 index 00000000000000..922d5627336223 --- /dev/null +++ b/packages/kbn-logging/package.json @@ -0,0 +1,18 @@ +{ + "name": "@kbn/logging", + "version": "1.0.0", + "private": true, + "license": "Apache-2.0", + "main": "./target/index.js", + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + }, + "dependencies": { + "@kbn/std": "1.0.0" + }, + "devDependencies": { + "typescript": "4.0.2" + } +} diff --git a/packages/kbn-logging/src/appenders.ts b/packages/kbn-logging/src/appenders.ts new file mode 100644 index 00000000000000..346d3d6dd10687 --- /dev/null +++ b/packages/kbn-logging/src/appenders.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { LogRecord } from './log_record'; + +/** + * Entity that can append `LogRecord` instances to file, stdout, memory or whatever + * is implemented internally. It's supposed to be used by `Logger`. + * @internal + */ +export interface Appender { + append(record: LogRecord): void; +} + +/** + * This interface should be additionally implemented by the `Appender`'s if they are supposed + * to be properly disposed. It's intentionally separated from `Appender` interface so that `Logger` + * that interacts with `Appender` doesn't have control over appender lifetime. + * @internal + */ +export interface DisposableAppender extends Appender { + dispose: () => void; +} diff --git a/packages/kbn-logging/src/index.ts b/packages/kbn-logging/src/index.ts new file mode 100644 index 00000000000000..d06218ac2eeb5c --- /dev/null +++ b/packages/kbn-logging/src/index.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { LogLevel, LogLevelId } from './log_level'; +export { LogRecord } from './log_record'; +export { Logger, LogMeta } from './logger'; +export { LoggerFactory } from './logger_factory'; +export { Layout } from './layout'; +export { Appender, DisposableAppender } from './appenders'; diff --git a/packages/kbn-logging/src/layout.ts b/packages/kbn-logging/src/layout.ts new file mode 100644 index 00000000000000..75556eab88bb67 --- /dev/null +++ b/packages/kbn-logging/src/layout.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { LogRecord } from './log_record'; + +/** + * Entity that can format `LogRecord` instance into a string. + * @internal + */ +export interface Layout { + format(record: LogRecord): string; +} diff --git a/src/core/server/logging/log_level.test.ts b/packages/kbn-logging/src/log_level.test.ts similarity index 100% rename from src/core/server/logging/log_level.test.ts rename to packages/kbn-logging/src/log_level.test.ts diff --git a/src/core/server/logging/log_level.ts b/packages/kbn-logging/src/log_level.ts similarity index 98% rename from src/core/server/logging/log_level.ts rename to packages/kbn-logging/src/log_level.ts index 577239ddae8e55..165e56e632d6db 100644 --- a/src/core/server/logging/log_level.ts +++ b/packages/kbn-logging/src/log_level.ts @@ -17,7 +17,7 @@ * under the License. */ -import { assertNever } from '../../utils'; +import { assertNever } from '@kbn/std'; /** * Possible log level string values. diff --git a/src/core/server/logging/log_record.ts b/packages/kbn-logging/src/log_record.ts similarity index 100% rename from src/core/server/logging/log_record.ts rename to packages/kbn-logging/src/log_record.ts diff --git a/packages/kbn-logging/src/logger.ts b/packages/kbn-logging/src/logger.ts new file mode 100644 index 00000000000000..50e002a87fc52f --- /dev/null +++ b/packages/kbn-logging/src/logger.ts @@ -0,0 +1,96 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { LogRecord } from './log_record'; + +/** + * Contextual metadata + * + * @public + */ +export interface LogMeta { + [key: string]: any; +} + +/** + * Logger exposes all the necessary methods to log any type of information and + * this is the interface used by the logging consumers including plugins. + * + * @public + */ +export interface Logger { + /** + * Log messages at the most detailed log level + * + * @param message - The log message + * @param meta - + */ + trace(message: string, meta?: LogMeta): void; + + /** + * Log messages useful for debugging and interactive investigation + * @param message - The log message + * @param meta - + */ + debug(message: string, meta?: LogMeta): void; + + /** + * Logs messages related to general application flow + * @param message - The log message + * @param meta - + */ + info(message: string, meta?: LogMeta): void; + + /** + * Logs abnormal or unexpected errors or messages + * @param errorOrMessage - An Error object or message string to log + * @param meta - + */ + warn(errorOrMessage: string | Error, meta?: LogMeta): void; + + /** + * Logs abnormal or unexpected errors or messages that caused a failure in the application flow + * + * @param errorOrMessage - An Error object or message string to log + * @param meta - + */ + error(errorOrMessage: string | Error, meta?: LogMeta): void; + + /** + * Logs abnormal or unexpected errors or messages that caused an unrecoverable failure + * + * @param errorOrMessage - An Error object or message string to log + * @param meta - + */ + fatal(errorOrMessage: string | Error, meta?: LogMeta): void; + + /** @internal */ + log(record: LogRecord): void; + + /** + * Returns a new {@link Logger} instance extending the current logger context. + * + * @example + * ```typescript + * const logger = loggerFactory.get('plugin', 'service'); // 'plugin.service' context + * const subLogger = logger.get('feature'); // 'plugin.service.feature' context + * ``` + */ + get(...childContextPaths: string[]): Logger; +} diff --git a/src/core/server/logging/logger_factory.ts b/packages/kbn-logging/src/logger_factory.ts similarity index 100% rename from src/core/server/logging/logger_factory.ts rename to packages/kbn-logging/src/logger_factory.ts diff --git a/packages/kbn-logging/src/mocks/index.ts b/packages/kbn-logging/src/mocks/index.ts new file mode 100644 index 00000000000000..c7be3a1b8ce8c7 --- /dev/null +++ b/packages/kbn-logging/src/mocks/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { MockedLogger, loggerMock } from './logger.mock'; diff --git a/packages/kbn-logging/src/mocks/logger.mock.ts b/packages/kbn-logging/src/mocks/logger.mock.ts new file mode 100644 index 00000000000000..1a4c7a2dadf68a --- /dev/null +++ b/packages/kbn-logging/src/mocks/logger.mock.ts @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Logger } from '../logger'; + +export type MockedLogger = jest.Mocked & { context: string[] }; + +const createLoggerMock = (context: string[] = []) => { + const mockLog: MockedLogger = { + context, + debug: jest.fn(), + error: jest.fn(), + fatal: jest.fn(), + info: jest.fn(), + log: jest.fn(), + trace: jest.fn(), + warn: jest.fn(), + get: jest.fn(), + }; + mockLog.get.mockImplementation((...ctx) => ({ + ctx, + ...mockLog, + })); + + return mockLog; +}; + +const clearLoggerMock = (logger: MockedLogger) => { + logger.debug.mockClear(); + logger.info.mockClear(); + logger.warn.mockClear(); + logger.error.mockClear(); + logger.trace.mockClear(); + logger.fatal.mockClear(); + logger.log.mockClear(); +}; + +const collectLoggerMock = (logger: MockedLogger) => { + return { + debug: logger.debug.mock.calls, + error: logger.error.mock.calls, + fatal: logger.fatal.mock.calls, + info: logger.info.mock.calls, + log: logger.log.mock.calls, + trace: logger.trace.mock.calls, + warn: logger.warn.mock.calls, + }; +}; + +export const loggerMock = { + create: createLoggerMock, + clear: clearLoggerMock, + collect: collectLoggerMock, +}; diff --git a/packages/kbn-logging/tsconfig.json b/packages/kbn-logging/tsconfig.json new file mode 100644 index 00000000000000..c55c05de30a528 --- /dev/null +++ b/packages/kbn-logging/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target", + "stripInternal": false, + "declaration": true, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": ["./src/**/*.ts"] +} diff --git a/packages/kbn-logging/yarn.lock b/packages/kbn-logging/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-logging/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-optimizer/README.md b/packages/kbn-optimizer/README.md index 13be836f0ea885..a666907f026789 100644 --- a/packages/kbn-optimizer/README.md +++ b/packages/kbn-optimizer/README.md @@ -69,7 +69,8 @@ To run the optimizer from code, you can import the [`OptimizerConfig`][Optimizer Example: ```ts import { runOptimizer, OptimizerConfig, logOptimizerState } from '@kbn/optimizer'; -import { REPO_ROOT, ToolingLog } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { ToolingLog } from '@kbn/dev-utils'; const log = new ToolingLog({ level: 'verbose', diff --git a/packages/kbn-optimizer/src/cli.ts b/packages/kbn-optimizer/src/cli.ts index 542dc7255f22f2..dcfb56be66efd8 100644 --- a/packages/kbn-optimizer/src/cli.ts +++ b/packages/kbn-optimizer/src/cli.ts @@ -21,7 +21,8 @@ import 'source-map-support/register'; import Path from 'path'; -import { run, REPO_ROOT, createFlagError, CiStatsReporter } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { run, createFlagError, CiStatsReporter } from '@kbn/dev-utils'; import { logOptimizerState } from './log_optimizer_state'; import { OptimizerConfig } from './optimizer'; diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index 12f037f5080fc4..de3838eb92975c 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -25,7 +25,8 @@ import { inspect } from 'util'; import cpy from 'cpy'; import del from 'del'; import { toArray, tap, filter } from 'rxjs/operators'; -import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { ToolingLog } from '@kbn/dev-utils'; import { runOptimizer, OptimizerConfig, OptimizerUpdate, logOptimizerState } from '@kbn/optimizer'; const TMP_DIR = Path.resolve(__dirname, '../__fixtures__/__tmp__'); diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts index 47d01347a8f7d1..1b4c9b117c4c30 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.test.ts @@ -20,7 +20,8 @@ import Path from 'path'; import jestDiff from 'jest-diff'; -import { REPO_ROOT, createAbsolutePathSerializer } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import { reformatJestDiff, getOptimizerCacheKey, diffCacheKey } from './cache_keys'; import { OptimizerConfig } from './optimizer_config'; diff --git a/packages/kbn-optimizer/src/optimizer/cache_keys.ts b/packages/kbn-optimizer/src/optimizer/cache_keys.ts index d0aaad979485d2..8dde67683a7394 100644 --- a/packages/kbn-optimizer/src/optimizer/cache_keys.ts +++ b/packages/kbn-optimizer/src/optimizer/cache_keys.ts @@ -23,7 +23,7 @@ import { promisify } from 'util'; import Chalk from 'chalk'; import execa from 'execa'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import stripAnsi from 'strip-ansi'; import jestDiff from 'jest-diff'; diff --git a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts index 3cc58e744a7b94..6edcde56e26de9 100644 --- a/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts +++ b/packages/kbn-optimizer/src/optimizer/handle_optimizer_completion.test.ts @@ -18,7 +18,7 @@ */ import * as Rx from 'rxjs'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { Update } from '../common'; diff --git a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts index afc2dc8952c87a..fd887e8c2c0122 100644 --- a/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts +++ b/packages/kbn-optimizer/src/optimizer/optimizer_config.test.ts @@ -32,7 +32,8 @@ jest.mock('os', () => { }); import Path from 'path'; -import { REPO_ROOT, createAbsolutePathSerializer } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import { OptimizerConfig, ParsedOptions } from './optimizer_config'; import { parseThemeTags } from '../common'; diff --git a/packages/kbn-plugin-generator/src/ask_questions.ts b/packages/kbn-plugin-generator/src/ask_questions.ts index b5983961872454..732e22b0e22259 100644 --- a/packages/kbn-plugin-generator/src/ask_questions.ts +++ b/packages/kbn-plugin-generator/src/ask_questions.ts @@ -19,7 +19,7 @@ import Path from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import inquirer from 'inquirer'; export interface Answers { diff --git a/packages/kbn-plugin-generator/src/cli.ts b/packages/kbn-plugin-generator/src/cli.ts index f6966a245e46fc..14c910a943fd5f 100644 --- a/packages/kbn-plugin-generator/src/cli.ts +++ b/packages/kbn-plugin-generator/src/cli.ts @@ -21,7 +21,8 @@ import Path from 'path'; import Fs from 'fs'; import execa from 'execa'; -import { REPO_ROOT, run, createFailError, createFlagError } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { run, createFailError, createFlagError } from '@kbn/dev-utils'; import { snakeCase } from './casing'; import { askQuestions, getDefaultAnswers } from './ask_questions'; diff --git a/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts b/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts index b48113afc0ca7e..25669b65e1ac9c 100644 --- a/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts +++ b/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts @@ -21,7 +21,8 @@ import Path from 'path'; import del from 'del'; import execa from 'execa'; -import { REPO_ROOT, createAbsolutePathSerializer } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import globby from 'globby'; const GENERATED_DIR = Path.resolve(REPO_ROOT, `plugins`); diff --git a/packages/kbn-plugin-generator/src/plugin_types.ts b/packages/kbn-plugin-generator/src/plugin_types.ts index ae5201f4e8dbb2..778e33353a2aaa 100644 --- a/packages/kbn-plugin-generator/src/plugin_types.ts +++ b/packages/kbn-plugin-generator/src/plugin_types.ts @@ -19,7 +19,7 @@ import Path from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; export interface PluginType { thirdParty: boolean; diff --git a/packages/kbn-plugin-generator/src/render_template.ts b/packages/kbn-plugin-generator/src/render_template.ts index 894088c1196516..ecb168042b1c2b 100644 --- a/packages/kbn-plugin-generator/src/render_template.ts +++ b/packages/kbn-plugin-generator/src/render_template.ts @@ -23,7 +23,8 @@ import { promisify } from 'util'; import vfs from 'vinyl-fs'; import prettier from 'prettier'; -import { REPO_ROOT, transformFileStream } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { transformFileStream } from '@kbn/dev-utils'; import ejs from 'ejs'; import { Minimatch } from 'minimatch'; diff --git a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts index be23d8dbde6467..5c1ecc4ee4ee48 100644 --- a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts @@ -21,7 +21,8 @@ import Path from 'path'; import Fs from 'fs'; import execa from 'execa'; -import { createStripAnsiSerializer, REPO_ROOT, createReplaceSerializer } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createStripAnsiSerializer, createReplaceSerializer } from '@kbn/dev-utils'; import extract from 'extract-zip'; import del from 'del'; import globby from 'globby'; diff --git a/packages/kbn-plugin-helpers/src/load_kibana_platform_plugin.ts b/packages/kbn-plugin-helpers/src/load_kibana_platform_plugin.ts index 8f48670e49de45..8ed20a26649e7c 100644 --- a/packages/kbn-plugin-helpers/src/load_kibana_platform_plugin.ts +++ b/packages/kbn-plugin-helpers/src/load_kibana_platform_plugin.ts @@ -19,12 +19,8 @@ import Path from 'path'; -import { - REPO_ROOT, - parseKibanaPlatformPlugin, - KibanaPlatformPlugin, - createFailError, -} from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { parseKibanaPlatformPlugin, KibanaPlatformPlugin, createFailError } from '@kbn/dev-utils'; export type Plugin = KibanaPlatformPlugin; diff --git a/packages/kbn-plugin-helpers/src/tasks/optimize.ts b/packages/kbn-plugin-helpers/src/tasks/optimize.ts index 6cfeda8b2d81ba..fc1bf48cc0e36e 100644 --- a/packages/kbn-plugin-helpers/src/tasks/optimize.ts +++ b/packages/kbn-plugin-helpers/src/tasks/optimize.ts @@ -21,7 +21,7 @@ import Fs from 'fs'; import Path from 'path'; import { promisify } from 'util'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { OptimizerConfig, runOptimizer, logOptimizerState } from '@kbn/optimizer'; import { BuildContext } from '../build_context'; diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 914ca2fd65fa24..1fb94e4c92ce13 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -66,6 +66,7 @@ "write-pkg": "^4.0.0" }, "dependencies": { + "@kbn/utils": "1.0.0", "tslib": "^2.0.0" } } diff --git a/packages/kbn-release-notes/package.json b/packages/kbn-release-notes/package.json index 12d0122f9a4d3d..f8971fa02aa872 100644 --- a/packages/kbn-release-notes/package.json +++ b/packages/kbn-release-notes/package.json @@ -8,6 +8,7 @@ "kbn:watch": "tsc --watch" }, "dependencies": { + "@kbn/utils": "1.0.0", "@kbn/dev-utils": "1.0.0", "axios": "^0.19.2", "cheerio": "0.22.0", diff --git a/packages/kbn-release-notes/src/cli.ts b/packages/kbn-release-notes/src/cli.ts index 7dcfa380783919..dff59d79cb2b29 100644 --- a/packages/kbn-release-notes/src/cli.ts +++ b/packages/kbn-release-notes/src/cli.ts @@ -21,7 +21,8 @@ import Fs from 'fs'; import Path from 'path'; import { inspect } from 'util'; -import { run, createFlagError, createFailError, REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { run, createFlagError, createFailError } from '@kbn/dev-utils'; import { FORMATS, SomeFormat } from './formats'; import { diff --git a/packages/kbn-std/README.md b/packages/kbn-std/README.md new file mode 100644 index 00000000000000..dfd98287ada4b5 --- /dev/null +++ b/packages/kbn-std/README.md @@ -0,0 +1,3 @@ +# `@kbn/std` — Kibana standard library + +This package is a set of utilities that can be used both on server-side and client-side. \ No newline at end of file diff --git a/packages/kbn-std/package.json b/packages/kbn-std/package.json new file mode 100644 index 00000000000000..2cc9fd72082be5 --- /dev/null +++ b/packages/kbn-std/package.json @@ -0,0 +1,20 @@ +{ + "name": "@kbn/std", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build" + }, + "devDependencies": { + "typescript": "4.0.2", + "tsd": "^0.13.1" + }, + "dependencies": { + "@kbn/utility-types": "1.0.0", + "lodash": "^4.17.15" + } +} diff --git a/src/core/utils/__snapshots__/get.test.ts.snap b/packages/kbn-std/src/__snapshots__/get.test.ts.snap similarity index 100% rename from src/core/utils/__snapshots__/get.test.ts.snap rename to packages/kbn-std/src/__snapshots__/get.test.ts.snap diff --git a/src/core/utils/assert_never.ts b/packages/kbn-std/src/assert_never.ts similarity index 100% rename from src/core/utils/assert_never.ts rename to packages/kbn-std/src/assert_never.ts diff --git a/src/core/utils/deep_freeze.test.ts b/packages/kbn-std/src/deep_freeze.test.ts similarity index 100% rename from src/core/utils/deep_freeze.test.ts rename to packages/kbn-std/src/deep_freeze.test.ts diff --git a/src/core/utils/deep_freeze.ts b/packages/kbn-std/src/deep_freeze.ts similarity index 100% rename from src/core/utils/deep_freeze.ts rename to packages/kbn-std/src/deep_freeze.ts diff --git a/src/core/utils/get.test.ts b/packages/kbn-std/src/get.test.ts similarity index 100% rename from src/core/utils/get.test.ts rename to packages/kbn-std/src/get.test.ts diff --git a/src/core/utils/get.ts b/packages/kbn-std/src/get.ts similarity index 100% rename from src/core/utils/get.ts rename to packages/kbn-std/src/get.ts diff --git a/src/core/utils/get_flattened_object.test.ts b/packages/kbn-std/src/get_flattened_object.test.ts similarity index 100% rename from src/core/utils/get_flattened_object.test.ts rename to packages/kbn-std/src/get_flattened_object.test.ts diff --git a/src/core/utils/get_flattened_object.ts b/packages/kbn-std/src/get_flattened_object.ts similarity index 100% rename from src/core/utils/get_flattened_object.ts rename to packages/kbn-std/src/get_flattened_object.ts diff --git a/packages/kbn-std/src/index.ts b/packages/kbn-std/src/index.ts new file mode 100644 index 00000000000000..8cffcd43d75379 --- /dev/null +++ b/packages/kbn-std/src/index.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { assertNever } from './assert_never'; +export { deepFreeze, Freezable } from './deep_freeze'; +export { get } from './get'; +export { mapToObject } from './map_to_object'; +export { merge } from './merge'; +export { pick } from './pick'; +export { withTimeout } from './promise'; +export { isRelativeUrl, modifyUrl, URLMeaningfulParts, ParsedQuery } from './url'; +export { unset } from './unset'; +export { getFlattenedObject } from './get_flattened_object'; diff --git a/src/core/utils/map_to_object.ts b/packages/kbn-std/src/map_to_object.ts similarity index 100% rename from src/core/utils/map_to_object.ts rename to packages/kbn-std/src/map_to_object.ts diff --git a/src/core/utils/map_utils.test.ts b/packages/kbn-std/src/map_utils.test.ts similarity index 100% rename from src/core/utils/map_utils.test.ts rename to packages/kbn-std/src/map_utils.test.ts diff --git a/src/core/utils/map_utils.ts b/packages/kbn-std/src/map_utils.ts similarity index 100% rename from src/core/utils/map_utils.ts rename to packages/kbn-std/src/map_utils.ts diff --git a/src/core/utils/merge.test.ts b/packages/kbn-std/src/merge.test.ts similarity index 100% rename from src/core/utils/merge.test.ts rename to packages/kbn-std/src/merge.test.ts diff --git a/src/core/utils/merge.ts b/packages/kbn-std/src/merge.ts similarity index 98% rename from src/core/utils/merge.ts rename to packages/kbn-std/src/merge.ts index 43878c27b1e199..c0de50544a34e1 100644 --- a/src/core/utils/merge.ts +++ b/packages/kbn-std/src/merge.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { isPlainObject } from 'lodash'; +import isPlainObject from 'lodash/isPlainObject'; /** * Deeply merges two objects, omitting undefined values, and not deeply merging Arrays. * diff --git a/src/core/utils/pick.ts b/packages/kbn-std/src/pick.ts similarity index 100% rename from src/core/utils/pick.ts rename to packages/kbn-std/src/pick.ts diff --git a/src/core/utils/promise.test.ts b/packages/kbn-std/src/promise.test.ts similarity index 100% rename from src/core/utils/promise.test.ts rename to packages/kbn-std/src/promise.test.ts diff --git a/src/core/utils/promise.ts b/packages/kbn-std/src/promise.ts similarity index 100% rename from src/core/utils/promise.ts rename to packages/kbn-std/src/promise.ts diff --git a/src/core/utils/unset.test.ts b/packages/kbn-std/src/unset.test.ts similarity index 100% rename from src/core/utils/unset.test.ts rename to packages/kbn-std/src/unset.test.ts diff --git a/src/core/utils/unset.ts b/packages/kbn-std/src/unset.ts similarity index 100% rename from src/core/utils/unset.ts rename to packages/kbn-std/src/unset.ts diff --git a/src/core/utils/url.test.ts b/packages/kbn-std/src/url.test.ts similarity index 100% rename from src/core/utils/url.test.ts rename to packages/kbn-std/src/url.test.ts diff --git a/src/core/utils/url.ts b/packages/kbn-std/src/url.ts similarity index 96% rename from src/core/utils/url.ts rename to packages/kbn-std/src/url.ts index 910fc8eaa43818..7a0f08130816de 100644 --- a/src/core/utils/url.ts +++ b/packages/kbn-std/src/url.ts @@ -16,9 +16,14 @@ * specific language governing permissions and limitations * under the License. */ -import { ParsedQuery } from 'query-string'; + import { format as formatUrl, parse as parseUrl, UrlObject } from 'url'; +// duplicate type from 'query-string' to avoid adding the d.ts file to all packages depending on kbn-std +export interface ParsedQuery { + [key: string]: T | T[] | null | undefined; +} + /** * We define our own typings because the current version of @types/node * declares properties to be optional "hostname?: string". diff --git a/packages/kbn-std/tsconfig.json b/packages/kbn-std/tsconfig.json new file mode 100644 index 00000000000000..fd186a6e43d1c0 --- /dev/null +++ b/packages/kbn-std/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "declarationDir": "./target", + "outDir": "./target", + "stripInternal": true, + "declarationMap": true, + "types": ["jest", "node"] + }, + "include": ["./src/**/*.ts"], + "exclude": ["target"] +} diff --git a/packages/kbn-std/yarn.lock b/packages/kbn-std/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-std/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/packages/kbn-storybook/lib/constants.js b/packages/kbn-storybook/lib/constants.js index 9d216d347eada9..4d8ca0adbfe17f 100644 --- a/packages/kbn-storybook/lib/constants.js +++ b/packages/kbn-storybook/lib/constants.js @@ -17,10 +17,10 @@ * under the License. */ -const { resolve, dirname } = require('path'); +const { resolve } = require('path'); +const { REPO_ROOT } = require('@kbn/utils'); -exports.REPO_ROOT = dirname(require.resolve('../../../package.json')); -exports.ASSET_DIR = resolve(exports.REPO_ROOT, 'built_assets/storybook'); +exports.ASSET_DIR = resolve(REPO_ROOT, 'built_assets/storybook'); exports.CURRENT_CONFIG = resolve(exports.ASSET_DIR, 'current.config.js'); exports.STORY_ENTRY_PATH = resolve(exports.ASSET_DIR, 'stories.entry.js'); exports.DLL_DIST_DIR = resolve(exports.ASSET_DIR, 'dll'); diff --git a/packages/kbn-storybook/lib/dll.js b/packages/kbn-storybook/lib/dll.js index a9154ca972120c..55bc8e43a02ec8 100644 --- a/packages/kbn-storybook/lib/dll.js +++ b/packages/kbn-storybook/lib/dll.js @@ -20,7 +20,8 @@ const { resolve } = require('path'); const { existsSync } = require('fs'); -const { REPO_ROOT, DLL_DIST_DIR } = require('./constants'); +const { REPO_ROOT } = require('@kbn/utils'); +const { DLL_DIST_DIR } = require('./constants'); exports.buildDll = async ({ rebuildDll, log, procRunner }) => { if (rebuildDll) { diff --git a/packages/kbn-storybook/lib/storybook_entry.js b/packages/kbn-storybook/lib/storybook_entry.js index 8b8aa4126ad884..fc970b1ff9d2a7 100644 --- a/packages/kbn-storybook/lib/storybook_entry.js +++ b/packages/kbn-storybook/lib/storybook_entry.js @@ -27,11 +27,12 @@ const { promisify } = require('util'); const watch = require('glob-watcher'); const mkdirp = require('mkdirp'); // eslint-disable-line const glob = require('fast-glob'); +const { REPO_ROOT } = require('@kbn/utils'); const mkdirpAsync = promisify(mkdirp); const writeFileAsync = promisify(Fs.writeFile); -const { REPO_ROOT, STORY_ENTRY_PATH } = require('./constants'); +const { STORY_ENTRY_PATH } = require('./constants'); const STORE_ENTRY_DIR = dirname(STORY_ENTRY_PATH); exports.generateStorybookEntry = ({ log, storyGlobs }) => { diff --git a/packages/kbn-storybook/lib/webpack.dll.config.js b/packages/kbn-storybook/lib/webpack.dll.config.js index 18dbe3bd049d3c..6e3b4d41bd7f09 100644 --- a/packages/kbn-storybook/lib/webpack.dll.config.js +++ b/packages/kbn-storybook/lib/webpack.dll.config.js @@ -20,8 +20,9 @@ const webpack = require('webpack'); const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const { REPO_ROOT } = require('@kbn/utils'); -const { DLL_NAME, REPO_ROOT, DLL_DIST_DIR } = require('./constants'); +const { DLL_NAME, DLL_DIST_DIR } = require('./constants'); // This is the Webpack config for the DLL of CSS and JS assets that are // not expected to change during development. This saves compile and run diff --git a/packages/kbn-storybook/package.json b/packages/kbn-storybook/package.json index 9f12cd1f46c68d..5271ddb96d8422 100644 --- a/packages/kbn-storybook/package.json +++ b/packages/kbn-storybook/package.json @@ -6,6 +6,7 @@ "dependencies": { "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "@kbn/utils": "1.0.0", "@storybook/addon-actions": "^5.3.19", "@storybook/addon-console": "^1.2.1", "@storybook/addon-info": "^5.3.19", diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js index d505c4f9a04481..60b6b6add66d15 100644 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ b/packages/kbn-storybook/storybook_config/webpack.config.js @@ -22,7 +22,8 @@ const webpack = require('webpack'); const webpackMerge = require('webpack-merge'); const { stringifyRequest } = require('loader-utils'); const CopyWebpackPlugin = require('copy-webpack-plugin'); -const { REPO_ROOT, DLL_DIST_DIR } = require('../lib/constants'); +const { REPO_ROOT } = require('@kbn/utils'); +const { DLL_DIST_DIR } = require('../lib/constants'); // eslint-disable-next-line import/no-unresolved const { currentConfig } = require('../../../built_assets/storybook/current.config'); diff --git a/packages/kbn-telemetry-tools/GUIDELINE.md b/packages/kbn-telemetry-tools/GUIDELINE.md new file mode 100644 index 00000000000000..e7d09babbf9e2a --- /dev/null +++ b/packages/kbn-telemetry-tools/GUIDELINE.md @@ -0,0 +1,211 @@ +# Collector Schema Guideline + +Table of contents: +- [Collector Schema Guideline](#collector-schema-guideline) + - [Adding schema to your collector](#adding-schema-to-your-collector) + - [1. Update the telemetryrc file](#1-update-the-telemetryrc-file) + - [2. Type the `fetch` function](#2-type-the-fetch-function) + - [3. Add a `schema` field](#3-add-a-schema-field) + - [4. Run the telemetry check](#4-run-the-telemetry-check) + - [5. Update the stored json files](#5-update-the-stored-json-files) + - [Updating the collector schema](#updating-the-collector-schema) + - [Writing the schema](#writing-the-schema) + - [Basics](#basics) + - [Allowed types](#allowed-types) + - [Dealing with arrays](#dealing-with-arrays) + - [Schema Restrictions](#schema-restrictions) + - [Root of schema can only be an object](#root-of-schema-can-only-be-an-object) + + +## Adding schema to your collector + +To add a `schema` to the collector, follow these steps until the telemetry check passes. +To check the next step needed simply run the telemetry check with the path of your collector: + +``` +node scripts/telemetry_check.js --path=.ts +``` + +### 1. Update the telemetryrc file + +Make sure your collector is not excluded in the `telemetryrc.json` files (located at the root of the kibana project, and another on in the `x-pack` dir). + +```s +[ + { + ... + "exclude": [ + "" + ] + } +] +``` + +Note that the check will fail if the collector in --path is excluded. + +### 2. Type the `fetch` function +1. Make sure the return of the `fetch` function is typed. + +The function `makeUsageCollector` accepts a generic type parameter of the returned type of the `fetch` function. + +``` +interface Usage { + someStat: number; +} + +usageCollection.makeUsageCollector({ + fetch: async () => { + return { + someStat: 3, + } + }, + ... +}) +``` + +The generic type passed to `makeUsageCollector` will automatically unwrap the `Promise` to check for the resolved type. + +### 3. Add a `schema` field + +Add a `schema` field to your collector. After passing the return type of the fetch function to the `makeUsageCollector` generic parameter. It will automaticallly figure out the correct type of the schema based on that provided type. + + +``` +interface Usage { + someStat: number; +} + +usageCollection.makeUsageCollector({ + schema: { + someStat: { + type: 'long' + } + }, + ... +}) +``` + +For full details on writing the `schema` object, check the [Writing the schema](#writing-the-schema) section. + +### 4. Run the telemetry check + +To make sure your changes pass the telemetry check you can run the following: + +``` +node scripts/telemetry_check.js --ignore-stored-json --path=.ts +``` + +### 5. Update the stored json files + +The `--fix` flag will automatically update the persisted json files used by the telemetry team. + +``` +node scripts/telemetry_check.js --fix +``` + +Note that any updates to the stored json files will require a review by the kibana-telemetry team to help us update the telemetry cluster mappings and ensure your changes adhere to our best practices. + + +## Updating the collector schema + +Simply update the fetch function to start returning the updated fields back to our cluster. The update the schema to accomodate these changes. + +Once youre run the changes to both the `fetch` function and the `schema` field run the following command + +``` +node scripts/telemetry_check.js --fix +``` + +The `--fix` flag will automatically update the persisted json files used by the telemetry team. Note that any updates to the stored json files will require a review by the kibana-telemetry team to help us update the telemetry cluster mappings and ensure your changes adhere to our best practices. + + +## Writing the schema + +We've designed the schema object to closely resemble elasticsearch mapping object to reduce any cognitive complexity. + +### Basics + +The function `makeUsageCollector` will automatically translate the returned `Usage` fetch type to the `schema` object. This way you'll have the typescript type checker helping you write the correct corrisponding schema. + +``` +interface Usage { + someStat: number; +} + +usageCollection.makeUsageCollector({ + schema: { + someStat: { + type: 'long' + } + }, + ... +}) +``` + + +### Allowed types + +Any field property in the schema accepts a `type` field. By default the type is `object` which accepts nested properties under it. Currently we accept the following property types: + +``` +AllowedSchemaTypes = + | 'keyword' + | 'text' + | 'number' + | 'boolean' + | 'long' + | 'date' + | 'float'; +``` + + +### Dealing with arrays + +You can optionally define a property to be an array by setting the `isArray` to `true`. Note that the `isArray` property is not currently required. + + +``` +interface Usage { + arrayOfStrings: string[]; + arrayOfObjects: {key: string; value: number; }[]; +} + +usageCollection.makeUsageCollector({ + fetch: () => { + return { + arrayOfStrings: ['item_one', 'item_two'], + arrayOfObjects: [ + { key: 'key_one', value: 13 }, + ] + } + } + schema: { + arrayOfStrings: { + type: 'keyword', + isArray: true, + }, + arrayOfObjects: { + isArray: true, + key: { + type: 'keyword', + }, + value: { + type: 'long', + }, + } + }, + ... +}) +``` + +Be careful adding arrays of objects due to the limitation in correlating the properties inside those objects inside kibana. It is advised to look for an alternative schema based on your use cases. + + +## Schema Restrictions + +We have enforced some restrictions to the schema object to adhere to our telemetry best practices. These practices are derived from the usablity of the sent data in our telemetry cluster. + + +### Root of schema can only be an object + +The root of the schema can only be an object. Currently any property must be nested inside the main schema object. \ No newline at end of file diff --git a/packages/kbn-telemetry-tools/package.json b/packages/kbn-telemetry-tools/package.json index 63a8fcf30335eb..4318cbcf2ec4e5 100644 --- a/packages/kbn-telemetry-tools/package.json +++ b/packages/kbn-telemetry-tools/package.json @@ -10,12 +10,12 @@ "kbn:watch": "yarn build --watch" }, "devDependencies": { - "lodash": "npm:@elastic/lodash@3.10.1-kibana4", + "lodash": "^4.17.20", "@kbn/dev-utils": "1.0.0", "@kbn/utility-types": "1.0.0", "@types/normalize-path": "^3.0.0", "normalize-path": "^3.0.0", - "@types/lodash": "^3.10.1", + "@types/lodash": "^4.14.159", "moment": "^2.24.0", "typescript": "4.0.2" } diff --git a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts index 2f85fd2cdd2a47..87ba68c1bcb272 100644 --- a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts +++ b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts @@ -35,7 +35,7 @@ import { export function runTelemetryCheck() { run( - async ({ flags: { fix = false, path }, log }) => { + async ({ flags: { fix = false, 'ignore-stored-json': ignoreStoredJson, path }, log }) => { if (typeof fix !== 'boolean') { throw createFailError(`${chalk.white.bgRed(' TELEMETRY ERROR ')} --fix can't have a value`); } @@ -50,6 +50,14 @@ export function runTelemetryCheck() { ); } + if (fix && typeof ignoreStoredJson !== 'undefined') { + throw createFailError( + `${chalk.white.bgRed( + ' TELEMETRY ERROR ' + )} --fix is incompatible with --ignore-stored-json flag.` + ); + } + const list = new Listr([ { title: 'Checking .telemetryrc.json files', @@ -59,11 +67,28 @@ export function runTelemetryCheck() { title: 'Extracting Collectors', task: (context) => new Listr(extractCollectorsTask(context, path), { exitOnError: true }), }, + { + enabled: () => typeof path !== 'undefined', + title: 'Checking collectors in --path are not excluded', + task: ({ roots }: TaskContext) => { + const totalCollections = roots.reduce((acc, root) => { + return acc + (root.parsedCollections?.length || 0); + }, 0); + const collectorsInPath = Array.isArray(path) ? path.length : 1; + + if (totalCollections !== collectorsInPath) { + throw new Error( + 'Collector specified in `path` is excluded; Check the telemetryrc.json files.' + ); + } + }, + }, { title: 'Checking Compatible collector.schema with collector.fetch type', task: (context) => new Listr(checkCompatibleTypesTask(context), { exitOnError: true }), }, { + enabled: (_) => !!ignoreStoredJson, title: 'Checking Matching collector.schema against stored json files', task: (context) => new Listr(checkMatchingSchemasTask(context, !fix), { exitOnError: true }), diff --git a/packages/kbn-telemetry-tools/src/tools/serializer.ts b/packages/kbn-telemetry-tools/src/tools/serializer.ts index d5412f64f36156..7afe828298b4bc 100644 --- a/packages/kbn-telemetry-tools/src/tools/serializer.ts +++ b/packages/kbn-telemetry-tools/src/tools/serializer.ts @@ -18,7 +18,7 @@ */ import * as ts from 'typescript'; -import { uniq } from 'lodash'; +import { uniqBy } from 'lodash'; import { getResolvedModuleSourceFile, getIdentifierDeclarationFromSource, @@ -148,7 +148,7 @@ export function getDescriptor(node: ts.Node, program: ts.Program): Descriptor | .map((typeNode) => getDescriptor(typeNode, program)) .filter(discardNullOrUndefined); - const uniqueKinds = uniq(kinds, 'kind'); + const uniqueKinds = uniqBy(kinds, 'kind'); if (uniqueKinds.length !== 1) { throw Error('Mapping does not support conflicting union types.'); diff --git a/packages/kbn-telemetry-tools/src/tools/utils.ts b/packages/kbn-telemetry-tools/src/tools/utils.ts index c1424785b22a54..3d6764117374c4 100644 --- a/packages/kbn-telemetry-tools/src/tools/utils.ts +++ b/packages/kbn-telemetry-tools/src/tools/utils.ts @@ -18,7 +18,18 @@ */ import * as ts from 'typescript'; -import { pick, isObject, each, isArray, reduce, isEmpty, merge, transform, isEqual } from 'lodash'; +import { + pick, + pickBy, + isObject, + forEach, + isArray, + reduce, + isEmpty, + merge, + transform, + isEqual, +} from 'lodash'; import * as path from 'path'; import glob from 'glob'; import { readFile, writeFile } from 'fs'; @@ -186,17 +197,17 @@ export function getPropertyValue( } } -export function pickDeep(collection: any, identity: any, thisArg?: any) { - const picked: any = pick(collection, identity, thisArg); - const collections = pick(collection, isObject, thisArg); +export function pickDeep(collection: any, identity: any) { + const picked: any = pick(collection, identity); + const collections = pickBy(collection, isObject); - each(collections, function (item, key) { + forEach(collections, function (item, key) { let object; if (isArray(item)) { object = reduce( item, function (result, value) { - const pickedDeep = pickDeep(value, identity, thisArg); + const pickedDeep = pickDeep(value, identity); if (!isEmpty(pickedDeep)) { result.push(pickedDeep); } @@ -205,7 +216,7 @@ export function pickDeep(collection: any, identity: any, thisArg?: any) { [] as any[] ); } else { - object = pickDeep(item, identity, thisArg); + object = pickDeep(item, identity); } if (!isEmpty(object)) { @@ -230,33 +241,38 @@ export const flattenKeys = (obj: any, keyPath: any[] = []): any => { return { [keyPath.join('.')]: obj }; }; +type ObjectDict = Record; export function difference(actual: any, expected: any) { - function changes(obj: { [key: string]: any }, base: { [key: string]: any }) { - return transform(obj, function (result, value, key) { - if (key && /@@INDEX@@/.test(`${key}`)) { - // The type definition is an Index Signature, fuzzy searching for similar keys - const regexp = new RegExp(`${key}`.replace(/@@INDEX@@/g, '(.+)?')); - const keysInBase = Object.keys(base) - .map((k) => { - const match = k.match(regexp); - return match && match[0]; - }) - .filter((s): s is string => !!s); - - if (keysInBase.length === 0) { - // Mark this key as wrong because we couldn't find any matching keys - result[key] = value; - } - - keysInBase.forEach((k) => { - if (!isEqual(value, base[k])) { - result[k] = isObject(value) && isObject(base[k]) ? changes(value, base[k]) : value; + function changes(obj: ObjectDict, base: ObjectDict) { + return transform( + obj, + function (result, value, key) { + if (key && /@@INDEX@@/.test(`${key}`)) { + // The type definition is an Index Signature, fuzzy searching for similar keys + const regexp = new RegExp(`${key}`.replace(/@@INDEX@@/g, '(.+)?')); + const keysInBase = Object.keys(base) + .map((k) => { + const match = k.match(regexp); + return match && match[0]; + }) + .filter((s): s is string => !!s); + + if (keysInBase.length === 0) { + // Mark this key as wrong because we couldn't find any matching keys + result[key] = value; } - }); - } else if (key && !isEqual(value, base[key])) { - result[key] = isObject(value) && isObject(base[key]) ? changes(value, base[key]) : value; - } - }); + + keysInBase.forEach((k) => { + if (!isEqual(value, base[k])) { + result[k] = isObject(value) && isObject(base[k]) ? changes(value, base[k]) : value; + } + }); + } else if (key && !isEqual(value, base[key])) { + result[key] = isObject(value) && isObject(base[key]) ? changes(value, base[key]) : value; + } + }, + {} as ObjectDict + ); } return changes(actual, expected); } diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index c84b0a93311bbb..8a4ff55dcf68fa 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -13,6 +13,7 @@ "@babel/cli": "^7.10.5", "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", + "@kbn/utils": "1.0.0", "@types/joi": "^13.4.2", "@types/lodash": "^4.14.159", "@types/parse-link-header": "^1.0.0", diff --git a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts index 3dfb1ea44d9e74..93616ce78a04a5 100644 --- a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts +++ b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts @@ -19,7 +19,8 @@ import Path from 'path'; -import { REPO_ROOT, run, createFailError, createFlagError } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { run, createFailError, createFlagError } from '@kbn/dev-utils'; import globby from 'globby'; import { getFailures, TestFailure } from './get_failures'; diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js index 133f4d2feb53e6..a010d9f0b038ee 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/basic.js @@ -21,7 +21,7 @@ import { spawnSync } from 'child_process'; import { resolve } from 'path'; import expect from '@kbn/expect'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); const BASIC_CONFIG = require.resolve('../fixtures/simple_project/config.js'); diff --git a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js index 12e28d2702c5a6..fa4ef88fd3e703 100644 --- a/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js +++ b/packages/kbn-test/src/functional_test_runner/__tests__/integration/failure_hooks.js @@ -22,7 +22,7 @@ import { resolve } from 'path'; import stripAnsi from 'strip-ansi'; import expect from '@kbn/expect'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; const SCRIPT = resolve(REPO_ROOT, 'scripts/functional_test_runner.js'); const FAILURE_HOOKS_CONFIG = require.resolve('../fixtures/failure_hooks/config.js'); diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index e1d3bf1a8d9016..701171876ad2c4 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -262,7 +262,7 @@ export const schema = Joi.object() // settings for the find service layout: Joi.object() .keys({ - fixedHeaderHeight: Joi.number().default(50), + fixedHeaderHeight: Joi.number().default(100), }) .default(), diff --git a/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts b/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts index fdf8b3c0ddfa8e..e5c60f1d208b11 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/failure_metadata.ts @@ -19,7 +19,7 @@ import Path from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { Lifecycle } from './lifecycle'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js index 5d3d8fe7d759bb..92137a8c4f841f 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js @@ -17,7 +17,7 @@ * under the License. */ import { relative } from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { createAssignmentProxy } from './assignment_proxy'; import { wrapFunction } from './wrap_function'; import { wrapRunnableArgs } from './wrap_runnable_args'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js index 3ac7a50cd28ea0..39eb69a1519189 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/setup_mocha.js @@ -19,7 +19,7 @@ import Mocha from 'mocha'; import { relative } from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { loadTestFiles } from './load_test_files'; import { filterSuitesByTags } from './filter_suites_by_tags'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts index f879408bf2bebb..5350b2709843d0 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts @@ -21,7 +21,7 @@ import fs from 'fs'; import { join, resolve } from 'path'; jest.mock('fs'); -jest.mock('@kbn/dev-utils', () => { +jest.mock('@kbn/utils', () => { return { REPO_ROOT: '/dev/null/root' }; }); diff --git a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts index b346be2d58dad2..6cbd74467106fd 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.ts @@ -19,7 +19,7 @@ import fs from 'fs'; import { dirname, relative, resolve } from 'path'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { Lifecycle } from './lifecycle'; diff --git a/packages/kbn-test/src/mocha/run_mocha_cli.js b/packages/kbn-test/src/mocha/run_mocha_cli.js index 3c77fef963a76d..0fc7c762be4252 100644 --- a/packages/kbn-test/src/mocha/run_mocha_cli.js +++ b/packages/kbn-test/src/mocha/run_mocha_cli.js @@ -17,7 +17,7 @@ * under the License. */ -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import getopts from 'getopts'; import globby from 'globby'; diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js index fa80dfdeef20f5..b7d4e929ac93f1 100644 --- a/packages/kbn-ui-shared-deps/webpack.config.js +++ b/packages/kbn-ui-shared-deps/webpack.config.js @@ -21,7 +21,7 @@ const Path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); -const { REPO_ROOT } = require('@kbn/dev-utils'); +const { REPO_ROOT } = require('@kbn/utils'); const webpack = require('webpack'); const UiSharedDeps = require('./index'); diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 6ccfeb8ab052c9..d3fb5bdf36194a 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -98,3 +98,15 @@ export type PublicKeys = keyof T; * Returns an object with public keys only. */ export type PublicContract = Pick>; + +/** + * Returns public method names + */ +export type MethodKeysOf = { + [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; +}[keyof T]; + +/** + * Returns an object with public methods only. + */ +export type PublicMethodsOf = Pick>; diff --git a/packages/kbn-utility-types/tsconfig.json b/packages/kbn-utility-types/tsconfig.json index 03cace5b9cb2c3..79cf423fe78ace 100644 --- a/packages/kbn-utility-types/tsconfig.json +++ b/packages/kbn-utility-types/tsconfig.json @@ -7,7 +7,6 @@ "stripInternal": true, "declarationMap": true, "types": [ - "jest", "node" ] }, diff --git a/packages/kbn-utils/README.md b/packages/kbn-utils/README.md new file mode 100644 index 00000000000000..fd132e4312487f --- /dev/null +++ b/packages/kbn-utils/README.md @@ -0,0 +1,3 @@ +# @kbn/utils + +Shared server-side utilities shared across packages and plugins. \ No newline at end of file diff --git a/packages/kbn-utils/package.json b/packages/kbn-utils/package.json new file mode 100644 index 00000000000000..15fe5c6df5648d --- /dev/null +++ b/packages/kbn-utils/package.json @@ -0,0 +1,19 @@ +{ + "name": "@kbn/utils", + "main": "./target/index.js", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "tsc", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + }, + "dependencies": { + "@kbn/config-schema": "1.0.0", + "load-json-file": "^6.2.0" + }, + "devDependencies": { + "typescript": "4.0.2" + } +} diff --git a/packages/kbn-utils/src/index.ts b/packages/kbn-utils/src/index.ts new file mode 100644 index 00000000000000..7a894d72d5624b --- /dev/null +++ b/packages/kbn-utils/src/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './package_json'; +export * from './path'; +export * from './repo_root'; diff --git a/packages/kbn-utils/src/package_json/index.test.ts b/packages/kbn-utils/src/package_json/index.test.ts new file mode 100644 index 00000000000000..afc84102999fe5 --- /dev/null +++ b/packages/kbn-utils/src/package_json/index.test.ts @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import path from 'path'; +import { kibanaPackageJSON } from './'; + +it('parses package.json', () => { + expect(kibanaPackageJSON.name).toEqual('kibana'); +}); + +it('includes __dirname and __filename', () => { + const root = path.resolve(__dirname, '../../../../'); + expect(kibanaPackageJSON.__filename).toEqual(path.resolve(root, 'package.json')); + expect(kibanaPackageJSON.__dirname).toEqual(root); +}); diff --git a/packages/kbn-utils/src/package_json/index.ts b/packages/kbn-utils/src/package_json/index.ts new file mode 100644 index 00000000000000..f439c0100e1931 --- /dev/null +++ b/packages/kbn-utils/src/package_json/index.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { dirname, resolve } from 'path'; +import { REPO_ROOT } from '../repo_root'; + +export const kibanaPackageJSON = { + __filename: resolve(REPO_ROOT, 'package.json'), + __dirname: dirname(resolve(REPO_ROOT, 'package.json')), + ...require(resolve(REPO_ROOT, 'package.json')), +}; diff --git a/src/core/server/path/index.test.ts b/packages/kbn-utils/src/path/index.test.ts similarity index 100% rename from src/core/server/path/index.test.ts rename to packages/kbn-utils/src/path/index.test.ts diff --git a/src/core/server/path/index.ts b/packages/kbn-utils/src/path/index.ts similarity index 94% rename from src/core/server/path/index.ts rename to packages/kbn-utils/src/path/index.ts index 7c1a81643fbc81..a7eddca5f2fde2 100644 --- a/src/core/server/path/index.ts +++ b/packages/kbn-utils/src/path/index.ts @@ -20,7 +20,7 @@ import { join } from 'path'; import { accessSync, constants } from 'fs'; import { TypeOf, schema } from '@kbn/config-schema'; -import { fromRoot } from '../utils'; +import { REPO_ROOT } from '../repo_root'; const isString = (v: any): v is string => typeof v === 'string'; @@ -28,19 +28,19 @@ const CONFIG_PATHS = [ process.env.KBN_PATH_CONF && join(process.env.KBN_PATH_CONF, 'kibana.yml'), process.env.KIBANA_PATH_CONF && join(process.env.KIBANA_PATH_CONF, 'kibana.yml'), process.env.CONFIG_PATH, // deprecated - fromRoot('config/kibana.yml'), + join(REPO_ROOT, 'config/kibana.yml'), ].filter(isString); const CONFIG_DIRECTORIES = [ process.env.KBN_PATH_CONF, process.env.KIBANA_PATH_CONF, - fromRoot('config'), + join(REPO_ROOT, 'config'), '/etc/kibana', ].filter(isString); const DATA_PATHS = [ process.env.DATA_PATH, // deprecated - fromRoot('data'), + join(REPO_ROOT, 'data'), '/var/lib/kibana', ].filter(isString); diff --git a/packages/kbn-dev-utils/src/repo_root.ts b/packages/kbn-utils/src/repo_root.ts similarity index 100% rename from packages/kbn-dev-utils/src/repo_root.ts rename to packages/kbn-utils/src/repo_root.ts diff --git a/packages/kbn-utils/tsconfig.json b/packages/kbn-utils/tsconfig.json new file mode 100644 index 00000000000000..e9dd6313e6f79e --- /dev/null +++ b/packages/kbn-utils/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target", + "declaration": true, + "declarationMap": true + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/kbn-utils/yarn.lock b/packages/kbn-utils/yarn.lock new file mode 120000 index 00000000000000..3f82ebc9cdbae3 --- /dev/null +++ b/packages/kbn-utils/yarn.lock @@ -0,0 +1 @@ +../../yarn.lock \ No newline at end of file diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index eb7db8dac7cb66..b1d1335eb18885 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -21,7 +21,7 @@ import { resolve } from 'path'; import { format as formatUrl } from 'url'; import opn from 'opn'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { FSWatcher } from 'chokidar'; import * as Rx from 'rxjs'; import { startWith, mapTo, filter, map, take, tap } from 'rxjs/operators'; diff --git a/src/cli/cluster/run_kbn_optimizer.ts b/src/cli/cluster/run_kbn_optimizer.ts index c231437da39437..8196cad4a99c73 100644 --- a/src/cli/cluster/run_kbn_optimizer.ts +++ b/src/cli/cluster/run_kbn_optimizer.ts @@ -19,12 +19,12 @@ import Chalk from 'chalk'; import moment from 'moment'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, pickLevelFromFlags, ToolingLogTextWriter, parseLogLevel, - REPO_ROOT, } from '@kbn/dev-utils'; import { runOptimizer, OptimizerConfig, logOptimizerState } from '@kbn/optimizer'; diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.ts b/src/cli/serve/integration_tests/reload_logging_config.test.ts index 35391b9b58ecc5..55f71ea2401dbb 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.ts +++ b/src/cli/serve/integration_tests/reload_logging_config.test.ts @@ -26,8 +26,7 @@ import Del from 'del'; import * as Rx from 'rxjs'; import { map, filter, take } from 'rxjs/operators'; import { safeDump } from 'js-yaml'; - -import { getConfigFromFiles } from '../../../core/server/config/read_config'; +import { getConfigFromFiles } from '@kbn/config'; const legacyConfig = follow('__fixtures__/reload_logging_config/kibana.test.yml'); const configFileLogConsole = follow( diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index c08f3aec64335b..eeb5564667ec4a 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -23,9 +23,9 @@ import { statSync } from 'fs'; import { resolve } from 'path'; import url from 'url'; +import { getConfigPath } from '@kbn/utils'; import { IS_KIBANA_DISTRIBUTABLE } from '../../legacy/utils'; import { fromRoot } from '../../core/server/utils'; -import { getConfigPath } from '../../core/server/path'; import { bootstrap } from '../../core/server'; import { readKeystore } from './read_keystore'; diff --git a/src/cli_keystore/get_keystore.js b/src/cli_keystore/get_keystore.js index e181efe9196b8e..b97efbb2cbf4db 100644 --- a/src/cli_keystore/get_keystore.js +++ b/src/cli_keystore/get_keystore.js @@ -21,7 +21,7 @@ import { existsSync } from 'fs'; import { join } from 'path'; import { Logger } from '../cli_plugin/lib/logger'; -import { getConfigDirectory, getDataPath } from '../core/server/path'; +import { getConfigDirectory, getDataPath } from '@kbn/utils'; export function getKeystore() { const configKeystore = join(getConfigDirectory(), 'kibana.keystore'); diff --git a/src/cli_plugin/install/index.js b/src/cli_plugin/install/index.js index bc7e95b8489f0c..eff14906853c18 100644 --- a/src/cli_plugin/install/index.js +++ b/src/cli_plugin/install/index.js @@ -17,10 +17,10 @@ * under the License. */ +import { getConfigPath } from '@kbn/utils'; import { pkg } from '../../core/server/utils'; import { install } from './install'; import { Logger } from '../lib/logger'; -import { getConfigPath } from '../../core/server/path'; import { parse, parseMilliseconds } from './settings'; import { logWarnings } from '../lib/log_warnings'; diff --git a/src/cli_plugin/remove/index.js b/src/cli_plugin/remove/index.js index c3bd96086db9b9..b9c37c0cf802b1 100644 --- a/src/cli_plugin/remove/index.js +++ b/src/cli_plugin/remove/index.js @@ -17,10 +17,10 @@ * under the License. */ +import { getConfigPath } from '@kbn/utils'; import { remove } from './remove'; import { Logger } from '../lib/logger'; import { parse } from './settings'; -import { getConfigPath } from '../../core/server/path'; import { logWarnings } from '../lib/log_warnings'; function processCommand(command, options) { diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index c6320e42655a27..6a21dcb1b06862 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1284,7 +1284,7 @@ _See also: [Server's CoreSetup API Docs](/docs/development/core/server/kibana-pl | Legacy Platform | New Platform | Notes | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ----- | -| `server.plugins.xpack_main.registerFeature` | [`plugins.features.registerFeature`](x-pack/plugins/features/server/plugin.ts) | | +| `server.plugins.xpack_main.registerFeature` | [`plugins.features.registerKibanaFeature`](x-pack/plugins/features/server/plugin.ts) | | | `server.plugins.xpack_main.feature(pluginID).registerLicenseCheckResultsGenerator` | [`x-pack licensing plugin`](/x-pack/plugins/licensing/README.md) | | #### UI Exports diff --git a/src/core/public/_variables.scss b/src/core/public/_variables.scss new file mode 100644 index 00000000000000..8c054e770bd4b7 --- /dev/null +++ b/src/core/public/_variables.scss @@ -0,0 +1,3 @@ +@import '@elastic/eui/src/global_styling/variables/header'; + +$kbnHeaderOffset: $euiHeaderHeightCompensation * 2; diff --git a/src/core/public/application/capabilities/capabilities_service.mock.ts b/src/core/public/application/capabilities/capabilities_service.mock.ts index 54aaa31e08859e..ee378547626669 100644 --- a/src/core/public/application/capabilities/capabilities_service.mock.ts +++ b/src/core/public/application/capabilities/capabilities_service.mock.ts @@ -16,8 +16,10 @@ * specific language governing permissions and limitations * under the License. */ + +import { deepFreeze } from '@kbn/std'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesStart } from './capabilities_service'; -import { deepFreeze } from '../../../utils'; const createStartContractMock = (): jest.Mocked => ({ capabilities: deepFreeze({ diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index 7304a8e5a66bc1..1164164aec4c59 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -17,9 +17,9 @@ * under the License. */ import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/application/test_types.ts b/src/core/public/application/test_types.ts index 64012f0c0b6c15..6d29b77d92f365 100644 --- a/src/core/public/application/test_types.ts +++ b/src/core/public/application/test_types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AppUnmount, Mounter } from './types'; import { ApplicationService } from './application_service'; diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index f668cf851da55f..089d1cf3f3ced8 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -94,8 +94,10 @@ export const AppContainer: FunctionComponent = ({ // eslint-disable-next-line no-console console.error(e); } finally { - setShowSpinner(false); - setIsMounting(false); + if (elementRef.current) { + setShowSpinner(false); + setIsMounting(false); + } } }; diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 5862ee7175f717..9cd96763d2e791 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -17,14 +17,8 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; -import { - ChromeBadge, - ChromeBrand, - ChromeBreadcrumb, - ChromeService, - InternalChromeStart, - NavType, -} from './'; +import type { PublicMethodsOf } from '@kbn/utility-types'; +import { ChromeBadge, ChromeBrand, ChromeBreadcrumb, ChromeService, InternalChromeStart } from './'; const createStartContractMock = () => { const startContract: DeeplyMockedKeys = { @@ -50,8 +44,10 @@ const createStartContractMock = () => { }, navControls: { registerLeft: jest.fn(), + registerCenter: jest.fn(), registerRight: jest.fn(), getLeft$: jest.fn(), + getCenter$: jest.fn(), getRight$: jest.fn(), }, setAppTitle: jest.fn(), @@ -70,7 +66,6 @@ const createStartContractMock = () => { setHelpExtension: jest.fn(), setHelpSupportUrl: jest.fn(), getIsNavDrawerLocked$: jest.fn(), - getNavType$: jest.fn(), getCustomNavLink$: jest.fn(), setCustomNavLink: jest.fn(), }; @@ -83,7 +78,6 @@ const createStartContractMock = () => { startContract.getCustomNavLink$.mockReturnValue(new BehaviorSubject(undefined)); startContract.getHelpExtension$.mockReturnValue(new BehaviorSubject(undefined)); startContract.getIsNavDrawerLocked$.mockReturnValue(new BehaviorSubject(false)); - startContract.getNavType$.mockReturnValue(new BehaviorSubject('modern' as NavType)); return startContract; }; diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index b96c34cd9fbe84..b01f120b81305d 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -37,7 +37,6 @@ import { ChromeNavControls, NavControlsService } from './nav_controls'; import { ChromeNavLinks, NavLinksService, ChromeNavLink } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; import { Header } from './ui'; -import { NavType } from './ui/header'; import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; @@ -172,10 +171,6 @@ export class ChromeService { const getIsNavDrawerLocked$ = isNavDrawerLocked$.pipe(takeUntil(this.stop$)); - // TODO #64541 - // Can delete - const getNavType$ = uiSettings.get$('pageNavigation').pipe(takeUntil(this.stop$)); - const isIE = () => { const ua = window.navigator.userAgent; const msie = ua.indexOf('MSIE '); // IE 10 or older @@ -241,10 +236,10 @@ export class ChromeService { navLinks$={navLinks.getNavLinks$()} recentlyAccessed$={recentlyAccessed.get$()} navControlsLeft$={navControls.getLeft$()} + navControlsCenter$={navControls.getCenter$()} navControlsRight$={navControls.getRight$()} onIsLockedUpdate={setIsNavDrawerLocked} isLocked$={getIsNavDrawerLocked$} - navType$={getNavType$} /> ), @@ -305,8 +300,6 @@ export class ChromeService { getIsNavDrawerLocked$: () => getIsNavDrawerLocked$, - getNavType$: () => getNavType$, - getCustomNavLink$: () => customNavLink$.pipe(takeUntil(this.stop$)), setCustomNavLink: (customNavLink?: ChromeNavLink) => { @@ -468,13 +461,6 @@ export interface ChromeStart { * Get an observable of the current locked state of the nav drawer. */ getIsNavDrawerLocked$(): Observable; - - /** - * Get the navigation type - * TODO #64541 - * Can delete - */ - getNavType$(): Observable; } /** @internal */ diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.ts b/src/core/public/chrome/nav_controls/nav_controls_service.ts index 167948e01cb362..2638f40c77dc4a 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -45,14 +45,18 @@ export interface ChromeNavControl { * @public */ export interface ChromeNavControls { - /** Register a nav control to be presented on the left side of the chrome header. */ + /** Register a nav control to be presented on the bottom-left side of the chrome header. */ registerLeft(navControl: ChromeNavControl): void; - /** Register a nav control to be presented on the right side of the chrome header. */ + /** Register a nav control to be presented on the top-right side of the chrome header. */ registerRight(navControl: ChromeNavControl): void; + /** Register a nav control to be presented on the top-center side of the chrome header. */ + registerCenter(navControl: ChromeNavControl): void; /** @internal */ getLeft$(): Observable; /** @internal */ getRight$(): Observable; + /** @internal */ + getCenter$(): Observable; } /** @internal */ @@ -62,6 +66,7 @@ export class NavControlsService { public start() { const navControlsLeft$ = new BehaviorSubject>(new Set()); const navControlsRight$ = new BehaviorSubject>(new Set()); + const navControlsCenter$ = new BehaviorSubject>(new Set()); return { // In the future, registration should be moved to the setup phase. This @@ -72,6 +77,9 @@ export class NavControlsService { registerRight: (navControl: ChromeNavControl) => navControlsRight$.next(new Set([...navControlsRight$.value.values(), navControl])), + registerCenter: (navControl: ChromeNavControl) => + navControlsCenter$.next(new Set([...navControlsCenter$.value.values(), navControl])), + getLeft$: () => navControlsLeft$.pipe( map((controls) => sortBy([...controls.values()], 'order')), @@ -82,6 +90,11 @@ export class NavControlsService { map((controls) => sortBy([...controls.values()], 'order')), takeUntil(this.stop$) ), + getCenter$: () => + navControlsCenter$.pipe( + map((controls) => sortBy([...controls.values()], 'order')), + takeUntil(this.stop$) + ), }; } diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index 4b82e0ced45057..80f0265819c40c 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -17,7 +17,7 @@ * under the License. */ -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { AppCategory } from '../../'; /** diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index a770ece8496e4c..1bff6cd9301edb 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -121,7 +121,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} - isOpen={true} + isNavOpen={true} navLinks$={ BehaviorSubject { "_isScalar": false, @@ -279,6 +279,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` } } navigateToApp={[Function]} + navigateToUrl={[Function]} onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -2105,7 +2106,7 @@ exports[`CollapsibleNav renders the default nav 1`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} - isOpen={false} + isNavOpen={false} navLinks$={ BehaviorSubject { "_isScalar": false, @@ -2156,6 +2157,7 @@ exports[`CollapsibleNav renders the default nav 1`] = ` } } navigateToApp={[Function]} + navigateToUrl={[Function]} onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -2339,6 +2341,7 @@ exports[`CollapsibleNav renders the default nav 2`] = ` homeHref="/" id="collapsibe-nav" isLocked={false} + isNavOpen={false} isOpen={true} navLinks$={ BehaviorSubject { @@ -2390,6 +2393,7 @@ exports[`CollapsibleNav renders the default nav 2`] = ` } } navigateToApp={[Function]} + navigateToUrl={[Function]} onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -2454,461 +2458,9 @@ exports[`CollapsibleNav renders the default nav 2`] = ` data-test-subj="collapsibleNav" id="collapsibe-nav" isDocked={false} - isOpen={true} + isOpen={false} onClose={[Function]} - > - - - -
- -
-
- + /> `; @@ -3025,6 +2577,7 @@ exports[`CollapsibleNav renders the default nav 3`] = ` homeHref="/" id="collapsibe-nav" isLocked={true} + isNavOpen={false} isOpen={true} navLinks$={ BehaviorSubject { @@ -3076,6 +2629,7 @@ exports[`CollapsibleNav renders the default nav 3`] = ` } } navigateToApp={[Function]} + navigateToUrl={[Function]} onIsLockedUpdate={[Function]} recentlyAccessed$={ BehaviorSubject { @@ -3140,7 +2694,7 @@ exports[`CollapsibleNav renders the default nav 3`] = ` data-test-subj="collapsibleNav" id="collapsibe-nav" isDocked={true} - isOpen={true} + isOpen={false} onClose={[Function]} > - -
-
-
- - -`; - -exports[`Header renders 2`] = ` -
+ -
- -
- -
- -
- - - -
-
- -
+ - - - -
- - - - -
- - , + ], + }, + Object { + "borders": "none", + "items": Array [ + -
- - - - - - - - - , ], - "thrownError": null, - } - } - /> - -
- -
+ }, + Object { + "borders": "none", + "items": Array [ , + , + ], + }, + ] + } + theme="dark" + > +
+ +
+ + + + +
+ +
+ +
+
+
+
+ +
+ +
+ - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
-
- - - -
-
-
-
- -
-
-
- -
-
-
- - - - -
-
-`; - -exports[`Header renders 3`] = ` -
- -
-
-
- -
- -
- -
- -
- - - -
-
- -
- - - - -
- - - - -
- - -
- - - - - - - - - - -
- -
- - - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
-
- - - -
-
-
-
-
-
-
-
- -
-
-
- - - - - -
- -
-
-
-
-
-
-`; - -exports[`Header renders 4`] = ` -
- -
-
-
- -
- -
- -
- - -
- - - -
-
-
- -
- - - - -
- - - - -
- - -
- - - - - - - - - - -
- -
- - + + + + } + closePopover={[Function]} + data-test-subj="helpMenuButton" + display="inlineBlock" + hasArrow={true} + id="headerHelpMenu" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" + repositionOnScroll={true} + > + +
+
+ + + +
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+ + +
+ +
+ +
+ + + +
+
+ +
+ + +
+ + + + + + + + + + +
+ +
+ - - - - } - closePopover={[Function]} - data-test-subj="helpMenuButton" - display="inlineBlock" - hasArrow={true} - id="headerHelpMenu" - isOpen={false} - ownFocus={true} - panelPaddingSize="m" - repositionOnScroll={true} - > - -
-
- - - -
-
-
-
- - -
-
- -
-
-
- - + +
+ +
+ +
+ +
+ - - + - - - - + close + + + + + + + + + + + + `; diff --git a/src/core/public/chrome/ui/header/_index.scss b/src/core/public/chrome/ui/header/_index.scss index e3b73abbcabc20..44cd8642783252 100644 --- a/src/core/public/chrome/ui/header/_index.scss +++ b/src/core/public/chrome/ui/header/_index.scss @@ -1,14 +1,5 @@ @include euiHeaderAffordForFixed; -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) { - width: 100%; - position: fixed; - top: 0; - z-index: 10; -} - .chrHeaderHelpMenu__version { text-transform: none; } diff --git a/src/core/public/chrome/ui/header/collapsible_nav.test.tsx b/src/core/public/chrome/ui/header/collapsible_nav.test.tsx index d4325e0caf88c4..267e17dc0a9d03 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.test.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.test.tsx @@ -59,7 +59,7 @@ function mockProps() { basePath: httpServiceMock.createSetupContract({ basePath: '/test' }).basePath, id: 'collapsibe-nav', isLocked: false, - isOpen: false, + isNavOpen: false, homeHref: '/', navLinks$: new BehaviorSubject([]), recentlyAccessed$: new BehaviorSubject([]), @@ -67,6 +67,7 @@ function mockProps() { onIsLockedUpdate: () => {}, closeNav: () => {}, navigateToApp: () => Promise.resolve(), + navigateToUrl: () => Promise.resolve(), customNavLink$: new BehaviorSubject(undefined), }; } @@ -123,7 +124,7 @@ describe('CollapsibleNav', () => { const component = mount( { const component = mount( @@ -147,9 +148,9 @@ describe('CollapsibleNav', () => { clickGroup(component, 'kibana'); clickGroup(component, 'recentlyViewed'); expectShownNavLinksCount(component, 1); - component.setProps({ isOpen: false }); + component.setProps({ isNavOpen: false }); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); expectShownNavLinksCount(component, 1); }); @@ -160,14 +161,14 @@ describe('CollapsibleNav', () => { const component = mount( ); component.setProps({ closeNav: () => { - component.setProps({ isOpen: false }); + component.setProps({ isNavOpen: false }); onClose(); }, }); @@ -175,11 +176,11 @@ describe('CollapsibleNav', () => { component.find('[data-test-subj="collapsibleNavGroup-recentlyViewed"] a').simulate('click'); expect(onClose.callCount).toEqual(1); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); component.find('[data-test-subj="collapsibleNavGroup-kibana"] a').simulate('click'); expect(onClose.callCount).toEqual(2); expectNavIsClosed(component); - component.setProps({ isOpen: true }); + component.setProps({ isNavOpen: true }); component.find('[data-test-subj="collapsibleNavGroup-noCategory"] a').simulate('click'); expect(onClose.callCount).toEqual(3); expectNavIsClosed(component); diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx index a5f42c09495626..b00e82b660e9f3 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -79,7 +79,7 @@ interface Props { basePath: HttpStart['basePath']; id: string; isLocked: boolean; - isOpen: boolean; + isNavOpen: boolean; homeHref: string; navLinks$: Rx.Observable; recentlyAccessed$: Rx.Observable; @@ -87,6 +87,7 @@ interface Props { onIsLockedUpdate: OnIsLockedUpdate; closeNav: () => void; navigateToApp: InternalApplicationStart['navigateToApp']; + navigateToUrl: InternalApplicationStart['navigateToUrl']; customNavLink$: Rx.Observable; } @@ -94,12 +95,13 @@ export function CollapsibleNav({ basePath, id, isLocked, - isOpen, + isNavOpen, homeHref, storage = window.localStorage, onIsLockedUpdate, closeNav, navigateToApp, + navigateToUrl, ...observables }: Props) { const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden); @@ -129,7 +131,7 @@ export function CollapsibleNav({ aria-label={i18n.translate('core.ui.primaryNav.screenReaderLabel', { defaultMessage: 'Primary', })} - isOpen={isOpen} + isOpen={isNavOpen} isDocked={isLocked} onClose={closeNav} > @@ -217,17 +219,21 @@ export function CollapsibleNav({ listItems={recentlyAccessed.map((link) => { // TODO #64541 // Can remove icon from recent links completely - const { iconType, ...hydratedLink } = createRecentNavLink(link, navLinks, basePath); + const { iconType, onClick, ...hydratedLink } = createRecentNavLink( + link, + navLinks, + basePath, + navigateToUrl + ); return { ...hydratedLink, 'data-test-subj': 'collapsibleNavAppLink--recent', onClick: (event) => { - if (isModifiedOrPrevented(event)) { - return; + if (!isModifiedOrPrevented(event)) { + closeNav(); + onClick(event); } - - closeNav(); }, }; })} diff --git a/src/core/public/chrome/ui/header/header.test.tsx b/src/core/public/chrome/ui/header/header.test.tsx index 04eb256f30f37c..7309b9af493889 100644 --- a/src/core/public/chrome/ui/header/header.test.tsx +++ b/src/core/public/chrome/ui/header/header.test.tsx @@ -21,7 +21,6 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { BehaviorSubject } from 'rxjs'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { NavType } from '.'; import { httpServiceMock } from '../../../http/http_service.mock'; import { applicationServiceMock } from '../../../mocks'; import { Header } from './header'; @@ -51,10 +50,10 @@ function mockProps() { helpExtension$: new BehaviorSubject(undefined), helpSupportUrl$: new BehaviorSubject(''), navControlsLeft$: new BehaviorSubject([]), + navControlsCenter$: new BehaviorSubject([]), navControlsRight$: new BehaviorSubject([]), basePath: http.basePath, isLocked$: new BehaviorSubject(false), - navType$: new BehaviorSubject('modern' as NavType), loadingCount$: new BehaviorSubject(0), onIsLockedUpdate: () => {}, }; @@ -71,7 +70,6 @@ describe('Header', () => { const isVisible$ = new BehaviorSubject(false); const breadcrumbs$ = new BehaviorSubject([{ text: 'test' }]); const isLocked$ = new BehaviorSubject(false); - const navType$ = new BehaviorSubject('modern' as NavType); const navLinks$ = new BehaviorSubject([ { id: 'kibana', title: 'kibana', baseUrl: '', href: '' }, ]); @@ -92,22 +90,19 @@ describe('Header', () => { navLinks$={navLinks$} recentlyAccessed$={recentlyAccessed$} isLocked$={isLocked$} - navType$={navType$} customNavLink$={customNavLink$} /> ); - expect(component).toMatchSnapshot(); + expect(component.find('EuiHeader').exists()).toBeFalsy(); act(() => isVisible$.next(true)); component.update(); - expect(component).toMatchSnapshot(); + expect(component.find('EuiHeader').exists()).toBeTruthy(); + expect(component.find('nav[aria-label="Primary"]').exists()).toBeFalsy(); act(() => isLocked$.next(true)); component.update(); - expect(component).toMatchSnapshot(); - - act(() => navType$.next('legacy' as NavType)); - component.update(); + expect(component.find('nav[aria-label="Primary"]').exists()).toBeTruthy(); expect(component).toMatchSnapshot(); }); }); diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index c0b3fc72930dc4..e01a62a54c34d8 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -23,8 +23,6 @@ import { EuiHeaderSectionItem, EuiHeaderSectionItemButton, EuiIcon, - EuiNavDrawer, - EuiShowFor, htmlIdGenerator, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -43,14 +41,14 @@ import { import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; import { ChromeHelpExtension } from '../../chrome_service'; -import { NavType, OnIsLockedUpdate } from './'; +import { OnIsLockedUpdate } from './'; import { CollapsibleNav } from './collapsible_nav'; import { HeaderBadge } from './header_badge'; import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderLogo } from './header_logo'; import { HeaderNavControls } from './header_nav_controls'; -import { NavDrawer } from './nav_drawer'; +import { HeaderActionMenu } from './header_action_menu'; export interface HeaderProps { kibanaVersion: string; @@ -68,27 +66,14 @@ export interface HeaderProps { helpExtension$: Observable; helpSupportUrl$: Observable; navControlsLeft$: Observable; + navControlsCenter$: Observable; navControlsRight$: Observable; basePath: HttpStart['basePath']; isLocked$: Observable; - navType$: Observable; loadingCount$: ReturnType; onIsLockedUpdate: OnIsLockedUpdate; } -function renderMenuTrigger(toggleOpen: () => void) { - return ( - - - - ); -} - export function Header({ kibanaVersion, kibanaDocLink, @@ -98,125 +83,117 @@ export function Header({ homeHref, ...observables }: HeaderProps) { - const isVisible = useObservable(observables.isVisible$, true); - const navType = useObservable(observables.navType$, 'modern'); + const isVisible = useObservable(observables.isVisible$, false); const isLocked = useObservable(observables.isLocked$, false); - const [isOpen, setIsOpen] = useState(false); + const [isNavOpen, setIsNavOpen] = useState(false); if (!isVisible) { return ; } - const navDrawerRef = createRef(); const toggleCollapsibleNavRef = createRef(); const navId = htmlIdGenerator()(); - const className = classnames( - 'chrHeaderWrapper', // TODO #64541 - delete this - 'hide-for-sharing', - { - 'chrHeaderWrapper--navIsLocked': isLocked, - headerWrapper: navType === 'modern', - } - ); + const className = classnames('hide-for-sharing', 'headerGlobalNav'); return ( <>
- - - {navType === 'modern' ? ( +
+ , + ], + borders: 'none', + }, + { + ...(observables.navControlsCenter$ && { + items: [], + }), + borders: 'none', + }, + { + items: [ + , + , + ], + borders: 'none', + }, + ]} + /> + + + setIsOpen(!isOpen)} - aria-expanded={isOpen} - aria-pressed={isOpen} + onClick={() => setIsNavOpen(!isNavOpen)} + aria-expanded={isNavOpen} + aria-pressed={isNavOpen} aria-controls={navId} ref={toggleCollapsibleNavRef} > - ) : ( - // TODO #64541 - // Delete this block - - - {renderMenuTrigger(() => navDrawerRef.current?.toggleOpen())} - - - )} - - - + - - + + - + - + - - - - + + + + + + +
- -
-
- {navType === 'modern' ? ( - { - setIsOpen(false); - if (toggleCollapsibleNavRef.current) { - toggleCollapsibleNavRef.current.focus(); - } - }} - customNavLink$={observables.customNavLink$} - /> - ) : ( - // TODO #64541 - // Delete this block - - )} + { + setIsNavOpen(false); + if (toggleCollapsibleNavRef.current) { + toggleCollapsibleNavRef.current.focus(); + } + }} + customNavLink$={observables.customNavLink$} + />
); diff --git a/src/core/public/chrome/ui/header/header_action_menu.test.tsx b/src/core/public/chrome/ui/header/header_action_menu.test.tsx new file mode 100644 index 00000000000000..a124c8ab669690 --- /dev/null +++ b/src/core/public/chrome/ui/header/header_action_menu.test.tsx @@ -0,0 +1,139 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { mount, ReactWrapper } from 'enzyme'; +import { act } from 'react-dom/test-utils'; +import { BehaviorSubject } from 'rxjs'; +import { HeaderActionMenu } from './header_action_menu'; +import { MountPoint, UnmountCallback } from '../../../types'; + +type MockedUnmount = jest.MockedFunction; + +describe('HeaderActionMenu', () => { + let component: ReactWrapper; + let menuMount$: BehaviorSubject; + let unmounts: Record; + + beforeEach(() => { + menuMount$ = new BehaviorSubject(undefined); + unmounts = {}; + }); + + const refresh = () => { + new Promise(async (resolve) => { + if (component) { + act(() => { + component.update(); + }); + } + setImmediate(() => resolve(component)); // flushes any pending promises + }); + }; + + const createMountPoint = (id: string, content: string = id): MountPoint => ( + root + ): MockedUnmount => { + const container = document.createElement('DIV'); + // eslint-disable-next-line no-unsanitized/property + container.innerHTML = content; + root.appendChild(container); + const unmount = jest.fn(() => container.remove()); + unmounts[id] = unmount; + return unmount; + }; + + it('mounts the current value of the provided observable', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
FOO
"` + ); + }); + + it('clears the content of the component when emitting undefined', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
FOO
"` + ); + + act(() => { + menuMount$.next(undefined); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
"` + ); + }); + + it('updates the dom when a new mount point is emitted', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
FOO
"` + ); + + act(() => { + menuMount$.next(createMountPoint('BAR')); + }); + await refresh(); + + expect(component.html()).toMatchInlineSnapshot( + `"
BAR
"` + ); + }); + + it('calls the previous mount point `unmount` when mounting a new mount point', async () => { + component = mount(); + + act(() => { + menuMount$.next(createMountPoint('FOO')); + }); + await refresh(); + + expect(Object.keys(unmounts)).toEqual(['FOO']); + expect(unmounts.FOO).not.toHaveBeenCalled(); + + act(() => { + menuMount$.next(createMountPoint('BAR')); + }); + await refresh(); + + expect(Object.keys(unmounts)).toEqual(['FOO', 'BAR']); + expect(unmounts.FOO).toHaveBeenCalledTimes(1); + expect(unmounts.BAR).not.toHaveBeenCalled(); + }); +}); diff --git a/src/core/public/chrome/ui/header/header_action_menu.tsx b/src/core/public/chrome/ui/header/header_action_menu.tsx new file mode 100644 index 00000000000000..3a7a09608ba66e --- /dev/null +++ b/src/core/public/chrome/ui/header/header_action_menu.tsx @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC, useRef, useLayoutEffect, useState } from 'react'; +import { Observable } from 'rxjs'; +import { MountPoint, UnmountCallback } from '../../../types'; + +interface HeaderActionMenuProps { + actionMenu$: Observable; +} + +export const HeaderActionMenu: FC = ({ actionMenu$ }) => { + // useObservable relies on useState under the hood. The signature is type SetStateAction = S | ((prevState: S) => S); + // As we got a Observable here, React's setState setter assume he's getting a `(prevState: S) => S` signature, + // therefore executing the mount method, causing everything to crash. + // piping the observable before calling `useObservable` causes the effect to always having a new reference, as + // the piped observable is a new instance on every render, causing infinite loops. + // this is why we use `useLayoutEffect` manually here. + const [mounter, setMounter] = useState<{ mount: MountPoint | undefined }>({ mount: undefined }); + useLayoutEffect(() => { + const s = actionMenu$.subscribe((value) => { + setMounter({ mount: value }); + }); + return () => s.unsubscribe(); + }, [actionMenu$]); + + const elementRef = useRef(null); + const unmountRef = useRef(null); + + useLayoutEffect(() => { + if (unmountRef.current) { + unmountRef.current(); + unmountRef.current = null; + } + + if (mounter.mount && elementRef.current) { + try { + unmountRef.current = mounter.mount(elementRef.current); + } catch (e) { + // TODO: use client-side logger when feature is implemented + // eslint-disable-next-line no-console + console.error(e); + } + } + }, [mounter]); + + return
; +}; diff --git a/src/core/public/chrome/ui/header/header_logo.tsx b/src/core/public/chrome/ui/header/header_logo.tsx index 9bec946b6b76e2..dee93ecb1a804f 100644 --- a/src/core/public/chrome/ui/header/header_logo.tsx +++ b/src/core/public/chrome/ui/header/header_logo.tsx @@ -105,6 +105,8 @@ export function HeaderLogo({ href, navigateToApp, ...observables }: Props) { aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel', { defaultMessage: 'Go to home page', })} - /> + > + Elastic + ); } diff --git a/src/core/public/chrome/ui/header/header_nav_controls.tsx b/src/core/public/chrome/ui/header/header_nav_controls.tsx index 0941f7b27b6625..8d9d8097fd8e3f 100644 --- a/src/core/public/chrome/ui/header/header_nav_controls.tsx +++ b/src/core/public/chrome/ui/header/header_nav_controls.tsx @@ -26,7 +26,7 @@ import { HeaderExtension } from './header_extension'; interface Props { navControls$: Observable; - side: 'left' | 'right'; + side?: 'left' | 'right'; } export function HeaderNavControls({ navControls$, side }: Props) { @@ -41,7 +41,10 @@ export function HeaderNavControls({ navControls$, side }: Props) { return ( <> {navControls.map((navControl: ChromeNavControl, index: number) => ( - + ))} diff --git a/src/core/public/chrome/ui/header/nav_drawer.tsx b/src/core/public/chrome/ui/header/nav_drawer.tsx deleted file mode 100644 index fc080fbafc3030..00000000000000 --- a/src/core/public/chrome/ui/header/nav_drawer.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { EuiHorizontalRule, EuiNavDrawer, EuiNavDrawerGroup } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { useObservable } from 'react-use'; -import { Observable } from 'rxjs'; -import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem, CoreStart } from '../../..'; -import { InternalApplicationStart } from '../../../application/types'; -import { HttpStart } from '../../../http'; -import { OnIsLockedUpdate } from './'; -import { createEuiListItem, createRecentNavLink } from './nav_link'; -import { RecentLinks } from './recent_links'; - -export interface Props { - appId$: InternalApplicationStart['currentAppId$']; - basePath: HttpStart['basePath']; - isLocked?: boolean; - navLinks$: Observable; - recentlyAccessed$: Observable; - navigateToApp: CoreStart['application']['navigateToApp']; - onIsLockedUpdate?: OnIsLockedUpdate; -} - -function NavDrawerRenderer( - { isLocked, onIsLockedUpdate, basePath, navigateToApp, ...observables }: Props, - ref: React.Ref -) { - const appId = useObservable(observables.appId$, ''); - const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden); - const recentNavLinks = useObservable(observables.recentlyAccessed$, []).map((link) => - createRecentNavLink(link, navLinks, basePath) - ); - - return ( - - {RecentLinks({ recentNavLinks })} - - - createEuiListItem({ - link, - appId, - basePath, - navigateToApp, - dataTestSubj: 'navDrawerAppsMenuLink', - }) - )} - aria-label={i18n.translate('core.ui.primaryNavList.screenReaderLabel', { - defaultMessage: 'Primary navigation links', - })} - /> - - ); -} - -export const NavDrawer = React.forwardRef(NavDrawerRenderer); diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx index 04d9c5bf7a10a6..a3c73fc4543628 100644 --- a/src/core/public/chrome/ui/header/nav_link.tsx +++ b/src/core/public/chrome/ui/header/nav_link.tsx @@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem, CoreStart } from '../../..'; import { HttpStart } from '../../../http'; +import { InternalApplicationStart } from '../../../application/types'; import { relativeToAbsolute } from '../../nav_links/to_nav_link'; export const isModifiedOrPrevented = (event: React.MouseEvent) => @@ -87,6 +88,7 @@ export interface RecentNavLink { title: string; 'aria-label': string; iconType?: string; + onClick: React.MouseEventHandler; } /** @@ -102,8 +104,9 @@ export interface RecentNavLink { export function createRecentNavLink( recentLink: ChromeRecentlyAccessedHistoryItem, navLinks: ChromeNavLink[], - basePath: HttpStart['basePath'] -) { + basePath: HttpStart['basePath'], + navigateToUrl: InternalApplicationStart['navigateToUrl'] +): RecentNavLink { const { link, label } = recentLink; const href = relativeToAbsolute(basePath.prepend(link)); const navLink = navLinks.find((nl) => href.startsWith(nl.baseUrl)); @@ -125,5 +128,12 @@ export function createRecentNavLink( title: titleAndAriaLabel, 'aria-label': titleAndAriaLabel, iconType: navLink?.euiIconType, + /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ + onClick(event: React.MouseEvent) { + if (event.button === 0 && !isModifiedOrPrevented(event)) { + event.preventDefault(); + navigateToUrl(href); + } + }, }; } diff --git a/src/core/public/context/context_service.mock.ts b/src/core/public/context/context_service.mock.ts index eb55ced69dc048..3f9f647e1f7d00 100644 --- a/src/core/public/context/context_service.mock.ts +++ b/src/core/public/context/context_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/public/core_app/core_app.mock.ts b/src/core/public/core_app/core_app.mock.ts index b0e3871a40bf5d..b2af81b3630a30 100644 --- a/src/core/public/core_app/core_app.mock.ts +++ b/src/core/public/core_app/core_app.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CoreApp } from './core_app'; type CoreAppContract = PublicMethodsOf; diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 006d0036f7a129..a1d6f9c988b270 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -17,6 +17,7 @@ * under the License. */ +import { pick } from '@kbn/std'; import { CoreId } from '../server'; import { PackageInfo, EnvironmentMode } from '../server/types'; import { CoreSetup, CoreStart } from '.'; @@ -35,7 +36,6 @@ import { OverlayService } from './overlays'; import { PluginsService } from './plugins'; import { UiSettingsService } from './ui_settings'; import { ApplicationService } from './application'; -import { pick } from '../utils/'; import { DocLinksService } from './doc_links'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; diff --git a/src/core/public/doc_links/doc_links_service.mock.ts b/src/core/public/doc_links/doc_links_service.mock.ts index 105c13f96cef65..07e29edad8974b 100644 --- a/src/core/public/doc_links/doc_links_service.mock.ts +++ b/src/core/public/doc_links/doc_links_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { DocLinksService, DocLinksStart } from './doc_links_service'; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 95ac8bba570496..47f58a3a9fcbfb 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -17,8 +17,8 @@ * under the License. */ +import { deepFreeze } from '@kbn/std'; import { InjectedMetadataSetup } from '../injected_metadata'; -import { deepFreeze } from '../../utils'; interface StartDeps { injectedMetadata: InjectedMetadataSetup; @@ -38,6 +38,9 @@ export class DocLinksService { links: { dashboard: { drilldowns: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/drilldowns.html`, + drilldownsTriggerPicker: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/url-drilldown.html#trigger-picker`, + urlDrilldownTemplateSyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/url-drilldown.html#templating`, + urlDrilldownVariables: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/url-drilldown.html#variables`, }, filebeat: { base: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}`, @@ -143,6 +146,9 @@ export interface DocLinksStart { readonly links: { readonly dashboard: { readonly drilldowns: string; + readonly drilldownsTriggerPicker: string; + readonly urlDrilldownTemplateSyntax: string; + readonly urlDrilldownVariables: string; }; readonly filebeat: { readonly base: string; diff --git a/src/core/public/fatal_errors/fatal_errors_service.mock.ts b/src/core/public/fatal_errors/fatal_errors_service.mock.ts index 6d9876f787fa97..326ce9a3923e9f 100644 --- a/src/core/public/fatal_errors/fatal_errors_service.mock.ts +++ b/src/core/public/fatal_errors/fatal_errors_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors_service'; const createSetupContractMock = () => { diff --git a/src/core/public/http/base_path.ts b/src/core/public/http/base_path.ts index ac85d71c793fe5..5d9eb51023b78f 100644 --- a/src/core/public/http/base_path.ts +++ b/src/core/public/http/base_path.ts @@ -35,7 +35,7 @@ * under the License. */ -import { modifyUrl } from '../../utils'; +import { modifyUrl } from '@kbn/std'; export class BasePath { constructor( diff --git a/src/core/public/http/http_service.mock.ts b/src/core/public/http/http_service.mock.ts index 1111fd39ec78e6..68533159765fb1 100644 --- a/src/core/public/http/http_service.mock.ts +++ b/src/core/public/http/http_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { HttpService } from './http_service'; import { HttpSetup } from './types'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/core/public/http/loading_count_service.mock.ts b/src/core/public/http/loading_count_service.mock.ts index 79928aa4b160de..2ff635e815296e 100644 --- a/src/core/public/http/loading_count_service.mock.ts +++ b/src/core/public/http/loading_count_service.mock.ts @@ -19,6 +19,7 @@ import { LoadingCountSetup, LoadingCountService } from './loading_count_service'; import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { diff --git a/src/core/public/i18n/i18n_service.mock.ts b/src/core/public/i18n/i18n_service.mock.ts index 1a9ca0869d7c15..a91710fbed7806 100644 --- a/src/core/public/i18n/i18n_service.mock.ts +++ b/src/core/public/i18n/i18n_service.mock.ts @@ -18,6 +18,8 @@ */ import React from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { I18nService, I18nStart } from './i18n_service'; const PassThroughComponent = ({ children }: { children: React.ReactNode }) => children; diff --git a/src/core/public/index.scss b/src/core/public/index.scss index c2ad2841d5a773..6ba9254e5d381f 100644 --- a/src/core/public/index.scss +++ b/src/core/public/index.scss @@ -1,6 +1,6 @@ +@import './variables'; @import './core'; @import './chrome/index'; @import './overlays/index'; @import './rendering/index'; @import './styles/index'; - diff --git a/src/core/public/index.ts b/src/core/public/index.ts index a9774dafd2340a..24d19e2d32074e 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -68,7 +68,6 @@ import { UiSettingsState, IUiSettingsClient } from './ui_settings'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; -export { PackageInfo, EnvironmentMode } from '../server/types'; import { IContextContainer, IContextProvider, @@ -78,17 +77,9 @@ import { HandlerParameters, } from './context'; +export { PackageInfo, EnvironmentMode } from '../server/types'; export { CoreContext, CoreSystem } from './core_system'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { AppCategory, UiSettingsParams, diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index 3bb4358406246b..33d04eedebb072 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { InjectedMetadataService, InjectedMetadataSetup } from './injected_metadata_service'; const createSetupContractMock = () => { diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 23630a5bcf228b..5b51bc823d166e 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -18,6 +18,7 @@ */ import { get } from 'lodash'; +import { deepFreeze } from '@kbn/std'; import { DiscoveredPlugin, PluginName } from '../../server'; import { EnvironmentMode, @@ -25,7 +26,6 @@ import { UiSettingsParams, UserProvidedValues, } from '../../server/types'; -import { deepFreeze } from '../../utils/'; import { AppCategory } from '../'; export interface InjectedPluginMetadata { diff --git a/src/core/public/integrations/integrations_service.mock.ts b/src/core/public/integrations/integrations_service.mock.ts index 4f6ca0fb684597..88458ebb747fe0 100644 --- a/src/core/public/integrations/integrations_service.mock.ts +++ b/src/core/public/integrations/integrations_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IntegrationsService } from './integrations_service'; type IntegrationsServiceContract = PublicMethodsOf; diff --git a/src/core/public/notifications/notifications_service.mock.ts b/src/core/public/notifications/notifications_service.mock.ts index 464f47e20aa3b0..990ab479d35c3c 100644 --- a/src/core/public/notifications/notifications_service.mock.ts +++ b/src/core/public/notifications/notifications_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsService, NotificationsSetup, diff --git a/src/core/public/overlays/banners/banners_service.mock.ts b/src/core/public/overlays/banners/banners_service.mock.ts index 14041b2720877f..acd38af383d677 100644 --- a/src/core/public/overlays/banners/banners_service.mock.ts +++ b/src/core/public/overlays/banners/banners_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayBannersStart, OverlayBannersService } from './banners_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/flyout/flyout_service.mock.ts b/src/core/public/overlays/flyout/flyout_service.mock.ts index 91544500713d6f..90dcb308de1b9e 100644 --- a/src/core/public/overlays/flyout/flyout_service.mock.ts +++ b/src/core/public/overlays/flyout/flyout_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FlyoutService, OverlayFlyoutStart } from './flyout_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/modal/modal_service.mock.ts b/src/core/public/overlays/modal/modal_service.mock.ts index 5ac49874dcf933..0af207d168fae3 100644 --- a/src/core/public/overlays/modal/modal_service.mock.ts +++ b/src/core/public/overlays/modal/modal_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ModalService, OverlayModalStart } from './modal_service'; const createStartContractMock = () => { diff --git a/src/core/public/overlays/overlay_service.mock.ts b/src/core/public/overlays/overlay_service.mock.ts index e29247494034f9..66ba36b20b45cd 100644 --- a/src/core/public/overlays/overlay_service.mock.ts +++ b/src/core/public/overlays/overlay_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { OverlayService, OverlayStart } from './overlay_service'; import { overlayBannersServiceMock } from './banners/banners_service.mock'; import { overlayFlyoutServiceMock } from './flyout/flyout_service.mock'; diff --git a/src/core/public/plugins/plugins_service.mock.ts b/src/core/public/plugins/plugins_service.mock.ts index 900f20422b8260..0625d2c3ec4b24 100644 --- a/src/core/public/plugins/plugins_service.mock.ts +++ b/src/core/public/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; const createSetupContractMock = () => { diff --git a/src/core/public/plugins/plugins_service.ts b/src/core/public/plugins/plugins_service.ts index f9bc40ca526019..87219f4c0bdd3b 100644 --- a/src/core/public/plugins/plugins_service.ts +++ b/src/core/public/plugins/plugins_service.ts @@ -17,6 +17,7 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { PluginName, PluginOpaqueId } from '../../server'; import { CoreService } from '../../types'; import { CoreContext } from '../core_system'; @@ -28,7 +29,6 @@ import { } from './plugin_context'; import { InternalCoreSetup, InternalCoreStart } from '../core_system'; import { InjectedPluginMetadata } from '../injected_metadata'; -import { withTimeout } from '../../utils'; const Sec = 1000; /** @internal */ diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index c473ea67d9bcdc..d22c7ae8058278 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -7,7 +7,8 @@ import { Action } from 'history'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from 'boom'; -import { ErrorToastOptions as ErrorToastOptions_2 } from 'src/core/public/notifications'; +import { ConfigPath } from '@kbn/config'; +import { EnvironmentMode } from '@kbn/config'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; @@ -20,17 +21,18 @@ import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { KibanaConfigType } from 'src/core/server/kibana_config'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; +import { Logger } from '@kbn/logging'; +import { LogMeta } from '@kbn/logging'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; +import { PackageInfo } from '@kbn/config'; import { Path } from 'history'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; import React from 'react'; import { RecursiveReadonly } from '@kbn/utility-types'; import * as Rx from 'rxjs'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { ShallowPromise } from '@kbn/utility-types'; -import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -187,9 +189,6 @@ export type AppUpdatableFields = Pick Partial | undefined; -// @public -export function assertNever(x: never): never; - // @public export interface Capabilities { [key: string]: Record>; @@ -272,10 +271,13 @@ export interface ChromeNavControl { // @public export interface ChromeNavControls { + // @internal (undocumented) + getCenter$(): Observable; // @internal (undocumented) getLeft$(): Observable; // @internal (undocumented) getRight$(): Observable; + registerCenter(navControl: ChromeNavControl): void; registerLeft(navControl: ChromeNavControl): void; registerRight(navControl: ChromeNavControl): void; } @@ -345,7 +347,6 @@ export interface ChromeStart { getHelpExtension$(): Observable; getIsNavDrawerLocked$(): Observable; getIsVisible$(): Observable; - getNavType$(): Observable; navControls: ChromeNavControls; navLinks: ChromeNavLinks; recentlyAccessed: ChromeRecentlyAccessed; @@ -444,9 +445,6 @@ export class CoreSystem { stop(): void; } -// @public -export function deepFreeze(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -490,6 +488,9 @@ export interface DocLinksStart { readonly links: { readonly dashboard: { readonly drilldowns: string; + readonly drilldownsTriggerPicker: string; + readonly urlDrilldownTemplateSyntax: string; + readonly urlDrilldownVariables: string; }; readonly filebeat: { readonly base: string; @@ -580,15 +581,7 @@ export interface DocLinksStart { }; } -// @public (undocumented) -export interface EnvironmentMode { - // (undocumented) - dev: boolean; - // (undocumented) - name: 'development' | 'production'; - // (undocumented) - prod: boolean; -} +export { EnvironmentMode } // @public export interface ErrorToastOptions extends ToastOptions { @@ -613,16 +606,6 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -834,9 +817,6 @@ export interface ImageValidation { }; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export type IToasts = Pick; @@ -865,9 +845,6 @@ export interface IUiSettingsClient { set: (key: string, value: any) => Promise; } -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MountPoint = (element: T) => UnmountCallback; @@ -932,19 +909,7 @@ export interface OverlayStart { openModal: OverlayModalStart['open']; } -// @public (undocumented) -export interface PackageInfo { - // (undocumented) - branch: string; - // (undocumented) - buildNum: number; - // (undocumented) - buildSha: string; - // (undocumented) - dist: boolean; - // (undocumented) - version: string; -} +export { PackageInfo } // @public export interface Plugin { @@ -1444,26 +1409,6 @@ export type UnmountCallback = () => void; // @public export const URL_MAX_LENGTH: number; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index 211e9c03beea50..b806ac270331d2 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -1,5 +1,4 @@ -@import '@elastic/eui/src/global_styling/variables/header'; -@import '@elastic/eui/src/components/nav_drawer/variables'; +@include euiHeaderAffordForFixed($kbnHeaderOffset); /** * stretch the root element of the Kibana application to set the base-size that @@ -12,74 +11,11 @@ min-height: 100%; } -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) ~ .app-wrapper { +.app-wrapper { display: flex; flex-flow: column nowrap; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - z-index: 5; margin: 0 auto; - - &:not(.hidden-chrome) { - top: $euiHeaderChildSize; - left: $euiHeaderChildSize; - - // HOTFIX: Temporary fix for flyouts not inside portals - // SASSTODO: Find an actual solution - .euiFlyout { - top: $euiHeaderChildSize; - height: calc(100% - #{$euiHeaderChildSize}); - } - - @include euiBreakpoint('xs', 's') { - left: 0; - } - } - - /** - * 1. Dirty, but we need to override the .kbnGlobalNav-isOpen state - * when we're looking at the log-in screen. - */ - &.hidden-chrome { - left: 0 !important; /* 1 */ - } - - .navbar-right { - margin-right: 0; - } -} - -// TODO #64541 -// Delete this block -@include euiBreakpoint('xl') { - .chrHeaderWrapper--navIsLocked:not(.headerWrapper) { - ~ .app-wrapper:not(.hidden-chrome) { - // Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS) - left: $euiNavDrawerWidthExpanded !important; // sass-lint:disable-line no-important - transition: left $euiAnimSpeedFast $euiAnimSlightResistance; - } - } -} - -// TODO #64541 -// Remove .headerWrapper and header conditionals -.headerWrapper ~ .app-wrapper, -:not(header) ~ .app-wrapper { - display: flex; - flex-flow: column nowrap; - margin: 0 auto; - min-height: calc(100vh - #{$euiHeaderHeightCompensation}); - - @include internetExplorerOnly { - // IE specific bug with min-height in flex container, described in the next link - // https://github.com/philipwalton/flexbugs#3-min-height-on-a-flex-container-wont-apply-to-its-flex-items - height: calc(100vh - #{$euiHeaderHeightCompensation}); - } + min-height: calc(100vh - #{$kbnHeaderOffset}); &.hidden-chrome { min-height: 100vh; diff --git a/src/core/public/rendering/rendering_service.mock.ts b/src/core/public/rendering/rendering_service.mock.ts index bb4723e69ab5e8..803a7dae91a408 100644 --- a/src/core/public/rendering/rendering_service.mock.ts +++ b/src/core/public/rendering/rendering_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService } from './rendering_service'; type RenderingServiceContract = PublicMethodsOf; diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 351020004b0e70..5a8949ca2f55ff 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -19,6 +19,7 @@ import { cloneDeep, pick, throttle } from 'lodash'; import { resolve as resolveUrl } from 'url'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObject, diff --git a/src/core/public/styles/_base.scss b/src/core/public/styles/_base.scss index 427c6b7735435a..bfb07c1b51427d 100644 --- a/src/core/public/styles/_base.scss +++ b/src/core/public/styles/_base.scss @@ -7,17 +7,6 @@ // Application Layout -// chrome-context -// TODO #64541 -// Delete this block -.chrHeaderWrapper:not(.headerWrapper) .content { - display: flex; - flex-flow: row nowrap; - width: 100%; - height: 100%; - overflow: hidden; -} - .application, .app-container { > * { diff --git a/src/core/public/ui_settings/ui_settings_service.mock.ts b/src/core/public/ui_settings/ui_settings_service.mock.ts index e1f7eeff934719..1921c26e579719 100644 --- a/src/core/public/ui_settings/ui_settings_service.mock.ts +++ b/src/core/public/ui_settings/ui_settings_service.mock.ts @@ -17,6 +17,7 @@ * under the License. */ import * as Rx from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { UiSettingsService } from './'; import { IUiSettingsClient } from './types'; diff --git a/src/core/server/audit_trail/audit_trail_service.mock.ts b/src/core/server/audit_trail/audit_trail_service.mock.ts index d63b3539e5cdc7..4c9c064840750c 100644 --- a/src/core/server/audit_trail/audit_trail_service.mock.ts +++ b/src/core/server/audit_trail/audit_trail_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AuditTrailSetup, AuditTrailStart, Auditor } from './types'; import { AuditTrailService } from './audit_trail_service'; diff --git a/src/core/server/bootstrap.ts b/src/core/server/bootstrap.ts index c0cbe3a39ff548..ff1a5c0340c466 100644 --- a/src/core/server/bootstrap.ts +++ b/src/core/server/bootstrap.ts @@ -60,7 +60,15 @@ export async function bootstrap({ return; } - const env = Env.createDefault({ + // `bootstrap` is exported from the `src/core/server/index` module, + // meaning that any test importing, implicitly or explicitly, anything concrete + // from `core/server` will load `dev-utils`. As some tests are mocking the `fs` package, + // and as `REPO_ROOT` is initialized on the fly when importing `dev-utils` and requires + // the `fs` package, it causes failures. This is why we use a dynamic `require` here. + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { REPO_ROOT } = require('@kbn/utils'); + + const env = Env.createDefault(REPO_ROOT, { configs, cliArgs, isDevClusterMaster: isMaster && cliArgs.dev && features.isClusterModeSupported, diff --git a/src/core/server/capabilities/capabilities_service.mock.ts b/src/core/server/capabilities/capabilities_service.mock.ts index 3f31eca8339d8d..7d134f9592dc72 100644 --- a/src/core/server/capabilities/capabilities_service.mock.ts +++ b/src/core/server/capabilities/capabilities_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CapabilitiesService, CapabilitiesSetup, CapabilitiesStart } from './capabilities_service'; const createSetupContractMock = () => { diff --git a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts index b4d620965b0471..17f2c77bbf660f 100644 --- a/src/core/server/capabilities/integration_tests/capabilities_service.test.ts +++ b/src/core/server/capabilities/integration_tests/capabilities_service.test.ts @@ -18,16 +18,18 @@ */ import supertest from 'supertest'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { HttpService, InternalHttpServiceSetup } from '../../http'; import { contextServiceMock } from '../../context/context_service.mock'; import { loggingSystemMock } from '../../logging/logging_system.mock'; import { Env } from '../../config'; -import { getEnvOptions } from '../../config/__mocks__/env'; +import { getEnvOptions } from '../../config/mocks'; import { CapabilitiesService, CapabilitiesSetup } from '..'; import { createHttpServer } from '../../http/test_utils'; const coreId = Symbol('core'); -const env = Env.createDefault(getEnvOptions()); + +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); describe('CapabilitiesService', () => { let server: HttpService; diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index adf0f523393660..7a69dc2fa726e0 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -17,9 +17,8 @@ * under the License. */ +import { configDeprecationFactory, applyDeprecations } from '@kbn/config'; import { coreDeprecationProvider } from './core_deprecations'; -import { configDeprecationFactory } from './deprecation_factory'; -import { applyDeprecations } from './apply_deprecations'; const initialEnv = { ...process.env }; diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 2b8b8e383da241..2701edcf44e032 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -18,7 +18,7 @@ */ import { has, get } from 'lodash'; -import { ConfigDeprecationProvider, ConfigDeprecation } from './types'; +import { ConfigDeprecationProvider, ConfigDeprecation } from '@kbn/config'; const configPathDeprecation: ConfigDeprecation = (settings, fromPath, log) => { if (has(process.env, 'CONFIG_PATH')) { diff --git a/src/core/server/config/deprecation/index.ts b/src/core/server/config/deprecation/index.ts index f79338665166be..9e8e2e5a2bddf7 100644 --- a/src/core/server/config/deprecation/index.ts +++ b/src/core/server/config/deprecation/index.ts @@ -17,13 +17,4 @@ * under the License. */ -export { - ConfigDeprecation, - ConfigDeprecationWithContext, - ConfigDeprecationLogger, - ConfigDeprecationFactory, - ConfigDeprecationProvider, -} from './types'; -export { configDeprecationFactory } from './deprecation_factory'; export { coreDeprecationProvider } from './core_deprecations'; -export { applyDeprecations } from './apply_deprecations'; diff --git a/src/core/server/config/index.ts b/src/core/server/config/index.ts index 04dc402d35b226..f69a5d081cc8aa 100644 --- a/src/core/server/config/index.ts +++ b/src/core/server/config/index.ts @@ -17,17 +17,25 @@ * under the License. */ -export { ConfigService, IConfigService } from './config_service'; -export { RawConfigService, RawConfigurationProvider } from './raw_config_service'; -export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './config'; -export { ObjectToConfigAdapter } from './object_to_config_adapter'; -export { CliArgs, Env } from './env'; +export { coreDeprecationProvider } from './deprecation'; + export { + ConfigService, + IConfigService, + RawConfigService, + RawConfigurationProvider, + Config, + ConfigPath, + isConfigPath, + hasConfigPathIntersection, + ObjectToConfigAdapter, + CliArgs, + Env, ConfigDeprecation, ConfigDeprecationLogger, ConfigDeprecationProvider, ConfigDeprecationFactory, - coreDeprecationProvider, -} from './deprecation'; - -export { EnvironmentMode, PackageInfo } from './types'; + EnvironmentMode, + PackageInfo, + LegacyObjectToConfigAdapter, +} from '@kbn/config'; diff --git a/src/core/server/config/mocks.ts b/src/core/server/config/mocks.ts new file mode 100644 index 00000000000000..960dda496e6359 --- /dev/null +++ b/src/core/server/config/mocks.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { + getEnvOptions, + rawConfigServiceMock, + configServiceMock, + configMock, +} from '@kbn/config/target/mocks'; diff --git a/src/core/server/context/context_service.mock.ts b/src/core/server/context/context_service.mock.ts index eb55ced69dc048..a8d895acad6245 100644 --- a/src/core/server/context/context_service.mock.ts +++ b/src/core/server/context/context_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ContextService, ContextSetup } from './context_service'; import { contextMock } from '../../utils/context.mock'; diff --git a/src/core/server/core_context.mock.ts b/src/core/server/core_context.mock.ts index f870d30528df42..bbf04783278f7e 100644 --- a/src/core/server/core_context.mock.ts +++ b/src/core/server/core_context.mock.ts @@ -17,15 +17,15 @@ * under the License. */ +import { REPO_ROOT } from '@kbn/dev-utils'; import { CoreContext } from './core_context'; -import { getEnvOptions } from './config/__mocks__/env'; import { Env, IConfigService } from './config'; +import { configServiceMock, getEnvOptions } from './config/mocks'; import { loggingSystemMock } from './logging/logging_system.mock'; -import { configServiceMock } from './config/config_service.mock'; import { ILoggingSystem } from './logging'; function create({ - env = Env.createDefault(getEnvOptions()), + env = Env.createDefault(REPO_ROOT, getEnvOptions()), logger = loggingSystemMock.create(), configService = configServiceMock.create(), }: { diff --git a/src/core/server/elasticsearch/client/configure_client.test.ts b/src/core/server/elasticsearch/client/configure_client.test.ts index 716e2fd98a5e10..250cfc18a757d9 100644 --- a/src/core/server/elasticsearch/client/configure_client.test.ts +++ b/src/core/server/elasticsearch/client/configure_client.test.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ +import { Buffer } from 'buffer'; +import { Readable } from 'stream'; import { RequestEvent, errors } from '@elastic/elasticsearch'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestParams, RequestBody } from '@elastic/elasticsearch/lib/Transport'; import { parseClientOptionsMock, ClientMock } from './configure_client.test.mocks'; import { loggingSystemMock } from '../../logging/logging_system.mock'; @@ -195,40 +197,184 @@ describe('configureClient', () => { `); }); - it('logs each queries if `logQueries` is true', () => { - const client = configureClient( - createFakeConfig({ - logQueries: true, - }), - { logger, scoped: false } - ); + describe('logs each queries if `logQueries` is true', () => { + function createResponseWithBody(body?: RequestBody) { + return createApiResponse({ + body: {}, + statusCode: 200, + params: { + method: 'GET', + path: '/foo', + querystring: { hello: 'dolly' }, + body, + }, + }); + } + + it('when request body is an object', () => { + const client = configureClient( + createFakeConfig({ + logQueries: true, + }), + { logger, scoped: false } + ); + + const response = createResponseWithBody({ + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }); + + client.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` + Array [ + Array [ + "200 + GET /foo?hello=dolly + {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}", + Object { + "tags": Array [ + "query", + ], + }, + ], + ] + `); + }); - const response = createApiResponse({ - body: {}, - statusCode: 200, - params: { - method: 'GET', - path: '/foo', - querystring: { hello: 'dolly' }, - }, + it('when request body is a string', () => { + const client = configureClient( + createFakeConfig({ + logQueries: true, + }), + { logger, scoped: false } + ); + + const response = createResponseWithBody( + JSON.stringify({ + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }) + ); + + client.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` + Array [ + Array [ + "200 + GET /foo?hello=dolly + {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}", + Object { + "tags": Array [ + "query", + ], + }, + ], + ] + `); }); - client.emit('response', null, response); + it('when request body is a buffer', () => { + const client = configureClient( + createFakeConfig({ + logQueries: true, + }), + { logger, scoped: false } + ); + + const response = createResponseWithBody( + Buffer.from( + JSON.stringify({ + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }) + ) + ); + + client.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` + Array [ + Array [ + "200 + GET /foo?hello=dolly + [buffer]", + Object { + "tags": Array [ + "query", + ], + }, + ], + ] + `); + }); - expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` - Array [ + it('when request body is a readable stream', () => { + const client = configureClient( + createFakeConfig({ + logQueries: true, + }), + { logger, scoped: false } + ); + + const response = createResponseWithBody( + // @ts-expect-error definition doesn't know about from + Readable.from( + JSON.stringify({ + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }) + ) + ); + + client.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ - "200 - GET /foo - hello=dolly", - Object { - "tags": Array [ - "query", - ], - }, - ], - ] - `); + Array [ + "200 + GET /foo?hello=dolly + [stream]", + Object { + "tags": Array [ + "query", + ], + }, + ], + ] + `); + }); + + it('when request body is not defined', () => { + const client = configureClient( + createFakeConfig({ + logQueries: true, + }), + { logger, scoped: false } + ); + + const response = createResponseWithBody(); + + client.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` + Array [ + Array [ + "200 + GET /foo?hello=dolly", + Object { + "tags": Array [ + "query", + ], + }, + ], + ] + `); + }); }); it('properly encode queries', () => { @@ -255,8 +401,7 @@ describe('configureClient', () => { Array [ Array [ "200 - GET /foo - city=M%C3%BCnich", + GET /foo?city=M%C3%BCnich", Object { "tags": Array [ "query", @@ -286,6 +431,12 @@ describe('configureClient', () => { method: 'GET', path: '/foo', querystring: { hello: 'dolly' }, + body: { + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }, }, }); client.emit('response', new errors.ResponseError(response), response); @@ -294,8 +445,8 @@ describe('configureClient', () => { Array [ Array [ "500 - GET /foo - hello=dolly", + GET /foo?hello=dolly + {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}", Object { "tags": Array [ "query", diff --git a/src/core/server/elasticsearch/client/configure_client.ts b/src/core/server/elasticsearch/client/configure_client.ts index a777344813068d..bf07ea604d228d 100644 --- a/src/core/server/elasticsearch/client/configure_client.ts +++ b/src/core/server/elasticsearch/client/configure_client.ts @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - +import { Buffer } from 'buffer'; import { stringify } from 'querystring'; import { Client } from '@elastic/elasticsearch'; +import { RequestBody } from '@elastic/elasticsearch/lib/Transport'; + import { Logger } from '../../logging'; import { parseClientOptions, ElasticsearchClientConfig } from './client_config'; @@ -48,15 +50,11 @@ const addLogging = (client: Client, logger: Logger, logQueries: boolean) => { // definition is wrong, `params.querystring` can be either a string or an object const querystring = convertQueryString(params.querystring); - - logger.debug( - `${event.statusCode}\n${params.method} ${params.path}${ - querystring ? `\n${querystring}` : '' - }`, - { - tags: ['query'], - } - ); + const url = `${params.path}${querystring ? `?${querystring}` : ''}`; + const body = params.body ? `\n${ensureString(params.body)}` : ''; + logger.debug(`${event.statusCode}\n${params.method} ${url}${body}`, { + tags: ['query'], + }); } }); }; @@ -67,3 +65,10 @@ const convertQueryString = (qs: string | Record | undefined): strin } return stringify(qs); }; + +function ensureString(body: RequestBody): string { + if (typeof body === 'string') return body; + if (Buffer.isBuffer(body)) return '[buffer]'; + if ('readable' in body && body.readable && typeof body._read === 'function') return '[stream]'; + return JSON.stringify(body); +} diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 2f2ca08fee6f20..6fb3dc090bfb4f 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { Client, ApiResponse } from '@elastic/elasticsearch'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { ElasticsearchClient } from './types'; @@ -75,7 +74,7 @@ export type ElasticsearchClientMock = DeeplyMockedKeys; const createClientMock = (): ElasticsearchClientMock => (createInternalClientMock() as unknown) as ElasticsearchClientMock; -interface ScopedClusterClientMock { +export interface ScopedClusterClientMock { asInternalUser: ElasticsearchClientMock; asCurrentUser: ElasticsearchClientMock; } diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index 648eaaf8a97f27..3912c68836bb24 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -23,8 +23,8 @@ import { mockReadPkcs12Truststore, } from './elasticsearch_config.test.mocks'; +import { applyDeprecations, configDeprecationFactory } from '@kbn/config'; import { ElasticsearchConfig, config } from './elasticsearch_config'; -import { applyDeprecations, configDeprecationFactory } from '../config/deprecation'; const CONFIG_PATH = 'elasticsearch'; diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index 26186efc286bfa..ad80928d2fe5ef 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -18,6 +18,8 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { ILegacyClusterClient, ILegacyCustomClusterClient } from './legacy'; import { elasticsearchClientMock, @@ -32,7 +34,7 @@ import { InternalElasticsearchServiceSetup, ElasticsearchStatusMeta } from './ty import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus, ServiceStatusLevels } from '../status'; -interface MockedElasticSearchServiceSetup { +export interface MockedElasticSearchServiceSetup { legacy: { config$: BehaviorSubject; createClient: jest.Mock; diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.ts b/src/core/server/elasticsearch/elasticsearch_service.test.ts index 49f5c8dd987902..ce82410f6061e0 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.ts @@ -20,10 +20,10 @@ import { MockLegacyClusterClient, MockClusterClient } from './elasticsearch_service.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { first } from 'rxjs/operators'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; +import { configServiceMock, getEnvOptions } from '../config/mocks'; import { CoreContext } from '../core_context'; -import { configServiceMock } from '../config/config_service.mock'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { httpServiceMock } from '../http/http_service.mock'; import { auditTrailServiceMock } from '../audit_trail/audit_trail_service.mock'; @@ -64,7 +64,7 @@ let mockClusterClientInstance: ReturnType; beforeEach(() => { - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); coreContext = { coreId: Symbol(), env, logger, configService: configService as any }; elasticsearchService = new ElasticsearchService(coreContext); diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 2cc065aaaaeb14..5d07840e8bda79 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -19,9 +19,9 @@ import { Observable, Subject } from 'rxjs'; import { first, map, shareReplay, takeUntil } from 'rxjs/operators'; +import { merge } from '@kbn/std'; import { CoreService } from '../../types'; -import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { diff --git a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 3dbc1c2c647a99..6896c0a2e301f2 100644 --- a/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -22,7 +22,7 @@ import { cloneDeep } from 'lodash'; import { Duration } from 'moment'; import { checkServerIdentity } from 'tls'; import url from 'url'; -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; import { Logger } from '../../logging'; import { ElasticsearchConfig } from '../elasticsearch_config'; diff --git a/src/core/server/environment/create_data_folder.test.ts b/src/core/server/environment/create_data_folder.test.ts index 2a480a7a3954f4..25c1d57996e0d9 100644 --- a/src/core/server/environment/create_data_folder.test.ts +++ b/src/core/server/environment/create_data_folder.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { PathConfigType } from '../path'; +import { PathConfigType } from '@kbn/utils'; import { createDataFolder } from './create_data_folder'; import { mkdir } from './fs'; import { loggingSystemMock } from '../logging/logging_system.mock'; diff --git a/src/core/server/environment/create_data_folder.ts b/src/core/server/environment/create_data_folder.ts index 641d95cbf94117..f90e9f93694eb2 100644 --- a/src/core/server/environment/create_data_folder.ts +++ b/src/core/server/environment/create_data_folder.ts @@ -17,9 +17,9 @@ * under the License. */ +import { PathConfigType } from '@kbn/utils'; import { mkdir } from './fs'; import { Logger } from '../logging'; -import { PathConfigType } from '../path'; export async function createDataFolder({ pathConfig, diff --git a/src/core/server/environment/environment_service.mock.ts b/src/core/server/environment/environment_service.mock.ts index 8bf726b4a6388b..a956e369ba4a72 100644 --- a/src/core/server/environment/environment_service.mock.ts +++ b/src/core/server/environment/environment_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; diff --git a/src/core/server/environment/environment_service.test.ts b/src/core/server/environment/environment_service.test.ts index 06fd250ebe4f93..e4dcfc49c11301 100644 --- a/src/core/server/environment/environment_service.test.ts +++ b/src/core/server/environment/environment_service.test.ts @@ -18,12 +18,14 @@ */ import { BehaviorSubject } from 'rxjs'; + import { EnvironmentService } from './environment_service'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; import { CoreContext } from '../core_context'; -import { configServiceMock } from '../config/config_service.mock'; +import { configServiceMock } from '../config/mocks'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { mockCoreContext } from '../core_context.mock'; @@ -35,12 +37,20 @@ jest.mock('./create_data_folder', () => ({ createDataFolder: jest.fn(), })); +jest.mock('./write_pid_file', () => ({ + writePidFile: jest.fn(), +})); + const pathConfig = { data: 'data-folder', }; const serverConfig = { uuid: 'SOME_UUID', }; +const pidConfig = { + file: '/pid/file', + exclusive: 'false', +}; const getConfigService = () => { const configService = configServiceMock.create(); @@ -51,6 +61,9 @@ const getConfigService = () => { if (path === 'server') { return new BehaviorSubject(serverConfig); } + if (path === 'pid') { + return new BehaviorSubject(pidConfig); + } return new BehaviorSubject({}); }); return configService; @@ -76,7 +89,7 @@ describe('UuidService', () => { expect(resolveInstanceUuid).toHaveBeenCalledWith({ pathConfig, serverConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), }); }); @@ -86,7 +99,17 @@ describe('UuidService', () => { expect(createDataFolder).toHaveBeenCalledTimes(1); expect(createDataFolder).toHaveBeenCalledWith({ pathConfig, - logger: logger.get('uuid'), + logger: logger.get('environment'), + }); + }); + + it('calls writePidFile with correct parameters', async () => { + const service = new EnvironmentService(coreContext); + await service.setup(); + expect(writePidFile).toHaveBeenCalledTimes(1); + expect(writePidFile).toHaveBeenCalledWith({ + pidConfig, + logger: logger.get('environment'), }); }); diff --git a/src/core/server/environment/environment_service.ts b/src/core/server/environment/environment_service.ts index 6a0b1122c70534..b051dfbe4c7f2b 100644 --- a/src/core/server/environment/environment_service.ts +++ b/src/core/server/environment/environment_service.ts @@ -18,13 +18,15 @@ */ import { take } from 'rxjs/operators'; +import { PathConfigType, config as pathConfigDef } from '@kbn/utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { IConfigService } from '../config'; -import { PathConfigType, config as pathConfigDef } from '../path'; import { HttpConfigType, config as httpConfigDef } from '../http'; +import { PidConfigType, config as pidConfigDef } from './pid_config'; import { resolveInstanceUuid } from './resolve_uuid'; import { createDataFolder } from './create_data_folder'; +import { writePidFile } from './write_pid_file'; /** * @internal @@ -43,17 +45,24 @@ export class EnvironmentService { private uuid: string = ''; constructor(core: CoreContext) { - this.log = core.logger.get('uuid'); + this.log = core.logger.get('environment'); this.configService = core.configService; } public async setup() { - const [pathConfig, serverConfig] = await Promise.all([ + const [pathConfig, serverConfig, pidConfig] = await Promise.all([ this.configService.atPath(pathConfigDef.path).pipe(take(1)).toPromise(), this.configService.atPath(httpConfigDef.path).pipe(take(1)).toPromise(), + this.configService.atPath(pidConfigDef.path).pipe(take(1)).toPromise(), ]); + // was present in the legacy `pid` file. + process.on('unhandledRejection', (reason) => { + this.log.warn(`Detected an unhandled Promise rejection.\n${reason}`); + }); + await createDataFolder({ pathConfig, logger: this.log }); + await writePidFile({ pidConfig, logger: this.log }); this.uuid = await resolveInstanceUuid({ pathConfig, diff --git a/src/core/server/environment/fs.ts b/src/core/server/environment/fs.ts index dc040ccb736159..b79c70dbee280d 100644 --- a/src/core/server/environment/fs.ts +++ b/src/core/server/environment/fs.ts @@ -23,3 +23,4 @@ import { promisify } from 'util'; export const readFile = promisify(Fs.readFile); export const writeFile = promisify(Fs.writeFile); export const mkdir = promisify(Fs.mkdir); +export const exists = promisify(Fs.exists); diff --git a/src/core/server/environment/index.ts b/src/core/server/environment/index.ts index 57a26d5ea3c797..92b57c6af2fff2 100644 --- a/src/core/server/environment/index.ts +++ b/src/core/server/environment/index.ts @@ -18,3 +18,4 @@ */ export { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service'; +export { config, PidConfigType } from './pid_config'; diff --git a/src/core/server/environment/pid_config.ts b/src/core/server/environment/pid_config.ts new file mode 100644 index 00000000000000..ee9963016717e2 --- /dev/null +++ b/src/core/server/environment/pid_config.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TypeOf, schema } from '@kbn/config-schema'; + +export const config = { + path: 'pid', + schema: schema.object({ + file: schema.maybe(schema.string()), + exclusive: schema.boolean({ defaultValue: false }), + }), +}; + +export type PidConfigType = TypeOf; diff --git a/src/core/server/environment/resolve_uuid.test.ts b/src/core/server/environment/resolve_uuid.test.ts index d162c9d8e364b7..c6e8465507123f 100644 --- a/src/core/server/environment/resolve_uuid.test.ts +++ b/src/core/server/environment/resolve_uuid.test.ts @@ -18,10 +18,10 @@ */ import { join } from 'path'; +import { PathConfigType } from '@kbn/utils'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { readFile, writeFile } from './fs'; import { resolveInstanceUuid, UUID_7_6_0_BUG } from './resolve_uuid'; -import { PathConfigType } from '../path'; import { HttpConfigType } from '../http'; jest.mock('uuid', () => ({ diff --git a/src/core/server/environment/resolve_uuid.ts b/src/core/server/environment/resolve_uuid.ts index 0267e069399972..a640319e30af47 100644 --- a/src/core/server/environment/resolve_uuid.ts +++ b/src/core/server/environment/resolve_uuid.ts @@ -19,8 +19,8 @@ import uuid from 'uuid'; import { join } from 'path'; +import { PathConfigType } from '@kbn/utils'; import { readFile, writeFile } from './fs'; -import { PathConfigType } from '../path'; import { HttpConfigType } from '../http'; import { Logger } from '../logging'; diff --git a/src/core/server/environment/write_pid_file.test.ts b/src/core/server/environment/write_pid_file.test.ts new file mode 100644 index 00000000000000..f9eb78a4869701 --- /dev/null +++ b/src/core/server/environment/write_pid_file.test.ts @@ -0,0 +1,144 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { writeFile, exists } from './fs'; +import { writePidFile } from './write_pid_file'; +import { loggingSystemMock } from '../logging/logging_system.mock'; + +jest.mock('./fs', () => ({ + writeFile: jest.fn(), + exists: jest.fn(), +})); + +const writeFileMock = writeFile as jest.MockedFunction; +const existsMock = exists as jest.MockedFunction; + +const pid = String(process.pid); + +describe('writePidFile', () => { + let logger: ReturnType; + + beforeEach(() => { + logger = loggingSystemMock.createLogger(); + jest.spyOn(process, 'once'); + + writeFileMock.mockImplementation(() => Promise.resolve()); + existsMock.mockImplementation(() => Promise.resolve(false)); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const allLogs = () => + Object.entries(loggingSystemMock.collect(logger)).reduce((messages, [key, value]) => { + return [...messages, ...(key === 'log' ? [] : (value as any[]).map(([msg]) => [key, msg]))]; + }, [] as any[]); + + it('does nothing if `pid.file` is not set', async () => { + await writePidFile({ + pidConfig: { + file: undefined, + exclusive: false, + }, + logger, + }); + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('writes the pid file to `pid.file`', async () => { + existsMock.mockResolvedValue(false); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + ] + `); + }); + + it('throws an error if the file exists and `pid.exclusive is true`', async () => { + existsMock.mockResolvedValue(true); + + await expect( + writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: true, + }, + logger, + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"pid file already exists at /pid-file"`); + + expect(writeFile).not.toHaveBeenCalled(); + expect(process.once).not.toHaveBeenCalled(); + expect(allLogs()).toMatchInlineSnapshot(`Array []`); + }); + + it('logs a warning if the file exists and `pid.exclusive` is false', async () => { + existsMock.mockResolvedValue(true); + + await writePidFile({ + pidConfig: { + file: '/pid-file', + exclusive: false, + }, + logger, + }); + + expect(writeFile).toHaveBeenCalledTimes(1); + expect(writeFile).toHaveBeenCalledWith('/pid-file', pid); + + expect(process.once).toHaveBeenCalledTimes(2); + expect(process.once).toHaveBeenCalledWith('exit', expect.any(Function)); + expect(process.once).toHaveBeenCalledWith('SIGINT', expect.any(Function)); + + expect(allLogs()).toMatchInlineSnapshot(` + Array [ + Array [ + "debug", + "wrote pid file to /pid-file", + ], + Array [ + "warn", + "pid file already exists at /pid-file", + ], + ] + `); + }); +}); diff --git a/src/core/server/environment/write_pid_file.ts b/src/core/server/environment/write_pid_file.ts new file mode 100644 index 00000000000000..6ee20af02d7b0f --- /dev/null +++ b/src/core/server/environment/write_pid_file.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { unlinkSync as unlink } from 'fs'; +import once from 'lodash/once'; +import { Logger } from '../logging'; +import { writeFile, exists } from './fs'; +import { PidConfigType } from './pid_config'; + +export const writePidFile = async ({ + pidConfig, + logger, +}: { + pidConfig: PidConfigType; + logger: Logger; +}) => { + const path = pidConfig.file; + if (!path) { + return; + } + + const pid = String(process.pid); + + if (await exists(path)) { + const message = `pid file already exists at ${path}`; + if (pidConfig.exclusive) { + throw new Error(message); + } else { + logger.warn(message, { path, pid }); + } + } + + await writeFile(path, pid); + + logger.debug(`wrote pid file to ${path}`, { path, pid }); + + const clean = once(() => { + unlink(path); + }); + + process.once('exit', clean); // for "natural" exits + process.once('SIGINT', () => { + // for Ctrl-C exits + clean(); + // resend SIGINT + process.kill(process.pid, 'SIGINT'); + }); +}; diff --git a/src/core/server/http/base_path_service.ts b/src/core/server/http/base_path_service.ts index 093d73b2da3bf3..059eb36f42dd5b 100644 --- a/src/core/server/http/base_path_service.ts +++ b/src/core/server/http/base_path_service.ts @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; +import { modifyUrl } from '@kbn/std'; -import { modifyUrl } from '../../utils'; +import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router'; /** * Access or manipulate the Kibana base path diff --git a/src/core/server/http/cookie_session_storage.test.ts b/src/core/server/http/cookie_session_storage.test.ts index 8e5dec7d4eadd7..b7ade0cbde0fcc 100644 --- a/src/core/server/http/cookie_session_storage.test.ts +++ b/src/core/server/http/cookie_session_storage.test.ts @@ -18,20 +18,20 @@ */ import request from 'request'; import supertest from 'supertest'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { ByteSizeValue } from '@kbn/config-schema'; import { BehaviorSubject } from 'rxjs'; import { CoreContext } from '../core_context'; import { HttpService } from './http_service'; import { KibanaRequest } from './router'; - import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; -import { configServiceMock } from '../config/config_service.mock'; + import { contextServiceMock } from '../context/context_service.mock'; import { loggingSystemMock } from '../logging/logging_system.mock'; - +import { getEnvOptions, configServiceMock } from '../config/mocks'; import { httpServerMock } from './http_server.mocks'; + import { createCookieSessionStorageFactory } from './cookie_session_storage'; let server: HttpService; @@ -72,7 +72,7 @@ configService.atPath.mockReturnValue( beforeEach(() => { logger = loggingSystemMock.create(); - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); coreContext = { coreId: Symbol(), env, logger, configService: configService as any }; server = new HttpService(coreContext); diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index 676cee1954c59a..f81708145edc46 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -18,9 +18,10 @@ */ import { Server } from 'hapi'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { CspConfig } from '../csp'; import { mockRouter, RouterMock } from './router/router.mock'; -import { configMock } from '../config/config.mock'; import { InternalHttpServiceSetup, HttpServiceSetup, @@ -35,6 +36,7 @@ import { sessionStorageMock } from './cookie_session_storage.mocks'; import { OnPostAuthToolkit } from './lifecycle/on_post_auth'; import { OnPreAuthToolkit } from './lifecycle/on_pre_auth'; import { OnPreResponseToolkit } from './lifecycle/on_pre_response'; +import { configMock } from '../config/mocks'; type BasePathMocked = jest.Mocked; type AuthMocked = jest.Mocked; diff --git a/src/core/server/http/http_service.test.ts b/src/core/server/http/http_service.test.ts index 3d759b427d9fb0..11cea88fa0dd2f 100644 --- a/src/core/server/http/http_service.test.ts +++ b/src/core/server/http/http_service.test.ts @@ -21,17 +21,18 @@ import { mockHttpServer } from './http_service.test.mocks'; import { noop } from 'lodash'; import { BehaviorSubject } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; +import { getEnvOptions } from '../config/mocks'; import { HttpService } from '.'; import { HttpConfigType, config } from './http_config'; import { httpServerMock } from './http_server.mocks'; import { ConfigService, Env } from '../config'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { contextServiceMock } from '../context/context_service.mock'; -import { getEnvOptions } from '../config/__mocks__/env'; import { config as cspConfig } from '../csp'; const logger = loggingSystemMock.create(); -const env = Env.createDefault(getEnvOptions()); +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); const coreId = Symbol(); const createConfigService = (value: Partial = {}) => { @@ -115,7 +116,7 @@ test('spins up notReady server until started if configured with `autoListen:true const service = new HttpService({ coreId, configService, - env: new Env('.', getEnvOptions()), + env: Env.createDefault(REPO_ROOT, getEnvOptions()), logger, }); @@ -263,7 +264,7 @@ test('does not start http server if process is dev cluster master', async () => const service = new HttpService({ coreId, configService, - env: new Env('.', getEnvOptions({ isDevClusterMaster: true })), + env: Env.createDefault(REPO_ROOT, getEnvOptions({ isDevClusterMaster: true })), logger, }); @@ -288,7 +289,7 @@ test('does not start http server if configured with `autoListen:false`', async ( const service = new HttpService({ coreId, configService, - env: new Env('.', getEnvOptions()), + env: Env.createDefault(REPO_ROOT, getEnvOptions()), logger, }); diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index c2fd6539181719..82b141c8e50dd0 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -20,9 +20,9 @@ import { Observable, Subscription, combineLatest } from 'rxjs'; import { first, map } from 'rxjs/operators'; import { Server } from 'hapi'; +import { pick } from '@kbn/std'; import { CoreService } from '../../types'; -import { pick } from '../../utils'; import { Logger, LoggerFactory } from '../logging'; import { ContextSetup } from '../context'; import { Env } from '../config'; diff --git a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts index a1401ba73813b3..a964130550bf55 100644 --- a/src/core/server/http/integration_tests/lifecycle_handlers.test.ts +++ b/src/core/server/http/integration_tests/lifecycle_handlers.test.ts @@ -20,16 +20,18 @@ import supertest from 'supertest'; import { BehaviorSubject } from 'rxjs'; import { ByteSizeValue } from '@kbn/config-schema'; -import pkg from '../../../../../package.json'; import { createHttpServer } from '../test_utils'; import { HttpService } from '../http_service'; import { HttpServerSetup } from '../http_server'; import { IRouter, RouteRegistrar } from '../router'; -import { configServiceMock } from '../../config/config_service.mock'; +import { configServiceMock } from '../../config/mocks'; import { contextServiceMock } from '../../context/context_service.mock'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = require('../../../../../package.json'); + const actualVersion = pkg.version; const versionHeader = 'kbn-version'; const xsrfHeader = 'kbn-xsrf'; diff --git a/src/core/server/http/router/headers.ts b/src/core/server/http/router/headers.ts index f27f5e937b2c04..498dd153a43dd7 100644 --- a/src/core/server/http/router/headers.ts +++ b/src/core/server/http/router/headers.ts @@ -17,8 +17,7 @@ * under the License. */ import { IncomingHttpHeaders } from 'http'; - -import { pick } from '../../../utils'; +import { pick } from '@kbn/std'; /** * Creates a Union type of all known keys of a given interface. diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index 76f8761a7e998b..e04f8585981b52 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -23,8 +23,8 @@ import { Request, RouteOptionsApp, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { deepFreeze } from '@kbn/std'; -import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; diff --git a/src/core/server/http/test_utils.ts b/src/core/server/http/test_utils.ts index c3afae108027e1..b4d91926f13f41 100644 --- a/src/core/server/http/test_utils.ts +++ b/src/core/server/http/test_utils.ts @@ -18,16 +18,16 @@ */ import { BehaviorSubject } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { ByteSizeValue } from '@kbn/config-schema'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; import { HttpService } from './http_service'; import { CoreContext } from '../core_context'; -import { configServiceMock } from '../config/config_service.mock'; +import { getEnvOptions, configServiceMock } from '../config/mocks'; import { loggingSystemMock } from '../logging/logging_system.mock'; const coreId = Symbol('core'); -const env = Env.createDefault(getEnvOptions()); +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); const logger = loggingSystemMock.create(); diff --git a/src/core/server/index.ts b/src/core/server/index.ts index d127471348d9f7..01797d073ae2e4 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -322,16 +322,7 @@ export { MetricsServiceSetup, } from './metrics'; -export { - DEFAULT_APP_CATEGORIES, - getFlattenedObject, - URLMeaningfulParts, - modifyUrl, - isRelativeUrl, - Freezable, - deepFreeze, - assertNever, -} from '../utils'; +export { DEFAULT_APP_CATEGORIES } from '../utils'; export { SavedObject, diff --git a/src/core/server/legacy/cli.js b/src/core/server/legacy/cli.js new file mode 100644 index 00000000000000..28e14d28eecd37 --- /dev/null +++ b/src/core/server/legacy/cli.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { startRepl } from '../../../cli/repl'; diff --git a/src/core/server/legacy/cluster_manager.js b/src/core/server/legacy/cluster_manager.js new file mode 100644 index 00000000000000..3c51fd6869a093 --- /dev/null +++ b/src/core/server/legacy/cluster_manager.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { ClusterManager } from '../../../cli/cluster/cluster_manager'; diff --git a/src/core/server/legacy/config/ensure_valid_configuration.test.ts b/src/core/server/legacy/config/ensure_valid_configuration.test.ts index d8917b46eba62b..702840b8a0a6a2 100644 --- a/src/core/server/legacy/config/ensure_valid_configuration.test.ts +++ b/src/core/server/legacy/config/ensure_valid_configuration.test.ts @@ -19,7 +19,7 @@ import { ensureValidConfiguration } from './ensure_valid_configuration'; import { getUnusedConfigKeys } from './get_unused_config_keys'; -import { configServiceMock } from '../../config/config_service.mock'; +import { configServiceMock } from '../../config/mocks'; jest.mock('./get_unused_config_keys'); diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index d10c574f049743..c15c3b270df056 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,8 +18,8 @@ */ import { difference } from 'lodash'; +import { getFlattenedObject } from '@kbn/std'; import { unset } from '../../../../legacy/utils'; -import { getFlattenedObject } from '../../../utils'; import { hasConfigPathIntersection } from '../../config'; import { LegacyPluginSpec, LegacyConfig, LegacyVars } from '../types'; diff --git a/src/core/server/legacy/config/index.ts b/src/core/server/legacy/config/index.ts index b56b83ca324cbc..c8781945d7cbcd 100644 --- a/src/core/server/legacy/config/index.ts +++ b/src/core/server/legacy/config/index.ts @@ -18,4 +18,3 @@ */ export { ensureValidConfiguration } from './ensure_valid_configuration'; -export { LegacyObjectToConfigAdapter } from './legacy_object_to_config_adapter'; diff --git a/src/core/server/legacy/index.ts b/src/core/server/legacy/index.ts index 208e9b11672536..6b0963e3129c6b 100644 --- a/src/core/server/legacy/index.ts +++ b/src/core/server/legacy/index.ts @@ -18,7 +18,7 @@ */ /** @internal */ -export { LegacyObjectToConfigAdapter, ensureValidConfiguration } from './config'; +export { ensureValidConfiguration } from './config'; /** @internal */ export { LegacyInternals } from './legacy_internals'; /** @internal */ diff --git a/src/core/server/legacy/integration_tests/logging.test.ts b/src/core/server/legacy/integration_tests/logging.test.ts index 2ebe17ea92978c..dfcecd3f36b361 100644 --- a/src/core/server/legacy/integration_tests/logging.test.ts +++ b/src/core/server/legacy/integration_tests/logging.test.ts @@ -16,6 +16,8 @@ * specific language governing permissions and limitations * under the License. */ + +import { LegacyLoggingConfig } from '@kbn/config'; import * as kbnTestServer from '../../../test_helpers/kbn_server'; import { @@ -23,8 +25,6 @@ import { getLegacyPlatformLogsFromMock, } from '../../logging/integration_tests/utils'; -import { LegacyLoggingConfig } from '../config/legacy_object_to_config_adapter'; - function createRoot(legacyLoggingConfig: LegacyLoggingConfig = {}) { return kbnTestServer.createRoot({ migrations: { skip: true }, // otherwise stuck in polling ES diff --git a/src/core/server/legacy/legacy_internals.test.ts b/src/core/server/legacy/legacy_internals.test.ts index 67f2f433d4570d..935e36a989a0cf 100644 --- a/src/core/server/legacy/legacy_internals.test.ts +++ b/src/core/server/legacy/legacy_internals.test.ts @@ -19,7 +19,7 @@ import { Server } from 'hapi'; -import { configMock } from '../config/config.mock'; +import { configMock } from '../config/mocks'; import { httpServiceMock } from '../http/http_service.mock'; import { httpServerMock } from '../http/http_server.mocks'; import { findLegacyPluginSpecsMock } from './legacy_service.test.mocks'; diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts index c27f5be04d965f..ab501bd6bb53b0 100644 --- a/src/core/server/legacy/legacy_service.mock.ts +++ b/src/core/server/legacy/legacy_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LegacyService } from './legacy_service'; import { LegacyConfig, LegacyServiceDiscoverPlugins, LegacyServiceSetupDeps } from './types'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index d0492ea88c5e8a..549252723be3f4 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -18,23 +18,23 @@ */ jest.mock('../../../legacy/server/kbn_server'); -jest.mock('../../../cli/cluster/cluster_manager'); - +jest.mock('./cluster_manager'); import { findLegacyPluginSpecsMock, logLegacyThirdPartyPluginDeprecationWarningMock, } from './legacy_service.test.mocks'; import { BehaviorSubject, throwError } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; -import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; +// @ts-expect-error js file to remove TS dependency on cli +import { ClusterManager as MockClusterManager } from './cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; import { BasePathProxyServer } from '../http'; import { DiscoveredPlugin } from '../plugins'; -import { configServiceMock } from '../config/config_service.mock'; +import { getEnvOptions, configServiceMock } from '../config/mocks'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { contextServiceMock } from '../context/context_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; @@ -68,7 +68,7 @@ let environmentSetup: ReturnType { coreId = Symbol(); - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); configService = configServiceMock.create(); environmentSetup = environmentServiceMock.createSetupContract(); @@ -363,6 +363,7 @@ describe('once LegacyService is set up in `devClusterMaster` mode', () => { const devClusterLegacyService = new LegacyService({ coreId, env: Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { silent: true, basePath: false }, isDevClusterMaster: true, @@ -391,6 +392,7 @@ describe('once LegacyService is set up in `devClusterMaster` mode', () => { const devClusterLegacyService = new LegacyService({ coreId, env: Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { quiet: true, basePath: true }, isDevClusterMaster: true, diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 6e6d5cfc24340e..fd3e3a694e6ae8 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -16,10 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { combineLatest, ConnectableObservable, EMPTY, Observable, Subscription } from 'rxjs'; import { first, map, publishReplay, tap } from 'rxjs/operators'; +import { PathConfigType } from '@kbn/utils'; import { CoreService } from '../../types'; import { Config } from '../config'; import { CoreContext } from '../core_context'; @@ -27,7 +28,6 @@ import { CspConfigType, config as cspConfig } from '../csp'; import { DevConfig, DevConfigType, config as devConfig } from '../dev'; import { BasePathProxyServer, HttpConfig, HttpConfigType, config as httpConfig } from '../http'; import { Logger } from '../logging'; -import { PathConfigType } from '../path'; import { findLegacyPluginSpecs, logLegacyThirdPartyPluginDeprecationWarning } from './plugins'; import { ILegacyInternals, @@ -233,7 +233,7 @@ export class LegacyService implements CoreService { : EMPTY; // eslint-disable-next-line @typescript-eslint/no-var-requires - const { ClusterManager } = require('../../../cli/cluster/cluster_manager'); + const { ClusterManager } = require('./cluster_manager'); return new ClusterManager( this.coreContext.env.cliArgs, config, @@ -368,7 +368,7 @@ export class LegacyService implements CoreService { // We only want one REPL. if (this.coreContext.env.cliArgs.repl && process.env.kbnWorkerType === 'server') { // eslint-disable-next-line @typescript-eslint/no-var-requires - require('../../../cli/repl').startRepl(kbnServer); + require('./cli').startRepl(kbnServer); } const { autoListen } = await this.httpConfig$.pipe(first()).toPromise(); diff --git a/src/core/server/legacy/logging/appenders/legacy_appender.test.ts b/src/core/server/legacy/logging/appenders/legacy_appender.test.ts index 538d987e781d06..697e5bc37d6027 100644 --- a/src/core/server/legacy/logging/appenders/legacy_appender.test.ts +++ b/src/core/server/legacy/logging/appenders/legacy_appender.test.ts @@ -19,8 +19,7 @@ jest.mock('../legacy_logging_server'); -import { LogLevel } from '../../../logging/log_level'; -import { LogRecord } from '../../../logging/log_record'; +import { LogRecord, LogLevel } from '../../../logging'; import { LegacyLoggingServer } from '../legacy_logging_server'; import { LegacyAppender } from './legacy_appender'; diff --git a/src/core/server/legacy/logging/appenders/legacy_appender.ts b/src/core/server/legacy/logging/appenders/legacy_appender.ts index a5d36423ba4c69..67337c7d676297 100644 --- a/src/core/server/legacy/logging/appenders/legacy_appender.ts +++ b/src/core/server/legacy/logging/appenders/legacy_appender.ts @@ -18,8 +18,7 @@ */ import { schema } from '@kbn/config-schema'; -import { DisposableAppender } from '../../../logging/appenders/appenders'; -import { LogRecord } from '../../../logging/log_record'; +import { DisposableAppender, LogRecord } from '../../../logging'; import { LegacyLoggingServer } from '../legacy_logging_server'; import { LegacyVars } from '../../types'; diff --git a/src/core/server/legacy/logging/legacy_logging_server.test.ts b/src/core/server/legacy/logging/legacy_logging_server.test.ts index 6dca3a199728e6..2f6c34e0fc5d6b 100644 --- a/src/core/server/legacy/logging/legacy_logging_server.test.ts +++ b/src/core/server/legacy/logging/legacy_logging_server.test.ts @@ -20,7 +20,7 @@ jest.mock('../../../../legacy/server/config'); jest.mock('../../../../legacy/server/logging'); -import { LogLevel } from '../../logging/log_level'; +import { LogLevel } from '../../logging'; import { LegacyLoggingServer } from './legacy_logging_server'; test('correctly forwards log records.', () => { diff --git a/src/core/server/legacy/logging/legacy_logging_server.ts b/src/core/server/legacy/logging/legacy_logging_server.ts index 4a7fea87cf69f8..096dbe54565e11 100644 --- a/src/core/server/legacy/logging/legacy_logging_server.ts +++ b/src/core/server/legacy/logging/legacy_logging_server.ts @@ -23,8 +23,7 @@ import Podium from 'podium'; import { Config } from '../../../../legacy/server/config'; // @ts-expect-error: implicit any for JS file import { setupLogging } from '../../../../legacy/server/logging'; -import { LogLevel } from '../../logging/log_level'; -import { LogRecord } from '../../logging/log_record'; +import { LogLevel, LogRecord } from '../../logging'; import { LegacyVars } from '../../types'; export const metadataSymbol = Symbol('log message with metadata'); diff --git a/src/core/server/legacy/plugins/collect_ui_exports.js b/src/core/server/legacy/plugins/collect_ui_exports.js new file mode 100644 index 00000000000000..842ab554d79d14 --- /dev/null +++ b/src/core/server/legacy/plugins/collect_ui_exports.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { collectUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 82e04496ffc3e6..cb4277b130a88c 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -25,12 +25,12 @@ import { defaultConfig, // @ts-expect-error } from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; +// @ts-expect-error +import { collectUiExports as collectLegacyUiExports } from './collect_ui_exports'; import { LoggerFactory } from '../../logging'; import { PackageInfo } from '../../config'; -import { LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; +import { LegacyUiExports, LegacyPluginSpec, LegacyPluginPack, LegacyConfig } from '../types'; export async function findLegacyPluginSpecs( settings: unknown, @@ -123,7 +123,7 @@ export async function findLegacyPluginSpecs( spec$.pipe(toArray()), log$.pipe(toArray()) ).toPromise(); - const uiExports = collectLegacyUiExports(pluginSpecs); + const uiExports: LegacyUiExports = collectLegacyUiExports(pluginSpecs); return { disabledPluginSpecs, diff --git a/src/core/server/logging/appenders/appenders.ts b/src/core/server/logging/appenders/appenders.ts index edfce4988275ac..4e6920c50686c5 100644 --- a/src/core/server/logging/appenders/appenders.ts +++ b/src/core/server/logging/appenders/appenders.ts @@ -18,14 +18,14 @@ */ import { schema } from '@kbn/config-schema'; +import { assertNever } from '@kbn/std'; +import { DisposableAppender } from '@kbn/logging'; -import { assertNever } from '../../../utils'; import { LegacyAppender, LegacyAppenderConfig, } from '../../legacy/logging/appenders/legacy_appender'; import { Layouts } from '../layouts/layouts'; -import { LogRecord } from '../log_record'; import { ConsoleAppender, ConsoleAppenderConfig } from './console/console_appender'; import { FileAppender, FileAppenderConfig } from './file/file_appender'; @@ -44,25 +44,6 @@ export const appendersSchema = schema.oneOf([ /** @public */ export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig; -/** - * Entity that can append `LogRecord` instances to file, stdout, memory or whatever - * is implemented internally. It's supposed to be used by `Logger`. - * @internal - */ -export interface Appender { - append(record: LogRecord): void; -} - -/** - * This interface should be additionally implemented by the `Appender`'s if they are supposed - * to be properly disposed. It's intentionally separated from `Appender` interface so that `Logger` - * that interacts with `Appender` doesn't have control over appender lifetime. - * @internal - */ -export interface DisposableAppender extends Appender { - dispose: () => void; -} - /** @internal */ export class Appenders { public static configSchema = appendersSchema; diff --git a/src/core/server/logging/appenders/buffer/buffer_appender.test.ts b/src/core/server/logging/appenders/buffer/buffer_appender.test.ts index 49d70db8d5d43e..7981aef64e5890 100644 --- a/src/core/server/logging/appenders/buffer/buffer_appender.test.ts +++ b/src/core/server/logging/appenders/buffer/buffer_appender.test.ts @@ -17,8 +17,7 @@ * under the License. */ -import { LogLevel } from '../../log_level'; -import { LogRecord } from '../../log_record'; +import { LogLevel, LogRecord } from '@kbn/logging'; import { BufferAppender } from './buffer_appender'; test('`flush()` does not return any record buffered at the beginning.', () => { diff --git a/src/core/server/logging/appenders/buffer/buffer_appender.ts b/src/core/server/logging/appenders/buffer/buffer_appender.ts index 7024d3e5d16df1..9e3a9d0f910f89 100644 --- a/src/core/server/logging/appenders/buffer/buffer_appender.ts +++ b/src/core/server/logging/appenders/buffer/buffer_appender.ts @@ -17,8 +17,7 @@ * under the License. */ -import { LogRecord } from '../../log_record'; -import { DisposableAppender } from '../appenders'; +import { LogRecord, DisposableAppender } from '@kbn/logging'; /** * Simple appender that just buffers `LogRecord` instances it receives. It is a *reserved* appender diff --git a/src/core/server/logging/appenders/console/console_appender.test.ts b/src/core/server/logging/appenders/console/console_appender.test.ts index 6e30df1cfb65c4..0601ac10167ac5 100644 --- a/src/core/server/logging/appenders/console/console_appender.test.ts +++ b/src/core/server/logging/appenders/console/console_appender.test.ts @@ -29,8 +29,7 @@ jest.mock('../../layouts/layouts', () => { }; }); -import { LogLevel } from '../../log_level'; -import { LogRecord } from '../../log_record'; +import { LogRecord, LogLevel } from '@kbn/logging'; import { ConsoleAppender } from './console_appender'; test('`configSchema` creates correct schema.', () => { diff --git a/src/core/server/logging/appenders/console/console_appender.ts b/src/core/server/logging/appenders/console/console_appender.ts index a54674b1d347ce..dc491fcff664c5 100644 --- a/src/core/server/logging/appenders/console/console_appender.ts +++ b/src/core/server/logging/appenders/console/console_appender.ts @@ -18,10 +18,8 @@ */ import { schema } from '@kbn/config-schema'; - -import { Layout, Layouts, LayoutConfigType } from '../../layouts/layouts'; -import { LogRecord } from '../../log_record'; -import { DisposableAppender } from '../appenders'; +import { Layout, LogRecord, DisposableAppender } from '@kbn/logging'; +import { Layouts, LayoutConfigType } from '../../layouts/layouts'; const { literal, object } = schema; diff --git a/src/core/server/logging/appenders/file/file_appender.test.ts b/src/core/server/logging/appenders/file/file_appender.test.ts index bff60029faf116..645455c5ae04ce 100644 --- a/src/core/server/logging/appenders/file/file_appender.test.ts +++ b/src/core/server/logging/appenders/file/file_appender.test.ts @@ -19,8 +19,7 @@ import { mockCreateWriteStream } from './file_appender.test.mocks'; -import { LogLevel } from '../../log_level'; -import { LogRecord } from '../../log_record'; +import { LogRecord, LogLevel } from '@kbn/logging'; import { FileAppender } from './file_appender'; const tickMs = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/src/core/server/logging/appenders/file/file_appender.ts b/src/core/server/logging/appenders/file/file_appender.ts index a0e484cd87c8f5..b1712bd4e9412d 100644 --- a/src/core/server/logging/appenders/file/file_appender.ts +++ b/src/core/server/logging/appenders/file/file_appender.ts @@ -18,11 +18,10 @@ */ import { schema } from '@kbn/config-schema'; +import { LogRecord, Layout, DisposableAppender } from '@kbn/logging'; import { createWriteStream, WriteStream } from 'fs'; -import { Layout, Layouts, LayoutConfigType } from '../../layouts/layouts'; -import { LogRecord } from '../../log_record'; -import { DisposableAppender } from '../appenders'; +import { Layouts, LayoutConfigType } from '../../layouts/layouts'; export interface FileAppenderConfig { kind: 'file'; diff --git a/src/core/server/logging/index.ts b/src/core/server/logging/index.ts index 94719720302817..01f153cae9e2dc 100644 --- a/src/core/server/logging/index.ts +++ b/src/core/server/logging/index.ts @@ -17,10 +17,17 @@ * under the License. */ -export { Logger, LogMeta } from './logger'; -export { LoggerFactory } from './logger_factory'; -export { LogRecord } from './log_record'; -export { LogLevel } from './log_level'; +export { + DisposableAppender, + Appender, + LogRecord, + Layout, + LoggerFactory, + LogMeta, + Logger, + LogLevelId, + LogLevel, +} from '@kbn/logging'; export { config, LoggingConfigType, diff --git a/src/core/server/logging/layouts/conversions/date.ts b/src/core/server/logging/layouts/conversions/date.ts index d3ed54fb982402..3a43c0ffcd389f 100644 --- a/src/core/server/logging/layouts/conversions/date.ts +++ b/src/core/server/logging/layouts/conversions/date.ts @@ -18,9 +18,9 @@ */ import moment from 'moment-timezone'; import { last } from 'lodash'; +import { LogRecord } from '@kbn/logging'; import { Conversion } from './type'; -import { LogRecord } from '../../log_record'; const dateRegExp = /%date({(?[^}]+)})?({(?[^}]+)})?/g; diff --git a/src/core/server/logging/layouts/conversions/level.ts b/src/core/server/logging/layouts/conversions/level.ts index 58b271140eff5b..83208242dc2581 100644 --- a/src/core/server/logging/layouts/conversions/level.ts +++ b/src/core/server/logging/layouts/conversions/level.ts @@ -18,10 +18,9 @@ */ import chalk from 'chalk'; +import { LogRecord, LogLevel } from '@kbn/logging'; import { Conversion } from './type'; -import { LogLevel } from '../../log_level'; -import { LogRecord } from '../../log_record'; const LEVEL_COLORS = new Map([ [LogLevel.Fatal, chalk.red], diff --git a/src/core/server/logging/layouts/conversions/logger.ts b/src/core/server/logging/layouts/conversions/logger.ts index debb1737ab95a3..e63976052443bf 100644 --- a/src/core/server/logging/layouts/conversions/logger.ts +++ b/src/core/server/logging/layouts/conversions/logger.ts @@ -18,9 +18,9 @@ */ import chalk from 'chalk'; +import { LogRecord } from '@kbn/logging'; import { Conversion } from './type'; -import { LogRecord } from '../../log_record'; export const LoggerConversion: Conversion = { pattern: /%logger/g, diff --git a/src/core/server/logging/layouts/conversions/message.ts b/src/core/server/logging/layouts/conversions/message.ts index f8c5e68ada4fbf..73d85532a5a900 100644 --- a/src/core/server/logging/layouts/conversions/message.ts +++ b/src/core/server/logging/layouts/conversions/message.ts @@ -17,8 +17,8 @@ * under the License. */ +import { LogRecord } from '@kbn/logging'; import { Conversion } from './type'; -import { LogRecord } from '../../log_record'; export const MessageConversion: Conversion = { pattern: /%message/g, diff --git a/src/core/server/logging/layouts/conversions/meta.ts b/src/core/server/logging/layouts/conversions/meta.ts index ee8c207389fbe0..b78db41b7e9695 100644 --- a/src/core/server/logging/layouts/conversions/meta.ts +++ b/src/core/server/logging/layouts/conversions/meta.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + +import { LogRecord } from '@kbn/logging'; import { Conversion } from './type'; -import { LogRecord } from '../../log_record'; export const MetaConversion: Conversion = { pattern: /%meta/g, diff --git a/src/core/server/logging/layouts/conversions/pid.ts b/src/core/server/logging/layouts/conversions/pid.ts index 37d34a4f1cf8b7..f6902005f5668d 100644 --- a/src/core/server/logging/layouts/conversions/pid.ts +++ b/src/core/server/logging/layouts/conversions/pid.ts @@ -17,8 +17,8 @@ * under the License. */ +import { LogRecord } from '@kbn/logging'; import { Conversion } from './type'; -import { LogRecord } from '../../log_record'; export const PidConversion: Conversion = { pattern: /%pid/g, diff --git a/src/core/server/logging/layouts/conversions/type.ts b/src/core/server/logging/layouts/conversions/type.ts index a57a1f954e53ae..be172a0a98f7d2 100644 --- a/src/core/server/logging/layouts/conversions/type.ts +++ b/src/core/server/logging/layouts/conversions/type.ts @@ -16,7 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { LogRecord } from 'kibana/server'; + +import { LogRecord } from '@kbn/logging'; export interface Conversion { pattern: RegExp; diff --git a/src/core/server/logging/layouts/json_layout.test.ts b/src/core/server/logging/layouts/json_layout.test.ts index 6cda1e4806aa85..f476e3f217278b 100644 --- a/src/core/server/logging/layouts/json_layout.test.ts +++ b/src/core/server/logging/layouts/json_layout.test.ts @@ -17,8 +17,7 @@ * under the License. */ -import { LogLevel } from '../log_level'; -import { LogRecord } from '../log_record'; +import { LogLevel, LogRecord } from '@kbn/logging'; import { JsonLayout } from './json_layout'; const timestamp = new Date(Date.UTC(2012, 1, 1, 14, 30, 22, 11)); diff --git a/src/core/server/logging/layouts/json_layout.ts b/src/core/server/logging/layouts/json_layout.ts index 37eb6b8c4806e8..7573d0b8374161 100644 --- a/src/core/server/logging/layouts/json_layout.ts +++ b/src/core/server/logging/layouts/json_layout.ts @@ -20,9 +20,7 @@ import moment from 'moment-timezone'; import { merge } from 'lodash'; import { schema } from '@kbn/config-schema'; - -import { LogRecord } from '../log_record'; -import { Layout } from './layouts'; +import { LogRecord, Layout } from '@kbn/logging'; const { literal, object } = schema; diff --git a/src/core/server/logging/layouts/layouts.ts b/src/core/server/logging/layouts/layouts.ts index 124c007bae1040..faf05e4d1e3477 100644 --- a/src/core/server/logging/layouts/layouts.ts +++ b/src/core/server/logging/layouts/layouts.ts @@ -18,9 +18,9 @@ */ import { schema } from '@kbn/config-schema'; +import { Layout } from '@kbn/logging'; +import { assertNever } from '@kbn/std'; -import { assertNever } from '../../../utils'; -import { LogRecord } from '../log_record'; import { JsonLayout, JsonLayoutConfigType } from './json_layout'; import { PatternLayout, PatternLayoutConfigType } from './pattern_layout'; @@ -28,14 +28,6 @@ const { oneOf } = schema; export type LayoutConfigType = PatternLayoutConfigType | JsonLayoutConfigType; -/** - * Entity that can format `LogRecord` instance into a string. - * @internal - */ -export interface Layout { - format(record: LogRecord): string; -} - /** @internal */ export class Layouts { public static configSchema = oneOf([JsonLayout.configSchema, PatternLayout.configSchema]); diff --git a/src/core/server/logging/layouts/pattern_layout.test.ts b/src/core/server/logging/layouts/pattern_layout.test.ts index cce55b147e0ed3..d37ee3c87d08fd 100644 --- a/src/core/server/logging/layouts/pattern_layout.test.ts +++ b/src/core/server/logging/layouts/pattern_layout.test.ts @@ -17,9 +17,8 @@ * under the License. */ +import { LogLevel, LogRecord } from '@kbn/logging'; import { stripAnsiSnapshotSerializer } from '../../../test_helpers/strip_ansi_snapshot_serializer'; -import { LogLevel } from '../log_level'; -import { LogRecord } from '../log_record'; import { PatternLayout, patternSchema } from './pattern_layout'; const timestamp = new Date(Date.UTC(2012, 1, 1, 14, 30, 22, 11)); diff --git a/src/core/server/logging/layouts/pattern_layout.ts b/src/core/server/logging/layouts/pattern_layout.ts index 5dfc8aca77f181..2ca444f54b4994 100644 --- a/src/core/server/logging/layouts/pattern_layout.ts +++ b/src/core/server/logging/layouts/pattern_layout.ts @@ -18,9 +18,8 @@ */ import { schema } from '@kbn/config-schema'; +import { LogRecord, Layout } from '@kbn/logging'; -import { LogRecord } from '../log_record'; -import { Layout } from './layouts'; import { Conversion, LoggerConversion, diff --git a/src/core/server/logging/logger.mock.ts b/src/core/server/logging/logger.mock.ts index a3bb07ea4c0951..5af967ecd430eb 100644 --- a/src/core/server/logging/logger.mock.ts +++ b/src/core/server/logging/logger.mock.ts @@ -17,30 +17,4 @@ * under the License. */ -import { Logger } from './logger'; - -export type MockedLogger = jest.Mocked & { context: string[] }; - -const createLoggerMock = (context: string[] = []) => { - const mockLog: MockedLogger = { - context, - debug: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - log: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - get: jest.fn(), - }; - mockLog.get.mockImplementation((...ctx) => ({ - ctx, - ...mockLog, - })); - - return mockLog; -}; - -export const loggerMock = { - create: createLoggerMock, -}; +export { loggerMock, MockedLogger } from '@kbn/logging/target/mocks'; diff --git a/src/core/server/logging/logger.test.ts b/src/core/server/logging/logger.test.ts index 1cc00a254300b3..1796519ff65e50 100644 --- a/src/core/server/logging/logger.test.ts +++ b/src/core/server/logging/logger.test.ts @@ -17,9 +17,8 @@ * under the License. */ +import { LogLevel, Appender } from '@kbn/logging'; import { LoggingConfig } from './logging_config'; -import { Appender } from './appenders/appenders'; -import { LogLevel } from './log_level'; import { BaseLogger } from './logger'; const context = LoggingConfig.getLoggerContext(['context', 'parent', 'child']); diff --git a/src/core/server/logging/logger.ts b/src/core/server/logging/logger.ts index 285998c23832ce..6861072ef3b8b0 100644 --- a/src/core/server/logging/logger.ts +++ b/src/core/server/logging/logger.ts @@ -17,86 +17,7 @@ * under the License. */ -import { Appender } from './appenders/appenders'; -import { LogLevel } from './log_level'; -import { LogRecord } from './log_record'; -import { LoggerFactory } from './logger_factory'; - -/** - * Contextual metadata - * - * @public - */ -export interface LogMeta { - [key: string]: any; -} - -/** - * Logger exposes all the necessary methods to log any type of information and - * this is the interface used by the logging consumers including plugins. - * - * @public - */ -export interface Logger { - /** - * Log messages at the most detailed log level - * - * @param message - The log message - * @param meta - - */ - trace(message: string, meta?: LogMeta): void; - - /** - * Log messages useful for debugging and interactive investigation - * @param message - The log message - * @param meta - - */ - debug(message: string, meta?: LogMeta): void; - - /** - * Logs messages related to general application flow - * @param message - The log message - * @param meta - - */ - info(message: string, meta?: LogMeta): void; - - /** - * Logs abnormal or unexpected errors or messages - * @param errorOrMessage - An Error object or message string to log - * @param meta - - */ - warn(errorOrMessage: string | Error, meta?: LogMeta): void; - - /** - * Logs abnormal or unexpected errors or messages that caused a failure in the application flow - * - * @param errorOrMessage - An Error object or message string to log - * @param meta - - */ - error(errorOrMessage: string | Error, meta?: LogMeta): void; - - /** - * Logs abnormal or unexpected errors or messages that caused an unrecoverable failure - * - * @param errorOrMessage - An Error object or message string to log - * @param meta - - */ - fatal(errorOrMessage: string | Error, meta?: LogMeta): void; - - /** @internal */ - log(record: LogRecord): void; - - /** - * Returns a new {@link Logger} instance extending the current logger context. - * - * @example - * ```typescript - * const logger = loggerFactory.get('plugin', 'service'); // 'plugin.service' context - * const subLogger = logger.get('feature'); // 'plugin.service.feature' context - * ``` - */ - get(...childContextPaths: string[]): Logger; -} +import { Appender, LogLevel, LogRecord, LoggerFactory, LogMeta, Logger } from '@kbn/logging'; function isError(x: any): x is Error { return x instanceof Error; diff --git a/src/core/server/logging/logger_adapter.ts b/src/core/server/logging/logger_adapter.ts index 14e5712e55c584..4ce65bf3302e7c 100644 --- a/src/core/server/logging/logger_adapter.ts +++ b/src/core/server/logging/logger_adapter.ts @@ -17,8 +17,7 @@ * under the License. */ -import { LogRecord } from './log_record'; -import { Logger, LogMeta } from './logger'; +import { LogRecord, Logger, LogMeta } from '@kbn/logging'; /** @internal */ export class LoggerAdapter implements Logger { diff --git a/src/core/server/logging/logging_service.mock.ts b/src/core/server/logging/logging_service.mock.ts index 21edbe670eaecd..6a721e134feeda 100644 --- a/src/core/server/logging/logging_service.mock.ts +++ b/src/core/server/logging/logging_service.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { LoggingService, diff --git a/src/core/server/logging/logging_service.ts b/src/core/server/logging/logging_service.ts index 09051f8f077023..f2b609f2258c76 100644 --- a/src/core/server/logging/logging_service.ts +++ b/src/core/server/logging/logging_service.ts @@ -18,10 +18,10 @@ */ import { Observable, Subscription } from 'rxjs'; +import { Logger } from '@kbn/logging'; import { CoreService } from '../../types'; import { LoggingConfig, LoggerContextConfigInput } from './logging_config'; import { ILoggingSystem } from './logging_system'; -import { Logger } from './logger'; import { CoreContext } from '../core_context'; /** diff --git a/src/core/server/logging/logging_system.mock.ts b/src/core/server/logging/logging_system.mock.ts index ac1e9b5196002e..6ea784be5411fa 100644 --- a/src/core/server/logging/logging_system.mock.ts +++ b/src/core/server/logging/logging_system.mock.ts @@ -18,8 +18,8 @@ */ // Test helpers to simplify mocking logs and collecting all their outputs +import { LoggerFactory } from '@kbn/logging'; import { ILoggingSystem } from './logging_system'; -import { LoggerFactory } from './logger_factory'; import { loggerMock, MockedLogger } from './logger.mock'; const createLoggingSystemMock = () => { @@ -48,15 +48,7 @@ const createLoggingSystemMock = () => { const collectLoggingSystemMock = (loggerFactory: LoggerFactory) => { const mockLog = loggerFactory.get() as MockedLogger; - return { - debug: mockLog.debug.mock.calls, - error: mockLog.error.mock.calls, - fatal: mockLog.fatal.mock.calls, - info: mockLog.info.mock.calls, - log: mockLog.log.mock.calls, - trace: mockLog.trace.mock.calls, - warn: mockLog.warn.mock.calls, - }; + return loggerMock.collect(mockLog); }; const clearLoggingSystemMock = (loggerFactory: LoggerFactory) => { @@ -67,13 +59,7 @@ const clearLoggingSystemMock = (loggerFactory: LoggerFactory) => { mockedLoggerFactory.stop.mockClear(); const mockLog = loggerFactory.get() as MockedLogger; - mockLog.debug.mockClear(); - mockLog.info.mockClear(); - mockLog.warn.mockClear(); - mockLog.error.mockClear(); - mockLog.trace.mockClear(); - mockLog.fatal.mockClear(); - mockLog.log.mockClear(); + loggerMock.clear(mockLog); }; export const loggingSystemMock = { diff --git a/src/core/server/logging/logging_system.ts b/src/core/server/logging/logging_system.ts index 8aadab83bf7163..8bc22bdf537afb 100644 --- a/src/core/server/logging/logging_system.ts +++ b/src/core/server/logging/logging_system.ts @@ -16,12 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { Appenders, DisposableAppender } from './appenders/appenders'; + +import type { PublicMethodsOf } from '@kbn/utility-types'; +import { DisposableAppender, LogLevel, Logger, LoggerFactory } from '@kbn/logging'; +import { Appenders } from './appenders/appenders'; import { BufferAppender } from './appenders/buffer/buffer_appender'; -import { LogLevel } from './log_level'; -import { BaseLogger, Logger } from './logger'; +import { BaseLogger } from './logger'; import { LoggerAdapter } from './logger_adapter'; -import { LoggerFactory } from './logger_factory'; import { LoggingConfigType, LoggerConfigType, diff --git a/src/core/server/metrics/metrics_service.mock.ts b/src/core/server/metrics/metrics_service.mock.ts index 2af653004a479e..caa7acc001db30 100644 --- a/src/core/server/metrics/metrics_service.mock.ts +++ b/src/core/server/metrics/metrics_service.mock.ts @@ -17,6 +17,8 @@ * under the License. */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + import { MetricsService } from './metrics_service'; import { InternalMetricsServiceSetup, diff --git a/src/core/server/metrics/metrics_service.test.ts b/src/core/server/metrics/metrics_service.test.ts index f2019de7b6cabf..269931d0e33ad8 100644 --- a/src/core/server/metrics/metrics_service.test.ts +++ b/src/core/server/metrics/metrics_service.test.ts @@ -18,10 +18,11 @@ */ import moment from 'moment'; + +import { configServiceMock } from '../config/mocks'; import { mockOpsCollector } from './metrics_service.test.mocks'; import { MetricsService } from './metrics_service'; import { mockCoreContext } from '../core_context.mock'; -import { configServiceMock } from '../config/config_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; import { take } from 'rxjs/operators'; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 3c79706422cd43..5d6bf41fec3f36 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -37,10 +37,10 @@ import { environmentServiceMock } from './environment/environment_service.mock'; import { statusServiceMock } from './status/status_service.mock'; import { auditTrailServiceMock } from './audit_trail/audit_trail_service.mock'; +export { configServiceMock } from './config/mocks'; export { httpServerMock } from './http/http_server.mocks'; export { httpResourcesMock } from './http_resources/http_resources_service.mock'; export { sessionStorageMock } from './http/cookie_session_storage.mocks'; -export { configServiceMock } from './config/config_service.mock'; export { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; export { httpServiceMock } from './http/http_service.mock'; export { loggingSystemMock } from './logging/logging_system.mock'; diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts index eb8dc1e6095826..3634a7ed2c277b 100644 --- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.mocks.ts @@ -17,6 +17,12 @@ * under the License. */ +const realFs = jest.requireActual('fs'); + export const mockReadFile = jest.fn(); const mockStat = jest.fn(); -jest.mock('fs', () => ({ readFile: mockReadFile, stat: mockStat })); +jest.doMock('fs', () => ({ + ...realFs, + readFile: mockReadFile, + stat: mockStat, +})); diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts index 836aabf881474f..cb9f5982d0f198 100644 --- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts +++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts @@ -17,9 +17,9 @@ * under the License. */ -import { PluginDiscoveryErrorType } from './plugin_discovery_error'; - import { mockReadFile } from './plugin_manifest_parser.test.mocks'; + +import { PluginDiscoveryErrorType } from './plugin_discovery_error'; import { loggingSystemMock } from '../../logging/logging_system.mock'; import { resolve } from 'path'; diff --git a/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts b/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts index 83accc06cb9956..131ee58e21a81e 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts @@ -17,5 +17,10 @@ * under the License. */ -export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); -jest.mock('../../../../../package.json', () => mockPackage); +export const mockPackage = { + raw: {}, +}; + +jest.doMock('load-json-file', () => ({ + sync: () => mockPackage.raw, +})); diff --git a/src/core/server/plugins/discovery/plugins_discovery.test.ts b/src/core/server/plugins/discovery/plugins_discovery.test.ts index 4894f19e38df42..0dfc5599e8007c 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.test.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.test.ts @@ -17,18 +17,19 @@ * under the License. */ +// must be before mocks imports to avoid conflicting with `REPO_ROOT` accessor. +import { REPO_ROOT } from '@kbn/dev-utils'; import { mockPackage } from './plugins_discovery.test.mocks'; import mockFs from 'mock-fs'; import { loggingSystemMock } from '../../logging/logging_system.mock'; +import { getEnvOptions, rawConfigServiceMock } from '../../config/mocks'; import { first, map, toArray } from 'rxjs/operators'; import { resolve } from 'path'; import { ConfigService, Env } from '../../config'; -import { getEnvOptions } from '../../config/__mocks__/env'; import { PluginsConfig, PluginsConfigType, config } from '../plugins_config'; import type { InstanceInfo } from '../plugin_context'; import { discover } from './plugins_discovery'; -import { rawConfigServiceMock } from '../../config/raw_config_service.mock'; import { CoreContext } from '../../core_context'; const KIBANA_ROOT = process.cwd(); @@ -94,6 +95,7 @@ describe('plugins discovery system', () => { }; env = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { envName: 'development' }, }) @@ -382,6 +384,7 @@ describe('plugins discovery system', () => { const extraPluginTestPath = resolve(process.cwd(), 'my-extra-plugin'); env = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { dev: false, envName: 'development' }, }) @@ -409,6 +412,7 @@ describe('plugins discovery system', () => { const extraPluginTestPath = resolve(process.cwd(), 'my-extra-plugin'); env = Env.createDefault( + REPO_ROOT, getEnvOptions({ cliArgs: { dev: false, envName: 'production' }, }) diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts b/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts index d81a7eb5db4ae6..ed73fe9b99be61 100644 --- a/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts +++ b/src/core/server/plugins/integration_tests/plugins_service.test.mocks.ts @@ -17,11 +17,13 @@ * under the License. */ -export const mockPackage = new Proxy( - { raw: { __dirname: '/tmp' } as any }, - { get: (obj, prop) => obj.raw[prop] } -); -jest.mock('../../../../core/server/utils/package_json', () => ({ pkg: mockPackage })); +export const mockPackage = { + raw: { __dirname: '/tmp' } as any, +}; + +jest.doMock('load-json-file', () => ({ + sync: () => mockPackage.raw, +})); export const mockDiscover = jest.fn(); jest.mock('../discovery/plugins_discovery', () => ({ discover: mockDiscover })); diff --git a/src/core/server/plugins/integration_tests/plugins_service.test.ts b/src/core/server/plugins/integration_tests/plugins_service.test.ts index 5a216b75a83b9a..93fee05016ff21 100644 --- a/src/core/server/plugins/integration_tests/plugins_service.test.ts +++ b/src/core/server/plugins/integration_tests/plugins_service.test.ts @@ -17,15 +17,16 @@ * under the License. */ +// must be before mocks imports to avoid conflicting with `REPO_ROOT` accessor. +import { REPO_ROOT } from '@kbn/dev-utils'; import { mockPackage, mockDiscover } from './plugins_service.test.mocks'; import { join } from 'path'; import { PluginsService } from '../plugins_service'; import { ConfigPath, ConfigService, Env } from '../../config'; -import { getEnvOptions } from '../../config/__mocks__/env'; +import { getEnvOptions, rawConfigServiceMock } from '../../config/mocks'; import { BehaviorSubject, from } from 'rxjs'; -import { rawConfigServiceMock } from '../../config/raw_config_service.mock'; import { config } from '../plugins_config'; import { loggingSystemMock } from '../../logging/logging_system.mock'; import { environmentServiceMock } from '../../environment/environment_service.mock'; @@ -93,7 +94,7 @@ describe('PluginsService', () => { }, }; - const env = Env.createDefault(getEnvOptions()); + const env = Env.createDefault(REPO_ROOT, getEnvOptions()); const config$ = new BehaviorSubject>({ plugins: { initialize: true, diff --git a/src/core/server/plugins/plugin.test.ts b/src/core/server/plugins/plugin.test.ts index 1108ffc2481615..ae22ead2aa4be9 100644 --- a/src/core/server/plugins/plugin.test.ts +++ b/src/core/server/plugins/plugin.test.ts @@ -19,14 +19,14 @@ import { join } from 'path'; import { BehaviorSubject } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { schema } from '@kbn/config-schema'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; import { CoreContext } from '../core_context'; import { coreMock } from '../mocks'; -import { configServiceMock } from '../config/config_service.mock'; import { loggingSystemMock } from '../logging/logging_system.mock'; +import { getEnvOptions, configServiceMock } from '../config/mocks'; import { PluginWrapper } from './plugin'; import { PluginManifest } from './types'; @@ -77,7 +77,7 @@ const setupDeps = coreMock.createInternalSetup(); beforeEach(() => { coreId = Symbol('core'); - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); instanceInfo = { uuid: 'instance-uuid', }; diff --git a/src/core/server/plugins/plugin_context.test.ts b/src/core/server/plugins/plugin_context.test.ts index 578c5f39d71ea1..5ce91c9a623dc0 100644 --- a/src/core/server/plugins/plugin_context.test.ts +++ b/src/core/server/plugins/plugin_context.test.ts @@ -19,12 +19,12 @@ import { duration } from 'moment'; import { first } from 'rxjs/operators'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { createPluginInitializerContext, InstanceInfo } from './plugin_context'; import { CoreContext } from '../core_context'; import { Env } from '../config'; import { loggingSystemMock } from '../logging/logging_system.mock'; -import { rawConfigServiceMock } from '../config/raw_config_service.mock'; -import { getEnvOptions } from '../config/__mocks__/env'; +import { rawConfigServiceMock, getEnvOptions } from '../config/mocks'; import { PluginManifest } from './types'; import { Server } from '../server'; import { fromRoot } from '../utils'; @@ -58,7 +58,7 @@ describe('createPluginInitializerContext', () => { instanceInfo = { uuid: 'instance-uuid', }; - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); const config$ = rawConfigServiceMock.create({ rawConfig: {} }); server = new Server(config$, env, logger); await server.setupCoreConfig(); diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index af0b0e19b32275..8d173009656805 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -19,6 +19,8 @@ import { map, shareReplay } from 'rxjs/operators'; import { combineLatest } from 'rxjs'; +import { PathConfigType, config as pathConfig } from '@kbn/utils'; +import { pick, deepFreeze } from '@kbn/std'; import { CoreContext } from '../core_context'; import { PluginWrapper } from './plugin'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; @@ -28,13 +30,11 @@ import { PluginOpaqueId, SharedGlobalConfigKeys, } from './types'; -import { PathConfigType, config as pathConfig } from '../path'; import { KibanaConfigType, config as kibanaConfig } from '../kibana_config'; import { ElasticsearchConfigType, config as elasticsearchConfig, } from '../elasticsearch/elasticsearch_config'; -import { pick, deepFreeze } from '../../utils'; import { CoreSetup, CoreStart } from '..'; export interface InstanceInfo { diff --git a/src/core/server/plugins/plugins_config.test.ts b/src/core/server/plugins/plugins_config.test.ts index 180d6093e04045..2a64e79d19bdad 100644 --- a/src/core/server/plugins/plugins_config.test.ts +++ b/src/core/server/plugins/plugins_config.test.ts @@ -17,13 +17,14 @@ * under the License. */ +import { REPO_ROOT } from '@kbn/dev-utils'; +import { getEnvOptions } from '../config/mocks'; import { PluginsConfig, PluginsConfigType } from './plugins_config'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; describe('PluginsConfig', () => { it('retrieves additionalPluginPaths from config.paths when in production mode', () => { - const env = Env.createDefault(getEnvOptions({ cliArgs: { dev: false } })); + const env = Env.createDefault(REPO_ROOT, getEnvOptions({ cliArgs: { dev: false } })); const rawConfig: PluginsConfigType = { initialize: true, paths: ['some-path', 'another-path'], @@ -33,7 +34,7 @@ describe('PluginsConfig', () => { }); it('retrieves additionalPluginPaths from config.paths when in development mode', () => { - const env = Env.createDefault(getEnvOptions({ cliArgs: { dev: true } })); + const env = Env.createDefault(REPO_ROOT, getEnvOptions({ cliArgs: { dev: true } })); const rawConfig: PluginsConfigType = { initialize: true, paths: ['some-path', 'another-path'], diff --git a/src/core/server/plugins/plugins_service.mock.ts b/src/core/server/plugins/plugins_service.mock.ts index a40566767ddaef..14d6de889dd424 100644 --- a/src/core/server/plugins/plugins_service.mock.ts +++ b/src/core/server/plugins/plugins_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginsService, PluginsServiceSetup } from './plugins_service'; type PluginsServiceMock = jest.Mocked>; diff --git a/src/core/server/plugins/plugins_service.test.mocks.ts b/src/core/server/plugins/plugins_service.test.mocks.ts index 8d4ba12c8375c0..15e4187ef95edd 100644 --- a/src/core/server/plugins/plugins_service.test.mocks.ts +++ b/src/core/server/plugins/plugins_service.test.mocks.ts @@ -17,11 +17,25 @@ * under the License. */ -export const mockPackage = new Proxy( - { raw: { __dirname: '/tmp' } as any }, - { get: (obj, prop) => obj.raw[prop] } -); -jest.mock('../../../core/server/utils/package_json', () => ({ pkg: mockPackage })); +import { REPO_ROOT } from '@kbn/utils'; +import { resolve } from 'path'; + +const loadJsonFile = jest.requireActual('load-json-file'); +const kibanaPackagePath = resolve(REPO_ROOT, 'package.json'); + +export const mockPackage = { + raw: { __dirname: '/tmp', name: 'kibana' } as any, +}; + +jest.doMock('load-json-file', () => ({ + ...loadJsonFile, + sync: (path: string) => { + if (path === kibanaPackagePath) { + return mockPackage.raw; + } + return loadJsonFile.sync(path); + }, +})); export const mockDiscover = jest.fn(); jest.mock('./discovery/plugins_discovery', () => ({ discover: mockDiscover })); diff --git a/src/core/server/plugins/plugins_service.test.ts b/src/core/server/plugins/plugins_service.test.ts index 5e613343c302fa..d36fd2251176a2 100644 --- a/src/core/server/plugins/plugins_service.test.ts +++ b/src/core/server/plugins/plugins_service.test.ts @@ -22,11 +22,10 @@ import { mockDiscover, mockPackage } from './plugins_service.test.mocks'; import { resolve, join } from 'path'; import { BehaviorSubject, from } from 'rxjs'; import { schema } from '@kbn/config-schema'; -import { createAbsolutePathSerializer } from '@kbn/dev-utils'; +import { createAbsolutePathSerializer, REPO_ROOT } from '@kbn/dev-utils'; import { ConfigPath, ConfigService, Env } from '../config'; -import { rawConfigServiceMock } from '../config/raw_config_service.mock'; -import { getEnvOptions } from '../config/__mocks__/env'; +import { rawConfigServiceMock, getEnvOptions } from '../config/mocks'; import { coreMock } from '../mocks'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { environmentServiceMock } from '../environment/environment_service.mock'; @@ -116,7 +115,7 @@ describe('PluginsService', () => { }; coreId = Symbol('core'); - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); config$ = new BehaviorSubject>({ plugins: { initialize: true } }); const rawConfigService = rawConfigServiceMock.create({ rawConfig$: config$ }); diff --git a/src/core/server/plugins/plugins_service.ts b/src/core/server/plugins/plugins_service.ts index 30cd47c9d44e17..e8fe42ee491ca5 100644 --- a/src/core/server/plugins/plugins_service.ts +++ b/src/core/server/plugins/plugins_service.ts @@ -20,9 +20,10 @@ import Path from 'path'; import { Observable } from 'rxjs'; import { filter, first, map, mergeMap, tap, toArray } from 'rxjs/operators'; +import { pick } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; - import { Logger } from '../logging'; import { discover, PluginDiscoveryError, PluginDiscoveryErrorType } from './discovery'; import { PluginWrapper } from './plugin'; @@ -31,7 +32,6 @@ import { PluginsConfig, PluginsConfigType } from './plugins_config'; import { PluginsSystem } from './plugins_system'; import { InternalCoreSetup, InternalCoreStart } from '../internal_types'; import { IConfigService } from '../config'; -import { pick } from '../../utils'; import { InternalEnvironmentServiceSetup } from '../environment'; /** @internal */ diff --git a/src/core/server/plugins/plugins_system.test.ts b/src/core/server/plugins/plugins_system.test.ts index 71ac31db13f928..ae9267ca5cf607 100644 --- a/src/core/server/plugins/plugins_system.test.ts +++ b/src/core/server/plugins/plugins_system.test.ts @@ -24,10 +24,10 @@ import { import { BehaviorSubject } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; +import { configServiceMock, getEnvOptions } from '../config/mocks'; import { CoreContext } from '../core_context'; -import { configServiceMock } from '../config/config_service.mock'; import { loggingSystemMock } from '../logging/logging_system.mock'; import { PluginWrapper } from './plugin'; @@ -74,7 +74,7 @@ const setupDeps = coreMock.createInternalSetup(); const startDeps = coreMock.createInternalStart(); beforeEach(() => { - env = Env.createDefault(getEnvOptions()); + env = Env.createDefault(REPO_ROOT, getEnvOptions()); coreContext = { coreId: Symbol(), env, logger, configService: configService as any }; diff --git a/src/core/server/plugins/plugins_system.ts b/src/core/server/plugins/plugins_system.ts index b2acd9a6fd04bb..72d2cfe158b37b 100644 --- a/src/core/server/plugins/plugins_system.ts +++ b/src/core/server/plugins/plugins_system.ts @@ -17,13 +17,13 @@ * under the License. */ +import { withTimeout } from '@kbn/std'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { PluginWrapper } from './plugin'; import { DiscoveredPlugin, PluginName } from './types'; import { createPluginSetupContext, createPluginStartContext } from './plugin_context'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; -import { withTimeout } from '../../utils'; import { PluginDependencies } from '.'; const Sec = 1000; diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 517261b5bc9bb1..34d5e044222eb8 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -20,12 +20,12 @@ import { Observable } from 'rxjs'; import { Type } from '@kbn/config-schema'; import { RecursiveReadonly } from '@kbn/utility-types'; +import { PathConfigType } from '@kbn/utils'; import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } from '../config'; import { LoggerFactory } from '../logging'; import { KibanaConfigType } from '../kibana_config'; import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config'; -import { PathConfigType } from '../path'; import { CoreSetup, CoreStart } from '..'; /** diff --git a/src/core/server/rendering/__mocks__/rendering_service.ts b/src/core/server/rendering/__mocks__/rendering_service.ts index 2e35568873c9a7..179a09b8619b02 100644 --- a/src/core/server/rendering/__mocks__/rendering_service.ts +++ b/src/core/server/rendering/__mocks__/rendering_service.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RenderingService as Service } from '../rendering_service'; import { InternalRenderingServiceSetup } from '../types'; import { mockRenderingServiceParams } from './params'; diff --git a/src/core/server/root/index.test.mocks.ts b/src/core/server/root/index.test.mocks.ts index ef4a40fa3db2d0..d81b1575adb888 100644 --- a/src/core/server/root/index.test.mocks.ts +++ b/src/core/server/root/index.test.mocks.ts @@ -23,15 +23,14 @@ jest.doMock('../logging/logging_system', () => ({ LoggingSystem: jest.fn(() => logger), })); -import { configServiceMock } from '../config/config_service.mock'; -export const configService = configServiceMock.create(); -jest.doMock('../config/config_service', () => ({ - ConfigService: jest.fn(() => configService), -})); +const realKbnConfig = jest.requireActual('@kbn/config'); -import { rawConfigServiceMock } from '../config/raw_config_service.mock'; +import { configServiceMock, rawConfigServiceMock } from '../config/mocks'; +export const configService = configServiceMock.create(); export const rawConfigService = rawConfigServiceMock.create(); -jest.doMock('../config/raw_config_service', () => ({ +jest.doMock('@kbn/config', () => ({ + ...realKbnConfig, + ConfigService: jest.fn(() => configService), RawConfigService: jest.fn(() => rawConfigService), })); diff --git a/src/core/server/root/index.test.ts b/src/core/server/root/index.test.ts index 5b853903ea4be1..4d3fe24c7ba830 100644 --- a/src/core/server/root/index.test.ts +++ b/src/core/server/root/index.test.ts @@ -21,11 +21,12 @@ import { rawConfigService, configService, logger, mockServer } from './index.tes import { BehaviorSubject } from 'rxjs'; import { filter, first } from 'rxjs/operators'; +import { REPO_ROOT } from '@kbn/dev-utils'; +import { getEnvOptions } from '../config/mocks'; import { Root } from '.'; import { Env } from '../config'; -import { getEnvOptions } from '../config/__mocks__/env'; -const env = new Env('.', getEnvOptions()); +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); let mockConsoleError: jest.SpyInstance; diff --git a/src/core/server/saved_objects/es_query.js b/src/core/server/saved_objects/es_query.js new file mode 100644 index 00000000000000..68d582e3cae09f --- /dev/null +++ b/src/core/server/saved_objects/es_query.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +// a temporary file to remove circular deps in TS code between platform & data plugin +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +export { esKuery } from '../../../plugins/data/server'; diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts index fae33bc050deea..23d8c4518d3ab0 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaMigrator, KibanaMigratorStatus } from './kibana_migrator'; import { buildActiveMappings } from '../core'; diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index e3d44c20dd190d..bd76658c21731b 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsService, diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index d0035294226ea9..bb840e459bf225 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -17,7 +17,7 @@ * under the License. */ -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { SavedObjectsType } from './types'; /** diff --git a/src/core/server/saved_objects/service/lib/filter_utils.test.ts b/src/core/server/saved_objects/service/lib/filter_utils.test.ts index 60e8aa0afdda4c..0608035ce51a27 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.test.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.test.ts @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; import { validateFilterKueryNode, validateConvertFilterToKueryNode } from './filter_utils'; diff --git a/src/core/server/saved_objects/service/lib/filter_utils.ts b/src/core/server/saved_objects/service/lib/filter_utils.ts index d19f06d74e4193..be36807f0d02b8 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.ts @@ -21,8 +21,9 @@ import { set } from '@elastic/safer-lodash-set'; import { get } from 'lodash'; import { SavedObjectsErrorHelpers } from './errors'; import { IndexMapping } from '../../mappings'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../es_query'; +type KueryNode = any; const astFunctionType = ['is', 'range', 'nested']; diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 7d30875b90796a..352ce4c1c16eb2 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -25,8 +25,8 @@ import { encodeHitVersion } from '../../version'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { DocumentMigrator } from '../../migrations/core/document_migrator'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { nodeTypes } from '../../../../../plugins/data/common/es_query'; +import { esKuery } from '../../es_query'; +const { nodeTypes } = esKuery; jest.mock('./search_dsl/search_dsl', () => ({ getSearchDsl: jest.fn() })); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index 85c47029e36d58..4adc92df318058 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -17,8 +17,9 @@ * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; import { getQueryParams } from './query_params'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index 3ff72a86c2f894..642d51c70766e4 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; +// @ts-expect-error no ts +import { esKuery } from '../../../es_query'; +type KueryNode = any; import { getRootPropertiesObjects, IndexMapping } from '../../../mappings'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index ddf20606800c8e..aa79a10b2a9bef 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -22,10 +22,10 @@ import Boom from 'boom'; import { IndexMapping } from '../../../mappings'; import { getQueryParams } from './query_params'; import { getSortingParams } from './sorting_params'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../../../../plugins/data/server'; import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry'; +type KueryNode = any; + interface GetSearchDslOptions { type: string | string[]; search?: string; diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 50c118ca64ffb3..1885f5ec50139b 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -35,8 +35,7 @@ export { import { SavedObject } from '../../types'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { KueryNode } from '../../../plugins/data/common'; +type KueryNode = any; export { SavedObjectAttributes, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ec457704e89c7d..ab26f29dce3af0 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -21,6 +21,7 @@ import { CatSnapshotsParams } from 'elasticsearch'; import { CatTasksParams } from 'elasticsearch'; import { CatThreadPoolParams } from 'elasticsearch'; import { ClearScrollParams } from 'elasticsearch'; +import { CliArgs } from '@kbn/config'; import { Client } from 'elasticsearch'; import { ClientOptions } from '@elastic/elasticsearch'; import { ClusterAllocationExplainParams } from 'elasticsearch'; @@ -31,7 +32,13 @@ import { ClusterPutSettingsParams } from 'elasticsearch'; import { ClusterRerouteParams } from 'elasticsearch'; import { ClusterStateParams } from 'elasticsearch'; import { ClusterStatsParams } from 'elasticsearch'; +import { ConfigDeprecation } from '@kbn/config'; +import { ConfigDeprecationFactory } from '@kbn/config'; +import { ConfigDeprecationLogger } from '@kbn/config'; +import { ConfigDeprecationProvider } from '@kbn/config'; import { ConfigOptions } from 'elasticsearch'; +import { ConfigPath } from '@kbn/config'; +import { ConfigService } from '@kbn/config'; import { CountParams } from 'elasticsearch'; import { CreateDocumentParams } from 'elasticsearch'; import { DeleteDocumentByQueryParams } from 'elasticsearch'; @@ -40,7 +47,7 @@ import { DeleteScriptParams } from 'elasticsearch'; import { DeleteTemplateParams } from 'elasticsearch'; import { DetailedPeerCertificate } from 'tls'; import { Duration } from 'moment'; -import { ErrorToastOptions } from 'src/core/public/notifications'; +import { EnvironmentMode } from '@kbn/config'; import { ExistsParams } from 'elasticsearch'; import { ExplainParams } from 'elasticsearch'; import { FieldStatsParams } from 'elasticsearch'; @@ -95,6 +102,11 @@ import { IngestPutPipelineParams } from 'elasticsearch'; import { IngestSimulateParams } from 'elasticsearch'; import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { KibanaConfigType } from 'src/core/server/kibana_config'; +import { Logger } from '@kbn/logging'; +import { LoggerFactory } from '@kbn/logging'; +import { LogLevel } from '@kbn/logging'; +import { LogMeta } from '@kbn/logging'; +import { LogRecord } from '@kbn/logging'; import { MGetParams } from 'elasticsearch'; import { MGetResponse } from 'elasticsearch'; import { MSearchParams } from 'elasticsearch'; @@ -106,7 +118,8 @@ import { NodesInfoParams } from 'elasticsearch'; import { NodesStatsParams } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; import { Observable } from 'rxjs'; -import { ParsedQuery } from 'query-string'; +import { PackageInfo } from '@kbn/config'; +import { PathConfigType } from '@kbn/utils'; import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; @@ -119,7 +132,6 @@ import { RenderSearchTemplateParams } from 'elasticsearch'; import { Request } from 'hapi'; import { ResponseObject } from 'hapi'; import { ResponseToolkit } from 'hapi'; -import { SavedObject as SavedObject_2 } from 'src/core/server'; import { SchemaTypeError } from '@kbn/config-schema'; import { ScrollParams } from 'elasticsearch'; import { SearchParams } from 'elasticsearch'; @@ -143,7 +155,6 @@ import { TasksCancelParams } from 'elasticsearch'; import { TasksGetParams } from 'elasticsearch'; import { TasksListParams } from 'elasticsearch'; import { TermvectorsParams } from 'elasticsearch'; -import { ToastInputFields } from 'src/core/public/notifications'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -160,9 +171,6 @@ import { Url } from 'url'; // @public (undocumented) export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig; -// @public -export function assertNever(x: never): never; - // @public @deprecated (undocumented) export interface AssistanceAPIResponse { // (undocumented) @@ -369,45 +377,17 @@ export const config: { }; }; -// @public -export type ConfigDeprecation = (config: Record, fromPath: string, logger: ConfigDeprecationLogger) => Record; +export { ConfigDeprecation } -// @public -export interface ConfigDeprecationFactory { - rename(oldKey: string, newKey: string): ConfigDeprecation; - renameFromRoot(oldKey: string, newKey: string, silent?: boolean): ConfigDeprecation; - unused(unusedKey: string): ConfigDeprecation; - unusedFromRoot(unusedKey: string): ConfigDeprecation; -} +export { ConfigDeprecationFactory } -// @public -export type ConfigDeprecationLogger = (message: string) => void; +export { ConfigDeprecationLogger } -// @public -export type ConfigDeprecationProvider = (factory: ConfigDeprecationFactory) => ConfigDeprecation[]; +export { ConfigDeprecationProvider } -// @public (undocumented) -export type ConfigPath = string | string[]; +export { ConfigPath } -// @internal (undocumented) -export class ConfigService { - // Warning: (ae-forgotten-export) The symbol "RawConfigurationProvider" needs to be exported by the entry point index.d.ts - // Warning: (ae-forgotten-export) The symbol "Env" needs to be exported by the entry point index.d.ts - constructor(rawConfigProvider: RawConfigurationProvider, env: Env, logger: LoggerFactory); - addDeprecationProvider(path: ConfigPath, provider: ConfigDeprecationProvider): void; - atPath(path: ConfigPath): Observable; - // Warning: (ae-forgotten-export) The symbol "Config" needs to be exported by the entry point index.d.ts - getConfig$(): Observable; - // (undocumented) - getUnusedPaths(): Promise; - // (undocumented) - getUsedPaths(): Promise; - // (undocumented) - isEnabledAtPath(path: ConfigPath): Promise; - optionalAtPath(path: ConfigPath): Observable; - setSchema(path: ConfigPath, schema: Type): Promise; - validate(): Promise; - } +export { ConfigService } // @public export interface ContextSetup { @@ -504,9 +484,6 @@ export interface CustomHttpResponseOptions(object: T): RecursiveReadonly; - // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ kibana: { @@ -682,15 +659,7 @@ export interface ElasticsearchStatusMeta { warningNodes: NodesVersionCompatibility['warningNodes']; } -// @public (undocumented) -export interface EnvironmentMode { - // (undocumented) - dev: boolean; - // (undocumented) - name: 'development' | 'production'; - // (undocumented) - prod: boolean; -} +export { EnvironmentMode } // @public export interface ErrorHttpResponseOptions { @@ -716,11 +685,6 @@ export interface FakeRequest { headers: Headers; } -// @public (undocumented) -export type Freezable = { - [k: string]: any; -} | any[]; - // @public export type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; @@ -730,11 +694,6 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) state: T; }; -// @public -export function getFlattenedObject(rootValue: Record): { - [key: string]: any; -}; - // @public (undocumented) export interface GetResponse { // (undocumented) @@ -966,9 +925,6 @@ export interface IScopedClusterClient { readonly asInternalUser: ElasticsearchClient; } -// @public -export function isRelativeUrl(candidatePath: string): boolean; - // @public export interface IUiSettingsClient { get: (key: string) => Promise; @@ -1441,18 +1397,7 @@ export interface LegacyUiExports { // @public export type LifecycleResponseFactory = typeof lifecycleResponseFactory; -// @public -export interface Logger { - debug(message: string, meta?: LogMeta): void; - error(errorOrMessage: string | Error, meta?: LogMeta): void; - fatal(errorOrMessage: string | Error, meta?: LogMeta): void; - get(...childContextPaths: string[]): Logger; - info(message: string, meta?: LogMeta): void; - // @internal (undocumented) - log(record: LogRecord): void; - trace(message: string, meta?: LogMeta): void; - warn(errorOrMessage: string | Error, meta?: LogMeta): void; -} +export { Logger } // Warning: (ae-forgotten-export) The symbol "loggerSchema" needs to be exported by the entry point index.d.ts // @@ -1467,69 +1412,18 @@ export interface LoggerContextConfigInput { loggers?: LoggerConfigType[]; } -// @public -export interface LoggerFactory { - get(...contextParts: string[]): Logger; -} +export { LoggerFactory } // @public export interface LoggingServiceSetup { configure(config$: Observable): void; } -// @internal -export class LogLevel { - // (undocumented) - static readonly All: LogLevel; - // (undocumented) - static readonly Debug: LogLevel; - // (undocumented) - static readonly Error: LogLevel; - // (undocumented) - static readonly Fatal: LogLevel; - static fromId(level: LogLevelId): LogLevel; - // Warning: (ae-forgotten-export) The symbol "LogLevelId" needs to be exported by the entry point index.d.ts - // - // (undocumented) - readonly id: LogLevelId; - // (undocumented) - static readonly Info: LogLevel; - // (undocumented) - static readonly Off: LogLevel; - supports(level: LogLevel): boolean; - // (undocumented) - static readonly Trace: LogLevel; - // (undocumented) - readonly value: number; - // (undocumented) - static readonly Warn: LogLevel; -} +export { LogLevel } -// @public -export interface LogMeta { - // (undocumented) - [key: string]: any; -} +export { LogMeta } -// @internal -export interface LogRecord { - // (undocumented) - context: string; - // (undocumented) - error?: Error; - // (undocumented) - level: LogLevel; - // (undocumented) - message: string; - // (undocumented) - meta?: { - [name: string]: any; - }; - // (undocumented) - pid: number; - // (undocumented) - timestamp: Date; -} +export { LogRecord } // @public export interface MetricsServiceSetup { @@ -1543,9 +1437,6 @@ export type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; // @public @deprecated (undocumented) export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; -// @public -export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; - // @public export type MutatingOperationRefreshSetting = boolean | 'wait_for'; @@ -1691,19 +1582,7 @@ export interface OpsServerMetrics { }; } -// @public (undocumented) -export interface PackageInfo { - // (undocumented) - branch: string; - // (undocumented) - buildNum: number; - // (undocumented) - buildSha: string; - // (undocumented) - dist: boolean; - // (undocumented) - version: string; -} +export { PackageInfo } // @public export interface Plugin { @@ -1717,6 +1596,7 @@ export interface Plugin { + // Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported deprecations?: ConfigDeprecationProvider; exposeToBrowser?: { [P in keyof T]?: boolean; @@ -1754,6 +1634,7 @@ export interface PluginInitializerContext { // @public export interface PluginManifest { + // Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported readonly configPath: ConfigPath; // @deprecated readonly extraPublicDirs?: string[]; @@ -2848,26 +2729,6 @@ export interface UiSettingsServiceStart { // @public export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; -// @public -export interface URLMeaningfulParts { - // (undocumented) - auth?: string | null; - // (undocumented) - hash?: string | null; - // (undocumented) - hostname?: string | null; - // (undocumented) - pathname?: string | null; - // (undocumented) - port?: string | null; - // (undocumented) - protocol?: string | null; - // (undocumented) - query: ParsedQuery; - // (undocumented) - slashes?: boolean | null; -} - // @public export interface UserProvidedValues { // (undocumented) @@ -2886,6 +2747,5 @@ export const validBodyOutput: readonly ["data", "stream"]; // src/core/server/legacy/types.ts:135:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/server/server.test.mocks.ts b/src/core/server/server.test.mocks.ts index 471e482a20e962..77f2787b75412c 100644 --- a/src/core/server/server.test.mocks.ts +++ b/src/core/server/server.test.mocks.ts @@ -41,9 +41,12 @@ jest.mock('./legacy/legacy_service', () => ({ LegacyService: jest.fn(() => mockLegacyService), })); -import { configServiceMock } from './config/config_service.mock'; +const realKbnConfig = jest.requireActual('@kbn/config'); + +import { configServiceMock } from './config/mocks'; export const mockConfigService = configServiceMock.create(); -jest.doMock('./config/config_service', () => ({ +jest.doMock('@kbn/config', () => ({ + ...realKbnConfig, ConfigService: jest.fn(() => mockConfigService), })); diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts index 8bf16d9130ef5d..3258840d09df22 100644 --- a/src/core/server/server.test.ts +++ b/src/core/server/server.test.ts @@ -35,14 +35,14 @@ import { } from './server.test.mocks'; import { BehaviorSubject } from 'rxjs'; +import { REPO_ROOT } from '@kbn/dev-utils'; +import { rawConfigServiceMock, getEnvOptions } from './config/mocks'; import { Env } from './config'; import { Server } from './server'; -import { getEnvOptions } from './config/__mocks__/env'; import { loggingSystemMock } from './logging/logging_system.mock'; -import { rawConfigServiceMock } from './config/raw_config_service.mock'; -const env = new Env('.', getEnvOptions()); +const env = Env.createDefault(REPO_ROOT, getEnvOptions()); const logger = loggingSystemMock.create(); const rawConfigService = rawConfigServiceMock.create({}); diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a02b0f51b559f3..c689e2cb70cc94 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -17,6 +17,8 @@ * under the License. */ +import { config as pathConfig } from '@kbn/utils'; +import { mapToObject } from '@kbn/std'; import { ConfigService, Env, RawConfigurationProvider, coreDeprecationProvider } from './config'; import { CoreApp } from './core_app'; import { AuditTrailService } from './audit_trail'; @@ -31,7 +33,7 @@ import { PluginsService, config as pluginsConfig } from './plugins'; import { SavedObjectsService } from '../server/saved_objects'; import { MetricsService, opsConfig } from './metrics'; import { CapabilitiesService } from './capabilities'; -import { EnvironmentService } from './environment'; +import { EnvironmentService, config as pidConfig } from './environment'; import { StatusService } from './status/status_service'; import { config as cspConfig } from './csp'; @@ -39,12 +41,10 @@ import { config as elasticsearchConfig } from './elasticsearch'; import { config as httpConfig } from './http'; import { config as loggingConfig } from './logging'; import { config as devConfig } from './dev'; -import { config as pathConfig } from './path'; import { config as kibanaConfig } from './kibana_config'; import { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects'; import { config as uiSettingsConfig } from './ui_settings'; import { config as statusConfig } from './status'; -import { mapToObject } from '../utils'; import { ContextService } from './context'; import { RequestHandlerContext } from '.'; import { InternalCoreSetup, InternalCoreStart, ServiceConfigDescriptor } from './internal_types'; @@ -310,6 +310,7 @@ export class Server { uiSettingsConfig, opsConfig, statusConfig, + pidConfig, ]; this.configService.addDeprecationProvider(rootConfigPath, coreDeprecationProvider); diff --git a/src/core/server/status/status_service.mock.ts b/src/core/server/status/status_service.mock.ts index 42b3eecdca310f..930ee2970cf55b 100644 --- a/src/core/server/status/status_service.mock.ts +++ b/src/core/server/status/status_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { StatusService } from './status_service'; import { InternalStatusServiceSetup, diff --git a/src/core/server/status/types.ts b/src/core/server/status/types.ts index f884b80316fa81..9fa33a8c6d40c0 100644 --- a/src/core/server/status/types.ts +++ b/src/core/server/status/types.ts @@ -18,7 +18,7 @@ */ import { Observable } from 'rxjs'; -import { deepFreeze } from '../../utils'; +import { deepFreeze } from '@kbn/std'; import { PluginName } from '../plugins'; /** diff --git a/src/core/server/types.ts b/src/core/server/types.ts index 2433aad1a2be57..f8d2f635671fa8 100644 --- a/src/core/server/types.ts +++ b/src/core/server/types.ts @@ -22,4 +22,4 @@ export { PluginOpaqueId } from './plugins/types'; export * from './saved_objects/types'; export * from './ui_settings/types'; export * from './legacy/types'; -export { EnvironmentMode, PackageInfo } from './config/types'; +export type { EnvironmentMode, PackageInfo } from '@kbn/config'; diff --git a/src/core/server/ui_settings/settings/navigation.ts b/src/core/server/ui_settings/settings/navigation.ts index 6483e86a1395ab..ec825a2779f38a 100644 --- a/src/core/server/ui_settings/settings/navigation.ts +++ b/src/core/server/ui_settings/settings/navigation.ts @@ -19,8 +19,8 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; +import { isRelativeUrl } from '@kbn/std'; import { UiSettingsParams } from '../../../types'; -import { isRelativeUrl } from '../../../utils'; export const getNavigationSettings = (): Record => { return { diff --git a/src/core/server/ui_settings/ui_settings_service.mock.ts b/src/core/server/ui_settings/ui_settings_service.mock.ts index 83cea6d7ab3e22..b1ed0dd188cdec 100644 --- a/src/core/server/ui_settings/ui_settings_service.mock.ts +++ b/src/core/server/ui_settings/ui_settings_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IUiSettingsClient, InternalUiSettingsServiceSetup, diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts index 8598cf7a622872..25062490f5b6b5 100644 --- a/src/core/server/ui_settings/ui_settings_service.ts +++ b/src/core/server/ui_settings/ui_settings_service.ts @@ -19,10 +19,11 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; +import { mapToObject } from '@kbn/std'; + import { CoreService } from '../../types'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; - import { SavedObjectsClientContract } from '../saved_objects/types'; import { InternalSavedObjectsServiceSetup } from '../saved_objects'; import { InternalHttpServiceSetup } from '../http'; @@ -33,7 +34,6 @@ import { InternalUiSettingsServiceStart, UiSettingsParams, } from './types'; -import { mapToObject } from '../../utils/'; import { uiSettingsType } from './saved_objects'; import { registerRoutes } from './routes'; import { getCoreSettings } from './settings'; diff --git a/src/core/test_helpers/kbn_server.ts b/src/core/test_helpers/kbn_server.ts index 488c4b919d3e41..93a173cdbdece4 100644 --- a/src/core/test_helpers/kbn_server.ts +++ b/src/core/test_helpers/kbn_server.ts @@ -17,7 +17,7 @@ * under the License. */ import { Client } from 'elasticsearch'; -import { ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { createLegacyEsTestCluster, DEFAULT_SUPERUSER_PASS, @@ -66,7 +66,7 @@ export function createRootWithSettings( settings: Record, cliArgs: Partial = {} ) { - const env = Env.createDefault({ + const env = Env.createDefault(REPO_ROOT, { configs: [], cliArgs: { dev: false, diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json new file mode 100644 index 00000000000000..b8780321e11dd8 --- /dev/null +++ b/src/core/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "public/**/*", + "server/**/*", + "types/**/*", + "test_helpers/**/*", + "utils/**/*", + "index.ts", + "typings.ts" + ], + "references": [ + { "path": "../test_utils/" } + ] +} diff --git a/src/core/typings.ts b/src/core/typings.ts new file mode 100644 index 00000000000000..a84e1c01d2bd2d --- /dev/null +++ b/src/core/typings.ts @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +declare module 'query-string' { + type ArrayFormat = 'bracket' | 'index' | 'none'; + + export interface ParseOptions { + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export interface ParsedQuery { + [key: string]: T | T[] | null | undefined; + } + + export function parse(str: string, options?: ParseOptions): ParsedQuery; + + export function parseUrl(str: string, options?: ParseOptions): { url: string; query: any }; + + export interface StringifyOptions { + strict?: boolean; + encode?: boolean; + arrayFormat?: ArrayFormat; + sort: ((itemLeft: string, itemRight: string) => number) | false; + } + + export function stringify(obj: object, options?: StringifyOptions): string; + + export function extract(str: string): string; +} + +type DeeplyMockedKeys = { + [P in keyof T]: T[P] extends (...args: any[]) => any + ? jest.MockInstance, Parameters> + : DeeplyMockedKeys; +} & + T; + +type MockedKeys = { [P in keyof T]: jest.Mocked }; diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts index 941bbceb0cd92f..f28d3330b8e36e 100644 --- a/src/core/utils/context.ts +++ b/src/core/utils/context.ts @@ -19,8 +19,8 @@ import { flatten } from 'lodash'; import { ShallowPromise } from '@kbn/utility-types'; -import { pick } from '.'; -import { CoreId, PluginOpaqueId } from '../server'; +import { pick } from '@kbn/std'; +import type { CoreId, PluginOpaqueId } from '../server'; /** * Make all properties in T optional, except for the properties whose keys are in the union K diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index a6df0992f6cc67..c620e4e5ee155e 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -17,15 +17,12 @@ * under the License. */ -export * from './assert_never'; -export * from './context'; -export * from './deep_freeze'; -export * from './get'; -export * from './map_to_object'; -export * from './merge'; -export * from './pick'; -export * from './promise'; -export * from './url'; -export * from './unset'; -export * from './get_flattened_object'; -export * from './default_app_categories'; +export { + ContextContainer, + HandlerContextType, + HandlerFunction, + HandlerParameters, + IContextContainer, + IContextProvider, +} from './context'; +export { DEFAULT_APP_CATEGORIES } from './default_app_categories'; diff --git a/src/dev/build/lib/build.test.ts b/src/dev/build/lib/build.test.ts index 9fdf21cee65673..7ccd5b8e13a2cb 100644 --- a/src/dev/build/lib/build.test.ts +++ b/src/dev/build/lib/build.test.ts @@ -17,7 +17,8 @@ * under the License. */ -import { REPO_ROOT, createAbsolutePathSerializer } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import { Config } from './config'; import { Build } from './build'; diff --git a/src/dev/build/lib/config.test.ts b/src/dev/build/lib/config.test.ts index 0539adc840a6a0..bb4d4c000e9d53 100644 --- a/src/dev/build/lib/config.test.ts +++ b/src/dev/build/lib/config.test.ts @@ -19,7 +19,8 @@ import { resolve } from 'path'; -import { createAbsolutePathSerializer, REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { createAbsolutePathSerializer } from '@kbn/dev-utils'; import pkg from '../../../../package.json'; import { Config } from './config'; diff --git a/src/dev/build/tasks/build_kibana_platform_plugins.ts b/src/dev/build/tasks/build_kibana_platform_plugins.ts index 48625078e9bd15..44b441ad898c35 100644 --- a/src/dev/build/tasks/build_kibana_platform_plugins.ts +++ b/src/dev/build/tasks/build_kibana_platform_plugins.ts @@ -17,7 +17,8 @@ * under the License. */ -import { CiStatsReporter, REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; +import { CiStatsReporter } from '@kbn/dev-utils'; import { runOptimizer, OptimizerConfig, diff --git a/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts b/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts index a5b9e01714f384..cd197db2510936 100644 --- a/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts +++ b/src/dev/build/tasks/nodejs/extract_node_builds_task.test.ts @@ -20,12 +20,12 @@ import { readFileSync } from 'fs'; import Path from 'path'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, ToolingLogCollectingWriter, createAbsolutePathSerializer, createRecursiveSerializer, - REPO_ROOT, } from '@kbn/dev-utils'; import { Config } from '../../lib'; diff --git a/src/dev/build/tasks/nodejs/verify_existing_node_builds_task.test.ts b/src/dev/build/tasks/nodejs/verify_existing_node_builds_task.test.ts index 1a850890a33fed..9b03dcd828cf9c 100644 --- a/src/dev/build/tasks/nodejs/verify_existing_node_builds_task.test.ts +++ b/src/dev/build/tasks/nodejs/verify_existing_node_builds_task.test.ts @@ -20,12 +20,12 @@ import Path from 'path'; import Fs from 'fs'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, ToolingLogCollectingWriter, createAnyInstanceSerializer, createRecursiveSerializer, - REPO_ROOT, } from '@kbn/dev-utils'; import { Config, Platform } from '../../lib'; diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile index d235bfe9d6fbc3..24649a52b729bd 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/Dockerfile @@ -85,7 +85,6 @@ RUN groupadd --gid 1000 kibana && \ useradd --uid 1000 --gid 1000 \ --home-dir /usr/share/kibana --no-create-home \ kibana -USER kibana LABEL org.label-schema.build-date="{{dockerBuildDate}}" \ org.label-schema.license="{{license}}" \ @@ -115,8 +114,13 @@ LABEL name="Kibana" \ release="1" \ summary="Kibana" \ description="Your window into the Elastic Stack." + +RUN mkdir /licenses && \ + cp LICENSE.txt /licenses/LICENSE {{/ubi}} +USER kibana + ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] CMD ["/usr/local/bin/kibana-docker"] diff --git a/src/dev/ci_setup/setup.sh b/src/dev/ci_setup/setup.sh index 3351170c29e01a..aabc1e75b90255 100755 --- a/src/dev/ci_setup/setup.sh +++ b/src/dev/ci_setup/setup.sh @@ -16,12 +16,6 @@ echo " -- TEST_ES_SNAPSHOT_VERSION='$TEST_ES_SNAPSHOT_VERSION'" echo " -- installing node.js dependencies" yarn kbn bootstrap --prefer-offline -### -### ensure Chromedriver install hook is triggered -### when modules are up-to-date -### -node node_modules/chromedriver/install.js - ### ### Download es snapshots ### diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index 5757d72f995827..72ec73ad810e6d 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -134,13 +134,13 @@ export CYPRESS_DOWNLOAD_MIRROR="https://us-central1-elastic-kibana-184716.cloudf export CHECKS_REPORTER_ACTIVE=false # This is mainly for release-manager builds, which run in an environment that doesn't have Chrome installed -# if [[ "$(which google-chrome-stable)" || "$(which google-chrome)" ]]; then -# echo "Chrome detected, setting DETECT_CHROMEDRIVER_VERSION=true" -# export DETECT_CHROMEDRIVER_VERSION=true -# export CHROMEDRIVER_FORCE_DOWNLOAD=true -# else -# echo "Chrome not detected, installing default chromedriver binary for the package version" -# fi +if [[ "$(which google-chrome-stable)" || "$(which google-chrome)" ]]; then + echo "Chrome detected, setting DETECT_CHROMEDRIVER_VERSION=true" + export DETECT_CHROMEDRIVER_VERSION=true + export CHROMEDRIVER_FORCE_DOWNLOAD=true +else + echo "Chrome not detected, installing default chromedriver binary for the package version" +fi ### only run on pr jobs for elastic/kibana, checks-reporter doesn't work for other repos if [[ "$ghprbPullId" && "$ghprbGhRepository" == 'elastic/kibana' ]] ; then diff --git a/src/dev/constants.ts b/src/dev/constants.ts index d1b89719c69b7d..9ce18ffdc9bcd1 100644 --- a/src/dev/constants.ts +++ b/src/dev/constants.ts @@ -17,10 +17,6 @@ * under the License. */ -import { dirname } from 'path'; - -export const REPO_ROOT = dirname(require.resolve('../../package.json')); - // Files in directories of this name will be treated as Jest integration tests with instances of // Elasticsearch and the Kibana server. export const RESERVED_DIR_JEST_INTEGRATION_TESTS = 'integration_tests'; diff --git a/src/dev/eslint/lint_files.ts b/src/dev/eslint/lint_files.ts index ba16163fc9bd33..ebd6bedb5f56c8 100644 --- a/src/dev/eslint/lint_files.ts +++ b/src/dev/eslint/lint_files.ts @@ -19,9 +19,9 @@ import { CLIEngine } from 'eslint'; +import { REPO_ROOT } from '@kbn/utils'; import { createFailError, ToolingLog } from '@kbn/dev-utils'; import { File } from '../file'; -import { REPO_ROOT } from '../constants'; /** * Lints a list of files with eslint. eslint reports are written to the log diff --git a/src/dev/license_checker/run_check_licenses_cli.ts b/src/dev/license_checker/run_check_licenses_cli.ts index 0267a1a90d4fe1..70ebb43c788f99 100644 --- a/src/dev/license_checker/run_check_licenses_cli.ts +++ b/src/dev/license_checker/run_check_licenses_cli.ts @@ -17,12 +17,12 @@ * under the License. */ +import { REPO_ROOT } from '@kbn/utils'; import { run } from '@kbn/dev-utils'; import { getInstalledPackages } from '../npm'; import { LICENSE_WHITELIST, DEV_ONLY_LICENSE_WHITELIST, LICENSE_OVERRIDES } from './config'; import { assertLicensesValid } from './valid'; -import { REPO_ROOT } from '../constants'; run( async ({ log, flags }) => { diff --git a/src/dev/notice/cli.js b/src/dev/notice/cli.js index 34217ef48a33b2..ea0f884bb1ea07 100644 --- a/src/dev/notice/cli.js +++ b/src/dev/notice/cli.js @@ -22,9 +22,9 @@ import { resolve } from 'path'; import getopts from 'getopts'; import dedent from 'dedent'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils'; -import { REPO_ROOT } from '../constants'; import { generateNoticeFromSource } from './generate_notice_from_source'; const unknownFlags = []; diff --git a/src/dev/npm/integration_tests/installed_packages.test.ts b/src/dev/npm/integration_tests/installed_packages.test.ts index 58c954cbc12f72..3aeb5b106c2ec0 100644 --- a/src/dev/npm/integration_tests/installed_packages.test.ts +++ b/src/dev/npm/integration_tests/installed_packages.test.ts @@ -21,8 +21,8 @@ import { resolve, sep } from 'path'; import { uniq } from 'lodash'; +import { REPO_ROOT } from '@kbn/utils'; import { getInstalledPackages, InstalledPackage } from '../installed_packages'; -import { REPO_ROOT } from '../../constants'; const FIXTURE1_ROOT = resolve(__dirname, '__fixtures__/fixture1'); diff --git a/src/dev/precommit_hook/get_files_for_commit.js b/src/dev/precommit_hook/get_files_for_commit.js index dc5560be0d1ade..e700b587821749 100644 --- a/src/dev/precommit_hook/get_files_for_commit.js +++ b/src/dev/precommit_hook/get_files_for_commit.js @@ -20,7 +20,7 @@ import SimpleGit from 'simple-git'; import { fromNode as fcb } from 'bluebird'; -import { REPO_ROOT } from '../constants'; +import { REPO_ROOT } from '@kbn/utils'; import { File } from '../file'; /** diff --git a/src/dev/run_check_file_casing.js b/src/dev/run_check_file_casing.js index bdbf1827897e76..3acff74430abeb 100644 --- a/src/dev/run_check_file_casing.js +++ b/src/dev/run_check_file_casing.js @@ -19,9 +19,9 @@ import globby from 'globby'; +import { REPO_ROOT } from '@kbn/utils'; import { run } from '@kbn/dev-utils'; import { File } from './file'; -import { REPO_ROOT } from './constants'; import { checkFileCasing } from './precommit_hook/check_file_casing'; run(async ({ log }) => { diff --git a/src/dev/run_check_lockfile_symlinks.js b/src/dev/run_check_lockfile_symlinks.js index 5ebb7952e2cf32..c4e040c4bffa3d 100644 --- a/src/dev/run_check_lockfile_symlinks.js +++ b/src/dev/run_check_lockfile_symlinks.js @@ -21,9 +21,9 @@ import { existsSync, lstatSync, readFileSync, readlinkSync } from 'fs'; import globby from 'globby'; import { dirname } from 'path'; +import { REPO_ROOT } from '@kbn/utils'; import { run, createFailError } from '@kbn/dev-utils'; -import { REPO_ROOT } from './constants'; import { File } from './file'; import { matchesAnyGlob } from './globs'; diff --git a/src/dev/storybook/commands/clean.ts b/src/dev/storybook/commands/clean.ts index 328c4d9e2c23c2..539757d0e7ad22 100644 --- a/src/dev/storybook/commands/clean.ts +++ b/src/dev/storybook/commands/clean.ts @@ -18,7 +18,7 @@ */ import { ToolingLog } from '@kbn/dev-utils'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { join } from 'path'; import del from 'del'; diff --git a/src/dev/storybook/run_storybook_cli.ts b/src/dev/storybook/run_storybook_cli.ts index 7f97cff91aaaaf..b1e8d882e53528 100644 --- a/src/dev/storybook/run_storybook_cli.ts +++ b/src/dev/storybook/run_storybook_cli.ts @@ -19,7 +19,7 @@ import { join } from 'path'; import { run, createFlagError } from '@kbn/dev-utils'; -import { REPO_ROOT } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; import { storybookAliases } from './aliases'; import { clean } from './commands/clean'; diff --git a/src/dev/typescript/get_ts_project_for_absolute_path.ts b/src/dev/typescript/get_ts_project_for_absolute_path.ts index 54d7e950834a4c..0057263660b777 100644 --- a/src/dev/typescript/get_ts_project_for_absolute_path.ts +++ b/src/dev/typescript/get_ts_project_for_absolute_path.ts @@ -18,7 +18,7 @@ */ import { relative, resolve } from 'path'; -import { REPO_ROOT } from '../constants'; +import { REPO_ROOT } from '@kbn/utils'; import { File } from '../file'; import { Project } from './project'; import { PROJECTS } from './projects'; diff --git a/src/dev/typescript/project.ts b/src/dev/typescript/project.ts index 4cf87d812a0b38..811c1792f1988e 100644 --- a/src/dev/typescript/project.ts +++ b/src/dev/typescript/project.ts @@ -23,7 +23,7 @@ import { basename, dirname, relative, resolve } from 'path'; import { IMinimatch, Minimatch } from 'minimatch'; import { parseConfigFileTextToJson } from 'typescript'; -import { REPO_ROOT } from '../constants'; +import { REPO_ROOT } from '@kbn/utils'; function makeMatchers(directory: string, patterns: string[]) { return patterns.map( diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index e18c82b5b9e96e..4d1e549e192b65 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -19,12 +19,13 @@ import glob from 'glob'; import { resolve } from 'path'; -import { REPO_ROOT } from '../constants'; +import { REPO_ROOT } from '@kbn/utils'; import { Project } from './project'; export const PROJECTS = [ new Project(resolve(REPO_ROOT, 'tsconfig.json')), new Project(resolve(REPO_ROOT, 'src/test_utils/tsconfig.json')), + new Project(resolve(REPO_ROOT, 'src/core/tsconfig.json')), new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), { name: 'kibana/test' }), new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')), new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), { name: 'x-pack/test' }), diff --git a/src/dev/typescript/run_check_ts_projects_cli.ts b/src/dev/typescript/run_check_ts_projects_cli.ts index b0c125ea478294..a095bef047711e 100644 --- a/src/dev/typescript/run_check_ts_projects_cli.ts +++ b/src/dev/typescript/run_check_ts_projects_cli.ts @@ -22,8 +22,8 @@ import { resolve } from 'path'; import execa from 'execa'; import { run } from '@kbn/dev-utils'; +import { REPO_ROOT } from '@kbn/utils'; -const REPO_ROOT = resolve(__dirname, '../../../'); import { File } from '../file'; import { PROJECTS } from './projects'; diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index e1fca23274a5aa..00968b7259a303 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -98,7 +98,7 @@ export async function runTypeCheckCli() { } execInProjects(log, projects, process.execPath, (project) => [ - '--max-old-space-size=4096', + '--max-old-space-size=5120', require.resolve('typescript/bin/tsc'), ...['--project', project.tsConfigPath], ...tscArgs, diff --git a/src/legacy/server/config/schema.js b/src/legacy/server/config/schema.js index ce7a500a00dc8f..f8736fb30f90e9 100644 --- a/src/legacy/server/config/schema.js +++ b/src/legacy/server/config/schema.js @@ -42,10 +42,7 @@ export default () => basePathProxyTarget: Joi.number().default(5603), }).default(), - pid: Joi.object({ - file: Joi.string(), - exclusive: Joi.boolean().default(false), - }).default(), + pid: HANDLED_IN_NEW_PLATFORM, csp: HANDLED_IN_NEW_PLATFORM, diff --git a/src/legacy/server/i18n/index.ts b/src/legacy/server/i18n/index.ts index e895f83fe69017..cb86c3220bec12 100644 --- a/src/legacy/server/i18n/index.ts +++ b/src/legacy/server/i18n/index.ts @@ -21,6 +21,7 @@ import { i18n, i18nLoader } from '@kbn/i18n'; import { basename } from 'path'; import { Server } from 'hapi'; import { fromRoot } from '../../../core/server/utils'; +import type { UsageCollectionSetup } from '../../../plugins/usage_collection/server'; import { getTranslationPaths } from './get_translations_path'; import { I18N_RC } from './constants'; import KbnServer, { KibanaConfig } from '../kbn_server'; @@ -64,7 +65,10 @@ export async function i18nMixin(kbnServer: KbnServer, server: Server, config: Ki server.decorate('server', 'getTranslationsFilePaths', getTranslationsFilePaths); if (kbnServer.newPlatform.setup.plugins.usageCollection) { - registerLocalizationUsageCollector(kbnServer.newPlatform.setup.plugins.usageCollection, { + const { usageCollection } = kbnServer.newPlatform.setup.plugins as { + usageCollection: UsageCollectionSetup; + }; + registerLocalizationUsageCollector(usageCollection, { getLocale: () => config.get('i18n.locale') as string, getTranslationsFilePaths, }); diff --git a/src/legacy/server/kbn_server.d.ts b/src/legacy/server/kbn_server.d.ts index 663542618375a3..8827dc53c52750 100644 --- a/src/legacy/server/kbn_server.d.ts +++ b/src/legacy/server/kbn_server.d.ts @@ -19,7 +19,6 @@ import { Server } from 'hapi'; -import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { CoreSetup, CoreStart, @@ -35,8 +34,6 @@ import { LegacyConfig, ILegacyInternals } from '../../core/server/legacy'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { UiPlugins } from '../../core/server/plugins'; import { ElasticsearchPlugin } from '../core_plugins/elasticsearch'; -import { UsageCollectionSetup } from '../../plugins/usage_collection/server'; -import { HomeServerPluginSetup } from '../../plugins/home/server'; // lot of legacy code was assuming this type only had these two methods export type KibanaConfig = Pick; @@ -60,9 +57,6 @@ declare module 'hapi' { type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promise | void; export interface PluginsSetup { - usageCollection: UsageCollectionSetup; - telemetryCollectionManager: TelemetryCollectionManagerPluginSetup; - home: HomeServerPluginSetup; [key: string]: object; } diff --git a/src/legacy/server/kbn_server.js b/src/legacy/server/kbn_server.js index a5eefd140c8fa2..24d00abb99a058 100644 --- a/src/legacy/server/kbn_server.js +++ b/src/legacy/server/kbn_server.js @@ -29,7 +29,6 @@ import { coreMixin } from './core'; import { loggingMixin } from './logging'; import warningsMixin from './warnings'; import { statusMixin } from './status'; -import pidMixin from './pid'; import configCompleteMixin from './config/complete'; import { optimizeMixin } from '../../optimize'; import * as Plugins from './plugins'; @@ -93,9 +92,6 @@ export default class KbnServer { warningsMixin, statusMixin, - // writes pid file - pidMixin, - // scan translations dirs, register locale files and initialize i18n engine. i18nMixin, diff --git a/src/legacy/server/logging/log_interceptor.js b/src/legacy/server/logging/log_interceptor.js index 07545570445831..2298d83aa28571 100644 --- a/src/legacy/server/logging/log_interceptor.js +++ b/src/legacy/server/logging/log_interceptor.js @@ -20,7 +20,11 @@ import Stream from 'stream'; import { get, isEqual } from 'lodash'; -const GET_CLIENT_HELLO = /GET_CLIENT_HELLO:http/; +/** + * Matches error messages when clients connect via HTTP instead of HTTPS; see unit test for full message. Warning: this can change when Node + * and its bundled OpenSSL binary are upgraded. + */ +const OPENSSL_GET_RECORD_REGEX = /ssl3_get_record:http/; function doTagsMatch(event, tags) { return isEqual(get(event, 'tags'), tags); @@ -124,7 +128,7 @@ export class LogInterceptor extends Stream.Transform { } downgradeIfHTTPWhenHTTPS(event) { - return downgradeIfErrorMessage(GET_CLIENT_HELLO, event); + return downgradeIfErrorMessage(OPENSSL_GET_RECORD_REGEX, event); } _transform(event, enc, next) { diff --git a/src/legacy/server/logging/log_interceptor.test.js b/src/legacy/server/logging/log_interceptor.test.js index c99373ebe0a639..492d1ffc8d167f 100644 --- a/src/legacy/server/logging/log_interceptor.test.js +++ b/src/legacy/server/logging/log_interceptor.test.js @@ -147,7 +147,7 @@ describe('server logging LogInterceptor', () => { describe('#downgradeIfHTTPWhenHTTPS', () => { it('transforms http requests when serving https errors', () => { const message = - '40735139278848:error:1407609C:SSL routines:SSL23_GET_CLIENT_HELLO:http request:../deps/openssl/openssl/ssl/s23_srvr.c:394'; + '4584650176:error:1408F09C:SSL routines:ssl3_get_record:http request:../deps/openssl/openssl/ssl/record/ssl3_record.c:322:\n'; const interceptor = new LogInterceptor(); const event = stubClientErrorEvent({ message }); assertDowngraded(interceptor.downgradeIfHTTPWhenHTTPS(event)); diff --git a/src/legacy/server/pid/index.js b/src/legacy/server/pid/index.js deleted file mode 100644 index d7b9da12922520..00000000000000 --- a/src/legacy/server/pid/index.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import Boom from 'boom'; -import Bluebird from 'bluebird'; -import { unlinkSync as unlink } from 'fs'; -const writeFile = Bluebird.promisify(require('fs').writeFile); - -export default Bluebird.method(function (kbnServer, server, config) { - const path = config.get('pid.file'); - if (!path) return; - - const pid = String(process.pid); - - return writeFile(path, pid, { flag: 'wx' }) - .catch(function (err) { - if (err.code !== 'EEXIST') throw err; - - const message = `pid file already exists at ${path}`; - const metadata = { - path: path, - pid: pid, - }; - - if (config.get('pid.exclusive')) { - throw Boom.internal(message, { message, ...metadata }); - } else { - server.log(['pid', 'warning'], message, metadata); - } - - return writeFile(path, pid); - }) - .then(function () { - server.logWithMetadata(['pid', 'debug'], `wrote pid file to ${path}`, { - path: path, - pid: pid, - }); - - const clean = _.once(function () { - unlink(path); - }); - - process.once('exit', clean); // for "natural" exits - process.once('SIGINT', function () { - // for Ctrl-C exits - clean(); - - // resend SIGINT - process.kill(process.pid, 'SIGINT'); - }); - - process.on('unhandledRejection', function (reason) { - server.log(['warning'], `Detected an unhandled Promise rejection.\n${reason}`); - }); - }); -}); diff --git a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx index bbc3f3632bf64f..8c9e3847844d93 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx @@ -121,7 +121,7 @@ export class AdvancedSettingsComponent extends Component< setTimeout(() => { const id = hash.replace('#', ''); const element = document.getElementById(id); - const globalNavOffset = document.getElementById('headerGlobalNav')?.offsetHeight || 0; + const globalNavOffset = document.getElementById('globalHeaderBars')?.offsetHeight || 0; if (element) { element.scrollIntoView(); diff --git a/src/plugins/advanced_settings/public/management_app/components/_index.scss b/src/plugins/advanced_settings/public/management_app/components/_index.scss deleted file mode 100644 index d2d2e38947f762..00000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './form/index'; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/_form.scss b/src/plugins/advanced_settings/public/management_app/components/form/_form.scss deleted file mode 100644 index 8d768d200fdd2a..00000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/form/_form.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import '@elastic/eui/src/global_styling/variables/header'; -@import '@elastic/eui/src/components/nav_drawer/variables'; - -// TODO #64541 -// Delete this whole file -.mgtAdvancedSettingsForm__bottomBar { - margin-left: $euiNavDrawerWidthCollapsed; - z-index: 9; // Puts it inuder the nav drawer when expanded - &--pushForNav { - margin-left: $euiNavDrawerWidthExpanded; - } - @include euiBreakpoint('xs', 's') { - margin-left: 0; - } -} diff --git a/src/plugins/advanced_settings/public/management_app/components/form/_index.scss b/src/plugins/advanced_settings/public/management_app/components/form/_index.scss deleted file mode 100644 index 2ef4ef1d20ce99..00000000000000 --- a/src/plugins/advanced_settings/public/management_app/components/form/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './form'; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx index 5533f684870d90..0378d816fd2c3b 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx @@ -18,7 +18,6 @@ */ import React, { PureComponent, Fragment } from 'react'; -import classNames from 'classnames'; import { EuiFlexGroup, @@ -45,7 +44,6 @@ import { Field, getEditableValue } from '../field'; import { FieldSetting, SettingsChanges, FieldState } from '../../types'; type Category = string; -const NAV_IS_LOCKED_KEY = 'core.chrome.isLocked'; interface FormProps { settings: Record; @@ -326,23 +324,8 @@ export class Form extends PureComponent { renderBottomBar = () => { const areChangesInvalid = this.areChangesInvalid(); - - // TODO #64541 - // Delete these classes - let bottomBarClasses = ''; - const pageNav = this.props.settings.general.find( - (setting) => setting.name === 'pageNavigation' - ); - - if (pageNav?.value === 'legacy') { - bottomBarClasses = classNames('mgtAdvancedSettingsForm__bottomBar', { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'mgtAdvancedSettingsForm__bottomBar--pushForNav': - localStorage.getItem(NAV_IS_LOCKED_KEY) === 'true', - }); - } return ( - + ScopedHistory; + setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; savedObjects: SavedObjectsStart; restorePreviousUrl: () => void; } diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index 92d6f2ed91dde9..dd5eb1ee5ccaa4 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -153,6 +153,7 @@ export class DashboardAppController { i18n: i18nStart, }, history, + setHeaderActionMenu, kbnUrlStateStorage, usageCollection, navigation, @@ -709,7 +710,13 @@ export class DashboardAppController { }; const dashboardNavBar = document.getElementById('dashboardChrome'); const updateNavBar = () => { - ReactDOM.render(, dashboardNavBar); + ReactDOM.render( + , + dashboardNavBar + ); }; const unmountNavBar = () => { diff --git a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx index a36363d22d87da..84df05154fb630 100644 --- a/src/plugins/dashboard/public/attribute_service/attribute_service.tsx +++ b/src/plugins/dashboard/public/attribute_service/attribute_service.tsx @@ -57,7 +57,7 @@ export interface AttributeServiceOptions { type: string, attributes: A, savedObjectId?: string - ) => Promise<{ id: string }>; + ) => Promise<{ id?: string } | { error: Error }>; customUnwrapMethod?: (savedObject: SimpleSavedObject) => A; } @@ -124,7 +124,10 @@ export class AttributeService< newAttributes, savedObjectId ); - return { ...originalInput, savedObjectId: savedItem.id } as RefType; + if ('id' in savedItem) { + return { ...originalInput, savedObjectId: savedItem.id } as RefType; + } + return { ...originalInput } as RefType; } if (savedObjectId) { @@ -208,7 +211,6 @@ export class AttributeService< return { error }; } }; - if (saveOptions && (saveOptions as { showSaveModal: boolean }).showSaveModal) { this.showSaveModal( ; + +const createStartContract = (): DashboardStart => { + // @ts-ignore + const startContract: DashboardStart = { + getAttributeService: jest.fn(), + }; + + return startContract; +}; + +export const dashboardPluginMock = { + createStartContract, +}; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 49584f62215ead..5a45229a58a7d4 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -310,7 +310,7 @@ export class DashboardPlugin id: DashboardConstants.DASHBOARDS_ID, title: 'Dashboard', order: 2500, - euiIconType: 'dashboardApp', + euiIconType: 'logoKibana', defaultPath: `#${DashboardConstants.LANDING_PAGE_PATH}`, updater$: this.appStateUpdater, category: DEFAULT_APP_CATEGORIES.kibana, @@ -352,6 +352,7 @@ export class DashboardPlugin localStorage: new Storage(localStorage), usageCollection, scopedHistory: () => this.currentHistory!, + setHeaderActionMenu: params.setHeaderActionMenu, savedObjects, restorePreviousUrl, }; diff --git a/src/plugins/data/common/es_query/kuery/node_types/types.ts b/src/plugins/data/common/es_query/kuery/node_types/types.ts index 6d3019e75d483f..894bd1812f0844 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/types.ts +++ b/src/plugins/data/common/es_query/kuery/node_types/types.ts @@ -76,6 +76,7 @@ export interface NamedArgTypeBuildNode { } interface WildcardType { + wildcardSymbol: string; buildNode: (value: string) => WildcardTypeBuildNode | KueryNode; test: (node: any, string: string) => boolean; toElasticsearchQuery: (node: any) => string; diff --git a/src/plugins/data/public/actions/apply_filter_action.ts b/src/plugins/data/public/actions/apply_filter_action.ts index a2621e6ce8802f..944da72bd11d1d 100644 --- a/src/plugins/data/public/actions/apply_filter_action.ts +++ b/src/plugins/data/public/actions/apply_filter_action.ts @@ -44,6 +44,7 @@ export function createFilterAction( return createAction({ type: ACTION_GLOBAL_APPLY_FILTER, id: ACTION_GLOBAL_APPLY_FILTER, + order: 100, getIconType: () => 'filter', getDisplayName: () => { return i18n.translate('data.filter.applyFilterActionTitle', { diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index fa5d3cd85f4300..7ce53a219fb443 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -17,6 +17,7 @@ import { CoreSetup as CoreSetup_2 } from 'kibana/public'; import { CoreStart } from 'kibana/public'; import { CoreStart as CoreStart_2 } from 'src/core/public'; import { Ensure } from '@kbn/utility-types'; +import { EnvironmentMode } from '@kbn/config'; import { ErrorToastOptions } from 'src/core/public/notifications'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; @@ -28,7 +29,6 @@ import { ExpressionAstFunction } from 'src/plugins/expressions/common'; import { ExpressionsSetup } from 'src/plugins/expressions/public'; import { History } from 'history'; import { Href } from 'history'; -import { HttpStart } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; @@ -39,16 +39,20 @@ import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { KibanaConfigType } from 'src/core/server/kibana_config'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; +import { Logger } from '@kbn/logging'; +import { LogMeta } from '@kbn/logging'; import { MaybePromise } from '@kbn/utility-types'; import { METRIC_TYPE } from '@kbn/analytics'; import { Moment } from 'moment'; import moment from 'moment'; import { NameList } from 'elasticsearch'; import { Observable } from 'rxjs'; +import { PackageInfo } from '@kbn/config'; import { Path } from 'history'; import { Plugin as Plugin_2 } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; import { PopoverAnchorPosition } from '@elastic/eui'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PublicUiSettingsParams } from 'src/core/server/types'; import React from 'react'; import * as React_2 from 'react'; @@ -1685,7 +1689,7 @@ export interface QueryStateChange extends QueryStateChangePartial { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; @@ -2017,7 +2021,7 @@ export class SearchSource { onRequestStart(handler: (searchSource: SearchSource, options?: ISearchOptions) => Promise): void; serialize(): { searchSourceJSON: string; - references: import("../../../../../core/public").SavedObjectReference[]; + references: import("../../../../../core/types").SavedObjectReference[]; }; setField(field: K, value: SearchSourceFields[K]): this; setFields(newFields: SearchSourceFields): this; diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 224a597766909b..cdf10d8f1a1b06 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -17,9 +17,9 @@ * under the License. */ -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; +import { SearchResponse } from 'elasticsearch'; import { GetConfigFn } from '../../../common'; +import { LegacyFetchHandlers } from '../legacy/types'; /** * @internal @@ -31,9 +31,17 @@ import { GetConfigFn } from '../../../common'; export type SearchRequest = Record; export interface FetchHandlers { - config: { get: GetConfigFn }; - http: HttpStart; - loadingCount$: BehaviorSubject; + getConfig: GetConfigFn; + /** + * Callback which can be used to hook into responses, modify them, or perform + * side effects like displaying UI errors on the client. + */ + onResponse: (request: SearchRequest, response: SearchResponse) => SearchResponse; + /** + * These handlers are only used by the legacy defaultSearchStrategy and can be removed + * once that strategy has been deprecated. + */ + legacy: LegacyFetchHandlers; } export interface SearchError { diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index 943a02d22088d0..0a7913b0a734f8 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -17,18 +17,13 @@ * under the License. */ -import { coreMock } from '../../../../../core/public/mocks'; import { callClient } from './call_client'; import { SearchStrategySearchParams } from './types'; import { defaultSearchStrategy } from './default_search_strategy'; import { FetchHandlers } from '../fetch'; -import { handleResponse } from '../fetch/handle_response'; import { BehaviorSubject } from 'rxjs'; const mockAbortFn = jest.fn(); -jest.mock('../fetch/handle_response', () => ({ - handleResponse: jest.fn((request, response) => response), -})); jest.mock('./default_search_strategy', () => { return { @@ -50,32 +45,36 @@ jest.mock('./default_search_strategy', () => { }); describe('callClient', () => { + const handleResponse = jest.fn().mockImplementation((req, res) => res); + const handlers = { + getConfig: jest.fn(), + onResponse: handleResponse, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, + } as FetchHandlers; + beforeEach(() => { - (handleResponse as jest.Mock).mockClear(); + handleResponse.mockClear(); }); test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { - http: coreMock.createStart().http, - legacySearchService: {}, - config: { get: jest.fn() }, - loadingCount$: new BehaviorSubject(0), - } as FetchHandlers; - callClient(searchRequests, [], args); + callClient(searchRequests, [], handlers); expect(defaultSearchStrategy.search).toBeCalled(); expect((defaultSearchStrategy.search as any).mock.calls[0][0]).toEqual({ searchRequests, - ...args, + ...handlers, }); }); test('Returns the responses in the original order', async () => { const searchRequests = [{ _searchStrategyId: 1 }, { _searchStrategyId: 0 }]; - const responses = await Promise.all(callClient(searchRequests, [], {} as FetchHandlers)); + const responses = await Promise.all(callClient(searchRequests, [], handlers)); expect(responses[0]).toEqual({ id: searchRequests[0]._searchStrategyId }); expect(responses[1]).toEqual({ id: searchRequests[1]._searchStrategyId }); @@ -84,7 +83,7 @@ describe('callClient', () => { test('Calls handleResponse with each request and response', async () => { const searchRequests = [{ _searchStrategyId: 0 }, { _searchStrategyId: 1 }]; - const responses = callClient(searchRequests, [], {} as FetchHandlers); + const responses = callClient(searchRequests, [], handlers); await Promise.all(responses); expect(handleResponse).toBeCalledTimes(2); @@ -105,7 +104,7 @@ describe('callClient', () => { }, ]; - callClient(searchRequests, requestOptions, {} as FetchHandlers); + callClient(searchRequests, requestOptions, handlers); abortController.abort(); expect(mockAbortFn).toBeCalled(); diff --git a/src/plugins/data/public/search/legacy/call_client.ts b/src/plugins/data/public/search/legacy/call_client.ts index d66796b9427a14..b87affdd59c54a 100644 --- a/src/plugins/data/public/search/legacy/call_client.ts +++ b/src/plugins/data/public/search/legacy/call_client.ts @@ -19,7 +19,7 @@ import { SearchResponse } from 'elasticsearch'; import { ISearchOptions } from 'src/plugins/data/common'; -import { FetchHandlers, handleResponse } from '../fetch'; +import { FetchHandlers } from '../fetch'; import { defaultSearchStrategy } from './default_search_strategy'; import { SearchRequest } from '../index'; @@ -42,7 +42,7 @@ export function callClient( }); searchRequests.forEach((request, i) => { - const response = searching.then((results) => handleResponse(request, results[i])); + const response = searching.then((results) => fetchHandlers.onResponse(request, results[i])); const { abortSignal = null } = requestOptionsMap.get(request) || {}; if (abortSignal) abortSignal.addEventListener('abort', abort); requestResponseMap.set(request, response); diff --git a/src/plugins/data/public/search/legacy/call_msearch.ts b/src/plugins/data/public/search/legacy/call_msearch.ts new file mode 100644 index 00000000000000..fd4f8a07919f83 --- /dev/null +++ b/src/plugins/data/public/search/legacy/call_msearch.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { HttpStart } from 'src/core/public'; +import { LegacyFetchHandlers } from './types'; + +/** + * Wrapper for calling the internal msearch endpoint from the client. + * This is needed to abstract away differences in the http service + * between client & server. + * + * @internal + */ +export function getCallMsearch({ http }: { http: HttpStart }): LegacyFetchHandlers['callMsearch'] { + return async ({ body, signal }) => { + return http.post('/internal/_msearch', { + body: JSON.stringify(body), + signal, + }); + }; +} diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index e74ab49131430b..ad59e5c6c96257 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -19,8 +19,9 @@ import { HttpStart } from 'src/core/public'; import { coreMock } from '../../../../../core/public/mocks'; +import { getCallMsearch } from './call_msearch'; import { defaultSearchStrategy } from './default_search_strategy'; -import { SearchStrategySearchParams } from './types'; +import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; import { BehaviorSubject } from 'rxjs'; const { search } = defaultSearchStrategy; @@ -44,11 +45,12 @@ describe('defaultSearchStrategy', function () { index: { title: 'foo' }, }, ], - http, - config: { - get: jest.fn(), - }, - loadingCount$: new BehaviorSubject(0) as any, + getConfig: jest.fn(), + onResponse: (req, res) => res, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$: new BehaviorSubject(0) as any, + } as jest.Mocked, }; }); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index cbcd0da20207f3..bed86cb75cca64 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -29,12 +29,14 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategySearchParams) { +function msearch({ searchRequests, getConfig, legacy }: SearchStrategySearchParams) { + const { callMsearch, loadingCount$ } = legacy; + const requests = searchRequests.map(({ index, body }) => { return { header: { index: index.title || index, - preference: getPreference(config.get), + preference: getPreference(getConfig), }, body, }; @@ -55,12 +57,11 @@ function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategy } }; - const searching = http - .post('/internal/_msearch', { - body: JSON.stringify({ searches: requests }), - signal: abortController.signal, - }) - .then(({ body }) => body?.responses) + const searching = callMsearch({ + body: { searches: requests }, + signal: abortController.signal, + }) + .then((res: any) => res?.body?.responses) .finally(() => cleanup()); return { diff --git a/src/plugins/data/public/search/legacy/fetch_soon.test.ts b/src/plugins/data/public/search/legacy/fetch_soon.test.ts index d38a41cf5ffbc0..7243ab158009ad 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.test.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.test.ts @@ -67,25 +67,21 @@ describe('fetchSoon', () => { }); test('should execute asap if config is set to not batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: false }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).toBeCalled(); }); test('should delay by 50ms if config is set to batch searches', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const request = {}; const options = {}; - fetchSoon(request, options, { config } as FetchHandlers); + fetchSoon(request, options, { getConfig } as FetchHandlers); expect(callClient).not.toBeCalled(); jest.advanceTimersByTime(0); @@ -95,14 +91,12 @@ describe('fetchSoon', () => { }); test('should send a batch of requests to callClient', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ foo: 1 }, { foo: 2 }]; const options = [{ bar: 1 }, { bar: 2 }]; requests.forEach((request, i) => { - fetchSoon(request, options[i] as ISearchOptions, { config } as FetchHandlers); + fetchSoon(request, options[i] as ISearchOptions, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); @@ -112,13 +106,11 @@ describe('fetchSoon', () => { }); test('should return the response to the corresponding call for multiple batched requests', async () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const requests = [{ _mockResponseId: 'foo' }, { _mockResponseId: 'bar' }]; const promises = requests.map((request) => { - return fetchSoon(request, {}, { config } as FetchHandlers); + return fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); const results = await Promise.all(promises); @@ -127,18 +119,16 @@ describe('fetchSoon', () => { }); test('should wait for the previous batch to start before starting a new batch', () => { - const config = { - get: getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }), - }; + const getConfig = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); const firstBatch = [{ foo: 1 }, { foo: 2 }]; const secondBatch = [{ bar: 1 }, { bar: 2 }]; firstBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); jest.advanceTimersByTime(50); secondBatch.forEach((request) => { - fetchSoon(request, {}, { config } as FetchHandlers); + fetchSoon(request, {}, { getConfig } as FetchHandlers); }); expect(callClient).toBeCalledTimes(1); diff --git a/src/plugins/data/public/search/legacy/fetch_soon.ts b/src/plugins/data/public/search/legacy/fetch_soon.ts index 37c3827bb7bba5..1c0573aa895d78 100644 --- a/src/plugins/data/public/search/legacy/fetch_soon.ts +++ b/src/plugins/data/public/search/legacy/fetch_soon.ts @@ -32,7 +32,7 @@ export async function fetchSoon( options: ISearchOptions, fetchHandlers: FetchHandlers ) { - const msToDelay = fetchHandlers.config.get(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; + const msToDelay = fetchHandlers.getConfig(UI_SETTINGS.COURIER_BATCH_SEARCHES) ? 50 : 0; return delayedFetch(request, options, fetchHandlers, msToDelay); } diff --git a/src/plugins/data/public/search/legacy/types.ts b/src/plugins/data/public/search/legacy/types.ts index ed17db464feffa..740bc22a7485c5 100644 --- a/src/plugins/data/public/search/legacy/types.ts +++ b/src/plugins/data/public/search/legacy/types.ts @@ -17,10 +17,20 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { SearchResponse } from 'elasticsearch'; import { FetchHandlers } from '../fetch'; import { SearchRequest } from '..'; +// @internal +export interface LegacyFetchHandlers { + callMsearch: (params: { + body: SearchRequest; + signal: AbortSignal; + }) => Promise>>; + loadingCount$: BehaviorSubject; +} + export interface SearchStrategySearchParams extends FetchHandlers { searchRequests: SearchRequest[]; } diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6b73761c5a4373..c41e1f78ee74e0 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -21,6 +21,8 @@ import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; import { BehaviorSubject } from 'rxjs'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; +import { handleResponse } from './fetch'; +import { getCallMsearch } from './legacy/call_msearch'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; import { AggsService, AggsStartDependencies } from './aggs'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; @@ -49,7 +51,7 @@ export class SearchService implements Plugin { private usageCollector?: SearchUsageCollector; public setup( - { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, + { http, getStartServices, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { this.usageCollector = createUsageCollector(getStartServices, usageCollection); @@ -82,7 +84,7 @@ export class SearchService implements Plugin { } public start( - { application, http, injectedMetadata, notifications, uiSettings }: CoreStart, + { application, http, notifications, uiSettings }: CoreStart, { fieldFormats, indexPatterns }: SearchServiceStartDependencies ): ISearchStart { const search = ((request, options) => { @@ -95,8 +97,11 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), search, - http, - loadingCount$, + onResponse: handleResponse, + legacy: { + callMsearch: getCallMsearch({ http }), + loadingCount$, + }, }; return { diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index bc1c7c06c88064..6b6cfb0c9b1ca2 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -22,7 +22,6 @@ import { SearchSourceDependencies } from './search_source'; import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; -import { coreMock } from '../../../../../core/public/mocks'; import { BehaviorSubject } from 'rxjs'; describe('createSearchSource', () => { @@ -35,8 +34,11 @@ describe('createSearchSource', () => { dependencies = { getConfig: jest.fn(), search: jest.fn(), - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index adf53bee33fe1b..f582861e37c159 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -18,7 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import { httpServiceMock, uiSettingsServiceMock } from '../../../../../core/public/mocks'; +import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; import { SearchSourceFields } from './types'; @@ -54,6 +54,9 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { getConfig: uiSettingsServiceMock.createStartContract().get, search: jest.fn(), - http: httpServiceMock.createStartContract(), - loadingCount$: new BehaviorSubject(0), + onResponse: jest.fn().mockImplementation((req, res) => res), + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index 282a33e6d01f71..d9a9fb2f4fef37 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -22,7 +22,6 @@ import { GetConfigFn } from 'src/plugins/data/common'; import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; import { fetchSoon } from '../legacy'; -import { coreMock } from '../../../../../core/public/mocks'; jest.mock('../legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), @@ -68,8 +67,11 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - http: coreMock.createStart().http, - loadingCount$: new BehaviorSubject(0), + onResponse: (req, res) => res, + legacy: { + callMsearch: jest.fn(), + loadingCount$: new BehaviorSubject(0), + }, }; }); diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index a39898e6a9f52b..4afee223454e49 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -72,19 +72,12 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; -import { HttpStart } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; import { IIndexPattern, ISearchGeneric } from '../..'; import { SearchSourceOptions, SearchSourceFields } from './types'; -import { - RequestFailure, - handleResponse, - getSearchParamsFromRequest, - SearchRequest, -} from '../fetch'; +import { FetchHandlers, RequestFailure, getSearchParamsFromRequest, SearchRequest } from '../fetch'; import { getEsQueryConfig, @@ -94,7 +87,6 @@ import { ISearchOptions, } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; -import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; @@ -114,11 +106,8 @@ export const searchSourceRequiredUiSettings = [ UI_SETTINGS.SORT_OPTIONS, ]; -export interface SearchSourceDependencies { - getConfig: GetConfigFn; +export interface SearchSourceDependencies extends FetchHandlers { search: ISearchGeneric; - http: HttpStart; - loadingCount$: BehaviorSubject; } /** @public **/ @@ -321,14 +310,14 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, options: ISearchOptions) { - const { search, getConfig } = this.dependencies; + const { search, getConfig, onResponse } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { getConfig, }); return search({ params, indexType: searchRequest.indexType }, options).pipe( - map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)) + map(({ rawResponse }) => onResponse(searchRequest, rawResponse)) ); } @@ -337,7 +326,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: ISearchOptions) { - const { http, getConfig, loadingCount$ } = this.dependencies; + const { getConfig, legacy, onResponse } = this.dependencies; return await fetchSoon( searchRequest, @@ -346,9 +335,9 @@ export class SearchSource { ...options, }, { - http, - config: { get: getConfig }, - loadingCount$, + getConfig, + onResponse, + legacy, } ); } diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx index 3606bfbaeb1f96..1f124291669ec2 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx @@ -17,9 +17,9 @@ * under the License. */ import React from 'react'; +import { getFlattenedObject } from '@kbn/std'; import { EuiCodeBlock, EuiDescriptionList, EuiSpacer } from '@elastic/eui'; import { ShardFailure } from './shard_failure_types'; -import { getFlattenedObject } from '../../../../../core/public'; import { ShardFailureDescriptionHeader } from './shard_failure_description_header'; /** diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index cd0369a5c45511..14f176176f647e 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -32,6 +32,7 @@ import { ClusterPutSettingsParams } from 'elasticsearch'; import { ClusterRerouteParams } from 'elasticsearch'; import { ClusterStateParams } from 'elasticsearch'; import { ClusterStatsParams } from 'elasticsearch'; +import { ConfigDeprecationProvider } from '@kbn/config'; import { CoreSetup } from 'src/core/server'; import { CoreSetup as CoreSetup_2 } from 'kibana/server'; import { CoreStart } from 'src/core/server'; @@ -43,6 +44,7 @@ import { DeleteScriptParams } from 'elasticsearch'; import { DeleteTemplateParams } from 'elasticsearch'; import { Duration } from 'moment'; import { Ensure } from '@kbn/utility-types'; +import { EnvironmentMode } from '@kbn/config'; import { ErrorToastOptions } from 'src/core/public/notifications'; import { ExistsParams } from 'elasticsearch'; import { ExplainParams } from 'elasticsearch'; @@ -104,7 +106,10 @@ import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { KibanaConfigType as KibanaConfigType_2 } from 'src/core/server/kibana_config'; import { KibanaRequest } from 'kibana/server'; import { LegacyAPICaller as LegacyAPICaller_2 } from 'kibana/server'; +import { Logger } from '@kbn/logging'; import { Logger as Logger_2 } from 'kibana/server'; +import { LoggerFactory } from '@kbn/logging'; +import { LogMeta } from '@kbn/logging'; import { MGetParams } from 'elasticsearch'; import { MGetResponse } from 'elasticsearch'; import { Moment } from 'moment'; @@ -117,6 +122,8 @@ import { NodesHotThreadsParams } from 'elasticsearch'; import { NodesInfoParams } from 'elasticsearch'; import { NodesStatsParams } from 'elasticsearch'; import { Observable } from 'rxjs'; +import { PackageInfo } from '@kbn/config'; +import { PathConfigType } from '@kbn/utils'; import { PingParams } from 'elasticsearch'; import { Plugin as Plugin_2 } from 'src/core/server'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/server'; diff --git a/src/plugins/dev_tools/public/index.scss b/src/plugins/dev_tools/public/index.scss index c9d8dc7470656a..4bec602ea42db3 100644 --- a/src/plugins/dev_tools/public/index.scss +++ b/src/plugins/dev_tools/public/index.scss @@ -16,10 +16,6 @@ } } -.devApp { - height: 100%; -} - .devAppWrapper { display: flex; flex-direction: column; diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index fcc6a57361a94d..8c4743c93fab33 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -60,7 +60,7 @@ export class DevToolsPlugin implements Plugin { defaultMessage: 'Dev Tools', }), updater$: this.appStateUpdater, - euiIconType: 'devToolsApp', + euiIconType: 'logoElastic', order: 9010, category: DEFAULT_APP_CATEGORIES.management, mount: async (params: AppMountParameters) => { diff --git a/src/plugins/discover/public/application/angular/discover.html b/src/plugins/discover/public/application/angular/discover.html index 94f13e1cd81325..e0e452aaa41c51 100644 --- a/src/plugins/discover/public/application/angular/discover.html +++ b/src/plugins/discover/public/application/angular/discover.html @@ -5,6 +5,7 @@

{{screenTitle}}

an array of sort objects */ -export function getSort(sort: SortPair[], indexPattern: IndexPattern): SortPairObj[] { +export function getSort(sort: SortPair[] | SortPair, indexPattern: IndexPattern): SortPairObj[] { if (Array.isArray(sort)) { + if (isLegacySort(sort)) { + // To stay compatible with legacy sort, which just supported a single sort field + return [{ [sort[0]]: sort[1] }]; + } return sort .map((sortPair: SortPair) => createSortObject(sortPair, indexPattern)) .filter((sortPairObj) => typeof sortPairObj === 'object') as SortPairObj[]; diff --git a/src/plugins/discover/public/kibana_services.ts b/src/plugins/discover/public/kibana_services.ts index bc25fa71dcf415..064030b78d10ec 100644 --- a/src/plugins/discover/public/kibana_services.ts +++ b/src/plugins/discover/public/kibana_services.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; import { createHashHistory } from 'history'; -import { ScopedHistory } from 'kibana/public'; +import { ScopedHistory, AppMountParameters } from 'kibana/public'; import { UiActionsStart } from 'src/plugins/ui_actions/public'; import { DiscoverServices } from './build_services'; import { createGetterSetter } from '../../kibana_utils/public'; @@ -58,6 +58,10 @@ export function setServices(newServices: any) { export const setUiActions = (pluginUiActions: UiActionsStart) => (uiActions = pluginUiActions); export const getUiActions = () => uiActions; +export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] = createGetterSetter< + AppMountParameters['setHeaderActionMenu'] +>('headerActionMenuMounter'); + export const [getUrlTracker, setUrlTracker] = createGetterSetter<{ setTrackedUrl: (url: string) => void; restorePreviousUrl: () => void; diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index b6960c8a20abfc..dd9b57b568e42c 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -54,6 +54,7 @@ import { setUrlTracker, setAngularModule, setServices, + setHeaderActionMenuMounter, setUiActions, setScopedHistory, getScopedHistory, @@ -240,7 +241,7 @@ export class DiscoverPlugin title: 'Discover', updater$: this.appStateUpdater.asObservable(), order: 1000, - euiIconType: 'discoverApp', + euiIconType: 'logoKibana', defaultPath: '#/', category: DEFAULT_APP_CATEGORIES.kibana, mount: async (params: AppMountParameters) => { @@ -251,6 +252,7 @@ export class DiscoverPlugin throw Error('Discover plugin method initializeInnerAngular is undefined'); } setScopedHistory(params.history); + setHeaderActionMenuMounter(params.setHeaderActionMenu); syncHistoryLocations(); appMounted(); const { @@ -264,6 +266,7 @@ export class DiscoverPlugin params.element.classList.add('dscAppWrapper'); const unmount = await renderApp(innerAngularName, params.element); return () => { + params.element.classList.remove('dscAppWrapper'); unmount(); appUnMounted(); }; diff --git a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts index 1cdb5af00e7483..3460203aac29c6 100644 --- a/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts +++ b/src/plugins/embeddable/public/lib/actions/apply_filter_action.ts @@ -42,6 +42,7 @@ export function createFilterAction(): ActionByType { return createAction({ type: ACTION_APPLY_FILTER, id: ACTION_APPLY_FILTER, + order: 100, getIconType: () => 'filter', getDisplayName: () => { return i18n.translate('embeddableApi.actions.applyFilterActionTitle', { diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts index 570a78fc41ea91..b22f16c94aff8d 100644 --- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts +++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts @@ -37,11 +37,11 @@ export const defaultEmbeddableFactoryProvider = < getExplicitInput: def.getExplicitInput ? def.getExplicitInput.bind(def) : () => Promise.resolve({}), - createFromSavedObject: - def.createFromSavedObject ?? - ((savedObjectId: string, input: Partial, parent?: IContainer) => { - throw new Error(`Creation from saved object not supported by type ${def.type}`); - }), + createFromSavedObject: def.createFromSavedObject + ? def.createFromSavedObject.bind(def) + : (savedObjectId: string, input: Partial, parent?: IContainer) => { + throw new Error(`Creation from saved object not supported by type ${def.type}`); + }, create: def.create.bind(def), type: def.type, isEditable: def.isEditable.bind(def), diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx index c14471991ccd33..dbf53a9f0a359a 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useEffect } from 'react'; +import React, { useEffect, FunctionComponent } from 'react'; import { act } from 'react-dom/test-utils'; import { registerTestBed, TestBed } from '../shared_imports'; @@ -237,4 +237,64 @@ describe('', () => { expect(serializer).not.toBeCalled(); }); }); + + describe('custom components', () => { + interface MyForm { + name: string; + } + + let formHook: FormHook | null = null; + + beforeEach(() => { + formHook = null; + }); + + const onFormHook = (_form: FormHook) => { + formHook = _form; + }; + + const TestComp = ({ + component, + onForm, + }: { + component: FunctionComponent; + onForm: (form: FormHook) => void; + }) => { + const { form } = useForm(); + + useEffect(() => { + onForm(form); + }, [onForm, form]); + + return ( +
+ + + ); + }; + + it('allows function components', () => { + const Component = () =>