diff --git a/.eslintrc.js b/.eslintrc.js index 8d5b4525d51ba..32f59c4d6b3db 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -888,7 +888,7 @@ module.exports = { { // typescript only for front and back end files: [ - 'x-pack/{,legacy/}plugins/{alerting,alerting_builtins,actions,task_manager,event_log}/**/*.{ts,tsx}', + 'x-pack/{,legacy/}plugins/{alerts,alerting_builtins,actions,task_manager,event_log}/**/*.{ts,tsx}', ], rules: { '@typescript-eslint/no-explicit-any': 'error', @@ -1039,5 +1039,22 @@ module.exports = { ...require('eslint-config-prettier/@typescript-eslint').rules, }, }, + + { + files: [ + // platform-team owned code + 'src/core/**', + 'x-pack/plugins/features/**', + 'x-pack/plugins/licensing/**', + 'x-pack/plugins/global_search/**', + 'x-pack/plugins/cloud/**', + 'packages/kbn-config-schema', + 'src/plugins/status_page/**', + 'src/plugins/saved_objects_management/**', + ], + rules: { + '@typescript-eslint/prefer-ts-expect-error': 'error', + }, + }, ], }; diff --git a/docs/apm/apm-alerts.asciidoc b/docs/apm/apm-alerts.asciidoc index 75ce5f56c96c6..bc5e1ccc1dd55 100644 --- a/docs/apm/apm-alerts.asciidoc +++ b/docs/apm/apm-alerts.asciidoc @@ -15,15 +15,20 @@ and enables central management of all alerts from <>. + +The APM app supports two different types of threshold alerts: transaction duration, and error rate. Below, we'll create one of each. [float] [[apm-create-transaction-alert]] === Create a transaction duration alert -This guide creates an alert for the `opbeans-java` service based on the following criteria: +Transaction duration alerts trigger when the duration of a specific transaction type in a service exceeds a defined threshold. +This guide will create an alert for the `opbeans-java` service based on the following criteria: +* Environment: Production * Transaction type: `transaction.type:request` * Average request is above `1500ms` for the last 5 minutes * Check every 10 minutes, and repeat the alert every 30 minutes @@ -52,14 +57,22 @@ Enter a name for the connector, and paste the webhook URL. See Slack's webhook documentation if you need to create one. +Add a message body in markdown format. +You can use the https://mustache.github.io/[Mustache] template syntax, i.e., `{{variable}}` +to pass alert values at the time a condition is detected to an action. +A list of available variables can be accessed by selecting the +**add variable** button image:apm/images/add-variable.png[add variable button]. + Select **Save**. The alert has been created and is now active! [float] [[apm-create-error-alert]] === Create an error rate alert +Error rate alerts trigger when the number of errors in a service exceeds a defined threshold. This guide creates an alert for the `opbeans-python` service based on the following criteria: +* Environment: Production * Error rate is above 25 for the last minute * Check every 1 minute, and repeat the alert every 10 minutes * Send the alert via email to the `opbeans-python` team @@ -81,6 +94,12 @@ Based on the alert criteria, define the following alert details: Select the **Email** action type and click **Create a connector**. Fill out the required details: sender, host, port, etc., and click **save**. +Add a message body in markdown format. +You can use the https://mustache.github.io/[Mustache] template syntax, i.e., `{{variable}}` +to pass alert values at the time a condition is detected to an action. +A list of available variables can be accessed by selecting the +**add variable** button image:apm/images/add-variable.png[add variable button]. + Select **Save**. The alert has been created and is now active! [float] diff --git a/docs/apm/images/add-variable.png b/docs/apm/images/add-variable.png new file mode 100644 index 0000000000000..860ab66f22f4e Binary files /dev/null and b/docs/apm/images/add-variable.png differ diff --git a/docs/apm/troubleshooting.asciidoc b/docs/apm/troubleshooting.asciidoc index eb4fb790afd7f..65f7a378ec244 100644 --- a/docs/apm/troubleshooting.asciidoc +++ b/docs/apm/troubleshooting.asciidoc @@ -10,6 +10,11 @@ your proposed changes at https://github.com/elastic/kibana. Also, check out the https://discuss.elastic.co/c/apm[APM discussion forum]. +* <> +* <> +* <> +* <> + [float] [[no-apm-data-found]] === No APM data found @@ -58,6 +63,66 @@ Navigate to *APM* > *Settings* > *Indices*, and change all `apm_oss.*Pattern` va include the new index pattern. For example: `customIndexName-*`. [float] +[[troubleshooting-too-many-transactions]] +=== Too many unique transaction names + +Transaction names are defined in each APM Agent; when an Agent supports a framework, +it includes logic for naming the transactions that the framework creates. +In some cases though, like when using an Agent's API to create custom transactions, +it is up to the user to define a pattern for transaction naming. +When transactions are named incorrectly, each unique URL can be associated with a unique transaction group—causing +an explosion in the number of transaction groups per service, and leading to inaccuracies in the APM app. + +To fix a large number of unique transaction names, +you need to change how you are using the Agent API to name your transactions. +To do this, ensure you are **not** naming based on parameters that can change. +For example, user ids, product ids, order numbers, query parameters, etc., +should be stripped away, and commonality should be found between your unique URLs. + +Let's look at an example from the RUM Agent documentation. Here are a few URLs you might find on Elastic.co: + +[source,yml] +---- +// Blog Posts +https://www.elastic.co/blog/reflections-on-three-years-in-the-elastic-public-sector +https://www.elastic.co/blog/say-heya-to-the-elastic-search-awards +https://www.elastic.co/blog/and-the-winner-of-the-elasticon-2018-training-subscription-drawing-is + +// Documentation +https://www.elastic.co/guide/en/elastic-stack/current/index.html +https://www.elastic.co/guide/en/apm/get-started/current/index.html +https://www.elastic.co/guide/en/infrastructure/guide/current/index.html +---- + +These URLs, like most, include unique names. +If we named transactions based on each unique URL, we'd end up with the problem described above—a +very large number of different transaction names. +Instead, we should strip away the unique information and group our transactions based on common information. +In this case, that means naming all blog transactions, `/blog`, and all documentation transactions, `/guide`. + +If you feel like you'd be losing valuable information by following this naming convention, don't fret! +You can always add additional metadata to your transactions using {apm-overview-ref-v}/metadata.html#labels-fields[labels] (indexed) or +{apm-overview-ref-v}/metadata.html#custom-fields[custom context] (non-indexed). + +After ensuring you've correctly named your transactions, +you might still see an error in the APM app related to too many transaction names. +If this is the case, you can increase the default number of transaction groups displayed in the APM app by configuring +<>. + +**More information** + +While this can happen with any APM Agent, it typically occurs with the RUM Agent. +For more information on how to correctly set `transaction.name` in the RUM Agent, +see {apm-rum-ref}/custom-transaction-name.html[custom initial page load transaction names]. + +The RUM Agent can also set the `transaction.name` when observing for transaction events. +See {apm-rum-ref}/agent-api.html#observe[`apm.observe()`] for more information. + +If your problem is occurring in a different Agent, the tips above still apply. +See the relevant {apm-agents-ref}[Agent API documentation] to adjust how you're naming your transactions. + +[float] +[[troubleshooting-unknown-route]] === Unknown route The {apm-app-ref}/transactions.html[transaction overview] will only display helpful information @@ -78,6 +143,7 @@ Specifically, view the Agent's supported technologies page. You can also use the Agent's public API to manually set a name for the transaction. [float] +[[troubleshooting-fields-unsearchable]] === Fields are not searchable In Elasticsearch, index templates are used to define settings and mappings that determine how fields should be analyzed. diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index b0612ff4d5b65..8f2bde3856019 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -172,7 +172,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PublicAppInfo](./kibana-plugin-core-public.publicappinfo.md) | Public information about a registered [application](./kibana-plugin-core-public.app.md) | | [PublicLegacyAppInfo](./kibana-plugin-core-public.publiclegacyappinfo.md) | Information about a registered [legacy application](./kibana-plugin-core-public.legacyapp.md) | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) | | | [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | | [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | | [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md b/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md index c70f3a97a8882..4b3b103c92731 100644 --- a/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md +++ b/docs/development/core/public/kibana-plugin-core-public.publicappinfo.md @@ -11,5 +11,8 @@ Public information about a registered [application](./kibana-plugin-core-public. ```typescript export declare type PublicAppInfo = Omit & { legacy: false; + status: AppStatus; + navLinkStatus: AppNavLinkStatus; + appRoute: string; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.publiclegacyappinfo.md b/docs/development/core/public/kibana-plugin-core-public.publiclegacyappinfo.md index cc3e9de3193cb..051638daabd12 100644 --- a/docs/development/core/public/kibana-plugin-core-public.publiclegacyappinfo.md +++ b/docs/development/core/public/kibana-plugin-core-public.publiclegacyappinfo.md @@ -11,5 +11,7 @@ Information about a registered [legacy application](./kibana-plugin-core-public. ```typescript export declare type PublicLegacyAppInfo = Omit & { legacy: true; + status: AppStatus; + navLinkStatus: AppNavLinkStatus; }; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md b/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md deleted file mode 100644 index 2f47ef1086d71..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.md b/docs/development/core/server/kibana-plugin-core-server.callapioptions.md deleted file mode 100644 index 03f74424acf99..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) - -## CallAPIOptions interface - -The set of options that defines how API call should be made and result be processed. - -Signature: - -```typescript -export interface CallAPIOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [signal](./kibana-plugin-core-server.callapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | -| [wrap401Errors](./kibana-plugin-core-server.callapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md deleted file mode 100644 index d4b2f80443acb..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [(constructor)](./kibana-plugin-core-server.clusterclient._constructor_.md) - -## ClusterClient.(constructor) - -Constructs a new instance of the `ClusterClient` class - -Signature: - -```typescript -constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| config | ElasticsearchClientConfig | | -| log | Logger | | -| getAuthHeaders | GetAuthHeaders | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md deleted file mode 100644 index dd1dcffc5a969..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [asScoped](./kibana-plugin-core-server.clusterclient.asscoped.md) - -## ClusterClient.asScoped() method - -Creates an instance of [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. - -Signature: - -```typescript -asScoped(request?: ScopeableRequest): IScopedClusterClient; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | - -Returns: - -`IScopedClusterClient` - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md deleted file mode 100644 index ae9a9b46b52b6..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.clusterclient.callasinternaluser.md) - -## ClusterClient.callAsInternalUser property - -Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). - -Signature: - -```typescript -callAsInternalUser: APICaller; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.md deleted file mode 100644 index 0f6b2512a6d94..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.md +++ /dev/null @@ -1,35 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) - -## ClusterClient class - -Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). - -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). - -Signature: - -```typescript -export declare class ClusterClient implements IClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-core-server.clusterclient._constructor_.md) | | Constructs a new instance of the ClusterClient class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [callAsInternalUser](./kibana-plugin-core-server.clusterclient.callasinternaluser.md) | | APICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [asScoped(request)](./kibana-plugin-core-server.clusterclient.asscoped.md) | | Creates an instance of [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | -| [close()](./kibana-plugin-core-server.clusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md deleted file mode 100644 index d2b07e8d116ba..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) > [\[code\]](./kibana-plugin-core-server.elasticsearcherror._code_.md) - -## ElasticsearchError.\[code\] property - -Signature: - -```typescript -[code]?: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md deleted file mode 100644 index 42079c02689c5..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md +++ /dev/null @@ -1,19 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) - -## ElasticsearchError interface - - -Signature: - -```typescript -export interface ElasticsearchError extends Boom -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [\[code\]](./kibana-plugin-core-server.elasticsearcherror._code_.md) | string | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md deleted file mode 100644 index d85ae4f9ab530..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md) - -## ElasticsearchErrorHelpers.isNotAuthorizedError() method - -Signature: - -```typescript -static isNotAuthorizedError(error: any): error is ElasticsearchError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | any | | - -Returns: - -`error is ElasticsearchError` - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md index e8c4c63dc6a96..c683f0ba33189 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md @@ -13,7 +13,7 @@ ```typescript legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md index c1e23527e9516..0dd41a6154a1e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md @@ -15,5 +15,5 @@ export interface ElasticsearchServiceSetup | Property | Type | Description | | --- | --- | --- | -| [legacy](./kibana-plugin-core-server.elasticsearchservicesetup.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient;
readonly client: IClusterClient;
} | | +| [legacy](./kibana-plugin-core-server.elasticsearchservicesetup.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<LegacyElasticsearchClientConfig>) => ILegacyCustomClusterClient;
readonly client: ILegacyClusterClient;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md index 667a36091f232..5f346d7887c2a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md @@ -13,7 +13,7 @@ ```typescript legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md index 39c794af2c881..e059acdbd52fa 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md @@ -15,5 +15,5 @@ export interface ElasticsearchServiceStart | Property | Type | Description | | --- | --- | --- | -| [legacy](./kibana-plugin-core-server.elasticsearchservicestart.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient;
readonly client: IClusterClient;
} | | +| [legacy](./kibana-plugin-core-server.elasticsearchservicestart.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<LegacyElasticsearchClientConfig>) => ILegacyCustomClusterClient;
readonly client: ILegacyClusterClient;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.iclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md similarity index 56% rename from docs/development/core/server/kibana-plugin-core-server.iclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md index 28fbdf17cf31c..c70a5ac07c6ad 100644 --- a/docs/development/core/server/kibana-plugin-core-server.iclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IClusterClient](./kibana-plugin-core-server.iclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyClusterClient](./kibana-plugin-core-server.ilegacyclusterclient.md) -## IClusterClient type +## ILegacyClusterClient type Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). +See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). Signature: ```typescript -export declare type IClusterClient = Pick; +export declare type ILegacyClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md similarity index 53% rename from docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md index 3d379e1231cb1..a3cb8f1315021 100644 --- a/docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ICustomClusterClient](./kibana-plugin-core-server.icustomclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyCustomClusterClient](./kibana-plugin-core-server.ilegacycustomclusterclient.md) -## ICustomClusterClient type +## ILegacyCustomClusterClient type Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). +See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). Signature: ```typescript -export declare type ICustomClusterClient = Pick; +export declare type ILegacyCustomClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md similarity index 56% rename from docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md index 378836ee461f3..1263b85acb498 100644 --- a/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) -## IScopedClusterClient type +## ILegacyScopedClusterClient type Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. -See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). +See [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md). Signature: ```typescript -export declare type IScopedClusterClient = Pick; +export declare type ILegacyScopedClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.apicaller.md b/docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md similarity index 54% rename from docs/development/core/server/kibana-plugin-core-server.apicaller.md rename to docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md index 4da23b3f821c5..e6c2878d2b355 100644 --- a/docs/development/core/server/kibana-plugin-core-server.apicaller.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md @@ -1,12 +1,12 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [APICaller](./kibana-plugin-core-server.apicaller.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md) -## APICaller interface +## LegacyAPICaller interface Signature: ```typescript -export interface APICaller +export interface LegacyAPICaller ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md new file mode 100644 index 0000000000000..9ebe2fc57a54b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) + +## LegacyCallAPIOptions interface + +The set of options that defines how API call should be made and result be processed. + +Signature: + +```typescript +export interface LegacyCallAPIOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [signal](./kibana-plugin-core-server.legacycallapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | +| [wrap401Errors](./kibana-plugin-core-server.legacycallapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md similarity index 57% rename from docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md rename to docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md index 8b35924826f15..7d795a59e41a5 100644 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) > [signal](./kibana-plugin-core-server.callapioptions.signal.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) > [signal](./kibana-plugin-core-server.legacycallapioptions.signal.md) -## CallAPIOptions.signal property +## LegacyCallAPIOptions.signal property A signal object that allows you to abort the request via an AbortController object. diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md similarity index 69% rename from docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md rename to docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md index 2a5b8054819a3..38fac54db77a4 100644 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) > [wrap401Errors](./kibana-plugin-core-server.callapioptions.wrap401errors.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) > [wrap401Errors](./kibana-plugin-core-server.legacycallapioptions.wrap401errors.md) -## CallAPIOptions.wrap401Errors property +## LegacyCallAPIOptions.wrap401Errors property Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` header that could have been returned by the API itself. If API didn't specify that then `Basic realm="Authorization Required"` is used as `WWW-Authenticate`. diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md new file mode 100644 index 0000000000000..823f34bd7dd23 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [(constructor)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) + +## LegacyClusterClient.(constructor) + +Constructs a new instance of the `LegacyClusterClient` class + +Signature: + +```typescript +constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | LegacyElasticsearchClientConfig | | +| log | Logger | | +| getAuthHeaders | GetAuthHeaders | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md new file mode 100644 index 0000000000000..1c25fc1d072b6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [asScoped](./kibana-plugin-core-server.legacyclusterclient.asscoped.md) + +## LegacyClusterClient.asScoped() method + +Creates an instance of [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. + +Signature: + +```typescript +asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | + +Returns: + +`ILegacyScopedClusterClient` + diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md new file mode 100644 index 0000000000000..2e235485711c6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md) + +## LegacyClusterClient.callAsInternalUser property + +Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). + +Signature: + +```typescript +callAsInternalUser: LegacyAPICaller; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md similarity index 64% rename from docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md rename to docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md index 68a1bd4b9d7cf..88a5ffce5bb17 100644 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [close](./kibana-plugin-core-server.clusterclient.close.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [close](./kibana-plugin-core-server.legacyclusterclient.close.md) -## ClusterClient.close() method +## LegacyClusterClient.close() method Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md new file mode 100644 index 0000000000000..4f218ae552c99 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) + +## LegacyClusterClient class + + +Signature: + +```typescript +export declare class LegacyClusterClient implements ILegacyClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) | | Constructs a new instance of the LegacyClusterClient class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [callAsInternalUser](./kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md) | | LegacyAPICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [asScoped(request)](./kibana-plugin-core-server.legacyclusterclient.asscoped.md) | | Creates an instance of [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | +| [close()](./kibana-plugin-core-server.legacyclusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md similarity index 52% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md index 703b07808aca3..62b0f216c863c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md @@ -1,14 +1,14 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchClientConfig](./kibana-plugin-core-server.legacyelasticsearchclientconfig.md) -## ElasticsearchClientConfig type +## LegacyElasticsearchClientConfig type Signature: ```typescript -export declare type ElasticsearchClientConfig = Pick & Pick & { +export declare type LegacyElasticsearchClientConfig = Pick & Pick & { pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md new file mode 100644 index 0000000000000..05530ceb0d568 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) > [\[code\]](./kibana-plugin-core-server.legacyelasticsearcherror._code_.md) + +## LegacyElasticsearchError.\[code\] property + +Signature: + +```typescript +[code]?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md new file mode 100644 index 0000000000000..f760780504e55 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) + +## LegacyElasticsearchError interface + + +Signature: + +```typescript +export interface LegacyElasticsearchError extends Boom +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [\[code\]](./kibana-plugin-core-server.legacyelasticsearcherror._code_.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md similarity index 52% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md index 2b2eeceb4e3c9..bd802a39e9339 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md @@ -1,13 +1,13 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md) -## ElasticsearchErrorHelpers.decorateNotAuthorizedError() method +## LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError() method Signature: ```typescript -static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; +static decorateNotAuthorizedError(error: Error, reason?: string): LegacyElasticsearchError; ``` ## Parameters @@ -19,5 +19,5 @@ static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchE Returns: -`ElasticsearchError` +`LegacyElasticsearchError` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md new file mode 100644 index 0000000000000..f647916149458 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md) + +## LegacyElasticsearchErrorHelpers.isNotAuthorizedError() method + +Signature: + +```typescript +static isNotAuthorizedError(error: any): error is LegacyElasticsearchError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | any | | + +Returns: + +`error is LegacyElasticsearchError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md similarity index 65% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md index e9c205e3dfa2c..e20dcd4ed253e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) -## ElasticsearchErrorHelpers class +## LegacyElasticsearchErrorHelpers class Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as `body.error.header[WWW-Authenticate]` Signature: ```typescript -export declare class ElasticsearchErrorHelpers +export declare class LegacyElasticsearchErrorHelpers ``` ## Example @@ -30,6 +30,6 @@ try { | Method | Modifiers | Description | | --- | --- | --- | -| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | -| [isNotAuthorizedError(error)](./kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md) | static | | +| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | +| [isNotAuthorizedError(error)](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md) | static | | diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md new file mode 100644 index 0000000000000..bd1cd1e9f3d9b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [(constructor)](./kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md) + +## LegacyScopedClusterClient.(constructor) + +Constructs a new instance of the `LegacyScopedClusterClient` class + +Signature: + +```typescript +constructor(internalAPICaller: LegacyAPICaller, scopedAPICaller: LegacyAPICaller, headers?: Headers | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| internalAPICaller | LegacyAPICaller | | +| scopedAPICaller | LegacyAPICaller | | +| headers | Headers | undefined | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md similarity index 58% rename from docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md rename to docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md index 68c0f8e6be1be..9130f9adde76e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md) -## ScopedClusterClient.callAsCurrentUser() method +## LegacyScopedClusterClient.callAsCurrentUser() method -Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-core-server.apicaller.md). +Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). Signature: ```typescript -callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +callAsCurrentUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; ``` ## Parameters @@ -18,7 +18,7 @@ callAsCurrentUser(endpoint: string, clientParams?: Record, options? | --- | --- | --- | | endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | | clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | +| options | LegacyCallAPIOptions | Options that affect the way we call the API and process the result. | Returns: diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md similarity index 55% rename from docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md rename to docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md index e769fd692a4d1..bf95782299e72 100644 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md) -## ScopedClusterClient.callAsInternalUser() method +## LegacyScopedClusterClient.callAsInternalUser() method -Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). +Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). Signature: ```typescript -callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +callAsInternalUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; ``` ## Parameters @@ -18,7 +18,7 @@ callAsInternalUser(endpoint: string, clientParams?: Record, options | --- | --- | --- | | endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | | clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | +| options | LegacyCallAPIOptions | Options that affect the way we call the API and process the result. | Returns: diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md new file mode 100644 index 0000000000000..f3d8a69b8ed05 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) + +## LegacyScopedClusterClient class + + +Signature: + +```typescript +export declare class LegacyScopedClusterClient implements ILegacyScopedClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md) | | Constructs a new instance of the LegacyScopedClusterClient class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | +| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 74422c82fc9ea..f73595ea0a8ff 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -17,18 +17,18 @@ The plugin integrates with the core system via lifecycle events: `setup` | Class | Description | | --- | --- | | [BasePath](./kibana-plugin-core-server.basepath.md) | Access or manipulate the Kibana base path | -| [ClusterClient](./kibana-plugin-core-server.clusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | | [CspConfig](./kibana-plugin-core-server.cspconfig.md) | CSP configuration for use in Kibana. | | [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) | Wrapper of config schema. | -| [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | | [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | +| [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) | | +| [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | +| [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) | | | [RouteValidationError](./kibana-plugin-core-server.routevalidationerror.md) | Error to return when the validation is not successful. | | [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) | | | [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | | | [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | | [SavedObjectsSerializer](./kibana-plugin-core-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-core-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) documents to the other kind. | | [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) | Registry holding information about all the registered [saved object types](./kibana-plugin-core-server.savedobjectstype.md). | -| [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | ## Enumerations @@ -54,7 +54,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | Interface | Description | | --- | --- | -| [APICaller](./kibana-plugin-core-server.apicaller.md) | | | [AssistanceAPIResponse](./kibana-plugin-core-server.assistanceapiresponse.md) | | | [AssistantAPIClientParams](./kibana-plugin-core-server.assistantapiclientparams.md) | | | [Authenticated](./kibana-plugin-core-server.authenticated.md) | | @@ -63,7 +62,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AuthRedirectedParams](./kibana-plugin-core-server.authredirectedparams.md) | Result of auth redirection. | | [AuthResultParams](./kibana-plugin-core-server.authresultparams.md) | Result of successful authentication. | | [AuthToolkit](./kibana-plugin-core-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | -| [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | | [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). | @@ -78,7 +76,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | | [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | | [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | -| [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) | | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | | [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | | @@ -104,6 +101,9 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) | Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. | | [KibanaRequestEvents](./kibana-plugin-core-server.kibanarequestevents.md) | Request events. | | [KibanaRequestRoute](./kibana-plugin-core-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | +| [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md) | | +| [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) | The set of options that defines how API call should be made and result be processed. | +| [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) | | | [LegacyRequest](./kibana-plugin-core-server.legacyrequest.md) | | | [LegacyServiceSetupDeps](./kibana-plugin-core-server.legacyservicesetupdeps.md) | | | [LegacyServiceStartDeps](./kibana-plugin-core-server.legacyservicestartdeps.md) | | @@ -128,7 +128,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [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. | | [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | -| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | +| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | | [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. | | [RouteConfigOptions](./kibana-plugin-core-server.routeconfigoptions.md) | Additional route options. | | [RouteConfigOptionsBody](./kibana-plugin-core-server.routeconfigoptionsbody.md) | Additional body options for a route | @@ -222,7 +222,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [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. | -| [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.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. | @@ -234,16 +233,17 @@ The plugin integrates with the core system via lifecycle events: `setup` | [HttpResourcesResponseOptions](./kibana-plugin-core-server.httpresourcesresponseoptions.md) | HTTP Resources response parameters | | [HttpResponsePayload](./kibana-plugin-core-server.httpresponsepayload.md) | Data send to the client as a response payload. | | [IBasePath](./kibana-plugin-core-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-core-server.basepath.md) | -| [IClusterClient](./kibana-plugin-core-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | | [IContextProvider](./kibana-plugin-core-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | -| [ICustomClusterClient](./kibana-plugin-core-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | +| [ILegacyClusterClient](./kibana-plugin-core-server.ilegacyclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). | +| [ILegacyCustomClusterClient](./kibana-plugin-core-server.ilegacycustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). | +| [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md). | | [IsAuthenticated](./kibana-plugin-core-server.isauthenticated.md) | Returns authentication status for a request. | | [ISavedObjectsRepository](./kibana-plugin-core-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | [ISavedObjectTypeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) | See [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) for documentation. | -| [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | | [KibanaRequestRouteOptions](./kibana-plugin-core-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | | [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | | [KnownHeaders](./kibana-plugin-core-server.knownheaders.md) | Set of well-known HTTP headers. | +| [LegacyElasticsearchClientConfig](./kibana-plugin-core-server.legacyelasticsearchclientconfig.md) | | | [LifecycleResponseFactory](./kibana-plugin-core-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | | [LoggerConfigType](./kibana-plugin-core-server.loggerconfigtype.md) | | | [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-core-server.migration_assistance_index_action.md) | | @@ -257,7 +257,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginName](./kibana-plugin-core-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | | [PluginOpaqueId](./kibana-plugin-core-server.pluginopaqueid.md) | | | [PublicUiSettingsParams](./kibana-plugin-core-server.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) | | | [RedirectResponseOptions](./kibana-plugin-core-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | | [RequestHandler](./kibana-plugin-core-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) functions. | | [RequestHandlerContextContainer](./kibana-plugin-core-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | diff --git a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md b/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md deleted file mode 100644 index bc9cd4680b17d..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md index 7b887d6d421e4..b09fb121b8a63 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md @@ -14,7 +14,7 @@ core: { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md index 99be0676bcda3..55d6e931ac158 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md @@ -6,7 +6,7 @@ Plugin specific context passed to a route handler. -Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request +Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request Signature: @@ -18,5 +18,5 @@ export interface RequestHandlerContext | Property | Type | Description | | --- | --- | --- | -| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
};
elasticsearch: {
legacy: {
client: IScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | +| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
};
elasticsearch: {
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md deleted file mode 100644 index d4d1d442a57f9..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [(constructor)](./kibana-plugin-core-server.scopedclusterclient._constructor_.md) - -## ScopedClusterClient.(constructor) - -Constructs a new instance of the `ScopedClusterClient` class - -Signature: - -```typescript -constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| internalAPICaller | APICaller | | -| scopedAPICaller | APICaller | | -| headers | Headers | undefined | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md deleted file mode 100644 index 058d65b587dbe..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md +++ /dev/null @@ -1,29 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) - -## ScopedClusterClient class - -Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. - -See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). - -Signature: - -```typescript -export declare class ScopedClusterClient implements IScopedClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-core-server.scopedclusterclient._constructor_.md) | | Constructs a new instance of the ScopedClusterClient class | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-core-server.apicaller.md). | -| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). | - 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 85eb4825bc2e3..a25f4a0c373b2 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/server/kibana-plugin-plugins-data-server.gettime.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md new file mode 100644 index 0000000000000..54e7cf92f500c --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getTime](./kibana-plugin-plugins-data-server.gettime.md) + +## getTime() function + +Signature: + +```typescript +export declare function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPattern | IIndexPattern | undefined | | +| timeRange | TimeRange | | +| options | {
forceNow?: Date;
fieldName?: string;
} | | + +Returns: + +`import("../..").RangeFilter | undefined` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md index f9bbcc5a356e1..d36ebd0745e8d 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md @@ -9,12 +9,12 @@ Constructs a new instance of the `IndexPatternsFetcher` class Signature: ```typescript -constructor(callDataCluster: APICaller); +constructor(callDataCluster: LegacyAPICaller); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| callDataCluster | APICaller | | +| callDataCluster | LegacyAPICaller | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index f492ba2843a69..c80112fb17dde 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -23,6 +23,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | diff --git a/package.json b/package.json index b1202631a0c02..c225435b4e4ff 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "resolutions": { "**/@types/node": ">=10.17.17 <10.20.0", "**/@types/react": "^16.9.36", - "**/@types/react-router": "^5.1.3", "**/@types/hapi": "^17.0.18", "**/@types/angular": "^1.6.56", "**/@types/hoist-non-react-statics": "^3.3.1", @@ -202,6 +201,7 @@ "inline-style": "^2.0.0", "joi": "^13.5.2", "jquery": "^3.5.0", + "js-levenshtein": "^1.1.6", "js-yaml": "3.13.1", "json-stable-stringify": "^1.0.1", "json-stringify-pretty-compact": "1.2.0", @@ -245,8 +245,8 @@ "react-monaco-editor": "~0.27.0", "react-redux": "^7.2.0", "react-resize-detector": "^4.2.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "react-sizeme": "^2.3.6", "react-use": "^13.27.0", "reactcss": "1.2.3", @@ -377,8 +377,8 @@ "@types/react-grid-layout": "^0.16.7", "@types/react-redux": "^7.1.9", "@types/react-resize-detector": "^4.0.1", - "@types/react-router": "^5.1.3", - "@types/react-router-dom": "^5.1.3", + "@types/react-router": "^5.1.7", + "@types/react-router-dom": "^5.1.5", "@types/react-virtualized": "^9.18.7", "@types/recompose": "^0.30.6", "@types/redux-actions": "^2.6.1", diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 88e84fc87ae53..aaa46ab74714f 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -38,6 +38,7 @@ export const ReactDomServer = require('react-dom/server'); export const ReactIntl = require('react-intl'); export const ReactRouter = require('react-router'); // eslint-disable-line export const ReactRouterDom = require('react-router-dom'); +export const StyledComponents = require('styled-components'); Moment.tz.load(require('moment-timezone/data/packed/latest.json')); diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index 301d176555847..596c31820e80d 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -42,6 +42,7 @@ exports.externals = { 'react-intl': '__kbnSharedDeps__.ReactIntl', 'react-router': '__kbnSharedDeps__.ReactRouter', 'react-router-dom': '__kbnSharedDeps__.ReactRouterDom', + 'styled-components': '__kbnSharedDeps__.StyledComponents', '@kbn/monaco': '__kbnSharedDeps__.KbnMonaco', // this is how plugins/consumers from npm load monaco 'monaco-editor/esm/vs/editor/editor.api': '__kbnSharedDeps__.MonacoBarePluginApi', diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 1cc04afad5669..0e3bb235c3d9f 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -26,20 +26,22 @@ "react": "^16.12.0", "react-dom": "^16.12.0", "react-intl": "^2.8.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", + "react-is": "^16.8.0", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "regenerator-runtime": "^0.13.3", "rxjs": "^6.5.5", + "styled-components": "^5.1.0", "symbol-observable": "^1.2.0", "whatwg-fetch": "^3.0.0" }, "devDependencies": { "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", - "loader-utils": "^1.2.3", - "val-loader": "^1.1.1", "css-loader": "^3.4.2", "del": "^5.1.0", + "loader-utils": "^1.2.3", + "val-loader": "^1.1.1", "webpack": "^4.41.5" } } diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 9a8a81460f410..6ccfeb8ab052c 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -61,7 +61,8 @@ export type Ensure = T extends X ? T : never; // If we define this inside RecursiveReadonly TypeScript complains. // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} +export interface RecursiveReadonlyArray extends ReadonlyArray> {} + export type RecursiveReadonly = T extends (...args: any) => any ? T : T extends any[] diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index db8821ac3fc16..6db6199b391e1 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -269,8 +269,8 @@ export class ClusterManager { fromRoot('x-pack/plugins/case/server/scripts'), fromRoot('x-pack/plugins/lists/scripts'), fromRoot('x-pack/plugins/lists/server/scripts'), - fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'), fromRoot('x-pack/plugins/security_solution/scripts'), + fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'), 'plugins/java_languageserver', ]; diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index dfbb449b4d58e..286a93fdc2398 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -48,7 +48,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); @@ -59,7 +59,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); }); diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index d602422c14634..7304a8e5a66bc 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -16,9 +16,10 @@ * specific language governing permissions and limitations * under the License. */ +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 6926b6acf2411..0fe97431b1569 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -19,6 +19,7 @@ import { Observable } from 'rxjs'; import { History } from 'history'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from './capabilities'; import { ChromeStart } from '../chrome'; @@ -30,7 +31,6 @@ import { NotificationsStart } from '../notifications'; import { OverlayStart } from '../overlays'; import { PluginOpaqueId } from '../plugins'; import { IUiSettingsClient } from '../ui_settings'; -import { RecursiveReadonly } from '../../utils'; import { SavedObjectsStart } from '../saved_objects'; import { AppCategory } from '../../types'; import { ScopedHistory } from './scoped_history'; @@ -269,6 +269,10 @@ export interface LegacyApp extends AppBase { */ export type PublicAppInfo = Omit & { legacy: false; + // remove optional on fields populated with default values + status: AppStatus; + navLinkStatus: AppNavLinkStatus; + appRoute: string; }; /** @@ -278,6 +282,9 @@ export type PublicAppInfo = Omit & { */ export type PublicLegacyAppInfo = Omit & { legacy: true; + // remove optional on fields populated with default values + status: AppStatus; + navLinkStatus: AppNavLinkStatus; }; /** diff --git a/src/core/public/application/utils.ts b/src/core/public/application/utils.ts index 1dc9ec7059001..92d25fa468c4a 100644 --- a/src/core/public/application/utils.ts +++ b/src/core/public/application/utils.ts @@ -120,12 +120,17 @@ export function getAppInfo(app: App | LegacyApp): PublicAppInfo | Publi const { updater$, ...infos } = app; return { ...infos, + status: app.status!, + navLinkStatus: app.navLinkStatus!, legacy: true, }; } else { const { updater$, mount, ...infos } = app; return { ...infos, + status: app.status!, + navLinkStatus: app.navLinkStatus!, + appRoute: app.appRoute!, legacy: false, }; } diff --git a/src/core/public/chrome/recently_accessed/persisted_log.test.ts b/src/core/public/chrome/recently_accessed/persisted_log.test.ts index 9b307a2d25faf..4229efdf7ca9d 100644 --- a/src/core/public/chrome/recently_accessed/persisted_log.test.ts +++ b/src/core/public/chrome/recently_accessed/persisted_log.test.ts @@ -59,7 +59,7 @@ describe('PersistedLog', () => { describe('internal functionality', () => { test('reads from storage', () => { - // @ts-ignore + // @ts-expect-error const log = new PersistedLog(historyName, { maxLength: 10 }, storage); expect(storage.getItem).toHaveBeenCalledTimes(1); diff --git a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts index 3c9713a93144a..14c3c581f9f17 100644 --- a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts +++ b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts @@ -55,11 +55,11 @@ describe('RecentlyAccessed#start()', () => { let originalLocalStorage: Storage; beforeAll(() => { originalLocalStorage = window.localStorage; - // @ts-ignore + // @ts-expect-error window.localStorage = new LocalStorageMock(); }); beforeEach(() => localStorage.clear()); - // @ts-ignore + // @ts-expect-error afterAll(() => (window.localStorage = originalLocalStorage)); const getStart = async () => { diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx index 1023a561a0fe3..6d2938e3345a6 100644 --- a/src/core/public/chrome/ui/header/header_help_menu.tsx +++ b/src/core/public/chrome/ui/header/header_help_menu.tsx @@ -312,7 +312,6 @@ class HeaderHelpMenuUI extends Component { ); return ( - // @ts-ignore repositionOnScroll doesn't exist in EuiPopover { fetchMock.get('*', {}); await expect( fetchInstance.fetch( - // @ts-ignore + // @ts-expect-error { path: '/', headers: { hello: 'world' } }, { headers: { hello: 'mars' } } ) diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts index 78220af9cc83b..0afea5aaa506a 100644 --- a/src/core/public/http/http_service.test.ts +++ b/src/core/public/http/http_service.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import { loadingServiceMock } from './http_service.test.mocks'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 41af0f1b8395f..3e4e70fb99508 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -81,7 +81,6 @@ import { export { CoreContext, CoreSystem } from './core_system'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, diff --git a/src/core/public/injected_metadata/injected_metadata_service.test.ts b/src/core/public/injected_metadata/injected_metadata_service.test.ts index cf4b72114d5ac..1a8b4d14ee249 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.test.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.test.ts @@ -58,7 +58,6 @@ describe('setup.getCspConfig()', () => { const csp = injectedMetadata.setup().getCspConfig(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible csp.warnLegacyBrowsers = false; }).toThrowError(); }); @@ -100,11 +99,11 @@ describe('setup.getPlugins()', () => { plugins.push({ id: 'new-plugin', plugin: {} as DiscoveredPlugin }); }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].name = 'changed'; }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].newProp = 'changed'; }).toThrowError(); }); @@ -136,7 +135,7 @@ describe('setup.getLegacyMetadata()', () => { foo: true, }); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible legacyMetadata.foo = false; }).toThrowError(); }); diff --git a/src/core/public/integrations/styles/styles_service.ts b/src/core/public/integrations/styles/styles_service.ts index 41fc861d6cb39..d1d7f2170fde3 100644 --- a/src/core/public/integrations/styles/styles_service.ts +++ b/src/core/public/integrations/styles/styles_service.ts @@ -21,7 +21,7 @@ import { Subscription } from 'rxjs'; import { IUiSettingsClient } from '../../ui_settings'; import { CoreService } from '../../../types'; -// @ts-ignore +// @ts-expect-error import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; interface StartDeps { diff --git a/src/core/public/kbn_bootstrap.ts b/src/core/public/kbn_bootstrap.ts index 0f86061816701..a108b5aaa47ec 100644 --- a/src/core/public/kbn_bootstrap.ts +++ b/src/core/public/kbn_bootstrap.ts @@ -42,7 +42,6 @@ export function __kbnBootstrap__() { const APM_ENABLED = process.env.IS_KIBANA_DISTRIBUTABLE !== 'true' && apmConfig != null; if (APM_ENABLED) { - // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-var-requires const { init, apm } = require('@elastic/apm-rum'); if (apmConfig.globalLabels) { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index d10e351f4d13e..86e281a49b744 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -116,6 +116,7 @@ import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/ser import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import React from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -1143,23 +1144,21 @@ export type PluginOpaqueId = symbol; // @public export type PublicAppInfo = Omit & { legacy: false; + status: AppStatus; + navLinkStatus: AppNavLinkStatus; + appRoute: string; }; // @public export type PublicLegacyAppInfo = Omit & { legacy: true; + status: AppStatus; + navLinkStatus: AppNavLinkStatus; }; // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index 0c34a16c68e99..20824af38af0f 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -432,7 +432,7 @@ describe('SavedObjectsClient', () => { sortOrder: 'sort', // Not currently supported by API }; - // @ts-ignore + // @ts-expect-error savedObjectsClient.find(options); expect(http.fetch.mock.calls).toMatchInlineSnapshot(` Array [ diff --git a/src/core/public/ui_settings/ui_settings_api.test.ts b/src/core/public/ui_settings/ui_settings_api.test.ts index bab7081509d53..14791407d2550 100644 --- a/src/core/public/ui_settings/ui_settings_api.test.ts +++ b/src/core/public/ui_settings/ui_settings_api.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import * as Rx from 'rxjs'; import { takeUntil, toArray } from 'rxjs/operators'; diff --git a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap b/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap deleted file mode 100644 index 75627f311d9a5..0000000000000 --- a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`#username throws if equal to "elastic", only while running from source 1`] = `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana_system\\" user instead."`; diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index ccd5fd0c7a571..648eaaf8a97f2 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -367,6 +367,8 @@ test('#username throws if equal to "elastic", only while running from source', ( const obj = { username: 'elastic', }; - expect(() => config.schema.validate(obj, { dist: false })).toThrowErrorMatchingSnapshot(); + expect(() => config.schema.validate(obj, { dist: false })).toThrowErrorMatchingInlineSnapshot( + `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana_system\\" user instead."` + ); expect(() => config.schema.validate(obj, { dist: true })).not.toThrow(); }); diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index 55e60f5987604..fdfc48fa9f754 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -19,26 +19,29 @@ import { BehaviorSubject } from 'rxjs'; import { Client } from 'elasticsearch'; -import { IClusterClient, ICustomClusterClient } from './cluster_client'; -import { IScopedClusterClient } from './scoped_cluster_client'; +import { + ILegacyClusterClient, + ILegacyCustomClusterClient, + ILegacyScopedClusterClient, +} from './legacy'; import { ElasticsearchConfig } from './elasticsearch_config'; import { ElasticsearchService } from './elasticsearch_service'; import { InternalElasticsearchServiceSetup, ElasticsearchStatusMeta } from './types'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus, ServiceStatusLevels } from '../status'; -const createScopedClusterClientMock = (): jest.Mocked => ({ +const createScopedClusterClientMock = (): jest.Mocked => ({ callAsInternalUser: jest.fn(), callAsCurrentUser: jest.fn(), }); -const createCustomClusterClientMock = (): jest.Mocked => ({ +const createCustomClusterClientMock = (): jest.Mocked => ({ ...createClusterClientMock(), close: jest.fn(), }); function createClusterClientMock() { - const client: jest.Mocked = { + const client: jest.Mocked = { callAsInternalUser: jest.fn(), asScoped: jest.fn(), }; @@ -48,8 +51,8 @@ function createClusterClientMock() { interface MockedElasticSearchServiceSetup { legacy: { - createClient: jest.Mock; - client: jest.Mocked; + createClient: jest.Mock; + client: jest.Mocked; }; } @@ -81,7 +84,7 @@ const createStartContractMock = () => { type MockedInternalElasticSearchServiceSetup = jest.Mocked< InternalElasticsearchServiceSetup & { - legacy: { client: jest.Mocked }; + legacy: { client: jest.Mocked }; } >; const createInternalSetupContractMock = () => { diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts index e87913a3c5e4f..c30230a7847a0 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts @@ -18,4 +18,4 @@ */ export const MockClusterClient = jest.fn(); -jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); +jest.mock('./legacy/cluster_client', () => ({ LegacyClusterClient: MockClusterClient })); diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 26001bf83924f..f47b33dd410f6 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -34,23 +34,26 @@ import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { - ClusterClient, - ScopeableRequest, - IClusterClient, - ICustomClusterClient, -} from './cluster_client'; -import { ElasticsearchClientConfig } from './elasticsearch_client_config'; + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, + LegacyElasticsearchClientConfig, + LegacyCallAPIOptions, +} from './legacy'; import { ElasticsearchConfig, ElasticsearchConfigType } from './elasticsearch_config'; import { InternalHttpServiceSetup, GetAuthHeaders } from '../http/'; -import { InternalElasticsearchServiceSetup, ElasticsearchServiceStart } from './types'; -import { CallAPIOptions } from './api_types'; +import { + InternalElasticsearchServiceSetup, + ElasticsearchServiceStart, + ScopeableRequest, +} from './types'; import { pollEsNodesVersion } from './version_check/ensure_es_version'; import { calculateStatus$ } from './status'; /** @internal */ interface CoreClusterClients { config: ElasticsearchConfig; - client: ClusterClient; + client: LegacyClusterClient; } interface SetupDeps { @@ -67,9 +70,9 @@ export class ElasticsearchService private kibanaVersion: string; private createClient?: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; - private client?: IClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; + private client?: ILegacyClusterClient; constructor(private readonly coreContext: CoreContext) { this.kibanaVersion = coreContext.env.packageInfo.version; @@ -123,7 +126,7 @@ export class ElasticsearchService async callAsInternalUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const _client = await client$.pipe(take(1)).toPromise(); return await _client.callAsInternalUser(endpoint, clientParams, options); @@ -134,7 +137,7 @@ export class ElasticsearchService async callAsCurrentUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const _client = await client$.pipe(take(1)).toPromise(); return await _client @@ -155,7 +158,10 @@ export class ElasticsearchService kibanaVersion: this.kibanaVersion, }).pipe(takeUntil(this.stop$), shareReplay({ refCount: true, bufferSize: 1 })); - this.createClient = (type: string, clientConfig: Partial = {}) => { + this.createClient = ( + type: string, + clientConfig: Partial = {} + ) => { const finalConfig = merge({}, config, clientConfig); return this.createClusterClient(type, finalConfig, deps.http.getAuthHeaders); }; @@ -193,10 +199,10 @@ export class ElasticsearchService private createClusterClient( type: string, - config: ElasticsearchClientConfig, + config: LegacyElasticsearchClientConfig, getAuthHeaders?: GetAuthHeaders ) { - return new ClusterClient( + return new LegacyClusterClient( config, this.coreContext.logger.get('elasticsearch', type), getAuthHeaders diff --git a/src/core/server/elasticsearch/index.ts b/src/core/server/elasticsearch/index.ts index 2e45f710c4dcf..f5f5f5cc7b6f8 100644 --- a/src/core/server/elasticsearch/index.ts +++ b/src/core/server/elasticsearch/index.ts @@ -18,17 +18,14 @@ */ export { ElasticsearchService } from './elasticsearch_service'; +export { config, configSchema, ElasticsearchConfig } from './elasticsearch_config'; +export { NodesVersionCompatibility } from './version_check/ensure_es_version'; export { - ClusterClient, + ElasticsearchServiceSetup, + ElasticsearchServiceStart, + ElasticsearchStatusMeta, + InternalElasticsearchServiceSetup, FakeRequest, - IClusterClient, - ICustomClusterClient, ScopeableRequest, -} from './cluster_client'; -export { IScopedClusterClient, ScopedClusterClient, Headers } from './scoped_cluster_client'; -export { ElasticsearchClientConfig } from './elasticsearch_client_config'; -export { config, configSchema, ElasticsearchConfig } from './elasticsearch_config'; -export { ElasticsearchError, ElasticsearchErrorHelpers } from './errors'; -export * from './api_types'; -export * from './types'; -export { NodesVersionCompatibility } from './version_check/ensure_es_version'; +} from './types'; +export * from './legacy'; diff --git a/src/core/server/elasticsearch/api_types.ts b/src/core/server/elasticsearch/legacy/api_types.ts similarity index 54% rename from src/core/server/elasticsearch/api_types.ts rename to src/core/server/elasticsearch/legacy/api_types.ts index 5f2b61eb4935f..b9699ab290e3f 100644 --- a/src/core/server/elasticsearch/api_types.ts +++ b/src/core/server/elasticsearch/legacy/api_types.ts @@ -151,7 +151,7 @@ import { * * @public */ -export interface CallAPIOptions { +export interface LegacyCallAPIOptions { /** * Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API * should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` @@ -166,154 +166,154 @@ export interface CallAPIOptions { } /** @public */ -export interface APICaller { +export interface LegacyAPICaller { /* eslint-disable */ - (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'clearScroll', params: ClearScrollParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'count', params: CountParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'create', params: CreateDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'delete', params: DeleteDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteScript', params: DeleteScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'exists', params: ExistsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'explain', params: ExplainParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'fieldStats', params: FieldStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'clearScroll', params: ClearScrollParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'count', params: CountParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'create', params: CreateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'delete', params: DeleteDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteScript', params: DeleteScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'exists', params: ExistsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'explain', params: ExplainParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'fieldStats', params: FieldStatsParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'get', params: GetParams, options?: CallAPIOptions): Promise>; - (endpoint: 'getScript', params: GetScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'getSource', params: GetSourceParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'getTemplate', params: GetTemplateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'get', params: GetParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'getScript', params: GetScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'getSource', params: GetSourceParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'getTemplate', params: GetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'index', params: IndexDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'info', params: InfoParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'index', params: IndexDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'info', params: InfoParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'mget', params: MGetParams, options?: CallAPIOptions): Promise>; - (endpoint: 'msearch', params: MSearchParams, options?: CallAPIOptions): Promise>; - (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: CallAPIOptions): Promise>; - (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ping', params: PingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'putScript', params: PutScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'putTemplate', params: PutTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'reindex', params: ReindexParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'mget', params: MGetParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'msearch', params: MSearchParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ping', params: PingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'putScript', params: PutScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'putTemplate', params: PutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'reindex', params: ReindexParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'scroll', params: ScrollParams, options?: CallAPIOptions): Promise>; - (endpoint: 'search', params: SearchParams, options?: CallAPIOptions): Promise>; - (endpoint: 'searchShards', params: SearchShardsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'suggest', params: SuggestParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'termvectors', params: TermvectorsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'update', params: UpdateDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'scroll', params: ScrollParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'search', params: SearchParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'searchShards', params: SearchShardsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'suggest', params: SuggestParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'termvectors', params: TermvectorsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'update', params: UpdateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; // cat namespace - (endpoint: 'cat.aliases', params: CatAliasesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.allocation', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.count', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.health', params: CatHealthParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.help', params: CatHelpParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.indices', params: CatIndicesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.master', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.nodes', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.plugins', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.repositories', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.segments', params: CatSegmentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.shards', params: CatShardsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.tasks', params: CatTasksParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'cat.aliases', params: CatAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.allocation', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.count', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.health', params: CatHealthParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.help', params: CatHelpParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.indices', params: CatIndicesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.master', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.nodes', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.plugins', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.repositories', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.segments', params: CatSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.shards', params: CatShardsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.tasks', params: CatTasksParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: LegacyCallAPIOptions): ReturnType; // cluster namespace - (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.health', params: ClusterHealthParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.state', params: ClusterStateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.health', params: ClusterHealthParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.state', params: ClusterStateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: LegacyCallAPIOptions): ReturnType; // indices namespace - (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.close', params: IndicesCloseParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.create', params: IndicesCreateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.exists', params: IndicesExistsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.flush', params: IndicesFlushParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.get', params: IndicesGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.open', params: IndicesOpenParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.stats', params: IndicesStatsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.close', params: IndicesCloseParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.create', params: IndicesCreateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.exists', params: IndicesExistsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.flush', params: IndicesFlushParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.get', params: IndicesGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.open', params: IndicesOpenParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.stats', params: IndicesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: LegacyCallAPIOptions): ReturnType; // ingest namepsace - (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: LegacyCallAPIOptions): ReturnType; // nodes namespace - (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'nodes.info', params: NodesInfoParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'nodes.stats', params: NodesStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'nodes.info', params: NodesInfoParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'nodes.stats', params: NodesStatsParams, options?: LegacyCallAPIOptions): ReturnType; // snapshot namespace - (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; // tasks namespace - (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'tasks.get', params: TasksGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'tasks.list', params: TasksListParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'tasks.get', params: TasksGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'tasks.list', params: TasksListParams, options?: LegacyCallAPIOptions): ReturnType; // other APIs accessed via transport.request - (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: CallAPIOptions): Promise< + (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: LegacyCallAPIOptions): Promise< AssistanceAPIResponse >; - (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: CallAPIOptions): Promise< + (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: LegacyCallAPIOptions): Promise< DeprecationAPIResponse >; // Catch-all definition - (endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; + (endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; /* eslint-enable */ } diff --git a/src/core/server/elasticsearch/cluster_client.test.mocks.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts similarity index 95% rename from src/core/server/elasticsearch/cluster_client.test.mocks.ts rename to src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts index 6873117aecc35..08585c2305e9b 100644 --- a/src/core/server/elasticsearch/cluster_client.test.mocks.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts @@ -29,7 +29,7 @@ jest.mock('elasticsearch', () => { export const MockScopedClusterClient = jest.fn(); jest.mock('./scoped_cluster_client', () => ({ - ScopedClusterClient: MockScopedClusterClient, + LegacyScopedClusterClient: MockScopedClusterClient, })); export const mockParseElasticsearchClientConfig = jest.fn(); diff --git a/src/core/server/elasticsearch/cluster_client.test.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.ts similarity index 91% rename from src/core/server/elasticsearch/cluster_client.test.ts rename to src/core/server/elasticsearch/legacy/cluster_client.test.ts index 820272bdf14b8..9ab4862a1ab4c 100644 --- a/src/core/server/elasticsearch/cluster_client.test.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { ElasticsearchConfig } from './elasticsearch_config'; +import { ElasticsearchConfig } from '../elasticsearch_config'; import { MockClient, @@ -27,10 +27,10 @@ import { import { errors } from 'elasticsearch'; import { get } from 'lodash'; -import { Logger } from '../logging'; -import { loggingSystemMock } from '../logging/logging_system.mock'; -import { httpServerMock } from '../http/http_server.mocks'; -import { ClusterClient } from './cluster_client'; +import { Logger } from '../../logging'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; +import { httpServerMock } from '../../http/http_server.mocks'; +import { LegacyClusterClient } from './cluster_client'; const logger = loggingSystemMock.create(); afterEach(() => jest.clearAllMocks()); @@ -42,7 +42,7 @@ test('#constructor creates client with parsed config', () => { const mockEsConfig = { apiVersion: 'es-version' } as any; const mockLogger = logger.get(); - const clusterClient = new ClusterClient(mockEsConfig, mockLogger); + const clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); expect(clusterClient).toBeDefined(); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); @@ -58,7 +58,7 @@ describe('#callAsInternalUser', () => { ping: jest.Mock; security: { authenticate: jest.Mock }; }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; beforeEach(() => { mockEsClientInstance = { @@ -68,7 +68,7 @@ describe('#callAsInternalUser', () => { }; MockClient.mockImplementation(() => mockEsClientInstance); - clusterClient = new ClusterClient({ apiVersion: 'es-version' } as any, logger.get()); + clusterClient = new LegacyClusterClient({ apiVersion: 'es-version' } as any, logger.get()); }); test('fails if cluster client is closed', async () => { @@ -220,7 +220,7 @@ describe('#asScoped', () => { let mockEsClientInstance: { ping: jest.Mock; close: jest.Mock }; let mockScopedEsClientInstance: { ping: jest.Mock; close: jest.Mock }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; let mockLogger: Logger; let mockEsConfig: ElasticsearchConfig; @@ -237,7 +237,7 @@ describe('#asScoped', () => { requestHeadersWhitelist: ['one', 'two'], } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); jest.clearAllMocks(); }); @@ -272,7 +272,7 @@ describe('#asScoped', () => { test('properly configures `ignoreCertAndKey` for various configurations', () => { // Config without SSL. - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -285,7 +285,7 @@ describe('#asScoped', () => { // Config ssl.alwaysPresentCertificate === false mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: false } } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -298,7 +298,7 @@ describe('#asScoped', () => { // Config ssl.alwaysPresentCertificate === true mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: true } } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -341,7 +341,7 @@ describe('#asScoped', () => { }); test('does not fail when scope to not defined request', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped(); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -352,7 +352,7 @@ describe('#asScoped', () => { }); test('does not fail when scope to a request without headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped({} as any); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -363,7 +363,10 @@ describe('#asScoped', () => { }); test('calls getAuthHeaders and filters results for a real request', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger, () => ({ one: '1', three: '3' })); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ + one: '1', + three: '3', + })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { two: '2' } })); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -374,7 +377,7 @@ describe('#asScoped', () => { }); test('getAuthHeaders results rewrite extends a request headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger, () => ({ one: 'foo' })); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ one: 'foo' })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1', two: '2' } })); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -386,14 +389,14 @@ describe('#asScoped', () => { test("doesn't call getAuthHeaders for a fake request", async () => { const getAuthHeaders = jest.fn(); - clusterClient = new ClusterClient(mockEsConfig, mockLogger, getAuthHeaders); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, getAuthHeaders); clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } }); expect(getAuthHeaders).not.toHaveBeenCalled(); }); test('filters a fake request headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } }); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); @@ -409,7 +412,7 @@ describe('#close', () => { let mockEsClientInstance: { close: jest.Mock }; let mockScopedEsClientInstance: { close: jest.Mock }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; beforeEach(() => { mockEsClientInstance = { close: jest.fn() }; @@ -418,7 +421,7 @@ describe('#close', () => { () => mockScopedEsClientInstance ); - clusterClient = new ClusterClient( + clusterClient = new LegacyClusterClient( { apiVersion: 'es-version', requestHeadersWhitelist: [] } as any, logger.get() ); diff --git a/src/core/server/elasticsearch/cluster_client.ts b/src/core/server/elasticsearch/legacy/cluster_client.ts similarity index 77% rename from src/core/server/elasticsearch/cluster_client.ts rename to src/core/server/elasticsearch/legacy/cluster_client.ts index 2352677b8d3e0..8e2d20a8972fc 100644 --- a/src/core/server/elasticsearch/cluster_client.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.ts @@ -19,16 +19,17 @@ import { Client } from 'elasticsearch'; import { get } from 'lodash'; -import { ElasticsearchErrorHelpers } from './errors'; -import { GetAuthHeaders, isRealRequest, LegacyRequest } from '../http'; -import { filterHeaders, Headers, KibanaRequest, ensureRawRequest } from '../http/router'; -import { Logger } from '../logging'; +import { LegacyElasticsearchErrorHelpers } from './errors'; +import { GetAuthHeaders, isRealRequest } from '../../http'; +import { filterHeaders, ensureRawRequest } from '../../http/router'; +import { Logger } from '../../logging'; +import { ScopeableRequest } from '../types'; import { - ElasticsearchClientConfig, + LegacyElasticsearchClientConfig, parseElasticsearchClientConfig, } from './elasticsearch_client_config'; -import { ScopedClusterClient, IScopedClusterClient } from './scoped_cluster_client'; -import { CallAPIOptions, APICaller } from './api_types'; +import { LegacyScopedClusterClient, ILegacyScopedClusterClient } from './scoped_cluster_client'; +import { LegacyCallAPIOptions, LegacyAPICaller } from './api_types'; /** * Support Legacy platform request for the period of migration. @@ -50,7 +51,7 @@ const callAPI = async ( client: Client, endpoint: string, clientParams: Record = {}, - options: CallAPIOptions = { wrap401Errors: true } + options: LegacyCallAPIOptions = { wrap401Errors: true } ) => { const clientPath = endpoint.split('.'); const api: any = get(client, clientPath); @@ -75,55 +76,40 @@ const callAPI = async ( throw err; } - throw ElasticsearchErrorHelpers.decorateNotAuthorizedError(err); + throw LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(err); } }; -/** - * Fake request object created manually by Kibana plugins. - * @public - */ -export interface FakeRequest { - /** Headers used for authentication against Elasticsearch */ - headers: Headers; -} - /** * Represents an Elasticsearch cluster API client created by the platform. * It allows to call API on behalf of the internal Kibana user and * the actual user that is derived from the request headers (via `asScoped(...)`). * - * See {@link ClusterClient}. + * See {@link LegacyClusterClient}. * * @public */ -export type IClusterClient = Pick; +export type ILegacyClusterClient = Pick; /** * Represents an Elasticsearch cluster API client created by a plugin. * It allows to call API on behalf of the internal Kibana user and * the actual user that is derived from the request headers (via `asScoped(...)`). * - * See {@link ClusterClient}. - * - * @public - */ -export type ICustomClusterClient = Pick; - -/** - A user credentials container. - * It accommodates the necessary auth credentials to impersonate the current user. + * See {@link LegacyClusterClient}. * * @public - * See {@link KibanaRequest}. */ -export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; +export type ILegacyCustomClusterClient = Pick< + LegacyClusterClient, + 'callAsInternalUser' | 'close' | 'asScoped' +>; /** * {@inheritDoc IClusterClient} * @public */ -export class ClusterClient implements IClusterClient { +export class LegacyClusterClient implements ILegacyClusterClient { /** * Raw Elasticsearch JS client that acts on behalf of the Kibana internal user. */ @@ -141,7 +127,7 @@ export class ClusterClient implements IClusterClient { private isClosed = false; constructor( - private readonly config: ElasticsearchClientConfig, + private readonly config: LegacyElasticsearchClientConfig, private readonly log: Logger, private readonly getAuthHeaders: GetAuthHeaders = noop ) { @@ -151,20 +137,24 @@ export class ClusterClient implements IClusterClient { /** * Calls specified endpoint with provided clientParams on behalf of the * Kibana internal user. - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. * @param options - Options that affect the way we call the API and process the result. */ - public callAsInternalUser: APICaller = async ( + public callAsInternalUser: LegacyAPICaller = async ( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { this.assertIsNotClosed(); - return await (callAPI.bind(null, this.client) as APICaller)(endpoint, clientParams, options); + return await (callAPI.bind(null, this.client) as LegacyAPICaller)( + endpoint, + clientParams, + options + ); }; /** @@ -185,7 +175,7 @@ export class ClusterClient implements IClusterClient { } /** - * Creates an instance of {@link IScopedClusterClient} based on the configuration the + * Creates an instance of {@link ILegacyScopedClusterClient} based on the configuration the * current cluster client that exposes additional `callAsCurrentUser` method * scoped to the provided req. Consumers shouldn't worry about closing * scoped client instances, these will be automatically closed as soon as the @@ -194,7 +184,7 @@ export class ClusterClient implements IClusterClient { * @param request - Request the `IScopedClusterClient` instance will be scoped to. * Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform */ - public asScoped(request?: ScopeableRequest): IScopedClusterClient { + public asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient { // It'd have been quite expensive to create and configure client for every incoming // request since it involves parsing of the config, reading of the SSL certificate and // key files etc. Moreover scoped client needs two Elasticsearch JS clients at the same @@ -210,7 +200,7 @@ export class ClusterClient implements IClusterClient { ); } - return new ScopedClusterClient( + return new LegacyScopedClusterClient( this.callAsInternalUser, this.callAsCurrentUser, filterHeaders(this.getHeaders(request), this.config.requestHeadersWhitelist) @@ -220,20 +210,20 @@ export class ClusterClient implements IClusterClient { /** * Calls specified endpoint with provided clientParams on behalf of the * user initiated request to the Kibana server (via HTTP request headers). - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. * @param options - Options that affect the way we call the API and process the result. */ - private callAsCurrentUser: APICaller = async ( + private callAsCurrentUser: LegacyAPICaller = async ( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { this.assertIsNotClosed(); - return await (callAPI.bind(null, this.scopedClient!) as APICaller)( + return await (callAPI.bind(null, this.scopedClient!) as LegacyAPICaller)( endpoint, clientParams, options @@ -246,9 +236,7 @@ export class ClusterClient implements IClusterClient { } } - private getHeaders( - request?: KibanaRequest | LegacyRequest | FakeRequest - ): Record { + private getHeaders(request?: ScopeableRequest): Record { if (!isRealRequest(request)) { return request && request.headers ? request.headers : {}; } diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts similarity index 98% rename from src/core/server/elasticsearch/elasticsearch_client_config.test.ts rename to src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts index 77d1e41c9ad83..d6b65da7726d2 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts @@ -18,9 +18,9 @@ */ import { duration } from 'moment'; -import { loggingSystemMock } from '../logging/logging_system.mock'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; import { - ElasticsearchClientConfig, + LegacyElasticsearchClientConfig, parseElasticsearchClientConfig, } from './elasticsearch_client_config'; const logger = loggingSystemMock.create(); @@ -64,7 +64,7 @@ Object { }); test('parses fully specified config', () => { - const elasticsearchConfig: ElasticsearchClientConfig = { + const elasticsearchConfig: LegacyElasticsearchClientConfig = { apiVersion: 'v7.0.0', customHeaders: { xsrf: 'something' }, logQueries: true, diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts similarity index 93% rename from src/core/server/elasticsearch/elasticsearch_client_config.ts rename to src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 287d835c40351..260a60ac74f11 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -22,9 +22,9 @@ import { cloneDeep } from 'lodash'; import { Duration } from 'moment'; import { checkServerIdentity } from 'tls'; import url from 'url'; -import { pick } from '../../utils'; -import { Logger } from '../logging'; -import { ElasticsearchConfig } from './elasticsearch_config'; +import { pick } from '../../../utils'; +import { Logger } from '../../logging'; +import { ElasticsearchConfig } from '../elasticsearch_config'; /** * @privateRemarks Config that consumers can pass to the Elasticsearch JS client is complex and includes @@ -33,7 +33,7 @@ import { ElasticsearchConfig } from './elasticsearch_config'; * * @public */ -export type ElasticsearchClientConfig = Pick & +export type LegacyElasticsearchClientConfig = Pick & Pick< ElasticsearchConfig, | 'apiVersion' @@ -53,7 +53,7 @@ export type ElasticsearchClientConfig = Pick { describe('NotAuthorized error', () => { describe('decorateNotAuthorizedError', () => { it('returns original object', () => { const error = new Error(); - expect(ElasticsearchErrorHelpers.decorateNotAuthorizedError(error)).toBe(error); + expect(LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error)).toBe(error); }); it('makes the error identifiable as a NotAuthorized error', () => { const error = new Error(); - expect(ElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(false); - ElasticsearchErrorHelpers.decorateNotAuthorizedError(error); - expect(ElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(true); + expect(LegacyElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(false); + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error); + expect(LegacyElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(true); }); it('adds boom properties', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); expect(typeof error.output).toBe('object'); expect(error.output.statusCode).toBe(401); }); it('preserves boom properties of input', () => { const error = Boom.notFound(); - ElasticsearchErrorHelpers.decorateNotAuthorizedError(error); + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error); expect(error.output.statusCode).toBe(404); }); describe('error.output', () => { it('defaults to message of error', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error('foobar')); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( + new Error('foobar') + ); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); it('prefixes message with passed reason', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new Error('foobar'), 'biz' ); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); it('sets statusCode to 401', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error('foo')); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( + new Error('foo') + ); expect(error.output).toHaveProperty('statusCode', 401); }); }); diff --git a/src/core/server/elasticsearch/errors.ts b/src/core/server/elasticsearch/legacy/errors.ts similarity index 88% rename from src/core/server/elasticsearch/errors.ts rename to src/core/server/elasticsearch/legacy/errors.ts index 6852b8632ebf1..f81903d76547a 100644 --- a/src/core/server/elasticsearch/errors.ts +++ b/src/core/server/elasticsearch/legacy/errors.ts @@ -27,11 +27,11 @@ enum ErrorCode { } /** @public */ -export interface ElasticsearchError extends Boom { +export interface LegacyElasticsearchError extends Boom { [code]?: string; } -function isElasticsearchError(error: any): error is ElasticsearchError { +function isElasticsearchError(error: any): error is LegacyElasticsearchError { return Boolean(error && error[code]); } @@ -40,7 +40,7 @@ function decorate( errorCode: ErrorCode, statusCode: number, message?: string -): ElasticsearchError { +): LegacyElasticsearchError { if (isElasticsearchError(error)) { return error; } @@ -50,7 +50,7 @@ function decorate( message, // keep status and messages if Boom error object already has them override: false, - }) as ElasticsearchError; + }) as LegacyElasticsearchError; boom[code] = errorCode; @@ -74,8 +74,8 @@ function decorate( * } * ``` */ -export class ElasticsearchErrorHelpers { - public static isNotAuthorizedError(error: any): error is ElasticsearchError { +export class LegacyElasticsearchErrorHelpers { + public static isNotAuthorizedError(error: any): error is LegacyElasticsearchError { return isElasticsearchError(error) && error[code] === ErrorCode.NOT_AUTHORIZED; } diff --git a/src/core/server/elasticsearch/legacy/index.ts b/src/core/server/elasticsearch/legacy/index.ts new file mode 100644 index 0000000000000..165980b9f4522 --- /dev/null +++ b/src/core/server/elasticsearch/legacy/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 { + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, +} from './cluster_client'; +export { ILegacyScopedClusterClient, LegacyScopedClusterClient } from './scoped_cluster_client'; +export { LegacyElasticsearchClientConfig } from './elasticsearch_client_config'; +export { retryCallCluster, migrationsRetryCallCluster } from './retry_call_cluster'; +export { LegacyElasticsearchError, LegacyElasticsearchErrorHelpers } from './errors'; +export * from './api_types'; diff --git a/src/core/server/elasticsearch/retry_call_cluster.test.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts similarity index 98% rename from src/core/server/elasticsearch/retry_call_cluster.test.ts rename to src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts index 18ffa95048c4d..62789a4fe952d 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.test.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts @@ -19,7 +19,7 @@ import * as legacyElasticsearch from 'elasticsearch'; import { retryCallCluster, migrationsRetryCallCluster } from './retry_call_cluster'; -import { loggingSystemMock } from '../logging/logging_system.mock'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; describe('retryCallCluster', () => { it('retries ES API calls that rejects with NoConnections', () => { diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts similarity index 87% rename from src/core/server/elasticsearch/retry_call_cluster.ts rename to src/core/server/elasticsearch/legacy/retry_call_cluster.ts index aa3e39d948593..475a76d406017 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts @@ -21,9 +21,9 @@ import { retryWhen, concatMap } from 'rxjs/operators'; import { defer, throwError, iif, timer } from 'rxjs'; import * as legacyElasticsearch from 'elasticsearch'; -import { CallAPIOptions } from '.'; -import { APICaller } from './api_types'; -import { Logger } from '../logging'; +import { LegacyCallAPIOptions } from '.'; +import { LegacyAPICaller } from './api_types'; +import { Logger } from '../../logging'; const esErrors = legacyElasticsearch.errors; @@ -39,12 +39,16 @@ const esErrors = legacyElasticsearch.errors; * @param delay */ export function migrationsRetryCallCluster( - apiCaller: APICaller, + apiCaller: LegacyAPICaller, log: Logger, delay: number = 2500 ) { const previousErrors: string[] = []; - return (endpoint: string, clientParams: Record = {}, options?: CallAPIOptions) => { + return ( + endpoint: string, + clientParams: Record = {}, + options?: LegacyCallAPIOptions + ) => { return defer(() => apiCaller(endpoint, clientParams, options)) .pipe( retryWhen((error$) => @@ -63,7 +67,7 @@ export function migrationsRetryCallCluster( error instanceof esErrors.RequestTimeout || error instanceof esErrors.AuthenticationException || error instanceof esErrors.AuthorizationException || - // @ts-ignore + // @ts-expect-error error instanceof esErrors.Gone || error?.body?.error?.type === 'snapshot_in_progress_exception' ); @@ -86,8 +90,12 @@ export function migrationsRetryCallCluster( * * @param apiCaller */ -export function retryCallCluster(apiCaller: APICaller) { - return (endpoint: string, clientParams: Record = {}, options?: CallAPIOptions) => { +export function retryCallCluster(apiCaller: LegacyAPICaller) { + return ( + endpoint: string, + clientParams: Record = {}, + options?: LegacyCallAPIOptions + ) => { return defer(() => apiCaller(endpoint, clientParams, options)) .pipe( retryWhen((errors) => diff --git a/src/core/server/elasticsearch/scoped_cluster_client.test.ts b/src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts similarity index 95% rename from src/core/server/elasticsearch/scoped_cluster_client.test.ts rename to src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts index 04c13f85a1ef7..2eb8cefb564ae 100644 --- a/src/core/server/elasticsearch/scoped_cluster_client.test.ts +++ b/src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts @@ -17,15 +17,15 @@ * under the License. */ -import { ScopedClusterClient } from './scoped_cluster_client'; +import { LegacyScopedClusterClient } from './scoped_cluster_client'; let internalAPICaller: jest.Mock; let scopedAPICaller: jest.Mock; -let clusterClient: ScopedClusterClient; +let clusterClient: LegacyScopedClusterClient; beforeEach(() => { internalAPICaller = jest.fn(); scopedAPICaller = jest.fn(); - clusterClient = new ScopedClusterClient(internalAPICaller, scopedAPICaller, { one: '1' }); + clusterClient = new LegacyScopedClusterClient(internalAPICaller, scopedAPICaller, { one: '1' }); }); afterEach(() => jest.clearAllMocks()); @@ -184,7 +184,10 @@ describe('#callAsCurrentUser', () => { const mockResponse = { data: 'response' }; scopedAPICaller.mockResolvedValue(mockResponse); - const clusterClientWithoutHeaders = new ScopedClusterClient(internalAPICaller, scopedAPICaller); + const clusterClientWithoutHeaders = new LegacyScopedClusterClient( + internalAPICaller, + scopedAPICaller + ); await expect(clusterClientWithoutHeaders.callAsCurrentUser('ping')).resolves.toBe(mockResponse); expect(scopedAPICaller).toHaveBeenCalledTimes(1); diff --git a/src/core/server/elasticsearch/scoped_cluster_client.ts b/src/core/server/elasticsearch/legacy/scoped_cluster_client.ts similarity index 85% rename from src/core/server/elasticsearch/scoped_cluster_client.ts rename to src/core/server/elasticsearch/legacy/scoped_cluster_client.ts index 4b64bfba15190..e62409ff00c7e 100644 --- a/src/core/server/elasticsearch/scoped_cluster_client.ts +++ b/src/core/server/elasticsearch/legacy/scoped_cluster_client.ts @@ -18,11 +18,8 @@ */ import { intersection, isObject } from 'lodash'; -import { Headers } from '../http/router'; -import { APICaller, CallAPIOptions } from './api_types'; - -/** @public */ -export { Headers }; +import { Headers } from '../../http/router'; +import { LegacyAPICaller, LegacyCallAPIOptions } from './api_types'; /** * Serves the same purpose as "normal" `ClusterClient` but exposes additional @@ -30,12 +27,12 @@ export { Headers }; * user (as `callAsInternalUser` does) to request Elasticsearch API, but rather * passes HTTP headers extracted from the current user request to the API. * - * See {@link ScopedClusterClient}. + * See {@link LegacyScopedClusterClient}. * * @public */ -export type IScopedClusterClient = Pick< - ScopedClusterClient, +export type ILegacyScopedClusterClient = Pick< + LegacyScopedClusterClient, 'callAsCurrentUser' | 'callAsInternalUser' >; @@ -43,10 +40,10 @@ export type IScopedClusterClient = Pick< * {@inheritDoc IScopedClusterClient} * @public */ -export class ScopedClusterClient implements IScopedClusterClient { +export class LegacyScopedClusterClient implements ILegacyScopedClusterClient { constructor( - private readonly internalAPICaller: APICaller, - private readonly scopedAPICaller: APICaller, + private readonly internalAPICaller: LegacyAPICaller, + private readonly scopedAPICaller: LegacyAPICaller, private readonly headers?: Headers ) { this.callAsCurrentUser = this.callAsCurrentUser.bind(this); @@ -56,7 +53,7 @@ export class ScopedClusterClient implements IScopedClusterClient { /** * Calls specified `endpoint` with provided `clientParams` on behalf of the * Kibana internal user. - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. @@ -65,7 +62,7 @@ export class ScopedClusterClient implements IScopedClusterClient { public callAsInternalUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { return this.internalAPICaller(endpoint, clientParams, options); } @@ -73,7 +70,7 @@ export class ScopedClusterClient implements IScopedClusterClient { /** * Calls specified `endpoint` with provided `clientParams` on behalf of the * user initiated request to the Kibana server (via HTTP request headers). - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. @@ -82,7 +79,7 @@ export class ScopedClusterClient implements IScopedClusterClient { public callAsCurrentUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const defaultHeaders = this.headers; if (defaultHeaders !== undefined) { diff --git a/src/core/server/elasticsearch/types.ts b/src/core/server/elasticsearch/types.ts index 6fef08fc298ff..2b4ba4b0a0a55 100644 --- a/src/core/server/elasticsearch/types.ts +++ b/src/core/server/elasticsearch/types.ts @@ -18,9 +18,14 @@ */ import { Observable } from 'rxjs'; +import { Headers } from '../http/router'; +import { LegacyRequest, KibanaRequest } from '../http'; import { ElasticsearchConfig } from './elasticsearch_config'; -import { ElasticsearchClientConfig } from './elasticsearch_client_config'; -import { IClusterClient, ICustomClusterClient } from './cluster_client'; +import { + LegacyElasticsearchClientConfig, + ILegacyClusterClient, + ILegacyCustomClusterClient, +} from './legacy'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus } from '../status'; @@ -38,7 +43,7 @@ export interface ElasticsearchServiceSetup { * @deprecated * Use {@link ElasticsearchServiceStart.legacy | ElasticsearchServiceStart.legacy.createClient} instead. * - * Create application specific Elasticsearch cluster API client with customized config. See {@link IClusterClient}. + * Create application specific Elasticsearch cluster API client with customized config. See {@link ILegacyClusterClient}. * * @param type Unique identifier of the client * @param clientConfig A config consists of Elasticsearch JS client options and @@ -56,22 +61,22 @@ export interface ElasticsearchServiceSetup { */ readonly createClient: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; /** * @deprecated * Use {@link ElasticsearchServiceStart.legacy | ElasticsearchServiceStart.legacy.client} instead. * * All Elasticsearch config value changes are processed under the hood. - * See {@link IClusterClient}. + * See {@link ILegacyClusterClient}. * * @example * ```js * const client = core.elasticsearch.legacy.client; * ``` */ - readonly client: IClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -86,7 +91,7 @@ export interface ElasticsearchServiceStart { * */ legacy: { /** - * Create application specific Elasticsearch cluster API client with customized config. See {@link IClusterClient}. + * Create application specific Elasticsearch cluster API client with customized config. See {@link ILegacyClusterClient}. * * @param type Unique identifier of the client * @param clientConfig A config consists of Elasticsearch JS client options and @@ -104,19 +109,19 @@ export interface ElasticsearchServiceStart { */ readonly createClient: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; /** * A pre-configured Elasticsearch client. All Elasticsearch config value changes are processed under the hood. - * See {@link IClusterClient}. + * See {@link ILegacyClusterClient}. * * @example * ```js * const client = core.elasticsearch.client; * ``` */ - readonly client: IClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -135,3 +140,21 @@ export interface ElasticsearchStatusMeta { warningNodes: NodesVersionCompatibility['warningNodes']; incompatibleNodes: NodesVersionCompatibility['incompatibleNodes']; } + +/** + * Fake request object created manually by Kibana plugins. + * @public + */ +export interface FakeRequest { + /** Headers used for authentication against Elasticsearch */ + headers: Headers; +} + +/** + A user credentials container. + * It accommodates the necessary auth credentials to impersonate the current user. + * + * @public + * See {@link KibanaRequest}. + */ +export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; diff --git a/src/core/server/elasticsearch/version_check/ensure_es_version.ts b/src/core/server/elasticsearch/version_check/ensure_es_version.ts index 776298e5869a0..3f562dac22a02 100644 --- a/src/core/server/elasticsearch/version_check/ensure_es_version.ts +++ b/src/core/server/elasticsearch/version_check/ensure_es_version.ts @@ -29,10 +29,10 @@ import { esVersionEqualsKibana, } from './es_kibana_version_compatability'; import { Logger } from '../../logging'; -import { APICaller } from '..'; +import { LegacyAPICaller } from '..'; export interface PollEsNodesVersionOptions { - callWithInternalUser: APICaller; + callWithInternalUser: LegacyAPICaller; log: Logger; kibanaVersion: string; ignoreVersionMismatch: boolean; diff --git a/src/core/server/http/cookie_session_storage.ts b/src/core/server/http/cookie_session_storage.ts index 13f498233f695..5ca70045f81db 100644 --- a/src/core/server/http/cookie_session_storage.ts +++ b/src/core/server/http/cookie_session_storage.ts @@ -19,7 +19,7 @@ import { Request, Server } from 'hapi'; import hapiAuthCookie from 'hapi-auth-cookie'; -// @ts-ignore no TS definitions +// @ts-expect-error no TS definitions import Statehood from 'statehood'; import { KibanaRequest, ensureRawRequest } from './router'; diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index ca9dfde2e71dc..65d633260a791 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -25,6 +25,7 @@ export { CustomHttpResponseOptions, IKibanaSocket, isRealRequest, + Headers, HttpResponseOptions, HttpResponsePayload, ErrorHttpResponseOptions, diff --git a/src/core/server/http/integration_tests/core_service.test.mocks.ts b/src/core/server/http/integration_tests/core_service.test.mocks.ts index 8e782970e2a8e..6f9b4b96eae9d 100644 --- a/src/core/server/http/integration_tests/core_service.test.mocks.ts +++ b/src/core/server/http/integration_tests/core_service.test.mocks.ts @@ -19,8 +19,8 @@ import { elasticsearchServiceMock } from '../../elasticsearch/elasticsearch_service.mock'; export const clusterClientMock = jest.fn(); -jest.doMock('../../elasticsearch/scoped_cluster_client', () => ({ - ScopedClusterClient: clusterClientMock.mockImplementation(function () { +jest.doMock('../../elasticsearch/legacy/scoped_cluster_client', () => ({ + LegacyScopedClusterClient: clusterClientMock.mockImplementation(function () { return elasticsearchServiceMock.createScopedClusterClient(); }), })); diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index f266677c1a172..fefd75ad9710e 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -21,8 +21,9 @@ import { Url } from 'url'; import { Request, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; @@ -156,7 +157,7 @@ export class KibanaRequest< public readonly params: Params, public readonly query: Query, public readonly body: Body, - // @ts-ignore we will use this flag as soon as http request proxy is supported in the core + // @ts-expect-error we will use this flag as soon as http request proxy is supported in the core // until that time we have to expose all the headers private readonly withoutSecretHeaders: boolean ) { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 7520111bf33ac..35aabab4a0b26 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -41,7 +41,7 @@ import { ElasticsearchServiceSetup, - IScopedClusterClient, + ILegacyScopedClusterClient, configSchema as elasticsearchConfigSchema, ElasticsearchServiceStart, } from './elasticsearch'; @@ -91,25 +91,24 @@ export { export { CoreId } from './core_context'; export { CspConfig, ICspConfig } from './csp'; export { - ClusterClient, - IClusterClient, - ICustomClusterClient, - Headers, - ScopedClusterClient, - IScopedClusterClient, + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, + LegacyScopedClusterClient, + ILegacyScopedClusterClient, ElasticsearchConfig, - ElasticsearchClientConfig, - ElasticsearchError, - ElasticsearchErrorHelpers, + LegacyElasticsearchClientConfig, + LegacyElasticsearchError, + LegacyElasticsearchErrorHelpers, ElasticsearchServiceSetup, ElasticsearchServiceStart, ElasticsearchStatusMeta, NodesVersionCompatibility, - APICaller, + LegacyAPICaller, FakeRequest, ScopeableRequest, } from './elasticsearch'; -export * from './elasticsearch/api_types'; +export * from './elasticsearch/legacy/api_types'; export { AuthenticationHandler, AuthHeaders, @@ -127,6 +126,7 @@ export { CustomHttpResponseOptions, GetAuthHeaders, GetAuthState, + Headers, HttpAuth, HttpResponseOptions, HttpResponsePayload, @@ -307,7 +307,6 @@ export { } from './metrics'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, @@ -356,7 +355,7 @@ export { * which uses the credentials of the incoming request * - {@link ISavedObjectTypeRegistry | savedObjects.typeRegistry} - Type registry containing * all the registered types. - * - {@link ScopedClusterClient | elasticsearch.legacy.client} - Elasticsearch + * - {@link LegacyScopedClusterClient | elasticsearch.legacy.client} - Elasticsearch * data client which uses the credentials of the incoming request * - {@link IUiSettingsClient | uiSettings.client} - uiSettings client * which uses the credentials of the incoming request @@ -371,7 +370,7 @@ export interface RequestHandlerContext { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { 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 6cd193d896109..8e53178142180 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,7 +18,7 @@ */ import { difference, get, set } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { getTransform } from '../../../../legacy/deprecation/index'; import { unset } from '../../../../legacy/utils'; import { getFlattenedObject } from '../../../utils'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index ccadae757fe54..ffe3b2375bc90 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -29,7 +29,6 @@ import { import { BehaviorSubject, throwError } from 'rxjs'; -// @ts-ignore: implicit any for JS file import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; diff --git a/src/core/server/legacy/logging/legacy_logging_server.ts b/src/core/server/legacy/logging/legacy_logging_server.ts index 85a8686b4eded..4a7fea87cf69f 100644 --- a/src/core/server/legacy/logging/legacy_logging_server.ts +++ b/src/core/server/legacy/logging/legacy_logging_server.ts @@ -19,9 +19,9 @@ import { ServerExtType } from 'hapi'; import Podium from 'podium'; -// @ts-ignore: implicit any for JS file +// @ts-expect-error: implicit any for JS file import { Config } from '../../../../legacy/server/config'; -// @ts-ignore: implicit any for JS file +// @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'; 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 5039b3a55cc58..f3ec2ed8335c5 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -23,7 +23,7 @@ import { toArray, tap, distinct, map } from 'rxjs/operators'; import { findPluginSpecs, defaultConfig, - // @ts-ignore + // @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'; diff --git a/src/core/server/logging/logging_system.test.ts b/src/core/server/logging/logging_system.test.ts index f73e40fe320dc..ac52973081106 100644 --- a/src/core/server/logging/logging_system.test.ts +++ b/src/core/server/logging/logging_system.test.ts @@ -230,6 +230,49 @@ test('setContextConfig() updates config with relative contexts', () => { ); }); +test('setContextConfig() updates config for a root context', () => { + const testsLogger = system.get('tests'); + const testsChildLogger = system.get('tests', 'child'); + const testsGrandchildLogger = system.get('tests', 'child', 'grandchild'); + + system.upgrade( + config.schema.validate({ + appenders: { default: { kind: 'console', layout: { kind: 'json' } } }, + root: { level: 'info' }, + }) + ); + + system.setContextConfig(['tests', 'child'], { + appenders: new Map([ + [ + 'custom', + { kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } }, + ], + ]), + loggers: [{ context: '', appenders: ['custom'], level: 'debug' }], + }); + + testsLogger.warn('tests log to default!'); + testsChildLogger.error('tests.child log to custom!'); + testsGrandchildLogger.debug('tests.child.grandchild log to custom!'); + + expect(mockConsoleLog).toHaveBeenCalledTimes(3); + // Parent context is unaffected + expect(JSON.parse(mockConsoleLog.mock.calls[0][0])).toMatchObject({ + context: 'tests', + message: 'tests log to default!', + level: 'WARN', + }); + // Customized contexts + expect(mockConsoleLog.mock.calls[1][0]).toMatchInlineSnapshot( + `"[ERROR][tests.child] tests.child log to custom!"` + ); + + expect(mockConsoleLog.mock.calls[2][0]).toMatchInlineSnapshot( + `"[DEBUG][tests.child.grandchild] tests.child.grandchild log to custom!"` + ); +}); + test('custom context configs are applied on subsequent calls to update()', () => { system.setContextConfig(['tests', 'child'], { appenders: new Map([ diff --git a/src/core/server/logging/logging_system.ts b/src/core/server/logging/logging_system.ts index 0bab9534d2d05..8aadab83bf716 100644 --- a/src/core/server/logging/logging_system.ts +++ b/src/core/server/logging/logging_system.ts @@ -100,7 +100,9 @@ export class LoggingSystem implements LoggerFactory { // Automatically prepend the base context to the logger sub-contexts loggers: contextConfig.loggers.map((l) => ({ ...l, - context: LoggingConfig.getLoggerContext([context, l.context]), + context: LoggingConfig.getLoggerContext( + l.context.length > 0 ? [context, l.context] : [context] + ), })), }); diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 2ca5c9f6ed3c5..9e86ee22c607b 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -19,8 +19,8 @@ import { Observable } from 'rxjs'; import { Type } from '@kbn/config-schema'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { RecursiveReadonly } from 'kibana/public'; import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } from '../config'; import { LoggerFactory } from '../logging'; import { KibanaConfigType } from '../kibana_config'; diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 48b1e12fc187e..c2d4f49d7ee2a 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -30,13 +30,13 @@ import { KibanaMigrator, IKibanaMigrator } from './migrations'; import { CoreContext } from '../core_context'; import { LegacyServiceDiscoverPlugins } from '../legacy'; import { - APICaller, + LegacyAPICaller, ElasticsearchServiceStart, - IClusterClient, + ILegacyClusterClient, InternalElasticsearchServiceSetup, } from '../elasticsearch'; import { KibanaConfigType } from '../kibana_config'; -import { migrationsRetryCallCluster } from '../elasticsearch/retry_call_cluster'; +import { migrationsRetryCallCluster } from '../elasticsearch/legacy'; import { SavedObjectsConfigType, SavedObjectsMigrationConfigType, @@ -434,7 +434,7 @@ export class SavedObjectsService await migrator.runMigrations(); } - const createRepository = (callCluster: APICaller, includedHiddenTypes: string[] = []) => { + const createRepository = (callCluster: LegacyAPICaller, includedHiddenTypes: string[] = []) => { return SavedObjectsRepository.createRepository( migrator, this.typeRegistry, @@ -484,7 +484,7 @@ export class SavedObjectsService private createMigrator( kibanaConfig: KibanaConfigType, savedObjectsConfig: SavedObjectsMigrationConfigType, - esClient: IClusterClient, + esClient: ILegacyClusterClient, migrationsRetryDelay?: number ): KibanaMigrator { return new KibanaMigrator({ diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.ts index e57f08aa7a527..7d1575798c357 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.ts @@ -26,11 +26,11 @@ const { NoConnections, RequestTimeout, Conflict, - // @ts-ignore + // @ts-expect-error 401: NotAuthorized, - // @ts-ignore + // @ts-expect-error 403: Forbidden, - // @ts-ignore + // @ts-expect-error 413: RequestEntityTooLarge, NotFound, BadRequest, diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 40c5282a77e49..f24195c0f295e 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -19,8 +19,8 @@ import { omit } from 'lodash'; import uuid from 'uuid'; -import { retryCallCluster } from '../../../elasticsearch/retry_call_cluster'; -import { APICaller } from '../../../elasticsearch/'; +import { retryCallCluster } from '../../../elasticsearch/legacy'; +import { LegacyAPICaller } from '../../../elasticsearch/'; import { getRootPropertiesObjects, IndexMapping } from '../../mappings'; import { getSearchDsl } from './search_dsl'; @@ -74,7 +74,7 @@ const isRight = (either: Either): either is Right => either.tag === 'Right'; export interface SavedObjectsRepositoryOptions { index: string; mappings: IndexMapping; - callCluster: APICaller; + callCluster: LegacyAPICaller; typeRegistry: SavedObjectTypeRegistry; serializer: SavedObjectsSerializer; migrator: KibanaMigrator; @@ -117,7 +117,7 @@ export class SavedObjectsRepository { private _mappings: IndexMapping; private _registry: SavedObjectTypeRegistry; private _allowedTypes: string[]; - private _unwrappedCallCluster: APICaller; + private _unwrappedCallCluster: LegacyAPICaller; private _serializer: SavedObjectsSerializer; /** @@ -132,7 +132,7 @@ export class SavedObjectsRepository { migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, - callCluster: APICaller, + callCluster: LegacyAPICaller, includedHiddenTypes: string[] = [], injectedConstructor: any = SavedObjectsRepository ): ISavedObjectsRepository { @@ -188,7 +188,7 @@ export class SavedObjectsRepository { } this._allowedTypes = allowedTypes; - this._unwrappedCallCluster = async (...args: Parameters) => { + this._unwrappedCallCluster = async (...args: Parameters) => { await migrator.runMigrations(); return callCluster(...args); }; @@ -1300,7 +1300,7 @@ export class SavedObjectsRepository { }; } - private async _writeToCluster(...args: Parameters) { + private async _writeToCluster(...args: Parameters) { try { return await this._callCluster(...args); } catch (err) { @@ -1308,7 +1308,7 @@ export class SavedObjectsRepository { } } - private async _callCluster(...args: Parameters) { + private async _callCluster(...args: Parameters) { try { return await this._unwrappedCallCluster(...args); } catch (err) { diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 108826ad61aa2..9cc5a8a386b0b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -108,7 +108,7 @@ import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import { Readable } from 'stream'; -import { RecursiveReadonly as RecursiveReadonly_2 } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -144,250 +144,6 @@ import { UpdateDocumentByQueryParams } from 'elasticsearch'; import { UpdateDocumentParams } from 'elasticsearch'; import { Url } from 'url'; -// @public (undocumented) -export interface APICaller { - // (undocumented) - (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'clearScroll', params: ClearScrollParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'count', params: CountParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'create', params: CreateDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'delete', params: DeleteDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteScript', params: DeleteScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'exists', params: ExistsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'explain', params: ExplainParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'fieldStats', params: FieldStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'get', params: GetParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'getScript', params: GetScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'getSource', params: GetSourceParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'getTemplate', params: GetTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'index', params: IndexDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'info', params: InfoParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'mget', params: MGetParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'msearch', params: MSearchParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ping', params: PingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'putScript', params: PutScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'putTemplate', params: PutTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'reindex', params: ReindexParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'scroll', params: ScrollParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'search', params: SearchParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'searchShards', params: SearchShardsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'suggest', params: SuggestParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'termvectors', params: TermvectorsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'update', params: UpdateDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.aliases', params: CatAliasesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.allocation', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.count', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.health', params: CatHealthParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.help', params: CatHelpParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.indices', params: CatIndicesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.master', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.nodes', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.plugins', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.repositories', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.segments', params: CatSegmentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.shards', params: CatShardsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.tasks', params: CatTasksParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.health', params: ClusterHealthParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.state', params: ClusterStateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.close', params: IndicesCloseParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.create', params: IndicesCreateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.exists', params: IndicesExistsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.flush', params: IndicesFlushParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.get', params: IndicesGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.open', params: IndicesOpenParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.stats', params: IndicesStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.info', params: NodesInfoParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.stats', params: NodesStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.get', params: TasksGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.list', params: TasksListParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: CallAPIOptions): Promise; - // (undocumented) - (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: CallAPIOptions): Promise; - // (undocumented) - (endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; -} - // Warning: (ae-forgotten-export) The symbol "appendersSchema" needs to be exported by the entry point index.d.ts // // @public (undocumented) @@ -497,12 +253,6 @@ export class BasePath { // @internal (undocumented) export function bootstrap({ configs, cliArgs, applyConfigOverrides, features, }: BootstrapArgs): Promise; -// @public -export interface CallAPIOptions { - signal?: AbortSignal; - wrap401Errors?: boolean; -} - // @public export interface Capabilities { [key: string]: Record>; @@ -530,14 +280,6 @@ export interface CapabilitiesStart { // @public export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; -// @public -export class ClusterClient implements IClusterClient { - constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); - asScoped(request?: ScopeableRequest): IScopedClusterClient; - callAsInternalUser: APICaller; - close(): void; - } - // @alpha export const config: { elasticsearch: { @@ -557,7 +299,7 @@ export const config: { startupTimeout: import("@kbn/config-schema").Type; logQueries: import("@kbn/config-schema").Type; ssl: import("@kbn/config-schema").ObjectType<{ - verificationMode: import("@kbn/config-schema").Type<"none" | "full" | "certificate">; + verificationMode: import("@kbn/config-schema").Type<"none" | "certificate" | "full">; certificateAuthorities: import("@kbn/config-schema").Type; certificate: import("@kbn/config-schema").Type; key: import("@kbn/config-schema").Type; @@ -851,14 +593,6 @@ export interface DiscoveredPlugin { readonly requiredPlugins: readonly PluginName[]; } -// @public (undocumented) -export type ElasticsearchClientConfig = Pick & Pick & { - pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; - requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; - sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; - ssl?: Partial; -}; - // @public export class ElasticsearchConfig { constructor(rawConfig: ElasticsearchConfigType); @@ -884,26 +618,12 @@ export class ElasticsearchConfig { readonly username?: string; } -// @public (undocumented) -export interface ElasticsearchError extends Boom { - // (undocumented) - [code]?: string; -} - -// @public -export class ElasticsearchErrorHelpers { - // (undocumented) - static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; - // (undocumented) - static isNotAuthorizedError(error: any): error is ElasticsearchError; -} - // @public (undocumented) export interface ElasticsearchServiceSetup { // @deprecated (undocumented) legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -911,8 +631,8 @@ export interface ElasticsearchServiceSetup { export interface ElasticsearchServiceStart { // @deprecated (undocumented) legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -1056,9 +776,6 @@ export interface HttpServiceStart { // @public export type IBasePath = Pick; -// @public -export type IClusterClient = Pick; - // @public export interface IContextContainer> { createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; @@ -1078,9 +795,6 @@ export interface ICspConfig { readonly warnLegacyBrowsers: boolean; } -// @public -export type ICustomClusterClient = Pick; - // @public export interface IKibanaResponse { // (undocumented) @@ -1102,6 +816,15 @@ export interface IKibanaSocket { getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; } +// @public +export type ILegacyClusterClient = Pick; + +// @public +export type ILegacyCustomClusterClient = Pick; + +// @public +export type ILegacyScopedClusterClient = Pick; + // @public (undocumented) export interface ImageValidation { // (undocumented) @@ -1155,9 +878,6 @@ export type ISavedObjectsRepository = Pick; -// @public -export type IScopedClusterClient = Pick; - // @public export function isRelativeUrl(candidatePath: string): boolean; @@ -1247,6 +967,266 @@ export const kibanaResponseFactory: { // @public export type KnownHeaders = KnownKeys; +// @public (undocumented) +export interface LegacyAPICaller { + // (undocumented) + (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'clearScroll', params: ClearScrollParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'count', params: CountParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'create', params: CreateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'delete', params: DeleteDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteScript', params: DeleteScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'exists', params: ExistsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'explain', params: ExplainParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'fieldStats', params: FieldStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'get', params: GetParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'getScript', params: GetScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'getSource', params: GetSourceParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'getTemplate', params: GetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'index', params: IndexDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'info', params: InfoParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'mget', params: MGetParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'msearch', params: MSearchParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ping', params: PingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'putScript', params: PutScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'putTemplate', params: PutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'reindex', params: ReindexParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'scroll', params: ScrollParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'search', params: SearchParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'searchShards', params: SearchShardsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'suggest', params: SuggestParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'termvectors', params: TermvectorsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'update', params: UpdateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.aliases', params: CatAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.allocation', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.count', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.health', params: CatHealthParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.help', params: CatHelpParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.indices', params: CatIndicesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.master', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.nodes', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.plugins', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.repositories', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.segments', params: CatSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.shards', params: CatShardsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.tasks', params: CatTasksParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.health', params: ClusterHealthParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.state', params: ClusterStateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.close', params: IndicesCloseParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.create', params: IndicesCreateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.exists', params: IndicesExistsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.flush', params: IndicesFlushParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.get', params: IndicesGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.open', params: IndicesOpenParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.stats', params: IndicesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.info', params: NodesInfoParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.stats', params: NodesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.get', params: TasksGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.list', params: TasksListParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: LegacyCallAPIOptions): Promise; + // (undocumented) + (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: LegacyCallAPIOptions): Promise; + // (undocumented) + (endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; +} + +// @public +export interface LegacyCallAPIOptions { + signal?: AbortSignal; + wrap401Errors?: boolean; +} + +// Warning: (ae-unresolved-inheritdoc-reference) The @inheritDoc reference could not be resolved: The package "kibana" does not have an export "IClusterClient" +// +// @public (undocumented) +export class LegacyClusterClient implements ILegacyClusterClient { + constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); + asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient; + callAsInternalUser: LegacyAPICaller; + close(): void; + } + // @internal @deprecated export interface LegacyConfig { // (undocumented) @@ -1261,6 +1241,28 @@ export interface LegacyConfig { set(config: LegacyVars): void; } +// @public (undocumented) +export type LegacyElasticsearchClientConfig = Pick & Pick & { + pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; + requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; + sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; + ssl?: Partial; +}; + +// @public (undocumented) +export interface LegacyElasticsearchError extends Boom { + // (undocumented) + [code]?: string; +} + +// @public +export class LegacyElasticsearchErrorHelpers { + // (undocumented) + static decorateNotAuthorizedError(error: Error, reason?: string): LegacyElasticsearchError; + // (undocumented) + static isNotAuthorizedError(error: any): error is LegacyElasticsearchError; +} + // Warning: (ae-forgotten-export) The symbol "ILegacyInternals" needs to be exported by the entry point index.d.ts // // @internal @deprecated (undocumented) @@ -1280,6 +1282,15 @@ export class LegacyInternals implements ILegacyInternals { export interface LegacyRequest extends Request { } +// Warning: (ae-unresolved-inheritdoc-reference) The @inheritDoc reference could not be resolved: The package "kibana" does not have an export "IScopedClusterClient" +// +// @public (undocumented) +export class LegacyScopedClusterClient implements ILegacyScopedClusterClient { + constructor(internalAPICaller: LegacyAPICaller, scopedAPICaller: LegacyAPICaller, headers?: Headers | undefined); + callAsCurrentUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; + callAsInternalUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; + } + // Warning: (ae-forgotten-export) The symbol "LegacyPlugins" needs to be exported by the entry point index.d.ts // // @internal @deprecated (undocumented) @@ -1652,13 +1663,6 @@ export interface PluginsServiceStart { // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // @public export type RedirectResponseOptions = HttpResponseOptions & { headers: { @@ -1679,7 +1683,7 @@ export interface RequestHandlerContext { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { @@ -2323,7 +2327,7 @@ export class SavedObjectsRepository { // Warning: (ae-forgotten-export) The symbol "KibanaMigrator" needs to be exported by the entry point index.d.ts // // @internal - static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, callCluster: APICaller, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; + static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, callCluster: LegacyAPICaller, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; @@ -2478,13 +2482,6 @@ export type SavedObjectUnsanitizedDoc = SavedObjectDoc & Partial // @public export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; -// @public -export class ScopedClusterClient implements IScopedClusterClient { - constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); - callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; - callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; - } - // @public export interface ServiceStatus | unknown = unknown> { detail?: string; @@ -2546,7 +2543,7 @@ export interface SessionStorageFactory { } // @public (undocumented) -export type SharedGlobalConfig = RecursiveReadonly_2<{ +export type SharedGlobalConfig = RecursiveReadonly<{ kibana: Pick; elasticsearch: Pick; path: Pick; diff --git a/src/core/server/ui_settings/integration_tests/lib/servers.ts b/src/core/server/ui_settings/integration_tests/lib/servers.ts index 486abd5a0c790..ea462291059a5 100644 --- a/src/core/server/ui_settings/integration_tests/lib/servers.ts +++ b/src/core/server/ui_settings/integration_tests/lib/servers.ts @@ -25,7 +25,7 @@ import { TestKibanaUtils, TestUtils, } from '../../../../../test_utils/kbn_server'; -import { APICaller } from '../../../elasticsearch/'; +import { LegacyAPICaller } from '../../../elasticsearch/'; import { httpServerMock } from '../../../http/http_server.mocks'; let servers: TestUtils; @@ -37,7 +37,7 @@ let kbnServer: TestKibanaUtils['kbnServer']; interface AllServices { kbnServer: TestKibanaUtils['kbnServer']; savedObjectsClient: SavedObjectsClientContract; - callCluster: APICaller; + callCluster: LegacyAPICaller; uiSettings: IUiSettingsClient; deleteKibanaIndex: typeof deleteKibanaIndex; } @@ -62,7 +62,7 @@ export async function startServers() { kbnServer = kbn.kbnServer; } -async function deleteKibanaIndex(callCluster: APICaller) { +async function deleteKibanaIndex(callCluster: LegacyAPICaller) { const kibanaIndices = await callCluster('cat.indices', { index: '.kibana*', format: 'json' }); const indexNames = kibanaIndices.map((x: any) => x.index); if (!indexNames.length) { diff --git a/src/core/utils/deep_freeze.test.ts b/src/core/utils/deep_freeze.test.ts index b4531d80d0252..58aa9c9b8c92b 100644 --- a/src/core/utils/deep_freeze.test.ts +++ b/src/core/utils/deep_freeze.test.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { deepFreeze } from './deep_freeze'; it('returns the first argument with all original references', () => { @@ -33,7 +32,7 @@ it('returns the first argument with all original references', () => { it('prevents adding properties to argument', () => { const frozen = deepFreeze({}); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`object is not extensible`); }); @@ -41,7 +40,7 @@ it('prevents adding properties to argument', () => { it('prevents changing properties on argument', () => { const frozen = deepFreeze({ foo: false }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`read only property 'foo'`); }); @@ -49,7 +48,7 @@ it('prevents changing properties on argument', () => { it('prevents changing properties on nested children of argument', () => { const frozen = deepFreeze({ foo: { bar: { baz: { box: 1 } } } }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.bar.baz.box = 2; }).toThrowError(`read only property 'box'`); }); @@ -57,7 +56,7 @@ it('prevents changing properties on nested children of argument', () => { it('prevents adding items to a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.push(2); }).toThrowError(`object is not extensible`); }); @@ -65,7 +64,7 @@ it('prevents adding items to a frozen array', () => { it('prevents reassigning items in a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo[0] = 2; }).toThrowError(`read only property '0'`); }); diff --git a/src/core/utils/deep_freeze.ts b/src/core/utils/deep_freeze.ts index b0f283c60d0fc..fbc35acb45b0f 100644 --- a/src/core/utils/deep_freeze.ts +++ b/src/core/utils/deep_freeze.ts @@ -16,19 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -// if we define this inside RecursiveReadonly TypeScript complains -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} - -/** @public */ -export type RecursiveReadonly = T extends (...args: any[]) => any - ? T - : T extends any[] - ? RecursiveReadonlyArray - : T extends object - ? Readonly<{ [K in keyof T]: RecursiveReadonly }> - : T; +import { RecursiveReadonly } from '@kbn/utility-types'; /** @public */ export type Freezable = { [k: string]: any } | any[]; @@ -47,6 +35,5 @@ export function deepFreeze(object: T) { deepFreeze(value); } } - return Object.freeze(object) as RecursiveReadonly; } diff --git a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json b/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json deleted file mode 100644 index 12307c46b95fa..0000000000000 --- a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "skipLibCheck": true, - "lib": [ - "es2018" - ] - }, - "files": [ - "index.ts" - ] -} diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 18fc7ebaa2af4..da343aa0f0672 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -43,6 +43,7 @@ export default { 'src/plugins/**/*.{ts,tsx}', '!src/plugins/**/{__test__,__snapshots__,__examples__,mocks,tests}/**/*', '!src/plugins/**/*.d.ts', + '!src/plugins/**/test_helpers/**', 'packages/kbn-ui-framework/src/components/**/*.js', '!packages/kbn-ui-framework/src/components/index.js', '!packages/kbn-ui-framework/src/components/**/*/index.js', @@ -51,6 +52,7 @@ export default { '!packages/kbn-ui-framework/src/services/**/*/index.js', 'src/legacy/core_plugins/**/*.{js,jsx,ts,tsx}', '!src/legacy/core_plugins/**/{__test__,__snapshots__}/**/*', + '!src/legacy/core_plugins/tests_bundle/**', ], moduleNameMapper: { '@elastic/eui$': '/node_modules/@elastic/eui/test-env', diff --git a/src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts b/src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts index a595fffb3c235..0e7692f6be755 100644 --- a/src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts +++ b/src/legacy/core_plugins/elasticsearch/server/lib/cluster.ts @@ -19,18 +19,18 @@ import { Request } from 'hapi'; import { errors } from 'elasticsearch'; -import { CallAPIOptions, ClusterClient, FakeRequest } from 'kibana/server'; +import { LegacyCallAPIOptions, LegacyClusterClient, FakeRequest } from 'kibana/server'; export class Cluster { public readonly errors = errors; - constructor(private readonly clusterClient: ClusterClient) {} + constructor(private readonly clusterClient: LegacyClusterClient) {} public callWithRequest = async ( req: Request | FakeRequest, endpoint: string, clientParams?: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { return await this.clusterClient .asScoped(req) @@ -40,7 +40,7 @@ export class Cluster { public callWithInternalUser = async ( endpoint: string, clientParams?: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { return await this.clusterClient.callAsInternalUser(endpoint, clientParams, options); }; diff --git a/src/plugins/advanced_settings/public/plugin.ts b/src/plugins/advanced_settings/public/plugin.ts index 2784b74ab726c..8b3347f8d88f0 100644 --- a/src/plugins/advanced_settings/public/plugin.ts +++ b/src/plugins/advanced_settings/public/plugin.ts @@ -17,8 +17,8 @@ * under the License. */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; -import { ManagementApp, ManagementSectionId } from '../../management/public'; +import { CoreSetup, Plugin } from 'kibana/public'; +import { ManagementSectionId } from '../../management/public'; import { ComponentRegistry } from './component_registry'; import { AdvancedSettingsSetup, AdvancedSettingsStart, AdvancedSettingsPluginSetup } from './types'; @@ -30,11 +30,10 @@ const title = i18n.translate('advancedSettings.advancedSettingsLabel', { export class AdvancedSettingsPlugin implements Plugin { - private managementApp?: ManagementApp; public setup(core: CoreSetup, { management }: AdvancedSettingsPluginSetup) { const kibanaSection = management.sections.getSection(ManagementSectionId.Kibana); - this.managementApp = kibanaSection.registerApp({ + kibanaSection.registerApp({ id: 'settings', title, order: 3, @@ -51,11 +50,7 @@ export class AdvancedSettingsPlugin }; } - public start(core: CoreStart) { - if (!core.application.capabilities.management.kibana.settings) { - this.managementApp!.disable(); - } - + public start() { return { component: component.start, }; diff --git a/src/plugins/data/common/field_formats/mocks.ts b/src/plugins/data/common/field_formats/mocks.ts index 394d4c383032f..9bbaefe2d146a 100644 --- a/src/plugins/data/common/field_formats/mocks.ts +++ b/src/plugins/data/common/field_formats/mocks.ts @@ -17,7 +17,8 @@ * under the License. */ -import { IFieldFormatsRegistry } from '.'; +import { identity } from 'lodash'; +import { FieldFormat, IFieldFormatsRegistry } from '.'; export const fieldFormatsMock: IFieldFormatsRegistry = { getByFieldType: jest.fn(), @@ -35,6 +36,9 @@ export const fieldFormatsMock: IFieldFormatsRegistry = { init: jest.fn(), register: jest.fn(), parseDefaultTypeMap: jest.fn(), - deserialize: jest.fn(), + deserialize: jest.fn().mockImplementation(() => { + const DefaultFieldFormat = FieldFormat.from(identity); + return new DefaultFieldFormat(); + }), getTypeWithoutMetaParams: jest.fn(), }; diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index b40e02b709d30..0fb45fcc739d4 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -26,6 +26,5 @@ export * from './kbn_field_types'; export * from './query'; export * from './search'; export * from './search/aggs'; -export * from './timefilter'; export * from './types'; export * from './utils'; diff --git a/src/plugins/data/common/query/index.ts b/src/plugins/data/common/query/index.ts index 4e90f6f8bb83e..b0dfbbb82355e 100644 --- a/src/plugins/data/common/query/index.ts +++ b/src/plugins/data/common/query/index.ts @@ -18,5 +18,6 @@ */ export * from './filter_manager'; +export * from './timefilter'; export * from './types'; export * from './is_query'; diff --git a/src/plugins/data/public/query/timefilter/get_time.test.ts b/src/plugins/data/common/query/timefilter/get_time.test.ts similarity index 100% rename from src/plugins/data/public/query/timefilter/get_time.test.ts rename to src/plugins/data/common/query/timefilter/get_time.test.ts diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/common/query/timefilter/get_time.ts similarity index 90% rename from src/plugins/data/public/query/timefilter/get_time.ts rename to src/plugins/data/common/query/timefilter/get_time.ts index 3706972ce4a2e..6e4eda95accc7 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/common/query/timefilter/get_time.ts @@ -18,14 +18,16 @@ */ import dateMath from '@elastic/datemath'; -import { IIndexPattern } from '../..'; -import { TimeRange, buildRangeFilter } from '../../../common'; +import { buildRangeFilter, IIndexPattern, TimeRange, TimeRangeBounds } from '../..'; interface CalculateBoundsOptions { forceNow?: Date; } -export function calculateBounds(timeRange: TimeRange, options: CalculateBoundsOptions = {}) { +export function calculateBounds( + timeRange: TimeRange, + options: CalculateBoundsOptions = {} +): TimeRangeBounds { return { min: dateMath.parse(timeRange.from, { forceNow: options.forceNow }), max: dateMath.parse(timeRange.to, { roundUp: true, forceNow: options.forceNow }), diff --git a/src/plugins/data/common/timefilter/index.ts b/src/plugins/data/common/query/timefilter/index.ts similarity index 92% rename from src/plugins/data/common/timefilter/index.ts rename to src/plugins/data/common/query/timefilter/index.ts index e0c509e119fda..55739511a0ef5 100644 --- a/src/plugins/data/common/timefilter/index.ts +++ b/src/plugins/data/common/query/timefilter/index.ts @@ -17,4 +17,5 @@ * under the License. */ -export { isTimeRange } from './is_time_range'; +export * from './get_time'; +export * from './is_time_range'; diff --git a/src/plugins/data/common/timefilter/is_time_range.ts b/src/plugins/data/common/query/timefilter/is_time_range.ts similarity index 100% rename from src/plugins/data/common/timefilter/is_time_range.ts rename to src/plugins/data/common/query/timefilter/is_time_range.ts diff --git a/src/plugins/data/common/timefilter/types.ts b/src/plugins/data/common/query/timefilter/types.ts similarity index 88% rename from src/plugins/data/common/timefilter/types.ts rename to src/plugins/data/common/query/timefilter/types.ts index b197b16e67dd1..60008ce6054e1 100644 --- a/src/plugins/data/common/timefilter/types.ts +++ b/src/plugins/data/common/query/timefilter/types.ts @@ -17,6 +17,8 @@ * under the License. */ +import { Moment } from 'moment'; + export interface RefreshInterval { pause: boolean; value: number; @@ -27,3 +29,8 @@ export interface TimeRange { to: string; mode?: 'absolute' | 'relative'; } + +export interface TimeRangeBounds { + min: Moment | undefined; + max: Moment | undefined; +} diff --git a/src/plugins/data/common/query/types.ts b/src/plugins/data/common/query/types.ts index 61b5d5b2b7b4a..6b34a1baf293b 100644 --- a/src/plugins/data/common/query/types.ts +++ b/src/plugins/data/common/query/types.ts @@ -17,6 +17,8 @@ * under the License. */ +export * from './timefilter/types'; + export interface Query { query: string | { [key: string]: any }; language: string; diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index 93629c3dbaf62..e2ec1a031b0ca 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -17,7 +17,6 @@ * under the License. */ -export * from './timefilter/types'; export * from './query/types'; export * from './kbn_field_types/types'; export * from './index_patterns/types'; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index efce8d2c021c9..89b0d7e0303b9 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -421,7 +421,6 @@ export { connectToQueryState, syncQueryStateWithUrl, QueryState, - getTime, getQueryLog, getDefaultQuery, FilterManager, @@ -435,6 +434,7 @@ export { } from './query'; export { + getTime, // kbn field types castEsToKbnFieldTypeName, getKbnTypeNames, diff --git a/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx b/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx index e32a8e023cf40..7ed6525db6350 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx +++ b/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx @@ -30,7 +30,7 @@ export const onRedirectNoIndexPattern = ( navigateToApp: CoreStart['application']['navigateToApp'], overlays: CoreStart['overlays'] ) => () => { - const canManageIndexPatterns = capabilities.management.kibana.index_patterns; + const canManageIndexPatterns = capabilities.management.kibana.indexPatterns; const redirectTarget = canManageIndexPatterns ? '/management/kibana/indexPatterns' : '/home'; let timeoutId: NodeJS.Timeout | undefined; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 493733daf261b..51f96f10aa7c7 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -146,7 +146,6 @@ export class DataPublicPlugin implements Plugin>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; diff --git a/src/plugins/data/public/query/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts index a5885a59f60ed..f71061677ceb7 100644 --- a/src/plugins/data/public/query/timefilter/index.ts +++ b/src/plugins/data/public/query/timefilter/index.ts @@ -22,6 +22,5 @@ export { TimefilterService, TimefilterSetup } from './timefilter_service'; export * from './types'; export { Timefilter, TimefilterContract } from './timefilter'; export { TimeHistory, TimeHistoryContract } from './time_history'; -export { getTime, calculateBounds } from './get_time'; export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter'; export { extractTimeFilter } from './lib/extract_time_filter'; diff --git a/src/plugins/kibana_utils/common/default_feedback_message.test.ts b/src/plugins/data/public/query/timefilter/lib/get_force_now.ts similarity index 67% rename from src/plugins/kibana_utils/common/default_feedback_message.test.ts rename to src/plugins/data/public/query/timefilter/lib/get_force_now.ts index 5c1afa4634b71..fe68656f0c3aa 100644 --- a/src/plugins/kibana_utils/common/default_feedback_message.test.ts +++ b/src/plugins/data/public/query/timefilter/lib/get_force_now.ts @@ -17,10 +17,18 @@ * under the License. */ -import { defaultFeedbackMessage } from './default_feedback_message'; +import { parseQueryString } from './parse_querystring'; -test('default feedback message with link', () => { - expect(defaultFeedbackMessage).toMatchInlineSnapshot( - `"Have feedback? Please create an issue in GitHub."` - ); -}); +/** @internal */ +export function getForceNow() { + const forceNow = parseQueryString().forceNow as string; + if (!forceNow) { + return; + } + + const ticks = Date.parse(forceNow); + if (isNaN(ticks)) { + throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`); + } + return new Date(ticks); +} diff --git a/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts b/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts index 2220ad4eef1b7..5982bfd0bd276 100644 --- a/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts +++ b/src/plugins/data/public/query/timefilter/lib/parse_querystring.ts @@ -18,6 +18,7 @@ */ import { parse } from 'query-string'; +/** @internal */ export function parseQueryString() { // window.location.search is an empty string // get search from href diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 86ef69be572a9..5eb1546fa015f 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -21,10 +21,9 @@ import _ from 'lodash'; import { Subject, BehaviorSubject } from 'rxjs'; import moment from 'moment'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; -import { parseQueryString } from './lib/parse_querystring'; -import { calculateBounds, getTime } from './get_time'; +import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; -import { RefreshInterval, TimeRange } from '../../../common'; +import { calculateBounds, getTime, RefreshInterval, TimeRange } from '../../../common'; import { TimeHistoryContract } from './time_history'; import { IndexPattern } from '../../index_patterns'; @@ -224,16 +223,7 @@ export class Timefilter { } private getForceNow = () => { - const forceNow = parseQueryString().forceNow as string; - if (!forceNow) { - return; - } - - const ticks = Date.parse(forceNow); - if (isNaN(ticks)) { - throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`); - } - return new Date(ticks); + return getForceNow(); }; } diff --git a/src/plugins/data/public/query/timefilter/types.ts b/src/plugins/data/public/query/timefilter/types.ts index 8b8deea43f808..d47a9cbb3bd60 100644 --- a/src/plugins/data/public/query/timefilter/types.ts +++ b/src/plugins/data/public/query/timefilter/types.ts @@ -16,7 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + import { Moment } from 'moment'; + import { TimeRange, RefreshInterval } from '../../../common'; export interface TimefilterConfig { @@ -32,7 +34,4 @@ export type InputTimeRange = to: Moment; }; -export interface TimeRangeBounds { - min: Moment | undefined; - max: Moment | undefined; -} +export { TimeRangeBounds } from '../../../common'; diff --git a/src/plugins/data/public/search/aggs/agg_config.test.ts b/src/plugins/data/public/search/aggs/agg_config.test.ts index 95e0b2cd27186..18a86d767c2de 100644 --- a/src/plugins/data/public/search/aggs/agg_config.test.ts +++ b/src/plugins/data/public/search/aggs/agg_config.test.ts @@ -25,31 +25,23 @@ import { AggType } from './agg_type'; import { AggTypesRegistryStart } from './agg_types_registry'; import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; import { MetricAggType } from './metrics/metric_agg_type'; -import { - Field as IndexPatternField, - IndexPattern, - IIndexPatternFieldList, -} from '../../index_patterns'; +import { IndexPattern, IIndexPatternFieldList } from '../../index_patterns'; import { stubIndexPatternWithFields } from '../../../public/stubs'; -import { FieldFormatsStart } from '../../field_formats'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('AggConfig', () => { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; - let fieldFormats: FieldFormatsStart; beforeEach(() => { jest.restoreAllMocks(); mockDataServices(); - fieldFormats = fieldFormatsServiceMock.createStartContract(); indexPattern = stubIndexPatternWithFields as IndexPattern; typesRegistry = mockAggTypesRegistry(); }); describe('#toDsl', () => { it('calls #write()', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -64,7 +56,7 @@ describe('AggConfig', () => { }); it('uses the type name as the agg name', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -79,7 +71,7 @@ describe('AggConfig', () => { }); it('uses the params from #write() output as the agg params', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -109,7 +101,7 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const histoConfig = ac.byName('date_histogram')[0]; const avgConfig = ac.byName('avg')[0]; @@ -219,8 +211,8 @@ describe('AggConfig', () => { testsIdentical.forEach((configState, index) => { it(`identical aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -260,8 +252,8 @@ describe('AggConfig', () => { testsIdenticalDifferentOrder.forEach((test, index) => { it(`identical aggregations (${index}) - init json is in different order`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -325,8 +317,8 @@ describe('AggConfig', () => { testsDifferent.forEach((test, index) => { it(`different aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false); }); }); @@ -334,7 +326,7 @@ describe('AggConfig', () => { describe('#serialize', () => { it('includes the aggs id, params, type and schema', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -365,8 +357,8 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry }); // this relies on the assumption that js-engines consistently loop over properties in insertion order. // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. @@ -394,7 +386,7 @@ describe('AggConfig', () => { params: { field: 'machine.os.keyword' }, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(` Array [ @@ -456,7 +448,7 @@ describe('AggConfig', () => { }, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(` Array [ @@ -478,20 +470,8 @@ describe('AggConfig', () => { }); describe('#toExpressionAst', () => { - beforeEach(() => { - fieldFormats.getDefaultInstance = (() => ({ - getConverterFor: (t?: string) => t || identity, - })) as any; - indexPattern.fields.getByName = (name) => - ({ - format: { - getConverterFor: (t?: string) => t || identity, - }, - } as IndexPatternField); - }); - it('works with primitive param types', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'terms', @@ -540,7 +520,7 @@ describe('AggConfig', () => { }); it('creates a subexpression for params of type "agg"', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'terms', params: { @@ -616,7 +596,7 @@ describe('AggConfig', () => { }, }); - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'range', params: { @@ -647,7 +627,7 @@ describe('AggConfig', () => { }); it('stringifies any other params which are an object', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'terms', params: { @@ -662,7 +642,7 @@ describe('AggConfig', () => { }); it(`returns undefined if an expressionName doesn't exist on the agg type`, () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'unknown type', params: {}, @@ -676,7 +656,7 @@ describe('AggConfig', () => { let aggConfig: AggConfig; beforeEach(() => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams); }); @@ -702,85 +682,4 @@ describe('AggConfig', () => { expect(label).toBe(''); }); }); - - describe('#fieldFormatter - custom getFormat handler', () => { - it('returns formatter from getFormat handler', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); - const configStates = { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }; - const aggConfig = ac.createAggConfig(configStates); - - const fieldFormatter = aggConfig.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - }); - - // TODO: Converting these field formatter tests from browser tests to unit - // tests makes them much less helpful due to the extensive use of mocking. - // We should revisit these and rewrite them into something more useful. - describe('#fieldFormatter - no custom getFormat handler', () => { - let aggConfig: AggConfig; - - beforeEach(() => { - fieldFormats.getDefaultInstance = (() => ({ - getConverterFor: (t?: string) => t || identity, - })) as any; - indexPattern.fields.getByName = (name) => - ({ - format: { - getConverterFor: (t?: string) => t || identity, - }, - } as IndexPatternField); - - const configStates = { - enabled: true, - type: 'histogram', - schema: 'bucket', - params: { - field: 'bytes', - }, - }; - const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry, fieldFormats }); - aggConfig = ac.createAggConfig(configStates); - }); - - it("returns the field's formatter", () => { - aggConfig.params.field = { - format: { - getConverterFor: (t?: string) => t || identity, - }, - }; - expect(aggConfig.fieldFormatter().toString()).toBe( - aggConfig.getField().format.getConverterFor().toString() - ); - }); - - it('returns the string format if the field does not have a format', () => { - const agg = aggConfig; - agg.params.field = { type: 'number', format: null }; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the string format if there is no field', () => { - const agg = aggConfig; - delete agg.params.field; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the html converter if "html" is passed in', () => { - const field = indexPattern.fields.getByName('bytes'); - expect(aggConfig.fieldFormatter('html').toString()).toBe( - field!.format.getConverterFor('html').toString() - ); - }); - }); }); diff --git a/src/plugins/data/public/search/aggs/agg_config.ts b/src/plugins/data/public/search/aggs/agg_config.ts index a2b74eca58476..8650f5920e520 100644 --- a/src/plugins/data/public/search/aggs/agg_config.ts +++ b/src/plugins/data/public/search/aggs/agg_config.ts @@ -30,8 +30,6 @@ import { writeParams } from './agg_params'; import { IAggConfigs } from './agg_configs'; import { FetchOptions } from '../fetch'; import { ISearchSource } from '../search_source'; -import { FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../common'; -import { FieldFormatsStart } from '../../field_formats'; type State = string | number | boolean | null | undefined | SerializableState; @@ -52,10 +50,6 @@ export type AggConfigSerialized = Ensure< SerializableState >; -export interface AggConfigDependencies { - fieldFormats: FieldFormatsStart; -} - export type AggConfigOptions = Assign; /** @@ -116,13 +110,8 @@ export class AggConfig { private __type: IAggType; private __typeDecorations: any; private subAggs: AggConfig[] = []; - private readonly fieldFormats: FieldFormatsStart; - constructor( - aggConfigs: IAggConfigs, - opts: AggConfigOptions, - { fieldFormats }: AggConfigDependencies - ) { + constructor(aggConfigs: IAggConfigs, opts: AggConfigOptions) { this.aggConfigs = aggConfigs; this.id = String(opts.id || AggConfig.nextId(aggConfigs.aggs as any)); this.enabled = typeof opts.enabled === 'boolean' ? opts.enabled : true; @@ -143,8 +132,6 @@ export class AggConfig { // @ts-ignore this.__type = this.__type; - - this.fieldFormats = fieldFormats; } /** @@ -433,24 +420,6 @@ export class AggConfig { return this.aggConfigs.timeRange; } - fieldFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const format = this.type && this.type.getFormat(this); - - if (format) { - return format.getConverterFor(contentType); - } - - return this.fieldOwnFormatter(contentType, defaultFormat); - } - - fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const field = this.getField(); - let format = field && field.format; - if (!format) format = defaultFormat; - if (!format) format = this.fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); - return format.getConverterFor(contentType); - } - fieldName() { const field = this.getField(); return field ? field.name : ''; diff --git a/src/plugins/data/public/search/aggs/agg_configs.test.ts b/src/plugins/data/public/search/aggs/agg_configs.test.ts index 6e6fb3350d901..121bb29f6f8ed 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.test.ts @@ -24,12 +24,10 @@ import { AggTypesRegistryStart } from './agg_types_registry'; import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; import { Field as IndexPatternField, IndexPattern } from '../../index_patterns'; import { stubIndexPattern, stubIndexPatternWithFields } from '../../../public/stubs'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('AggConfigs', () => { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); beforeEach(() => { mockDataServices(); @@ -47,7 +45,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); }); @@ -72,7 +70,7 @@ describe('AggConfigs', () => { ]; const spy = jest.spyOn(AggConfig, 'ensureIds'); - new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(spy).toHaveBeenCalledTimes(1); expect(spy.mock.calls[0]).toEqual([configStates]); spy.mockRestore(); @@ -94,20 +92,16 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(2); ac.createAggConfig( - new AggConfig( - ac, - { - enabled: true, - type: typesRegistry.get('terms'), - params: {}, - schema: 'split', - }, - { fieldFormats } - ) + new AggConfig(ac, { + enabled: true, + type: typesRegistry.get('terms'), + params: {}, + schema: 'split', + }) ); expect(ac.aggs).toHaveLength(3); }); @@ -121,7 +115,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig({ @@ -142,7 +136,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig( @@ -170,7 +164,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getRequestAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -193,7 +187,7 @@ describe('AggConfigs', () => { { type: 'count', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -210,7 +204,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -231,7 +225,7 @@ describe('AggConfigs', () => { it('uses the sorted aggs', () => { const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs'); ac.toDsl(); expect(spy).toHaveBeenCalledTimes(1); @@ -245,10 +239,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'count', params: {} }, ]; - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - fieldFormats, - }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const aggInfos = ac.aggs.map((aggConfig) => { const football = {}; @@ -291,7 +282,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; const count = ac.byName('count')[0]; @@ -316,10 +307,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, ]; - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - fieldFormats, - }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; const metrics = ac.bySchemaName('metrics'); @@ -344,7 +332,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const topLevelDsl = ac.toDsl(true); const buckets = ac.bySchemaName('buckets'); const metrics = ac.bySchemaName('metrics'); @@ -414,7 +402,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const topLevelDsl = ac.toDsl(true)['2']; expect(Object.keys(topLevelDsl.aggs)).toContain('1'); diff --git a/src/plugins/data/public/search/aggs/agg_configs.ts b/src/plugins/data/public/search/aggs/agg_configs.ts index 6cc03be292d7b..b272dfd3c7468 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.ts @@ -28,7 +28,6 @@ import { IndexPattern } from '../../index_patterns'; import { ISearchSource } from '../search_source'; import { FetchOptions } from '../fetch'; import { TimeRange } from '../../../common'; -import { FieldFormatsStart } from '../../field_formats'; function removeParentAggs(obj: any) { for (const prop in obj) { @@ -48,7 +47,6 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { export interface AggConfigsOptions { typesRegistry: AggTypesRegistryStart; - fieldFormats: FieldFormatsStart; } export type CreateAggConfigParams = Assign; @@ -70,7 +68,6 @@ export type IAggConfigs = AggConfigs; export class AggConfigs { public indexPattern: IndexPattern; public timeRange?: TimeRange; - private readonly fieldFormats: FieldFormatsStart; private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; @@ -86,7 +83,6 @@ export class AggConfigs { this.aggs = []; this.indexPattern = indexPattern; - this.fieldFormats = opts.fieldFormats; configStates.forEach((params: any) => this.createAggConfig(params)); } @@ -117,7 +113,6 @@ export class AggConfigs { const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), { typesRegistry: this.typesRegistry, - fieldFormats: this.fieldFormats, }); return aggConfigs; @@ -134,14 +129,10 @@ export class AggConfigs { aggConfig = params; params.parent = this; } else { - aggConfig = new AggConfig( - this, - { - ...params, - type: typeof type === 'string' ? this.typesRegistry.get(type) : type, - }, - { fieldFormats: this.fieldFormats } - ); + aggConfig = new AggConfig(this, { + ...params, + type: typeof type === 'string' ? this.typesRegistry.get(type) : type, + }); } if (addToAggConfigs) { diff --git a/src/plugins/data/public/search/aggs/agg_type.test.ts b/src/plugins/data/public/search/aggs/agg_type.test.ts index cc45b935d45b5..99b1c4d861219 100644 --- a/src/plugins/data/public/search/aggs/agg_type.test.ts +++ b/src/plugins/data/public/search/aggs/agg_type.test.ts @@ -159,47 +159,6 @@ describe('AggType Class', () => { }); }); - describe('getFormat', function () { - let aggConfig: IAggConfig; - let field: any; - - beforeEach(() => { - aggConfig = ({ - getField: jest.fn(() => field), - } as unknown) as IAggConfig; - }); - - test('returns the formatter for the aggConfig', () => { - const aggType = new AggType( - { - name: 'name', - title: 'title', - }, - dependencies - ); - - field = { - format: 'format', - }; - - expect(aggType.getFormat(aggConfig)).toBe('format'); - }); - - test('returns default formatter', () => { - const aggType = new AggType( - { - name: 'name', - title: 'title', - }, - dependencies - ); - - field = undefined; - - expect(aggType.getFormat(aggConfig)).toBe('default'); - }); - }); - describe('getSerializedFormat', () => { test('returns the default serialized field format if it exists', () => { const aggConfig = ({ diff --git a/src/plugins/data/public/search/aggs/agg_type.ts b/src/plugins/data/public/search/aggs/agg_type.ts index e909cd8134e83..13655afdf469e 100644 --- a/src/plugins/data/public/search/aggs/agg_type.ts +++ b/src/plugins/data/public/search/aggs/agg_type.ts @@ -28,7 +28,6 @@ import { IAggConfigs } from './agg_configs'; import { Adapters } from '../../../../../plugins/inspector/public'; import { BaseParamType } from './param_types/base'; import { AggParamType } from './param_types/agg'; -import { KBN_FIELD_TYPES, IFieldFormat } from '../../../common'; import { ISearchSource } from '../search_source'; import { GetInternalStartServicesFn } from '../../types'; @@ -58,7 +57,6 @@ export interface AggTypeConfig< inspectorAdapters: Adapters, abortSignal?: AbortSignal ) => Promise; - getFormat?: (agg: TAggConfig) => IFieldFormat; getSerializedFormat?: (agg: TAggConfig) => SerializedFieldFormat; getValue?: (agg: TAggConfig, bucket: any) => any; getKey?: (bucket: any, key: any, agg: TAggConfig) => any; @@ -197,16 +195,6 @@ export class AggType< inspectorAdapters: Adapters, abortSignal?: AbortSignal ) => Promise; - /** - * Pick a format for the values produced by this agg type, - * overridden by several metrics that always output a simple - * number - * - * @param {agg} agg - the agg to pick a format for - * @return {FieldFormat} - */ - getFormat: (agg: TAggConfig) => IFieldFormat; - /** * Get the serialized format for the values produced by this agg type, * overridden by several metrics that always output a simple number. @@ -283,15 +271,6 @@ export class AggType< this.decorateAggConfig = config.decorateAggConfig || (() => ({})); this.postFlightRequest = config.postFlightRequest || identity; - this.getFormat = - config.getFormat || - ((agg: TAggConfig) => { - const field = agg.getField(); - const { fieldFormats } = getInternalStartServices(); - - return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); - }); - this.getSerializedFormat = config.getSerializedFormat || ((agg: TAggConfig) => { diff --git a/src/plugins/data/public/search/aggs/agg_types.ts b/src/plugins/data/public/search/aggs/agg_types.ts index 2af29d3600246..68542b66e6c35 100644 --- a/src/plugins/data/public/search/aggs/agg_types.ts +++ b/src/plugins/data/public/search/aggs/agg_types.ts @@ -18,7 +18,8 @@ */ import { IUiSettingsClient } from 'src/core/public'; -import { QuerySetup } from '../../query/query_service'; +import { TimeRange, TimeRangeBounds } from '../../../common'; +import { GetInternalStartServicesFn } from '../../types'; import { getCountMetricAgg } from './metrics/count'; import { getAvgMetricAgg } from './metrics/avg'; @@ -54,18 +55,16 @@ import { getBucketAvgMetricAgg } from './metrics/bucket_avg'; import { getBucketMinMetricAgg } from './metrics/bucket_min'; import { getBucketMaxMetricAgg } from './metrics/bucket_max'; -import { GetInternalStartServicesFn } from '../../types'; - export interface AggTypesDependencies { - uiSettings: IUiSettingsClient; - query: QuerySetup; + calculateBounds: (timeRange: TimeRange) => TimeRangeBounds; getInternalStartServices: GetInternalStartServicesFn; + uiSettings: IUiSettingsClient; } export const getAggTypes = ({ - uiSettings, - query, + calculateBounds, getInternalStartServices, + uiSettings, }: AggTypesDependencies) => ({ metrics: [ getCountMetricAgg({ getInternalStartServices }), @@ -91,7 +90,7 @@ export const getAggTypes = ({ getGeoCentroidMetricAgg({ getInternalStartServices }), ], buckets: [ - getDateHistogramBucketAgg({ uiSettings, query, getInternalStartServices }), + getDateHistogramBucketAgg({ calculateBounds, uiSettings, getInternalStartServices }), getHistogramBucketAgg({ uiSettings, getInternalStartServices }), getRangeBucketAgg({ getInternalStartServices }), getDateRangeBucketAgg({ uiSettings, getInternalStartServices }), diff --git a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts index 44d99375bbd30..8e862b5692ca3 100644 --- a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts @@ -26,7 +26,6 @@ import { AggConfigs, CreateAggConfigParams } from '../agg_configs'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './bucket_agg_type'; import { mockAggTypesRegistry } from '../test_helpers'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; const indexPattern = { id: '1234', @@ -220,10 +219,9 @@ const nestedOtherResponse = { describe('Terms Agg Other bucket helper', () => { const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = (aggs: CreateAggConfigParams[] = []) => { - return new AggConfigs(indexPattern, [...aggs], { typesRegistry, fieldFormats }); + return new AggConfigs(indexPattern, [...aggs], { typesRegistry }); }; describe('buildOtherBucketAgg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 2f03b8ec67112..518bdbfe0c135 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -30,7 +30,6 @@ import { import { BUCKET_TYPES } from '../bucket_agg_types'; import { RangeFilter } from '../../../../../common'; import { coreMock, notificationServiceMock } from '../../../../../../../core/public/mocks'; -import { queryServiceMock } from '../../../../query/mocks'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; import { InternalStartServices } from '../../../../types'; @@ -46,13 +45,13 @@ describe('AggConfig Filters', () => { const { uiSettings } = coreMock.createSetup(); aggTypesDependencies = { - uiSettings, - query: queryServiceMock.createSetupContract(), + calculateBounds: jest.fn(), getInternalStartServices: () => (({ fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), + uiSettings, }; mockDataServices(); @@ -82,7 +81,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); const bucketKey = 1422579600000; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index 0d66d9cfcdca2..08f39e10b6006 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -76,7 +76,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index 0fdb07cc4198a..c5ad1a61e6676 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -73,7 +73,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts index 396d515f3b580..3f9f5dd5672f0 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts @@ -23,12 +23,21 @@ import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../bucket_agg_type'; import { BytesFormat, FieldFormatsGetConfigFn } from '../../../../../common'; +import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types'; +import { FieldFormatsStart } from '../../../../field_formats'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; describe('AggConfig Filters', () => { + let getInternalStartServices: GetInternalStartServicesFn; + let fieldFormats: FieldFormatsStart; + + beforeEach(() => { + fieldFormats = fieldFormatsServiceMock.createStartContract(); + getInternalStartServices = () => (({ fieldFormats } as unknown) as InternalStartServices); + }); + describe('histogram', () => { const getConfig = (() => {}) as FieldFormatsGetConfigFn; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = () => { const field = { name: 'bytes', @@ -57,21 +66,25 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry(), fieldFormats } + { typesRegistry: mockAggTypesRegistry() } ); }; test('should return an range filter for histogram', () => { const aggConfigs = getAggConfigs(); - const filter = createFilterHistogram(aggConfigs.aggs[0] as IBucketAggConfig, '2048'); + const filter = createFilterHistogram(getInternalStartServices)( + aggConfigs.aggs[0] as IBucketAggConfig, + '2048' + ); + expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1); expect(filter).toHaveProperty('meta'); expect(filter.meta).toHaveProperty('index', '1234'); expect(filter).toHaveProperty('range'); expect(filter.range).toHaveProperty('bytes'); expect(filter.range.bytes).toHaveProperty('gte', 2048); expect(filter.range.bytes).toHaveProperty('lt', 3072); - expect(filter.meta).toHaveProperty('formattedValue', '2,048'); + expect(filter.meta).toHaveProperty('formattedValue'); }); }); }); diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts index f8e7747d49147..f3626bc9130ad 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts @@ -19,15 +19,20 @@ import { IBucketAggConfig } from '../bucket_agg_type'; import { buildRangeFilter, RangeFilterParams } from '../../../../../common'; +import { GetInternalStartServicesFn } from '../../../../types'; -export const createFilterHistogram = (aggConfig: IBucketAggConfig, key: string) => { - const value = parseInt(key, 10); - const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval }; +/** @internal */ +export const createFilterHistogram = (getInternalStartServices: GetInternalStartServicesFn) => { + return (aggConfig: IBucketAggConfig, key: string) => { + const { fieldFormats } = getInternalStartServices(); + const value = parseInt(key, 10); + const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval }; - return buildRangeFilter( - aggConfig.params.field, - params, - aggConfig.getIndexPattern(), - aggConfig.fieldFormatter()(key) - ); + return buildRangeFilter( + aggConfig.params.field, + params, + aggConfig.getIndexPattern(), + fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(key) + ); + }; }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts index 990adde5f8a0b..89a5fd6577891 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts @@ -55,7 +55,7 @@ describe('AggConfig Filters', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { typesRegistry, fieldFormats }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; test('should return a range filter for ip_range agg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts index 564e7b4763c8d..238e5737d8f47 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts @@ -24,19 +24,29 @@ import { AggConfigs } from '../../agg_configs'; import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../bucket_agg_type'; +import { FieldFormatsStart } from '../../../../field_formats'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; import { notificationServiceMock } from '../../../../../../../core/public/mocks'; -import { InternalStartServices } from '../../../../types'; +import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types'; describe('AggConfig Filters', () => { describe('range', () => { let aggTypesDependencies: RangeBucketAggDependencies; + let getInternalStartServices: GetInternalStartServicesFn; + let fieldFormats: FieldFormatsStart; beforeEach(() => { + fieldFormats = fieldFormatsServiceMock.createStartContract(); + + getInternalStartServices = () => + (({ + fieldFormats, + notifications: notificationServiceMock.createStartContract(), + } as unknown) as InternalStartServices); + aggTypesDependencies = { getInternalStartServices: () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), }; @@ -75,25 +85,28 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; test('should return a range filter for range agg', () => { const aggConfigs = getAggConfigs(); - const filter = createFilterRange(aggConfigs.aggs[0] as IBucketAggConfig, { - gte: 1024, - lt: 2048.0, - }); + const filter = createFilterRange(getInternalStartServices)( + aggConfigs.aggs[0] as IBucketAggConfig, + { + gte: 1024, + lt: 2048.0, + } + ); + expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1); expect(filter).toHaveProperty('range'); expect(filter).toHaveProperty('meta'); expect(filter.meta).toHaveProperty('index', '1234'); expect(filter.range).toHaveProperty('bytes'); expect(filter.range.bytes).toHaveProperty('gte', 1024.0); expect(filter.range.bytes).toHaveProperty('lt', 2048.0); - expect(filter.meta).toHaveProperty('formattedValue', '≥ 1,024 and < 2,048'); + expect(filter.meta).toHaveProperty('formattedValue'); }); }); }); diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts index cbad8742bfab6..f9db2973af136 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts @@ -19,12 +19,17 @@ import { IBucketAggConfig } from '../bucket_agg_type'; import { buildRangeFilter } from '../../../../../common'; +import { GetInternalStartServicesFn } from '../../../../types'; -export const createFilterRange = (aggConfig: IBucketAggConfig, params: any) => { - return buildRangeFilter( - aggConfig.params.field, - params, - aggConfig.getIndexPattern(), - aggConfig.fieldFormatter()(params) - ); +/** @internal */ +export const createFilterRange = (getInternalStartServices: GetInternalStartServicesFn) => { + return (aggConfig: IBucketAggConfig, params: any) => { + const { fieldFormats } = getInternalStartServices(); + return buildRangeFilter( + aggConfig.params.field, + params, + aggConfig.getIndexPattern(), + fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(params) + ); + }; }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts index 36e4bef025ef9..a45087916a395 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts @@ -60,7 +60,6 @@ describe('AggConfig Filters', () => { return new AggConfigs(indexPattern, aggs, { typesRegistry: mockAggTypesRegistry([getTermsBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, }); }; diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts index fc42d43b2fea8..e4c4bc0cedc3c 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -27,28 +27,30 @@ import { BucketAggType, IBucketAggConfig } from './bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { createFilterDateHistogram } from './create_filter/date_histogram'; import { intervalOptions } from './_interval_options'; -import { dateHistogramInterval, TimeRange } from '../../../../common'; import { writeParams } from '../agg_params'; import { isMetricAggType } from '../metrics/metric_agg_type'; -import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common'; -import { TimefilterContract } from '../../../query'; -import { QuerySetup } from '../../../query/query_service'; +import { + dateHistogramInterval, + KBN_FIELD_TYPES, + TimeRange, + TimeRangeBounds, + UI_SETTINGS, +} from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; import { ExtendedBounds } from './lib/extended_bounds'; -const detectedTimezone = moment.tz.guess(); -const tzOffset = moment().format('Z'); +type CalculateBoundsFn = (timeRange: TimeRange) => TimeRangeBounds; const updateTimeBuckets = ( agg: IBucketDateHistogramAggConfig, - timefilter: TimefilterContract, + calculateBounds: CalculateBoundsFn, customBuckets?: IBucketDateHistogramAggConfig['buckets'] ) => { const bounds = agg.params.timeRange && (agg.fieldIsTimeField() || agg.params.interval === 'auto') - ? timefilter.calculateBounds(agg.params.timeRange) + ? calculateBounds(agg.params.timeRange) : undefined; const buckets = customBuckets || agg.buckets; buckets.setBounds(bounds); @@ -56,9 +58,9 @@ const updateTimeBuckets = ( }; export interface DateHistogramBucketAggDependencies { - uiSettings: IUiSettingsClient; - query: QuerySetup; + calculateBounds: CalculateBoundsFn; getInternalStartServices: GetInternalStartServicesFn; + uiSettings: IUiSettingsClient; } export interface IBucketDateHistogramAggConfig extends IBucketAggConfig { @@ -83,9 +85,9 @@ export interface AggParamsDateHistogram extends BaseAggParams { } export const getDateHistogramBucketAgg = ({ - uiSettings, - query, + calculateBounds, getInternalStartServices, + uiSettings, }: DateHistogramBucketAggDependencies) => new BucketAggType( { @@ -123,35 +125,19 @@ export const getDateHistogramBucketAgg = ({ get() { if (buckets) return buckets; - const { timefilter } = query.timefilter; buckets = new TimeBuckets({ 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), dateFormat: uiSettings.get('dateFormat'), 'dateFormat:scaled': uiSettings.get('dateFormat:scaled'), }); - updateTimeBuckets(this, timefilter, buckets); + updateTimeBuckets(this, calculateBounds, buckets); return buckets; }, } as any, }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); - - if (!DateFieldFormat) { - throw new Error('Unable to retrieve Date Field Format'); - } - - return new DateFieldFormat( - { - pattern: agg.buckets.getScaledDateFormat(), - }, - (key: string) => uiSettings.get(key) - ); - }, getSerializedFormat(agg) { return { id: 'date', @@ -210,8 +196,7 @@ export const getDateHistogramBucketAgg = ({ default: 'auto', options: intervalOptions, write(agg, output, aggs) { - const { timefilter } = query.timefilter; - updateTimeBuckets(agg, timefilter); + updateTimeBuckets(agg, calculateBounds); const { useNormalizedEsInterval, scaleMetricValues } = agg.params; const interval = agg.buckets.getInterval(useNormalizedEsInterval); @@ -272,6 +257,8 @@ export const getDateHistogramBucketAgg = ({ if (!tz) { // If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz'); + const detectedTimezone = moment.tz.guess(); + const tzOffset = moment().format('Z'); tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz'); diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts index e1881c3bbc7f4..0829d6e9cdc9f 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts @@ -78,7 +78,6 @@ describe('date_range params', () => { ], { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.ts b/src/plugins/data/public/search/aggs/buckets/date_range.ts index 3e14ab422ccbe..dbcf5517fb08f 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.ts @@ -25,9 +25,9 @@ import { IUiSettingsClient } from 'src/core/public'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; -import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; +import { DateRangeKey } from './lib/date_range'; -import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -58,18 +58,6 @@ export const getDateRangeBucketAgg = ({ getKey({ from, to }): DateRangeKey { return { from, to }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - - const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE) - ); - const DateRangeFormat = FieldFormat.from(function (range: DateRangeKey) { - return convertDateRangeToString(range, formatter); - }); - return new DateRangeFormat(); - }, getSerializedFormat(agg) { return { id: 'date_range', diff --git a/src/plugins/data/public/search/aggs/buckets/filter.ts b/src/plugins/data/public/search/aggs/buckets/filter.ts index 69157edad4f68..d048df9f0e43e 100644 --- a/src/plugins/data/public/search/aggs/buckets/filter.ts +++ b/src/plugins/data/public/search/aggs/buckets/filter.ts @@ -41,6 +41,7 @@ export const getFilterBucketAgg = ({ getInternalStartServices }: FilterBucketAgg { name: BUCKET_TYPES.FILTER, title: filterTitle, + makeLabel: () => filterTitle, params: [ { name: 'geo_bounding_box', diff --git a/src/plugins/data/public/search/aggs/buckets/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/filters.test.ts index 295e740a2a780..7554e4081726c 100644 --- a/src/plugins/data/public/search/aggs/buckets/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/filters.test.ts @@ -71,7 +71,6 @@ describe('Filters Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts index 877a817984dc6..d4c0a5b328844 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -81,7 +81,6 @@ describe('Geohash Agg', () => { ], { typesRegistry: mockAggTypesRegistry(), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.ts index be339de5d7fae..fbe7c76681f81 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.ts @@ -54,6 +54,7 @@ export const getGeoHashBucketAgg = ({ getInternalStartServices }: GeoHashBucketA { name: BUCKET_TYPES.GEOHASH_GRID, title: geohashGridTitle, + makeLabel: () => geohashGridTitle, params: [ { name: 'field', diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts index 4756669f5b4b3..787603ee14361 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -74,7 +74,6 @@ describe('Histogram Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.ts b/src/plugins/data/public/search/aggs/buckets/histogram.ts index c1fad17f488db..ce275e2dc1639 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.ts @@ -67,7 +67,7 @@ export const getHistogramBucketAgg = ({ makeLabel(aggConfig) { return aggConfig.getFieldDisplayName(); }, - createFilter: createFilterHistogram, + createFilter: createFilterHistogram(getInternalStartServices), decorateAggConfig() { let autoBounds: AutoBounds; diff --git a/src/plugins/data/public/search/aggs/buckets/ip_range.ts b/src/plugins/data/public/search/aggs/buckets/ip_range.ts index b3e90bdf9b56a..018fcb365b585 100644 --- a/src/plugins/data/public/search/aggs/buckets/ip_range.ts +++ b/src/plugins/data/public/search/aggs/buckets/ip_range.ts @@ -23,13 +23,8 @@ import { BucketAggType } from './bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { createFilterIpRange } from './create_filter/ip_range'; -import { - convertIPRangeToString, - IpRangeKey, - RangeIpRangeAggKey, - CidrMaskIpRangeAggKey, -} from './lib/ip_range'; -import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common'; +import { IpRangeKey, RangeIpRangeAggKey, CidrMaskIpRangeAggKey } from './lib/ip_range'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -67,17 +62,6 @@ export const getIpRangeBucketAgg = ({ getInternalStartServices }: IpRangeBucketA } return { type: 'range', from: bucket.from, to: bucket.to }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP) - ); - const IpRangeFormat = FieldFormat.from(function (range: IpRangeKey) { - return convertIPRangeToString(range, formatter); - }); - return new IpRangeFormat(); - }, getSerializedFormat(agg) { return { id: 'ip_range', diff --git a/src/plugins/data/public/search/aggs/buckets/range.test.ts b/src/plugins/data/public/search/aggs/buckets/range.test.ts index 2b8a36f2fbdbc..fea5572b75795 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.test.ts @@ -22,30 +22,9 @@ import { AggConfigs } from '../agg_configs'; import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { FieldFormatsGetConfigFn, NumberFormat } from '../../../../common'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; import { InternalStartServices } from '../../../types'; -const buckets = [ - { - to: 1024, - to_as_string: '1024.0', - doc_count: 20904, - }, - { - from: 1024, - from_as_string: '1024.0', - to: 2560, - to_as_string: '2560.0', - doc_count: 23358, - }, - { - from: 2560, - from_as_string: '2560.0', - doc_count: 174250, - }, -]; - describe('Range Agg', () => { let aggTypesDependencies: RangeBucketAggDependencies; @@ -53,7 +32,6 @@ describe('Range Agg', () => { aggTypesDependencies = { getInternalStartServices: () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), }; @@ -99,23 +77,10 @@ describe('Range Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; - describe('formatting', () => { - test('formats bucket keys properly', () => { - const aggConfigs = getAggConfigs(); - const agg = aggConfigs.aggs[0]; - const format = (val: any) => agg.fieldFormatter()(agg.getKey(val)); - - expect(format(buckets[0])).toBe('≥ -∞ and < 1 KB'); - expect(format(buckets[1])).toBe('≥ 1 KB and < 2.5 KB'); - expect(format(buckets[2])).toBe('≥ 2.5 KB and < +∞'); - }); - }); - describe('getSerializedFormat', () => { test('generates a serialized field format in the expected shape', () => { const aggConfigs = getAggConfigs(); diff --git a/src/plugins/data/public/search/aggs/buckets/range.ts b/src/plugins/data/public/search/aggs/buckets/range.ts index 543e5d66b9fa8..92c5193d55a20 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.ts @@ -19,16 +19,13 @@ import { i18n } from '@kbn/i18n'; import { BucketAggType } from './bucket_agg_type'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { RangeKey } from './range_key'; import { createFilterRange } from './create_filter/range'; import { BUCKET_TYPES } from './bucket_agg_types'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; -const keyCaches = new WeakMap(); -const formats = new WeakMap(); - const rangeTitle = i18n.translate('data.search.aggs.buckets.rangeTitle', { defaultMessage: 'Range', }); @@ -45,12 +42,14 @@ export interface AggParamsRange extends BaseAggParams { }>; } -export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) => - new BucketAggType( +export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) => { + const keyCaches = new WeakMap(); + + return new BucketAggType( { name: BUCKET_TYPES.RANGE, title: rangeTitle, - createFilter: createFilterRange, + createFilter: createFilterRange(getInternalStartServices), makeLabel(aggConfig) { return i18n.translate('data.search.aggs.aggTypesLabel', { defaultMessage: '{fieldName} ranges', @@ -77,30 +76,6 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe return key; }, - getFormat(agg) { - let aggFormat = formats.get(agg); - if (aggFormat) return aggFormat; - - const RangeFormat = FieldFormat.from((range: any) => { - const format = agg.fieldOwnFormatter(); - const gte = '\u2265'; - const lt = '\u003c'; - return i18n.translate('data.search.aggs.aggTypes.rangesFormatMessage', { - defaultMessage: '{gte} {from} and {lt} {to}', - values: { - gte, - from: format(range.gte), - lt, - to: format(range.lt), - }, - }); - }); - - aggFormat = new RangeFormat(); - - formats.set(agg, aggFormat); - return aggFormat; - }, getSerializedFormat(agg) { const format = agg.params.field ? agg.params.field.format.toJSON() : {}; return { @@ -132,3 +107,4 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe }, { getInternalStartServices } ); +}; diff --git a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts index 156f7f8108482..8fe833aa99cb2 100644 --- a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -72,7 +72,6 @@ describe('Significant Terms Agg', () => { typesRegistry: mockAggTypesRegistry([ getSignificantTermsBucketAgg(aggTypesDependencies), ]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/terms.test.ts index 9769efb6da749..2c5be00c8afea 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.test.ts @@ -20,11 +20,9 @@ import { AggConfigs } from '../agg_configs'; import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; describe('Terms Agg', () => { describe('order agg editor UI', () => { - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -49,7 +47,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - { typesRegistry: mockAggTypesRegistry(), fieldFormats } + { typesRegistry: mockAggTypesRegistry() } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/terms.ts b/src/plugins/data/public/search/aggs/buckets/terms.ts index 1e8e9ab4ef9d0..57a5ebf72316c 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.ts @@ -30,7 +30,7 @@ import { AggConfigSerialized, BaseAggParams, IAggConfigs } from '../types'; import { Adapters } from '../../../../../inspector/public'; import { ISearchSource } from '../../search_source'; -import { IFieldFormat, FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { getRequestInspectorStats, getResponseInspectorStats } from '../../expressions'; import { @@ -88,22 +88,6 @@ export const getTermsBucketAgg = ({ getInternalStartServices }: TermsBucketAggDe const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.text; }, - getFormat(bucket): IFieldFormat { - return { - getConverterFor: (type: FieldFormatsContentType) => { - return (val: any) => { - if (val === '__other__') { - return bucket.params.otherBucketLabel; - } - if (val === '__missing__') { - return bucket.params.missingBucketLabel; - } - - return bucket.params.field.format.convert(val, type); - }; - }, - } as IFieldFormat; - }, getSerializedFormat(agg) { const format = agg.params.field ? agg.params.field.format.toJSON() : {}; return { diff --git a/src/plugins/data/public/search/aggs/index.test.ts b/src/plugins/data/public/search/aggs/index.test.ts index 4864a8b9d013b..73068326ca97e 100644 --- a/src/plugins/data/public/search/aggs/index.test.ts +++ b/src/plugins/data/public/search/aggs/index.test.ts @@ -22,7 +22,6 @@ import { getAggTypes } from './index'; import { isBucketAggType } from './buckets/bucket_agg_type'; import { isMetricAggType } from './metrics/metric_agg_type'; -import { QueryStart } from '../../query'; import { FieldFormatsStart } from '../../field_formats'; import { InternalStartServices } from '../../types'; @@ -31,13 +30,13 @@ describe('AggTypesComponent', () => { const coreStart = coreMock.createSetup(); const aggTypes = getAggTypes({ - uiSettings: coreSetup.uiSettings, - query: {} as QueryStart, + calculateBounds: jest.fn(), getInternalStartServices: () => (({ notifications: coreStart.notifications, fieldFormats: {} as FieldFormatsStart, } as unknown) as InternalStartServices), + uiSettings: coreSetup.uiSettings, }); const { buckets, metrics } = aggTypes; diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts index 38312ec5cfa81..a30e426dd2390 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts @@ -46,7 +46,7 @@ const averageBucketTitle = i18n.translate('data.search.aggs.metrics.averageBucke export const getBucketAvgMetricAgg = ({ getInternalStartServices, }: BucketAvgMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getBucketAvgMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallAverageLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, getValue(agg, bucket) { const customMetric = agg.getParam('customMetric'); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts index e2c6a5105bac6..307c7ed3f9d38 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts @@ -45,7 +45,7 @@ const maxBucketTitle = i18n.translate('data.search.aggs.metrics.maxBucketTitle', export const getBucketMaxMetricAgg = ({ getInternalStartServices, }: BucketMaxMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketMaxMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallMaxLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts index c46a3eb9425d1..bb4ed9d44b0b3 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts @@ -45,7 +45,7 @@ const minBucketTitle = i18n.translate('data.search.aggs.metrics.minBucketTitle', export const getBucketMinMetricAgg = ({ getInternalStartServices, }: BucketMinMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketMinMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallMinLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts index 57212ec9ff91b..dd065b52acd12 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts @@ -45,7 +45,7 @@ const sumBucketTitle = i18n.translate('data.search.aggs.metrics.sumBucketTitle', export const getBucketSumMetricAgg = ({ getInternalStartServices, }: BucketSumMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketSumMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallSumLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/cardinality.ts b/src/plugins/data/public/search/aggs/metrics/cardinality.ts index 2855cc1b6b16e..efc79a8559566 100644 --- a/src/plugins/data/public/search/aggs/metrics/cardinality.ts +++ b/src/plugins/data/public/search/aggs/metrics/cardinality.ts @@ -49,11 +49,6 @@ export const getCardinalityMetricAgg = ({ values: { field: aggConfig.getFieldDisplayName() }, }); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }, getSerializedFormat(agg) { return { id: 'number', diff --git a/src/plugins/data/public/search/aggs/metrics/count.ts b/src/plugins/data/public/search/aggs/metrics/count.ts index 4c7b8139b0162..86faca053a9cf 100644 --- a/src/plugins/data/public/search/aggs/metrics/count.ts +++ b/src/plugins/data/public/search/aggs/metrics/count.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; export interface CountMetricAggDependencies { @@ -40,11 +39,6 @@ export const getCountMetricAgg = ({ getInternalStartServices }: CountMetricAggDe defaultMessage: 'Count', }); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }, getSerializedFormat(agg) { return { id: 'number', diff --git a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts index c392f44a7961e..3de88bb71740f 100644 --- a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts @@ -46,7 +46,7 @@ const cumulativeSumTitle = i18n.translate('data.search.aggs.metrics.cumulativeSu export const getCumulativeSumMetricAgg = ({ getInternalStartServices, }: CumulativeSumMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getCumulativeSumMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, cumulativeSumLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/derivative.ts b/src/plugins/data/public/search/aggs/metrics/derivative.ts index f3c1cc9bc2977..c9507029080e6 100644 --- a/src/plugins/data/public/search/aggs/metrics/derivative.ts +++ b/src/plugins/data/public/search/aggs/metrics/derivative.ts @@ -46,7 +46,7 @@ const derivativeTitle = i18n.translate('data.search.aggs.metrics.derivativeTitle export const getDerivativeMetricAgg = ({ getInternalStartServices, }: DerivativeMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -57,7 +57,6 @@ export const getDerivativeMetricAgg = ({ }, subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts b/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts index 2a74a446ce84e..73acd26860076 100644 --- a/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts +++ b/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts @@ -18,14 +18,12 @@ */ import { i18n } from '@kbn/i18n'; -import { noop, identity } from 'lodash'; +import { noop } from 'lodash'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { parentPipelineAggWriter } from './parent_pipeline_agg_writer'; -import { FieldFormat } from '../../../../../common'; - const metricAggFilter = [ '!top_hits', '!percentiles', @@ -73,18 +71,6 @@ export const parentPipelineAggHelper = { ] as Array>; }, - getFormat(agg: IMetricAggConfig) { - let subAgg; - const customMetric = agg.getParam('customMetric'); - - if (customMetric) { - subAgg = customMetric; - } else { - subAgg = agg.aggConfigs.byId(agg.getParam('metricAgg')); - } - return subAgg ? subAgg.type.getFormat(subAgg) : new (FieldFormat.from(identity))(); - }, - getSerializedFormat(agg: IMetricAggConfig) { let subAgg; const customMetric = agg.getParam('customMetric'); diff --git a/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts b/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts index 8e3e0143bf915..347ac76b8e27b 100644 --- a/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts +++ b/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts @@ -17,12 +17,10 @@ * under the License. */ -import { identity } from 'lodash'; import { i18n } from '@kbn/i18n'; import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; -import { FieldFormat } from '../../../../../common'; const metricAggFilter: string[] = [ '!top_hits', @@ -87,13 +85,6 @@ export const siblingPipelineAggHelper = { ] as Array>; }, - getFormat(agg: IMetricAggConfig) { - const customMetric = agg.getParam('customMetric'); - return customMetric - ? customMetric.type.getFormat(customMetric) - : new (FieldFormat.from(identity))(); - }, - getSerializedFormat(agg: IMetricAggConfig) { const customMetric = agg.getParam('customMetric'); return customMetric ? customMetric.type.getSerializedFormat(customMetric) : {}; diff --git a/src/plugins/data/public/search/aggs/metrics/median.test.ts b/src/plugins/data/public/search/aggs/metrics/median.test.ts index 71c48f04a3ca8..b3721e2c1e679 100644 --- a/src/plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/median.test.ts @@ -63,7 +63,6 @@ describe('AggTypeMetricMedianProvider class', () => { ], { typesRegistry, - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts b/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts index 83656db4ac547..5c4ff91258fb0 100644 --- a/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts +++ b/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts @@ -22,7 +22,6 @@ import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; import { METRIC_TYPES } from './metric_agg_types'; -import { KBN_FIELD_TYPES } from '../../../../common'; import { FieldTypes } from '../param_types'; import { GetInternalStartServicesFn } from '../../../types'; @@ -82,14 +81,6 @@ export class MetricAggType { - const { fieldFormats } = dependencies.getInternalStartServices(); - const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }); - this.subtype = config.subtype || i18n.translate('data.search.aggs.metrics.metricAggregationsSubtypeTitle', { diff --git a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts index abad2782f9d20..61384ef1dc106 100644 --- a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts @@ -48,7 +48,7 @@ const movingAvgLabel = i18n.translate('data.search.aggs.metrics.movingAvgLabel', export const getMovingAvgMetricAgg = ({ getInternalStartServices, }: MovingAvgMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -57,7 +57,6 @@ export const getMovingAvgMetricAgg = ({ title: movingAvgTitle, makeLabel: (agg) => makeNestedLabel(agg, movingAvgLabel), subtype, - getFormat, getSerializedFormat, params: [ ...params(), diff --git a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts index 2201366cdf78b..91149a3f29f94 100644 --- a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts @@ -24,14 +24,12 @@ import { getSerialDiffMetricAgg } from './serial_diff'; import { AggConfigs } from '../agg_configs'; import { mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { GetInternalStartServicesFn, InternalStartServices } from '../../../types'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; describe('parent pipeline aggs', function () { const getInternalStartServices: GetInternalStartServicesFn = () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices); @@ -76,9 +74,7 @@ describe('parent pipeline aggs', function () { const field = { name: 'field', format: { - type: { - id: 'bytes', - }, + toJSON: () => ({ id: 'bytes' }), }, }; const indexPattern = { @@ -111,7 +107,7 @@ describe('parent pipeline aggs', function () { schema: 'metric', }, ], - { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -197,14 +193,14 @@ describe('parent pipeline aggs', function () { ); }); - it('should have correct formatter', () => { + it('should have correct serialized format', () => { init({ metricAgg: '3', }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); - it('should have correct customMetric nested formatter', () => { + it('should have correct customMetric nested serialized format', () => { init({ metricAgg: 'custom', customMetric: { @@ -222,7 +218,7 @@ describe('parent pipeline aggs', function () { schema: 'orderAgg', }, }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); it("should call modifyAggConfigOnSearchRequestStart for its customMetric's parameters", () => { diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts index df52c10a82495..39e371763ed4b 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts @@ -74,7 +74,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function () { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts index c5aee380b9776..1953c81a99874 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts @@ -22,7 +22,7 @@ import { MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; -import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -96,13 +96,6 @@ export const getPercentileRanksMetricAgg = ({ return values.map((value: any) => new ValueAggConfig(value)); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - return ( - fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) || - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) - ); - }, getSerializedFormat(agg) { return { id: 'percent', diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts index 76382c01bcc10..52ab325ac5806 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts @@ -67,7 +67,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts index 7cb1b194fed1c..9ea01be11fe8f 100644 --- a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts +++ b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts @@ -46,7 +46,7 @@ const serialDiffLabel = i18n.translate('data.search.aggs.metrics.serialDiffLabel export const getSerialDiffMetricAgg = ({ getInternalStartServices, }: SerialDiffMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getSerialDiffMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, serialDiffLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts index 56bd33b2b6345..f08e850caadce 100644 --- a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts @@ -25,14 +25,12 @@ import { getBucketMaxMetricAgg } from './bucket_max'; import { AggConfigs } from '../agg_configs'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { mockAggTypesRegistry } from '../test_helpers'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { GetInternalStartServicesFn, InternalStartServices } from '../../../types'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; describe('sibling pipeline aggs', () => { const getInternalStartServices: GetInternalStartServicesFn = () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices); @@ -71,9 +69,7 @@ describe('sibling pipeline aggs', () => { const field = { name: 'field', format: { - type: { - id: 'bytes', - }, + toJSON: () => ({ id: 'bytes' }), }, }; const indexPattern = { @@ -112,7 +108,7 @@ describe('sibling pipeline aggs', () => { }, }, ], - { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -155,7 +151,7 @@ describe('sibling pipeline aggs', () => { expect(aggDsl.parentAggs['2-bucket'].aggs['2-metric'].avg.field).toEqual('field'); }); - it('should have correct formatter', () => { + it('should have correct serialized field format', () => { init({ customMetric: { id: '5', @@ -171,7 +167,7 @@ describe('sibling pipeline aggs', () => { }, }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); it("should call modifyAggConfigOnSearchRequestStart for nested aggs' parameters", () => { diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts index 536764b2bcf0b..2fa207e62771e 100644 --- a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts @@ -66,7 +66,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }; diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts index 49e0a3e4b349a..94a970a72a46f 100644 --- a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts @@ -91,7 +91,7 @@ describe('Top hit metric', () => { params, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/plugins/data/public/search/aggs/mocks.ts b/src/plugins/data/public/search/aggs/mocks.ts index 16544fd8f46b0..7a5dcc9be4592 100644 --- a/src/plugins/data/public/search/aggs/mocks.ts +++ b/src/plugins/data/public/search/aggs/mocks.ts @@ -27,7 +27,6 @@ import { } from './'; import { SearchAggsSetup, SearchAggsStart } from './types'; import { mockAggTypesRegistry } from './test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; const aggTypeBaseParamMock = () => ({ name: 'some_param', @@ -73,7 +72,6 @@ export const searchAggsStartMock = (): SearchAggsStart => ({ createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: mockAggTypesRegistry(), - fieldFormats: fieldFormatsServiceMock.createStartContract(), }); }), types: mockAggTypesRegistry(), diff --git a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts index 836aaad2cda0c..385d0cd6c6b39 100644 --- a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts +++ b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts @@ -22,7 +22,6 @@ import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry'; import { getAggTypes } from '../agg_types'; import { BucketAggType } from '../buckets/bucket_agg_type'; import { MetricAggType } from '../metrics/metric_agg_type'; -import { queryServiceMock } from '../../../query/mocks'; import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { InternalStartServices } from '../../../types'; import { TimeBucketsConfig } from '../buckets/lib/time_buckets/time_buckets'; @@ -79,8 +78,7 @@ export function mockAggTypesRegistry | MetricAggTyp coreSetup.uiSettings.get = mockUiSettings; const aggTypes = getAggTypes({ - uiSettings: coreSetup.uiSettings, - query: queryServiceMock.createSetupContract(), + calculateBounds: jest.fn(), getInternalStartServices: () => (({ fieldFormats: fieldFormatsServiceMock.createStartContract(), @@ -88,6 +86,7 @@ export function mockAggTypesRegistry | MetricAggTyp uiSettings: coreStart.uiSettings, injectedMetadata: coreStart.injectedMetadata, } as unknown) as InternalStartServices), + uiSettings: coreSetup.uiSettings, }); aggTypes.buckets.forEach((type) => registrySetup.registerBucket(type)); diff --git a/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts b/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts index 906b8862d00aa..c4846a98f124f 100644 --- a/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts +++ b/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts @@ -19,6 +19,7 @@ import { set } from 'lodash'; import { FormattedData } from '../../../../../plugins/inspector/public'; +import { FormatFactory } from '../../../common/field_formats/utils'; import { TabbedTable } from '../tabify'; import { createFilter } from './create_filter'; @@ -38,14 +39,30 @@ import { createFilter } from './create_filter'; */ export async function buildTabularInspectorData( table: TabbedTable, - queryFilter: { addFilters: (filter: any) => void } + { + queryFilter, + deserializeFieldFormat, + }: { + queryFilter: { addFilters: (filter: any) => void }; + deserializeFieldFormat: FormatFactory; + } ) { const aggConfigs = table.columns.map((column) => column.aggConfig); const rows = table.rows.map((row) => { return table.columns.reduce>((prev, cur, colIndex) => { const value = row[cur.id]; - const fieldFormatter = cur.aggConfig.fieldFormatter('text'); - prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData(value, fieldFormatter(value)); + + let format = cur.aggConfig.toSerializedFieldFormat(); + if (Object.keys(format).length < 1) { + // If no format exists, fall back to string as a default + format = { id: 'string' }; + } + const fieldFormatter = deserializeFieldFormat(format); + + prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData( + value, + fieldFormatter.convert(value) + ); return prev; }, {}); }); diff --git a/src/plugins/data/public/search/expressions/create_filter.test.ts b/src/plugins/data/public/search/expressions/create_filter.test.ts index 51b5e175761bd..23da060cba203 100644 --- a/src/plugins/data/public/search/expressions/create_filter.test.ts +++ b/src/plugins/data/public/search/expressions/create_filter.test.ts @@ -22,12 +22,10 @@ import { AggConfigs, IAggConfig } from '../aggs'; import { TabbedTable } from '../tabify'; import { isRangeFilter, BytesFormat, FieldFormatsGetConfigFn } from '../../../common'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('createFilter', () => { let table: TabbedTable; let aggConfig: IAggConfig; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const typesRegistry = mockAggTypesRegistry(); @@ -60,7 +58,7 @@ describe('createFilter', () => { params, }, ], - { typesRegistry, fieldFormats } + { typesRegistry } ); }; diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 77475cd3ce88b..e9daec0b4191b 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -32,9 +32,22 @@ import { Adapters } from '../../../../../plugins/inspector/public'; import { IAggConfigs } from '../aggs'; import { ISearchSource } from '../search_source'; import { tabifyAggResponse } from '../tabify'; -import { Filter, Query, TimeRange, IIndexPattern, isRangeFilter } from '../../../common'; -import { FilterManager, calculateBounds, getTime } from '../../query'; -import { getSearchService, getQueryService, getIndexPatterns } from '../../services'; +import { + calculateBounds, + Filter, + getTime, + IIndexPattern, + isRangeFilter, + Query, + TimeRange, +} from '../../../common'; +import { FilterManager } from '../../query'; +import { + getFieldFormats, + getIndexPatterns, + getQueryService, + getSearchService, +} from '../../services'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils'; @@ -220,7 +233,11 @@ const handleCourierRequest = async ({ } inspectorAdapters.data.setTabularLoader( - () => buildTabularInspectorData((searchSource as any).tabifiedResponse, filterManager), + () => + buildTabularInspectorData((searchSource as any).tabifiedResponse, { + queryFilter: filterManager, + deserializeFieldFormat: getFieldFormats().deserialize, + }), { returnsFormattedValues: true } ); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index d5997c15817f6..134dc89c2421a 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -25,10 +25,11 @@ import { ExpressionsSetup } from '../../../../plugins/expressions/public'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; import { TStrategyTypes } from './strategy_types'; import { getEsClient, LegacyApiCaller } from './legacy'; +import { getForceNow } from '../query/timefilter/lib/get_force_now'; +import { calculateBounds, TimeRange } from '../../common/query'; import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search'; import { esSearchStrategyProvider } from './es_search'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; -import { QuerySetup } from '../query'; import { GetInternalStartServicesFn } from '../types'; import { SearchInterceptor } from './search_interceptor'; import { @@ -38,19 +39,16 @@ import { AggConfigs, getCalculateAutoTimeExpression, } from './aggs'; -import { FieldFormatsStart } from '../field_formats'; import { ISearchGeneric } from './i_search'; interface SearchServiceSetupDependencies { expressions: ExpressionsSetup; getInternalStartServices: GetInternalStartServicesFn; packageInfo: PackageInfo; - query: QuerySetup; } interface SearchServiceStartDependencies { indexPatterns: IndexPatternsContract; - fieldFormats: FieldFormatsStart; } /** @@ -85,9 +83,16 @@ export class SearchService implements Plugin { return strategy; }; + /** + * getForceNow uses window.location, so we must have a separate implementation + * of calculateBounds on the client and the server. + */ + private calculateBounds = (timeRange: TimeRange) => + calculateBounds(timeRange, { forceNow: getForceNow() }); + public setup( core: CoreSetup, - { expressions, packageInfo, query, getInternalStartServices }: SearchServiceSetupDependencies + { expressions, packageInfo, getInternalStartServices }: SearchServiceSetupDependencies ): ISearchSetup { this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo); @@ -100,9 +105,9 @@ export class SearchService implements Plugin { // register each agg type const aggTypes = getAggTypes({ - query, - uiSettings: core.uiSettings, + calculateBounds: this.calculateBounds, getInternalStartServices, + uiSettings: core.uiSettings, }); aggTypes.buckets.forEach((b) => aggTypesSetup.registerBucket(b)); aggTypes.metrics.forEach((m) => aggTypesSetup.registerMetric(m)); @@ -158,7 +163,6 @@ export class SearchService implements Plugin { calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings), createAggConfigs: (indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { - fieldFormats: dependencies.fieldFormats, typesRegistry: aggTypesStart, }); }, diff --git a/src/plugins/data/public/search/tabify/get_columns.test.ts b/src/plugins/data/public/search/tabify/get_columns.test.ts index b4498aca4079c..0c5551d95690f 100644 --- a/src/plugins/data/public/search/tabify/get_columns.test.ts +++ b/src/plugins/data/public/search/tabify/get_columns.test.ts @@ -21,7 +21,6 @@ import { tabifyGetColumns } from './get_columns'; import { TabbedAggColumn } from './types'; import { AggConfigs } from '../aggs'; import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('get columns', () => { beforeEach(() => { @@ -29,7 +28,6 @@ describe('get columns', () => { }); const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: any[] = []) => { const field = { @@ -45,10 +43,7 @@ describe('get columns', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; test('should inject the metric after each bucket if the vis is hierarchical', () => { diff --git a/src/plugins/data/public/search/tabify/response_writer.test.ts b/src/plugins/data/public/search/tabify/response_writer.test.ts index 3334d858ce54e..94473d23ccc39 100644 --- a/src/plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/plugins/data/public/search/tabify/response_writer.test.ts @@ -21,7 +21,6 @@ import { TabbedAggResponseWriter } from './response_writer'; import { AggConfigs, BUCKET_TYPES } from '../aggs'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; import { TabbedResponseWriterOptions } from './types'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('TabbedAggResponseWriter class', () => { beforeEach(() => { @@ -31,7 +30,6 @@ describe('TabbedAggResponseWriter class', () => { let responseWriter: TabbedAggResponseWriter; const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const splitAggConfig = [ { @@ -73,17 +71,11 @@ describe('TabbedAggResponseWriter class', () => { }, } as any; - return new TabbedAggResponseWriter( - new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }), - { - metricsAtAllLevels: false, - partialRows: false, - ...opts, - } - ); + return new TabbedAggResponseWriter(new AggConfigs(indexPattern, aggs, { typesRegistry }), { + metricsAtAllLevels: false, + partialRows: false, + ...opts, + }); }; describe('Constructor', () => { diff --git a/src/plugins/data/public/search/tabify/tabify.test.ts b/src/plugins/data/public/search/tabify/tabify.test.ts index f6691360cec31..0a1e99c8bb200 100644 --- a/src/plugins/data/public/search/tabify/tabify.test.ts +++ b/src/plugins/data/public/search/tabify/tabify.test.ts @@ -22,11 +22,9 @@ import { IndexPattern } from '../../index_patterns'; import { AggConfigs, IAggConfig, IAggConfigs } from '../aggs'; import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('tabifyAggResponse Integration', () => { const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: IAggConfig[] = []) => { const field = { @@ -42,10 +40,7 @@ describe('tabifyAggResponse Integration', () => { }, } as unknown) as IndexPattern; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 19d028c1d41e1..6a4eb38b552ff 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -202,6 +202,7 @@ export { castEsToKbnFieldTypeName, // query Filter, + getTime, Query, // timefilter RefreshInterval, diff --git a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts index f563976cae9b8..ff9d67152e268 100644 --- a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { getFieldCapabilities, resolveTimePattern, createNoMatchingIndicesError } from './lib'; @@ -37,9 +37,9 @@ interface FieldSubType { } export class IndexPatternsFetcher { - private _callDataCluster: APICaller; + private _callDataCluster: LegacyAPICaller; - constructor(callDataCluster: APICaller) { + constructor(callDataCluster: LegacyAPICaller) { this._callDataCluster = callDataCluster; } diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts index 734e845e85769..0738a16034d46 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { convertEsError } from './errors'; import { FieldCapsResponse } from './field_capabilities'; @@ -46,7 +46,7 @@ export interface IndexAliasResponse { * @return {Promise} */ export async function callIndexAliasApi( - callCluster: APICaller, + callCluster: LegacyAPICaller, indices: string[] | string ): Promise { try { @@ -71,7 +71,7 @@ export async function callIndexAliasApi( * @param {Array|String} indices * @return {Promise} */ -export async function callFieldCapsApi(callCluster: APICaller, indices: string[] | string) { +export async function callFieldCapsApi(callCluster: LegacyAPICaller, indices: string[] | string) { try { return (await callCluster('fieldCaps', { index: indices, diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts index d8c9466432204..502364cdcba32 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts @@ -19,7 +19,7 @@ import { defaults, indexBy, sortBy } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { callFieldCapsApi } from '../es_api'; import { FieldCapsResponse, readFieldCapsResponse } from './field_caps_response'; import { mergeOverrides } from './overrides'; @@ -39,7 +39,7 @@ export function concatIfUniq(arr: T[], value: T) { * @return {Promise>} */ export async function getFieldCapabilities( - callCluster: APICaller, + callCluster: LegacyAPICaller, indices: string | string[] = [], metaFields: string[] = [] ) { diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts index 764307bef0ba6..a01d34dbe9df6 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts @@ -20,7 +20,7 @@ import { chain } from 'lodash'; import moment from 'moment'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { timePatternToWildcard } from './time_pattern_to_wildcard'; import { callIndexAliasApi, IndicesAliasResponse } from './es_api'; @@ -36,7 +36,7 @@ import { callIndexAliasApi, IndicesAliasResponse } from './es_api'; * and the indices that actually match the time * pattern (matches); */ -export async function resolveTimePattern(callCluster: APICaller, timePattern: string) { +export async function resolveTimePattern(callCluster: LegacyAPICaller, timePattern: string) { const aliases = await callIndexAliasApi(callCluster, timePatternToWildcard(timePattern)); const allIndexDetails = chain(aliases) diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts index 81e352fea51b2..35cee799ddb6a 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts @@ -18,7 +18,7 @@ */ import { fetchProvider } from './fetch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; jest.mock('../../../common', () => ({ DEFAULT_QUERY_LANGUAGE: 'lucene', @@ -28,7 +28,7 @@ jest.mock('../../../common', () => ({ })); let fetch: ReturnType; -let callCluster: APICaller; +let callCluster: LegacyAPICaller; function setupMockCallCluster( optCount: { optInCount?: number; optOutCount?: number } | null, @@ -78,7 +78,7 @@ function setupMockCallCluster( } throw new Error('invalid call'); - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; } describe('makeKQLUsageCollector', () => { diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts index 29f9be903a36f..109d6f812334d 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts @@ -18,7 +18,7 @@ */ import { get } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { DEFAULT_QUERY_LANGUAGE, UI_SETTINGS } from '../../../common'; const defaultSearchQueryLanguageSetting = DEFAULT_QUERY_LANGUAGE; @@ -30,7 +30,7 @@ export interface Usage { } export function fetchProvider(index: string) { - return async (callCluster: APICaller): Promise => { + return async (callCluster: LegacyAPICaller): Promise => { const [response, config] = await Promise.all([ callCluster('get', { index, diff --git a/src/plugins/data/server/saved_objects/index_patterns.ts b/src/plugins/data/server/saved_objects/index_patterns.ts index ee02f38427914..902cf2988f429 100644 --- a/src/plugins/data/server/saved_objects/index_patterns.ts +++ b/src/plugins/data/server/saved_objects/index_patterns.ts @@ -37,7 +37,7 @@ export const indexPatternSavedObjectType: SavedObjectsType = { getInAppUrl(obj) { return { path: `/app/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }; }, }, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 136d960b52c34..24ce42e2c20ae 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -4,7 +4,6 @@ ```ts -import { APICaller as APICaller_2 } from 'kibana/server'; import Boom from 'boom'; import { BulkIndexDocumentsParams } from 'elasticsearch'; import { CatAliasesParams } from 'elasticsearch'; @@ -92,6 +91,7 @@ import { IngestGetPipelineParams } from 'elasticsearch'; import { IngestPutPipelineParams } from 'elasticsearch'; import { IngestSimulateParams } from 'elasticsearch'; import { KibanaConfigType as KibanaConfigType_2 } from 'src/core/server/kibana_config'; +import { LegacyAPICaller as LegacyAPICaller_2 } from 'kibana/server'; import { Logger as Logger_2 } from 'kibana/server'; import { MGetParams } from 'elasticsearch'; import { MGetResponse } from 'elasticsearch'; @@ -109,7 +109,7 @@ import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; -import { RecursiveReadonly } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -335,6 +335,14 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; + // @internal export function getTotalLoaded({ total, failed, successful }: ShardsResponse): { total: number; @@ -477,7 +485,7 @@ export const indexPatterns: { // // @public (undocumented) export class IndexPatternsFetcher { - constructor(callDataCluster: APICaller_2); + constructor(callDataCluster: LegacyAPICaller_2); getFieldsForTimePattern(options: { pattern: string; metaFields: string[]; diff --git a/src/plugins/expressions/server/legacy.ts b/src/plugins/expressions/server/legacy.ts index 4dd9419e59e2d..8ff08542f18f8 100644 --- a/src/plugins/expressions/server/legacy.ts +++ b/src/plugins/expressions/server/legacy.ts @@ -26,7 +26,7 @@ import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common import Boom from 'boom'; import { schema } from '@kbn/config-schema'; -import { CoreSetup, Logger, APICaller } from 'src/core/server'; +import { CoreSetup, Logger, LegacyAPICaller } from 'src/core/server'; import { ExpressionsServerSetupDependencies } from './plugin'; import { typeSpecs, ExpressionType } from '../common'; import { serializeProvider } from '../common'; @@ -98,7 +98,7 @@ export const createLegacyServerEndpoints = ( * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` */ async function runFunction( - handlers: { environment: string; elasticsearchClient: APICaller }, + handlers: { environment: string; elasticsearchClient: LegacyAPICaller }, fnCall: any ) { const { functionName, args, context } = fnCall; diff --git a/src/plugins/home/server/capabilities_provider.ts b/src/plugins/home/server/capabilities_provider.ts index 1c662e2301e16..5e86e0ca54bf7 100644 --- a/src/plugins/home/server/capabilities_provider.ts +++ b/src/plugins/home/server/capabilities_provider.ts @@ -24,6 +24,6 @@ export const capabilitiesProvider = () => ({ visualize: true, console: true, advanced_settings: true, - index_patterns: true, + indexPatterns: true, }, }); diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index a98cc05a0a80a..6e93d23f8469c 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -27,7 +27,7 @@ import { IndexPatternManagementServiceStart, } from './service'; -import { ManagementSetup, ManagementApp, ManagementSectionId } from '../../management/public'; +import { ManagementSetup, ManagementSectionId } from '../../management/public'; export interface IndexPatternManagementSetupDependencies { management: ManagementSetup; @@ -57,7 +57,6 @@ export class IndexPatternManagementPlugin IndexPatternManagementStartDependencies > { private readonly indexPatternManagementService = new IndexPatternManagementService(); - private managementApp?: ManagementApp; constructor(initializerContext: PluginInitializerContext) {} @@ -80,7 +79,7 @@ export class IndexPatternManagementPlugin return pathInApp && `/patterns${pathInApp}`; }); - this.managementApp = kibanaSection.registerApp({ + kibanaSection.registerApp({ id: IPM_APP_ID, title: sectionsHeader, order: 0, @@ -95,10 +94,6 @@ export class IndexPatternManagementPlugin } public start(core: CoreStart, plugins: IndexPatternManagementStartDependencies) { - if (!core.application.capabilities.management.kibana.index_patterns) { - this.managementApp!.disable(); - } - return this.indexPatternManagementService.start(); } diff --git a/src/plugins/input_control_vis/public/input_control_vis_type.ts b/src/plugins/input_control_vis/public/input_control_vis_type.ts index 8114dbf110f8b..2af53ea4d28e8 100644 --- a/src/plugins/input_control_vis/public/input_control_vis_type.ts +++ b/src/plugins/input_control_vis/public/input_control_vis_type.ts @@ -23,7 +23,6 @@ import { createInputControlVisController } from './vis_controller'; import { getControlsTab } from './components/editor/controls_tab'; import { OptionsTab } from './components/editor/options_tab'; import { InputControlVisDependencies } from './plugin'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; export function createInputControlVisTypeDefinition(deps: InputControlVisDependencies) { const InputControlVisController = createInputControlVisController(deps); @@ -39,7 +38,6 @@ export function createInputControlVisTypeDefinition(deps: InputControlVisDepende defaultMessage: 'Create interactive controls for easy dashboard manipulation.', }), stage: 'experimental', - feedbackMessage: defaultFeedbackMessage, visualization: InputControlVisController, visConfig: { defaults: { diff --git a/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx b/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx index 8187e70b1bbd1..63b9b48ec809e 100644 --- a/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx +++ b/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx @@ -17,7 +17,7 @@ * under the License. */ import { i18n } from '@kbn/i18n'; -import React, { Component, createRef } from 'react'; +import React, { Component } from 'react'; import { EuiFormRow, EuiDualRange } from '@elastic/eui'; import { EuiFormRowDisplayKeys } from '@elastic/eui/src/components/form/form_row/form_row'; import { EuiDualRangeProps } from '@elastic/eui/src/components/form/range/dual_range'; @@ -72,18 +72,6 @@ export class ValidatedDualRange extends Component { return null; } - // Can remove after eui#3412 is resolved - componentDidMount() { - if (this.trackRef.current) { - const track = this.trackRef.current.querySelector('.euiRangeTrack'); - if (track) { - track.setAttribute('aria-hidden', 'true'); - } - } - } - - trackRef = createRef(); - // @ts-ignore state populated by getDerivedStateFromProps state: State = {}; @@ -119,34 +107,32 @@ export class ValidatedDualRange extends Component { } = this.props; return ( -
- + - - -
+ value={this.state.value} + onChange={this._onChange} + minInputProps={{ + 'aria-label': i18n.translate('kibana-react.dualRangeControl.minInputAriaLabel', { + defaultMessage: 'Range minimum', + }), + }} + maxInputProps={{ + 'aria-label': i18n.translate('kibana-react.dualRangeControl.maxInputAriaLabel', { + defaultMessage: 'Range maximum', + }), + }} + {...rest} + /> + ); } } diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts index 804c8b0ed2026..1adc0dc6896fd 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts @@ -27,7 +27,7 @@ */ import { snakeCase } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; const TYPES = [ 'dashboard', @@ -45,7 +45,7 @@ export interface KibanaSavedObjectCounts { } export async function getSavedObjectsCounts( - callCluster: APICaller, + callCluster: LegacyAPICaller, kibanaIndex: string // Typically '.kibana'. We might need a way to obtain it from the SavedObjects client (or the SavedObjects client to provide a way to run aggregations?) ): Promise { const savedObjectCountSearchParams = { diff --git a/src/plugins/kibana_utils/common/default_feedback_message.ts b/src/plugins/kibana_utils/common/default_feedback_message.ts deleted file mode 100644 index f61f36bc8810c..0000000000000 --- a/src/plugins/kibana_utils/common/default_feedback_message.ts +++ /dev/null @@ -1,28 +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 { i18n } from '@kbn/i18n'; - -export const defaultFeedbackMessage = i18n.translate('kibana_utils.defaultFeedbackMessage', { - defaultMessage: 'Have feedback? Please create an issue in {link}.', - values: { - link: - 'GitHub', - }, -}); diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts index 99daed98dbe64..c94021872b4e1 100644 --- a/src/plugins/kibana_utils/common/index.ts +++ b/src/plugins/kibana_utils/common/index.ts @@ -28,4 +28,3 @@ export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_w export { url } from './url'; export { now } from './now'; export { calculateObjectHash } from './calculate_object_hash'; -export { defaultFeedbackMessage } from './default_feedback_message'; diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index 6f61e2c228970..2911a9ae75689 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -31,7 +31,6 @@ export { UiComponentInstance, url, createGetterSetter, - defaultFeedbackMessage, } from '../common'; export * from './core'; export * from '../common/errors'; diff --git a/src/plugins/management/public/management_sections_service.test.ts b/src/plugins/management/public/management_sections_service.test.ts index 2c5d04883235c..fd56dd8a6ee27 100644 --- a/src/plugins/management/public/management_sections_service.test.ts +++ b/src/plugins/management/public/management_sections_service.test.ts @@ -27,9 +27,15 @@ describe('ManagementService', () => { managementService = new ManagementSectionsService(); }); + const capabilities = { + navLinks: {}, + catalogue: {}, + management: {}, + }; + test('Provides default sections', () => { managementService.setup(); - const start = managementService.start(); + const start = managementService.start({ capabilities }); expect(start.getAllSections().length).toEqual(6); expect(start.getSection(ManagementSectionId.Ingest)).toBeDefined(); @@ -48,7 +54,7 @@ describe('ManagementService', () => { expect(setup.getSection('test-section')).not.toBeUndefined(); // Start phase: - const start = managementService.start(); + const start = managementService.start({ capabilities }); expect(start.getSectionsEnabled().length).toEqual(7); @@ -56,4 +62,38 @@ describe('ManagementService', () => { expect(start.getSectionsEnabled().length).toEqual(6); }); + + test('Disables items that are not allowed by Capabilities', () => { + // Setup phase: + const setup = managementService.setup(); + const testSection = setup.register({ id: 'test-section', title: 'Test Section' }); + testSection.registerApp({ id: 'test-app-1', title: 'Test App 1', mount: jest.fn() }); + testSection.registerApp({ id: 'test-app-2', title: 'Test App 2', mount: jest.fn() }); + testSection.registerApp({ id: 'test-app-3', title: 'Test App 3', mount: jest.fn() }); + + expect(setup.getSection('test-section')).not.toBeUndefined(); + + // Start phase: + managementService.start({ + capabilities: { + navLinks: {}, + catalogue: {}, + management: { + ['test-section']: { + 'test-app-1': true, + 'test-app-2': false, + // test-app-3 intentionally left undefined. Should be enabled by default + }, + }, + }, + }); + + expect(testSection.apps).toHaveLength(3); + expect(testSection.getAppsEnabled().map((app) => app.id)).toMatchInlineSnapshot(` + Array [ + "test-app-1", + "test-app-3", + ] + `); + }); }); diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts index 08a87b3e89f2b..d8d148a9247ff 100644 --- a/src/plugins/management/public/management_sections_service.ts +++ b/src/plugins/management/public/management_sections_service.ts @@ -21,7 +21,12 @@ import { ReactElement } from 'react'; import { ManagementSection, RegisterManagementSectionArgs } from './utils'; import { managementSections } from './components/management_sections'; -import { ManagementSectionId, SectionsServiceSetup, SectionsServiceStart } from './types'; +import { + ManagementSectionId, + SectionsServiceSetup, + SectionsServiceStart, + SectionsServiceStartDeps, +} from './types'; export class ManagementSectionsService { private sections: Map = new Map(); @@ -55,7 +60,18 @@ export class ManagementSectionsService { }; } - start(): SectionsServiceStart { + start({ capabilities }: SectionsServiceStartDeps): SectionsServiceStart { + this.getAllSections().forEach((section) => { + if (capabilities.management.hasOwnProperty(section.id)) { + const sectionCapabilities = capabilities.management[section.id]; + section.apps.forEach((app) => { + if (sectionCapabilities.hasOwnProperty(app.id) && sectionCapabilities[app.id] !== true) { + app.disable(); + } + }); + } + }); + return { getSection: this.getSection, getAllSections: this.getAllSections, diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index 71656d7c0b83b..dada4636e6add 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -82,7 +82,7 @@ export class ManagementPlugin implements Plugin ManagementSection; + register: (args: Omit) => ManagementSection; getSection: (sectionId: ManagementSectionId | string) => ManagementSection; } diff --git a/src/plugins/management/server/capabilities_provider.ts b/src/plugins/management/server/capabilities_provider.ts index 9a69749c8233b..254ac3ed04dd7 100644 --- a/src/plugins/management/server/capabilities_provider.ts +++ b/src/plugins/management/server/capabilities_provider.ts @@ -25,7 +25,7 @@ export const capabilitiesProvider = () => ({ */ kibana: { settings: true, - index_patterns: true, + indexPatterns: true, objects: true, }, }, diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx index 2b7466ffd6ab3..a1653c5289255 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx @@ -19,7 +19,7 @@ import { ButtonIconSide } from '@elastic/eui'; -export type TopNavMenuAction = (anchorElement: EventTarget) => void; +export type TopNavMenuAction = (anchorElement: HTMLElement) => void; export interface TopNavMenuData { id?: string; @@ -29,7 +29,7 @@ export interface TopNavMenuData { testId?: string; className?: string; disableButton?: boolean | (() => boolean); - tooltip?: string | (() => string); + tooltip?: string | (() => string | undefined); emphasize?: boolean; iconType?: string; iconSide?: ButtonIconSide; diff --git a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts index 53ef1f3f04ad9..9e7346f3b673c 100644 --- a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts +++ b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts @@ -51,14 +51,17 @@ export class SavedObjectLoader { } /** - * Retrieve a saved object by id. Returns a promise that completes when the object finishes + * Retrieve a saved object by id or create new one. + * Returns a promise that completes when the object finishes * initializing. - * @param id + * @param opts * @returns {Promise} */ - async get(id?: string) { + async get(opts?: Record | string) { + // can accept object as argument in accordance to SavedVis class + // see src/plugins/saved_objects/public/saved_object/saved_object_loader.ts // @ts-ignore - const obj = new this.Class(id); + const obj = new this.Class(opts); return obj.init(); } diff --git a/src/plugins/saved_objects/public/types.ts b/src/plugins/saved_objects/public/types.ts index 973a493c0a15e..6db72b396a86a 100644 --- a/src/plugins/saved_objects/public/types.ts +++ b/src/plugins/saved_objects/public/types.ts @@ -63,6 +63,7 @@ export interface SavedObjectSaveOpts { confirmOverwrite?: boolean; isTitleDuplicateConfirmed?: boolean; onTitleDuplicate?: () => void; + returnToOrigin?: boolean; } export interface SavedObjectCreationOpts { diff --git a/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts index 09e08e6ec333b..e83952e82c953 100644 --- a/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts +++ b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts @@ -70,7 +70,7 @@ describe('canViewInApp', () => { let uiCapabilities = createCapabilities({ management: { kibana: { - index_patterns: true, + indexPatterns: true, }, }, }); @@ -81,7 +81,7 @@ describe('canViewInApp', () => { uiCapabilities = createCapabilities({ management: { kibana: { - index_patterns: false, + indexPatterns: false, }, }, }); diff --git a/src/plugins/saved_objects_management/public/lib/in_app_url.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.ts index 82146554afa6f..0fcf52cba254b 100644 --- a/src/plugins/saved_objects_management/public/lib/in_app_url.ts +++ b/src/plugins/saved_objects_management/public/lib/in_app_url.ts @@ -30,7 +30,7 @@ export function canViewInApp(uiCapabilities: Capabilities, type: string): boolea case 'index-pattern': case 'index-patterns': case 'indexPatterns': - return uiCapabilities.management.kibana.index_patterns as boolean; + return uiCapabilities.management.kibana.indexPatterns as boolean; case 'dashboard': case 'dashboards': return uiCapabilities.dashboard.show as boolean; diff --git a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx index fd7967f4128c3..50358c17e058c 100644 --- a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx @@ -18,14 +18,7 @@ */ import React, { PureComponent } from 'react'; -import { - EuiFieldNumber, - EuiFieldText, - EuiFormRow, - EuiSwitch, - // @ts-ignore - EuiCodeEditor, -} from '@elastic/eui'; +import { EuiFieldNumber, EuiFieldText, EuiFormRow, EuiSwitch, EuiCodeEditor } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { FieldState, FieldType } from '../../types'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 884f39b97e233..7d43158ad8878 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -304,7 +304,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap index 6eb9e36394ee3..15e5cb89b622c 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap @@ -456,7 +456,7 @@ exports[`Relationships should render searches normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/app/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "My Index Pattern", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index 92e4e637e0d3f..56fddc075a50c 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -178,7 +178,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, @@ -393,7 +393,7 @@ exports[`Table should render normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index 6e7397d1058bf..aac799da6ea67 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -31,7 +31,6 @@ import { EuiForm, EuiFormRow, EuiSwitch, - // @ts-ignore EuiFilePicker, EuiInMemoryTable, EuiSelect, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index 9277d9b00305b..2e545b372f781 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -77,7 +77,7 @@ describe('Relationships', () => { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, @@ -113,7 +113,7 @@ describe('Relationships', () => { icon: 'indexPatternApp', inAppUrl: { path: '/app/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, title: 'My Index Pattern', }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index b9dad983cb42d..6b209a62e1b98 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; -// @ts-ignore +// @ts-expect-error import { findTestSubject } from '@elastic/eui/lib/test'; import { keyCodes } from '@elastic/eui'; import { httpServiceMock } from '../../../../../../core/public/mocks'; @@ -41,7 +41,7 @@ const defaultProps: TableProps = { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, @@ -68,7 +68,7 @@ const defaultProps: TableProps = { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 51e7525d0e00a..719729cee2602 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -20,7 +20,6 @@ import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; import { - // @ts-ignore EuiSearchBar, EuiBasicTable, EuiButton, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index e3456240dc340..3719dac24e6e7 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -158,7 +158,7 @@ describe('SavedObjectsTable', () => { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 54bc649c33b60..340c0e3237f91 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -19,7 +19,7 @@ import React, { Component } from 'react'; import { debounce } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { saveAs } from '@elastic/filesaver'; import { EuiSpacer, diff --git a/src/plugins/telemetry/server/fetcher.ts b/src/plugins/telemetry/server/fetcher.ts index 9422df6030518..75cfac721bcd3 100644 --- a/src/plugins/telemetry/server/fetcher.ts +++ b/src/plugins/telemetry/server/fetcher.ts @@ -29,7 +29,7 @@ import { SavedObjectsClientContract, SavedObjectsClient, CoreStart, - ICustomClusterClient, + ILegacyCustomClusterClient, } from '../../../core/server'; import { getTelemetryOptIn, @@ -63,7 +63,7 @@ export class FetcherTask { private isSending = false; private internalRepository?: SavedObjectsClientContract; private telemetryCollectionManager?: TelemetryCollectionManagerPluginStart; - private elasticsearchClient?: ICustomClusterClient; + private elasticsearchClient?: ILegacyCustomClusterClient; constructor(initializerContext: PluginInitializerContext) { this.config$ = initializerContext.config.create(); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts index d5f0d2d8c9598..4a33356ee9761 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; // This can be removed when the ES client improves the types export interface ESClusterInfo { @@ -43,6 +43,6 @@ export interface ESClusterInfo { * * @param {function} callCluster The callWithInternalUser handler (exposed for testing) */ -export function getClusterInfo(callCluster: APICaller) { +export function getClusterInfo(callCluster: LegacyAPICaller) { return callCluster('info'); } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts index 89e2cae777985..d7c0110a99c6f 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts @@ -18,14 +18,14 @@ */ import { ClusterDetailsGetter } from 'src/plugins/telemetry_collection_manager/server'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { TIMEOUT } from './constants'; /** * Get the cluster stats from the connected cluster. * * This is the equivalent to GET /_cluster/stats?timeout=30s. */ -export async function getClusterStats(callCluster: APICaller) { +export async function getClusterStats(callCluster: LegacyAPICaller) { return await callCluster('cluster.stats', { timeout: TIMEOUT, }); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts index 645c5a4be8a6c..5d27774a630a5 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts @@ -19,7 +19,7 @@ import { omit } from 'lodash'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { StatsCollectionContext } from 'src/plugins/telemetry_collection_manager/server'; export interface KibanaUsageStats { @@ -83,7 +83,7 @@ export function handleKibanaStats( export async function getKibana( usageCollection: UsageCollectionSetup, - callWithInternalUser: APICaller + callWithInternalUser: LegacyAPICaller ): Promise { const usage = await usageCollection.bulkFetch(callWithInternalUser); return usageCollection.toObject(usage); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts index 0ba6fcc154d8b..d41904c6d8e0e 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts @@ -17,12 +17,12 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ESLicense, LicenseGetter } from 'src/plugins/telemetry_collection_manager/server'; let cachedLicense: ESLicense | undefined; -function fetchLicense(callCluster: APICaller, local: boolean) { +function fetchLicense(callCluster: LegacyAPICaller, local: boolean) { return callCluster<{ license: ESLicense }>('transport.request', { method: 'GET', path: '/_license', @@ -41,7 +41,7 @@ function fetchLicense(callCluster: APICaller, local: boolean) { * * Like any X-Pack related API, X-Pack must installed for this to work. */ -async function getLicenseFromLocalOrMaster(callCluster: APICaller) { +async function getLicenseFromLocalOrMaster(callCluster: LegacyAPICaller) { // Fetching the local license is cheaper than getting it from the master and good enough const { license } = await fetchLicense(callCluster, true).catch(async (err) => { if (cachedLicense) { diff --git a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts index 833fd9f7fd5bc..438fcadad9255 100644 --- a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts +++ b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts @@ -36,7 +36,7 @@ * under the License. */ -import { IClusterClient } from 'kibana/server'; +import { ILegacyClusterClient } from 'kibana/server'; import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { getLocalStats } from './get_local_stats'; import { getClusterUuids } from './get_cluster_stats'; @@ -44,7 +44,7 @@ import { getLocalLicense } from './get_local_license'; export function registerCollection( telemetryCollectionManager: TelemetryCollectionManagerPluginSetup, - esCluster: IClusterClient + esCluster: ILegacyClusterClient ) { telemetryCollectionManager.setCollection({ esCluster, diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts index d3a47694d38a7..16f96c07fd8ea 100644 --- a/src/plugins/telemetry_collection_manager/server/types.ts +++ b/src/plugins/telemetry_collection_manager/server/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller, Logger, KibanaRequest, IClusterClient } from 'kibana/server'; +import { LegacyAPICaller, Logger, KibanaRequest, ILegacyClusterClient } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { TelemetryCollectionManagerPlugin } from './plugin'; @@ -64,7 +64,7 @@ export interface ClusterDetails { export interface StatsCollectionConfig { usageCollection: UsageCollectionSetup; - callCluster: APICaller; + callCluster: LegacyAPICaller; start: string | number; end: string | number; } @@ -129,7 +129,7 @@ export interface CollectionConfig< > { title: string; priority: number; - esCluster: IClusterClient; + esCluster: ILegacyClusterClient; statsGetter: StatsGetter; clusterDetailsGetter: ClusterDetailsGetter; licenseGetter: LicenseGetter; @@ -144,6 +144,6 @@ export interface Collection< statsGetter: StatsGetter; licenseGetter: LicenseGetter; clusterDetailsGetter: ClusterDetailsGetter; - esCluster: IClusterClient; + esCluster: ILegacyClusterClient; title: string; } diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index 00d55ef1c06db..9ae63b9f50e42 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Logger, APICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller } from 'kibana/server'; export type CollectorFormatForBulkUpload = (result: T) => { type: string; payload: U }; @@ -48,7 +48,7 @@ export interface CollectorOptions { type: string; init?: Function; schema?: MakeSchemaFrom; - fetch: (callCluster: APICaller) => Promise | T; + fetch: (callCluster: LegacyAPICaller) => Promise | T; /* * A hook for allowing the fetched data payload to be organized into a typed * data model for internal bulk upload. See defaultFormatterForBulkUpload for diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts index 04ba7452f99e2..b6308d6603388 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.ts @@ -18,7 +18,7 @@ */ import { snakeCase } from 'lodash'; -import { Logger, APICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller } from 'kibana/server'; import { Collector, CollectorOptions } from './collector'; import { UsageCollector } from './usage_collector'; @@ -112,7 +112,7 @@ export class CollectorSet { }; public bulkFetch = async ( - callCluster: APICaller, + callCluster: LegacyAPICaller, collectors: Array> = this.collectors ) => { const responses = []; @@ -140,7 +140,7 @@ export class CollectorSet { return this.makeCollectorSetFromArray(filtered); }; - public bulkFetchUsage = async (callCluster: APICaller) => { + public bulkFetchUsage = async (callCluster: LegacyAPICaller) => { const usageCollectors = this.getFilteredCollectorSet((c) => c instanceof UsageCollector); return await this.bulkFetch(callCluster, usageCollectors.collectors); }; diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index 837dd9bff2c6d..c41315e7bc0dc 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -23,9 +23,13 @@ import { i18n } from '@kbn/i18n'; import { keyCodes, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EventEmitter } from 'events'; -import { Vis, PersistedState } from 'src/plugins/visualizations/public'; -import { SavedSearch } from 'src/plugins/discover/public'; +import { + Vis, + PersistedState, + VisualizeEmbeddableContract, +} from 'src/plugins/visualizations/public'; import { TimeRange } from 'src/plugins/data/public'; +import { SavedObject } from 'src/plugins/saved_objects/public'; import { DefaultEditorNavBar, OptionTab } from './navbar'; import { DefaultEditorControls } from './controls'; import { setStateParamValue, useEditorReducer, useEditorFormState, discardChanges } from './state'; @@ -34,6 +38,7 @@ import { SidebarTitle } from './sidebar_title'; import { Schema } from '../../schemas'; interface DefaultEditorSideBarProps { + embeddableHandler: VisualizeEmbeddableContract; isCollapsed: boolean; onClickCollapse: () => void; optionTabs: OptionTab[]; @@ -41,11 +46,12 @@ interface DefaultEditorSideBarProps { vis: Vis; isLinkedSearch: boolean; eventEmitter: EventEmitter; - savedSearch?: SavedSearch; + savedSearch?: SavedObject; timeRange: TimeRange; } function DefaultEditorSideBar({ + embeddableHandler, isCollapsed, onClickCollapse, optionTabs, @@ -104,12 +110,12 @@ function DefaultEditorSideBar({ aggs: state.data.aggs ? (state.data.aggs.aggs.map((agg) => agg.toJSON()) as any) : [], }, }); - eventEmitter.emit('updateVis'); + embeddableHandler.reload(); eventEmitter.emit('dirtyStateChange', { isDirty: false, }); setTouched(false); - }, [vis, state, formState.invalid, setTouched, isDirty, eventEmitter]); + }, [vis, state, formState.invalid, setTouched, isDirty, eventEmitter, embeddableHandler]); const onSubmit: KeyboardEventHandler = useCallback( (event) => { diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx index ebc92170c8735..6713c2ce2391b 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx @@ -36,17 +36,17 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { Vis } from 'src/plugins/visualizations/public'; -import { SavedSearch } from 'src/plugins/discover/public'; +import { SavedObject } from 'src/plugins/saved_objects/public'; import { useKibana } from '../../../../kibana_react/public'; interface LinkedSearchProps { - savedSearch: SavedSearch; + savedSearch: SavedObject; eventEmitter: EventEmitter; } interface SidebarTitleProps { isLinkedSearch: boolean; - savedSearch?: SavedSearch; + savedSearch?: SavedObject; vis: Vis; eventEmitter: EventEmitter; } diff --git a/src/plugins/vis_default_editor/public/default_editor.tsx b/src/plugins/vis_default_editor/public/default_editor.tsx index 731358bdcbdec..60b6ebab5ad8e 100644 --- a/src/plugins/vis_default_editor/public/default_editor.tsx +++ b/src/plugins/vis_default_editor/public/default_editor.tsx @@ -59,7 +59,7 @@ function DefaultEditor({ embeddableHandler.render(visRef.current); setTimeout(() => { - eventEmitter.emit('apply'); + eventEmitter.emit('embeddableRendered'); }); return () => embeddableHandler.destroy(); @@ -102,6 +102,7 @@ function DefaultEditor({ initialWidth={editorInitialWidth} > get(col.aggConfig.type.getFormat(col.aggConfig), 'type.id') === 'number') + .filter((col) => get(col.aggConfig.toSerializedFieldFormat(), 'id') === 'number') .map(({ name }) => ({ value: name, text: name })), ], [aggs] diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 435ec9027eef2..605c6be0a85df 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -20,11 +20,9 @@ import { i18n } from '@kbn/i18n'; import { first } from 'rxjs/operators'; import { TypeOf } from '@kbn/config-schema'; -import { - CoreSetup, - PluginInitializerContext, - RecursiveReadonly, -} from '../../../../src/core/server'; +import { RecursiveReadonly } from '@kbn/utility-types'; + +import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js index a96890d4d1502..300e70f3ae0c0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js @@ -80,7 +80,7 @@ export class VisEditor extends Component { updateVisState = debounce(() => { this.props.vis.params = this.state.model; - this.props.eventEmitter.emit('updateVis'); + this.props.embeddableHandler.reload(); this.props.eventEmitter.emit('dirtyStateChange', { isDirty: false, }); @@ -187,6 +187,7 @@ export class VisEditor extends Component { autoApply={this.state.autoApply} model={model} embeddableHandler={this.props.embeddableHandler} + eventEmitter={this.props.eventEmitter} vis={this.props.vis} timeRange={this.props.timeRange} uiState={this.uiState} diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js index 0ae1c86ae3117..23a9555da2452 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js @@ -73,6 +73,7 @@ class VisEditorVisualizationUI extends Component { this._handler = embeddableHandler; await this._handler.render(this._visEl.current); + this.props.eventEmitter.emit('embeddableRendered'); this._subscription = this._handler.handler.data$.subscribe((data) => { this.setPanelInterval(data.value.visData); @@ -279,6 +280,7 @@ VisEditorVisualizationUI.propTypes = { uiState: PropTypes.object, onToggleAutoApply: PropTypes.func, embeddableHandler: PropTypes.object, + eventEmitter: PropTypes.object, timeRange: PropTypes.object, dirty: PropTypes.bool, autoApply: PropTypes.bool, diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index c06f94efb3c49..649ee765cc642 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -24,7 +24,6 @@ import { metricsRequestHandler } from './request_handler'; import { EditorController } from './application'; // @ts-ignore import { PANEL_TYPES } from '../common/panel_types'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; import { VisEditor } from './application/components/vis_editor_lazy'; export const metricsVisDefinition = { @@ -34,7 +33,6 @@ export const metricsVisDefinition = { defaultMessage: 'Build time-series using a visual pipeline interface', }), icon: 'visVisualBuilder', - feedbackMessage: defaultFeedbackMessage, visConfig: { defaults: { id: '61ca57f0-469d-11e7-af02-69e470af7417', diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index a2146e493d4ed..0b1c6e6e20414 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -18,7 +18,7 @@ */ import { - APICaller, + LegacyAPICaller, FakeRequest, IUiSettingsClient, SavedObjectsClientContract, @@ -53,12 +53,12 @@ export type ReqFacade = FakeRequest & { }; export class AbstractSearchStrategy { - public getCallWithRequestInstance: (req: ReqFacade) => APICaller; + public getCallWithRequestInstance: (req: ReqFacade) => LegacyAPICaller; public getSearchRequest: (req: ReqFacade) => any; constructor( server: any, - callWithRequestFactory: (server: any, req: ReqFacade) => APICaller, + callWithRequestFactory: (server: any, req: ReqFacade) => LegacyAPICaller, SearchRequest: any ) { this.getCallWithRequestInstance = (req) => callWithRequestFactory(server, req); diff --git a/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts index 22e427bed24c3..a5f095a4c4f3d 100644 --- a/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts +++ b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller, CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; +import { LegacyAPICaller, CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; import { UsageCollectionSetup } from '../../../usage_collection/server'; import { tsvbTelemetrySavedObjectType } from '../saved_objects'; @@ -49,7 +49,7 @@ export class ValidationTelemetryService implements Plugin({ type: 'tsvb-validation', isReady: () => this.kibanaIndex !== '', - fetch: async (callCluster: APICaller) => { + fetch: async (callCluster: LegacyAPICaller) => { try { const response = await callCluster('get', { index: this.kibanaIndex, diff --git a/src/plugins/vis_type_vega/public/vega_type.ts b/src/plugins/vis_type_vega/public/vega_type.ts index c864553c118b9..55ad134c05301 100644 --- a/src/plugins/vis_type_vega/public/vega_type.ts +++ b/src/plugins/vis_type_vega/public/vega_type.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { DefaultEditorSize } from '../../vis_default_editor/public'; import { VegaVisualizationDependencies } from './plugin'; import { VegaVisEditor } from './components'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; import { createVegaRequestHandler } from './vega_request_handler'; // @ts-ignore @@ -56,6 +55,5 @@ export const createVegaTypeDefinition = (dependencies: VegaVisualizationDependen showFilterBar: true, }, stage: 'experimental', - feedbackMessage: defaultFeedbackMessage, }; }; diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 0bbf862216ed5..2ac53c2c81acc 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -51,4 +51,5 @@ export { VisSavedObject, VisResponseValue, } from './types'; +export { VisualizationListItem } from './vis_types/vis_type_alias_registry'; export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants'; diff --git a/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts index eb00dce8aba2f..8edf494ddc0ec 100644 --- a/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts +++ b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts @@ -62,6 +62,7 @@ export const convertFromSerializedVis = (vis: SerializedVis): ISavedVis => { title: vis.title, description: vis.description, visState: { + title: vis.title, type: vis.type, aggs: vis.data.aggs, params: vis.params, diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts index c6a25df7615a2..d44fc2f4a75af 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts @@ -56,7 +56,7 @@ export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisu source.icon = source.type.icon; source.image = source.type.image; source.typeTitle = source.type.title; - source.editUrl = `#/edit/${id}`; + source.editUrl = `/edit/${id}`; return source; }; diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index 3455d88b6ce9e..daf275297fb82 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -35,6 +35,7 @@ export type VisualizationControllerConstructor = new ( ) => VisualizationController; export interface SavedVisState { + title: string; type: string; params: VisParams; aggs: AggConfigOptions[]; diff --git a/src/plugins/visualizations/public/vis.ts b/src/plugins/visualizations/public/vis.ts index aaab0566af65e..e8ae48cdce145 100644 --- a/src/plugins/visualizations/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -29,6 +29,7 @@ import { isFunction, defaults, cloneDeep } from 'lodash'; import { Assign } from '@kbn/utility-types'; +import { i18n } from '@kbn/i18n'; import { PersistedState } from './persisted_state'; import { getTypes, getAggs, getSearch, getSavedSearchLoader } from './services'; import { VisType } from './vis_types'; @@ -105,7 +106,13 @@ export class Vis { private getType(visType: string) { const type = getTypes().get(visType); if (!type) { - throw new Error(`Invalid type "${visType}"`); + const errorMessage = i18n.translate('visualizations.visualizationTypeInvalidMessage', { + defaultMessage: 'Invalid visualization type "{visType}"', + values: { + visType, + }, + }); + throw new Error(errorMessage); } return type; } @@ -150,7 +157,13 @@ export class Vis { const configStates = this.initializeDefaultsFromSchemas(aggs, this.type.schemas.all || []); if (!this.data.indexPattern) { if (aggs.length) { - throw new Error('trying to initialize aggs without index pattern'); + const errorMessage = i18n.translate( + 'visualizations.initializeWithoutIndexPatternErrorMessage', + { + defaultMessage: 'Trying to initialize aggs without index pattern', + } + ); + throw new Error(errorMessage); } return; } diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 2464bb72d2695..44b76a52b34fe 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -27,7 +27,6 @@ export interface BaseVisTypeOptions { icon?: string; image?: string; stage?: 'experimental' | 'beta' | 'production'; - feedbackMessage?: string; options?: Record; visualization: VisualizationControllerConstructor; visConfig?: Record; @@ -48,7 +47,7 @@ export class BaseVisType { icon?: string; image?: string; stage: 'experimental' | 'beta' | 'production'; - feedbackMessage: string; + isExperimental: boolean; options: Record; visualization: VisualizationControllerConstructor; visConfig: Record; @@ -87,7 +86,7 @@ export class BaseVisType { this.editorConfig = _.defaultsDeep({}, opts.editorConfig, { collections: {} }); this.options = _.defaultsDeep({}, opts.options, defaultOptions); this.stage = opts.stage || 'production'; - this.feedbackMessage = opts.feedbackMessage || ''; + this.isExperimental = opts.stage === 'experimental'; this.hidden = opts.hidden || false; this.requestHandler = opts.requestHandler || 'courier'; this.responseHandler = opts.responseHandler || 'none'; @@ -97,10 +96,6 @@ export class BaseVisType { this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false; } - shouldMarkAsExperimentalInUI() { - return this.stage === 'experimental'; - } - public get schemas() { if (this.editorConfig && this.editorConfig.schemas) { return this.editorConfig.schemas; diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index 73e3360004e5a..bc80d549c81e6 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -27,6 +27,7 @@ export interface VisualizationListItem { title: string; description?: string; typeTitle: string; + image?: string; } export interface VisualizationsAppExtension { diff --git a/src/plugins/visualize/kibana.json b/src/plugins/visualize/kibana.json index cda45f3acc102..c27cfec24b332 100644 --- a/src/plugins/visualize/kibana.json +++ b/src/plugins/visualize/kibana.json @@ -9,7 +9,6 @@ "navigation", "savedObjects", "visualizations", - "dashboard", "embeddable" ], "optionalPlugins": ["home", "share"] diff --git a/src/plugins/visualize/public/application/_app.scss b/src/plugins/visualize/public/application/_app.scss deleted file mode 100644 index 8a52ebf4cc088..0000000000000 --- a/src/plugins/visualize/public/application/_app.scss +++ /dev/null @@ -1,5 +0,0 @@ -.visAppWrapper { - display: flex; - flex-direction: column; - flex-grow: 1; -} diff --git a/src/plugins/visualize/public/application/index.scss b/src/plugins/visualize/public/application/app.scss similarity index 67% rename from src/plugins/visualize/public/application/index.scss rename to src/plugins/visualize/public/application/app.scss index 620380a77ba46..f7f68fbc2c359 100644 --- a/src/plugins/visualize/public/application/index.scss +++ b/src/plugins/visualize/public/application/app.scss @@ -5,6 +5,8 @@ // visChart__legend--small // visChart__legend-isLoading -@import 'app'; -@import 'editor/index'; -@import 'listing/index'; +.visAppWrapper { + display: flex; + flex-direction: column; + flex-grow: 1; +} diff --git a/src/plugins/visualize/public/application/app.tsx b/src/plugins/visualize/public/application/app.tsx new file mode 100644 index 0000000000000..0e71d72a3d4c7 --- /dev/null +++ b/src/plugins/visualize/public/application/app.tsx @@ -0,0 +1,63 @@ +/* + * 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 './app.scss'; +import React, { useEffect } from 'react'; +import { Route, Switch, useLocation } from 'react-router-dom'; + +import { syncQueryStateWithUrl } from '../../../data/public'; +import { useKibana } from '../../../kibana_react/public'; +import { VisualizeServices } from './types'; +import { VisualizeEditor, VisualizeListing, VisualizeNoMatch } from './components'; +import { VisualizeConstants } from './visualize_constants'; + +export const VisualizeApp = () => { + const { + services: { + data: { query }, + kbnUrlStateStorage, + }, + } = useKibana(); + const { pathname } = useLocation(); + + useEffect(() => { + // syncs `_g` portion of url with query services + const { stop } = syncQueryStateWithUrl(query, kbnUrlStateStorage); + + return () => stop(); + + // this effect should re-run when pathname is changed to preserve querystring part, + // so the global state is always preserved + }, [query, kbnUrlStateStorage, pathname]); + + return ( + + + + + + + + + + ); +}; diff --git a/src/plugins/visualize/public/application/application.ts b/src/plugins/visualize/public/application/application.ts deleted file mode 100644 index 60bb73d6de2cc..0000000000000 --- a/src/plugins/visualize/public/application/application.ts +++ /dev/null @@ -1,111 +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 './index.scss'; - -import angular, { IModule } from 'angular'; - -// required for i18nIdDirective -import 'angular-sanitize'; -// required for ngRoute -import 'angular-route'; - -import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; - -import { AppMountContext } from 'kibana/public'; -import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public'; -import { - configureAppAngularModule, - createTopNavDirective, - createTopNavHelper, -} from '../../../kibana_legacy/public'; - -// @ts-ignore -import { initVisualizeApp } from './legacy_app'; -import { VisualizeKibanaServices } from '../kibana_services'; - -let angularModuleInstance: IModule | null = null; - -export const renderApp = ( - element: HTMLElement, - appBasePath: string, - deps: VisualizeKibanaServices -) => { - if (!angularModuleInstance) { - angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation); - // global routing stuff - configureAppAngularModule( - angularModuleInstance, - { core: deps.core, env: deps.pluginInitializerContext.env }, - true, - deps.scopedHistory - ); - initVisualizeApp(angularModuleInstance, deps); - } - const $injector = mountVisualizeApp(appBasePath, element); - return () => $injector.get('$rootScope').$destroy(); -}; - -const mainTemplate = (basePath: string) => `
- -
-`; - -const moduleName = 'app/visualize'; - -const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react']; - -function mountVisualizeApp(appBasePath: string, element: HTMLElement) { - const mountpoint = document.createElement('div'); - mountpoint.setAttribute('class', 'visAppWrapper'); - mountpoint.innerHTML = mainTemplate(appBasePath); - // bootstrap angular into detached element and attach it later to - // make angular-within-angular possible - const $injector = angular.bootstrap(mountpoint, [moduleName]); - // initialize global state handler - element.appendChild(mountpoint); - return $injector; -} - -function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) { - createLocalI18nModule(); - createLocalTopNavModule(navigation); - - const visualizeAngularModule: IModule = angular.module(moduleName, [ - ...thirdPartyAngularDependencies, - 'app/visualize/I18n', - 'app/visualize/TopNav', - ]); - return visualizeAngularModule; -} - -function createLocalTopNavModule(navigation: NavigationStart) { - angular - .module('app/visualize/TopNav', ['react']) - .directive('kbnTopNav', createTopNavDirective) - .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); -} - -function createLocalI18nModule() { - angular - .module('app/visualize/I18n', []) - .provider('i18n', I18nProvider) - .filter('i18n', i18nFilter) - .directive('i18nId', i18nDirective); -} diff --git a/src/core/utils/integration_tests/deep_freeze.test.ts b/src/plugins/visualize/public/application/components/experimental_vis_info.tsx similarity index 50% rename from src/core/utils/integration_tests/deep_freeze.test.ts rename to src/plugins/visualize/public/application/components/experimental_vis_info.tsx index f58e298fecfbf..51abb3ca530a4 100644 --- a/src/core/utils/integration_tests/deep_freeze.test.ts +++ b/src/plugins/visualize/public/application/components/experimental_vis_info.tsx @@ -17,24 +17,33 @@ * under the License. */ -import { resolve } from 'path'; +import React, { memo } from 'react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; -import execa from 'execa'; +export const InfoComponent = () => { + const title = ( + <> + {' '} + + GitHub + + {'.'} + + ); -const MINUTE = 60 * 1000; + return ( + + ); +}; -it( - 'types return values to prevent mutations in typescript', - async () => { - await expect( - execa('tsc', ['--noEmit'], { - cwd: resolve(__dirname, '__fixtures__/frozen_object_mutation'), - preferLocal: true, - }).catch((err) => err.stdout) - ).resolves.toMatchInlineSnapshot(` - "index.ts(28,12): error TS2540: Cannot assign to 'baz' because it is a read-only property. - index.ts(36,11): error TS2540: Cannot assign to 'bar' because it is a read-only property." - `); - }, - MINUTE -); +export const ExperimentalVisInfo = memo(InfoComponent); diff --git a/src/plugins/visualize/public/application/editor/lib/index.ts b/src/plugins/visualize/public/application/components/index.ts similarity index 80% rename from src/plugins/visualize/public/application/editor/lib/index.ts rename to src/plugins/visualize/public/application/components/index.ts index 78589383925fb..a3a7fde1d6569 100644 --- a/src/plugins/visualize/public/application/editor/lib/index.ts +++ b/src/plugins/visualize/public/application/components/index.ts @@ -17,6 +17,6 @@ * under the License. */ -export { useVisualizeAppState } from './visualize_app_state'; -export { makeStateful } from './make_stateful'; -export { addEmbeddableToDashboardUrl } from '../../../../../dashboard/public/'; +export { VisualizeListing } from './visualize_listing'; +export { VisualizeEditor } from './visualize_editor'; +export { VisualizeNoMatch } from './visualize_no_match'; diff --git a/src/plugins/visualize/public/application/editor/_editor.scss b/src/plugins/visualize/public/application/components/visualize_editor.scss similarity index 100% rename from src/plugins/visualize/public/application/editor/_editor.scss rename to src/plugins/visualize/public/application/components/visualize_editor.scss diff --git a/src/plugins/visualize/public/application/components/visualize_editor.tsx b/src/plugins/visualize/public/application/components/visualize_editor.tsx new file mode 100644 index 0000000000000..c571a5fb078bc --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_editor.tsx @@ -0,0 +1,115 @@ +/* + * 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 './visualize_editor.scss'; +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { EventEmitter } from 'events'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiScreenReaderOnly } from '@elastic/eui'; + +import { useKibana } from '../../../../kibana_react/public'; +import { + useChromeVisibility, + useSavedVisInstance, + useVisualizeAppState, + useEditorUpdates, + useLinkedSearchUpdates, +} from '../utils'; +import { VisualizeServices } from '../types'; +import { ExperimentalVisInfo } from './experimental_vis_info'; +import { VisualizeTopNav } from './visualize_top_nav'; + +export const VisualizeEditor = () => { + const { id: visualizationIdFromUrl } = useParams(); + const [originatingApp, setOriginatingApp] = useState(); + const { services } = useKibana(); + const [eventEmitter] = useState(new EventEmitter()); + const [hasUnsavedChanges, setHasUnsavedChanges] = useState(!visualizationIdFromUrl); + + const isChromeVisible = useChromeVisibility(services.chrome); + const { savedVisInstance, visEditorRef, visEditorController } = useSavedVisInstance( + services, + eventEmitter, + isChromeVisible, + visualizationIdFromUrl + ); + const { appState, hasUnappliedChanges } = useVisualizeAppState( + services, + eventEmitter, + savedVisInstance + ); + const { isEmbeddableRendered, currentAppState } = useEditorUpdates( + services, + eventEmitter, + setHasUnsavedChanges, + appState, + savedVisInstance, + visEditorController + ); + useLinkedSearchUpdates(services, eventEmitter, appState, savedVisInstance); + + useEffect(() => { + const { originatingApp: value } = + services.embeddable.getStateTransfer(services.scopedHistory).getIncomingEditorState() || {}; + setOriginatingApp(value); + }, [services]); + + useEffect(() => { + // clean up all registered listeners if any is left + return () => { + eventEmitter.removeAllListeners(); + }; + }, [eventEmitter]); + + return ( +
+ {savedVisInstance && appState && currentAppState && ( + + )} + {savedVisInstance?.vis?.type?.isExperimental && } + {savedVisInstance && ( + +

+ +

+
+ )} +
+
+ ); +}; diff --git a/src/plugins/visualize/public/application/listing/_listing.scss b/src/plugins/visualize/public/application/components/visualize_listing.scss similarity index 100% rename from src/plugins/visualize/public/application/listing/_listing.scss rename to src/plugins/visualize/public/application/components/visualize_listing.scss diff --git a/src/plugins/visualize/public/application/components/visualize_listing.tsx b/src/plugins/visualize/public/application/components/visualize_listing.tsx new file mode 100644 index 0000000000000..cbfbd6e0e3ab6 --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_listing.tsx @@ -0,0 +1,154 @@ +/* + * 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 './visualize_listing.scss'; + +import React, { useCallback, useRef, useMemo, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useUnmount, useMount } from 'react-use'; +import { useLocation } from 'react-router-dom'; + +import { useKibana, TableListView } from '../../../../kibana_react/public'; +import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; +import { VisualizeServices } from '../types'; +import { VisualizeConstants } from '../visualize_constants'; +import { getTableColumns, getNoItemsMessage } from '../utils'; + +export const VisualizeListing = () => { + const { + services: { + application, + chrome, + history, + savedVisualizations, + toastNotifications, + visualizations, + savedObjects, + savedObjectsPublic, + uiSettings, + visualizeCapabilities, + }, + } = useKibana(); + const { pathname } = useLocation(); + const closeNewVisModal = useRef(() => {}); + const listingLimit = savedObjectsPublic.settings.getListingLimit(); + + useEffect(() => { + if (pathname === '/new') { + // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately + closeNewVisModal.current = visualizations.showNewVisModal({ + onClose: () => { + // In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal + history.push(VisualizeConstants.LANDING_PAGE_PATH); + }, + }); + } else { + // close modal window if exists + closeNewVisModal.current(); + } + }, [history, pathname, visualizations]); + + useMount(() => { + chrome.setBreadcrumbs([ + { + text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', { + defaultMessage: 'Visualize', + }), + }, + ]); + chrome.docTitle.change( + i18n.translate('visualize.listingPageTitle', { defaultMessage: 'Visualize' }) + ); + }); + useUnmount(() => closeNewVisModal.current()); + + const createNewVis = useCallback(() => { + closeNewVisModal.current = visualizations.showNewVisModal(); + }, [visualizations]); + + const editItem = useCallback( + ({ editUrl, editApp }) => { + if (editApp) { + application.navigateToApp(editApp, { path: editUrl }); + return; + } + // for visualizations the edit and view URLs are the same + history.push(editUrl); + }, + [application, history] + ); + + const noItemsFragment = useMemo(() => getNoItemsMessage(createNewVis), [createNewVis]); + const tableColumns = useMemo(() => getTableColumns(application, history), [application, history]); + + const fetchItems = useCallback( + (filter) => { + const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING); + return savedVisualizations + .findListItems(filter, listingLimit) + .then(({ total, hits }: { total: number; hits: object[] }) => ({ + total, + hits: hits.filter((result: any) => isLabsEnabled || result.type.stage !== 'experimental'), + })); + }, + [listingLimit, savedVisualizations, uiSettings] + ); + + const deleteItems = useCallback( + async (selectedItems: object[]) => { + await Promise.all( + selectedItems.map((item: any) => savedObjects.client.delete(item.savedObjectType, item.id)) + ).catch((error) => { + toastNotifications.addError(error, { + title: i18n.translate('visualize.visualizeListingDeleteErrorTitle', { + defaultMessage: 'Error deleting visualization', + }), + }); + }); + }, + [savedObjects.client, toastNotifications] + ); + + return ( + + ); +}; diff --git a/src/plugins/visualize/public/application/components/visualize_no_match.tsx b/src/plugins/visualize/public/application/components/visualize_no_match.tsx new file mode 100644 index 0000000000000..7776c5e8ce486 --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_no_match.tsx @@ -0,0 +1,77 @@ +/* + * 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, { useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; + +import { useKibana, toMountPoint } from '../../../../kibana_react/public'; +import { VisualizeServices } from '../types'; +import { VisualizeConstants } from '../visualize_constants'; + +let bannerId: string; + +export const VisualizeNoMatch = () => { + const { services } = useKibana(); + + useEffect(() => { + services.restorePreviousUrl(); + + const { navigated } = services.kibanaLegacy.navigateToLegacyKibanaUrl( + services.history.location.pathname + ); + + if (!navigated) { + const bannerMessage = i18n.translate('visualize.noMatchRoute.bannerTitleText', { + defaultMessage: 'Page not found', + }); + + bannerId = services.overlays.banners.replace( + bannerId, + toMountPoint( + +

+ + {services.history.location.pathname} + + ), + }} + /> +

+
+ ) + ); + + // hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around + setTimeout(() => { + services.overlays.banners.remove(bannerId); + }, 15000); + + services.history.replace(VisualizeConstants.LANDING_PAGE_PATH); + } + }, [services]); + + return null; +}; diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx new file mode 100644 index 0000000000000..2e7dba46487ad --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -0,0 +1,178 @@ +/* + * 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, { memo, useCallback, useMemo, useState, useEffect } from 'react'; +import { isEqual } from 'lodash'; + +import { OverlayRef } from 'kibana/public'; +import { Query } from 'src/plugins/data/public'; +import { useKibana } from '../../../../kibana_react/public'; +import { + VisualizeServices, + VisualizeAppState, + VisualizeAppStateContainer, + SavedVisInstance, +} from '../types'; +import { APP_NAME } from '../visualize_constants'; +import { getTopNavConfig } from '../utils'; + +interface VisualizeTopNavProps { + currentAppState: VisualizeAppState; + isChromeVisible?: boolean; + isEmbeddableRendered: boolean; + hasUnsavedChanges: boolean; + setHasUnsavedChanges: (value: boolean) => void; + hasUnappliedChanges: boolean; + originatingApp?: string; + savedVisInstance: SavedVisInstance; + stateContainer: VisualizeAppStateContainer; + visualizationIdFromUrl?: string; +} + +const TopNav = ({ + currentAppState, + isChromeVisible, + isEmbeddableRendered, + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, +}: VisualizeTopNavProps) => { + const { services } = useKibana(); + const { TopNavMenu } = services.navigation.ui; + const { embeddableHandler, vis } = savedVisInstance; + const [inspectorSession, setInspectorSession] = useState(); + const openInspector = useCallback(() => { + const session = embeddableHandler.openInspector(); + setInspectorSession(session); + }, [embeddableHandler]); + + const updateQuery = useCallback( + ({ query }: { query?: Query }) => { + if (!isEqual(currentAppState.query, query)) { + stateContainer.transitions.set('query', query || currentAppState.query); + } else { + savedVisInstance.embeddableHandler.reload(); + } + }, + [currentAppState.query, savedVisInstance.embeddableHandler, stateContainer.transitions] + ); + + const config = useMemo(() => { + if (isEmbeddableRendered) { + return getTopNavConfig( + { + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + openInspector, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, + }, + services + ); + } + }, [ + isEmbeddableRendered, + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + openInspector, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, + services, + ]); + const [indexPattern, setIndexPattern] = useState(vis.data.indexPattern); + const showDatePicker = () => { + // tsvb loads without an indexPattern initially (TODO investigate). + // hide timefilter only if timeFieldName is explicitly undefined. + const hasTimeField = vis.data.indexPattern ? !!vis.data.indexPattern.timeFieldName : true; + return vis.type.options.showTimePicker && hasTimeField; + }; + const showFilterBar = vis.type.options.showFilterBar; + const showQueryInput = vis.type.requiresSearch && vis.type.options.showQueryBar; + + useEffect(() => { + return () => { + if (inspectorSession) { + // Close the inspector if this scope is destroyed (e.g. because the user navigates away). + inspectorSession.close(); + } + }; + }, [inspectorSession]); + + useEffect(() => { + if (!vis.data.indexPattern) { + services.data.indexPatterns.getDefault().then((index) => { + if (index) { + setIndexPattern(index); + } + }); + } + }, [services.data.indexPatterns, vis.data.indexPattern]); + + return isChromeVisible ? ( + /** + * Most visualizations have all search bar components enabled. + * Some visualizations have fewer options, but all visualizations have the search bar. + * That's is why the showSearchBar prop is set. + * All visualizations also have the timepicker\autorefresh component, + * it is enabled by default in the TopNavMenu component. + */ + + ) : showFilterBar ? ( + /** + * The top nav is hidden in embed mode, but the filter bar must still be present so + * we show the filter bar on its own here if the chrome is not visible. + */ + + ) : null; +}; + +export const VisualizeTopNav = memo(TopNav); diff --git a/src/plugins/visualize/public/application/editor/_index.scss b/src/plugins/visualize/public/application/editor/_index.scss deleted file mode 100644 index 9d3ca4b539947..0000000000000 --- a/src/plugins/visualize/public/application/editor/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'editor'; diff --git a/src/plugins/visualize/public/application/editor/editor.html b/src/plugins/visualize/public/application/editor/editor.html deleted file mode 100644 index 3c3455fb34f18..0000000000000 --- a/src/plugins/visualize/public/application/editor/editor.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - -
-
-

-
-
- - - -

-

- - -
diff --git a/src/plugins/visualize/public/application/editor/editor.js b/src/plugins/visualize/public/application/editor/editor.js deleted file mode 100644 index d7c7828c58f23..0000000000000 --- a/src/plugins/visualize/public/application/editor/editor.js +++ /dev/null @@ -1,763 +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 angular from 'angular'; -import _ from 'lodash'; -import { Subscription } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { i18n } from '@kbn/i18n'; -import { EventEmitter } from 'events'; - -import React from 'react'; -import { makeStateful, useVisualizeAppState } from './lib'; -import { VisualizeConstants } from '../visualize_constants'; -import { getEditBreadcrumbs } from '../breadcrumbs'; - -import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; -import { unhashUrl } from '../../../../kibana_utils/public'; -import { MarkdownSimple, toMountPoint } from '../../../../kibana_react/public'; -import { - addFatalError, - subscribeWithScope, - migrateLegacyQuery, -} from '../../../../kibana_legacy/public'; -import { showSaveModal, SavedObjectSaveModalOrigin } from '../../../../saved_objects/public'; -import { - esFilters, - connectToQueryState, - syncQueryStateWithUrl, - UI_SETTINGS, -} from '../../../../data/public'; - -import { initVisEditorDirective } from './visualization_editor'; -import { initVisualizationDirective } from './visualization'; - -import { getServices } from '../../kibana_services'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../visualizations/public'; - -export function initEditorDirective(app, deps) { - app.directive('visualizeApp', function () { - return { - restrict: 'E', - controllerAs: 'visualizeApp', - controller: VisualizeAppController, - }; - }); - - initVisEditorDirective(app, deps); - initVisualizationDirective(app, deps); -} - -function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlStateStorage, history) { - const { - localStorage, - visualizeCapabilities, - share, - data: { query: queryService, indexPatterns }, - toastNotifications, - chrome, - core: { docLinks, fatalErrors, uiSettings, application }, - I18nContext, - setActiveUrl, - visualizations, - embeddable, - scopedHistory, - } = getServices(); - - const { - filterManager, - timefilter: { timefilter }, - } = queryService; - - // starts syncing `_g` portion of url with query services - const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( - queryService, - kbnUrlStateStorage - ); - - // Retrieve the resolved SavedVis instance. - const { vis, savedVis, savedSearch, embeddableHandler } = $route.current.locals.resolved; - $scope.eventEmitter = new EventEmitter(); - const _applyVis = () => { - $scope.$apply(); - }; - // This will trigger a digest cycle. This is needed when vis is updated from a global angular like in visualize_embeddable.js. - $scope.eventEmitter.on('apply', _applyVis); - // vis is instance of src/legacy/ui/public/vis/vis.js. - // SearchSource is a promise-based stream of search results that can inherit from other search sources. - const searchSource = vis.data.searchSource; - - $scope.vis = vis; - $scope.savedSearch = savedSearch; - - const $appStatus = { - dirty: !savedVis.id, - }; - - const defaultQuery = { - query: '', - language: - localStorage.get('kibana.userQueryLanguage') || - uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE), - }; - - const { originatingApp } = - embeddable.getStateTransfer(scopedHistory()).getIncomingEditorState() || {}; - $scope.getOriginatingApp = () => originatingApp; - - const visStateToEditorState = () => { - const savedVisState = visualizations.convertFromSerializedVis(vis.serialize()); - return { - uiState: vis.uiState.toJSON(), - query: vis.data.searchSource.getOwnField('query') || defaultQuery, - filters: vis.data.searchSource.getOwnField('filter') || [], - vis: { ...savedVisState.visState, title: vis.title }, - linked: !!savedVis.savedSearchId, - }; - }; - - const stateDefaults = visStateToEditorState(); - - const { stateContainer, stopStateSync } = useVisualizeAppState({ - stateDefaults, - kbnUrlStateStorage, - }); - - $scope.eventEmitter.on('dirtyStateChange', ({ isDirty }) => { - if (!isDirty) { - stateContainer.transitions.updateVisState(visStateToEditorState().vis); - } - $timeout(() => { - $scope.dirty = isDirty; - }); - }); - - $scope.eventEmitter.on('updateVis', () => { - embeddableHandler.reload(); - }); - - $scope.embeddableHandler = embeddableHandler; - - $scope.topNavMenu = [ - ...($scope.getOriginatingApp() && savedVis.id - ? [ - { - id: 'saveAndReturn', - label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', { - defaultMessage: 'Save and return', - }), - emphasize: true, - iconType: 'check', - description: i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel', - { - defaultMessage: 'Finish editing visualization and return to the last app', - } - ), - testId: 'visualizesaveAndReturnButton', - disableButton() { - return Boolean($scope.dirty); - }, - tooltip() { - if ($scope.dirty) { - return i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip', - { - defaultMessage: 'Apply or Discard your changes before finishing', - } - ); - } - }, - run: async () => { - const saveOptions = { - confirmOverwrite: false, - returnToOrigin: true, - }; - return doSave(saveOptions); - }, - }, - ] - : []), - ...(visualizeCapabilities.save - ? [ - { - id: 'save', - label: - savedVis.id && $scope.getOriginatingApp() - ? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', { - defaultMessage: 'save as', - }) - : i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', { - defaultMessage: 'save', - }), - emphasize: !savedVis.id || !$scope.getOriginatingApp(), - description: i18n.translate('visualize.topNavMenu.saveVisualizationButtonAriaLabel', { - defaultMessage: 'Save Visualization', - }), - testId: 'visualizeSaveButton', - disableButton() { - return Boolean($scope.dirty); - }, - tooltip() { - if ($scope.dirty) { - return i18n.translate( - 'visualize.topNavMenu.saveVisualizationDisabledButtonTooltip', - { - defaultMessage: 'Apply or Discard your changes before saving', - } - ); - } - }, - run: async () => { - const onSave = ({ - newTitle, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - newDescription, - returnToOrigin, - }) => { - const currentTitle = savedVis.title; - savedVis.title = newTitle; - savedVis.copyOnSave = newCopyOnSave; - savedVis.description = newDescription; - const saveOptions = { - confirmOverwrite: false, - isTitleDuplicateConfirmed, - onTitleDuplicate, - returnToOrigin, - }; - return doSave(saveOptions).then((response) => { - // If the save wasn't successful, put the original values back. - if (!response.id || response.error) { - savedVis.title = currentTitle; - } - return response; - }); - }; - - const saveModal = ( - {}} - originatingApp={$scope.getOriginatingApp()} - /> - ); - showSaveModal(saveModal, I18nContext); - }, - }, - ] - : []), - { - id: 'share', - label: i18n.translate('visualize.topNavMenu.shareVisualizationButtonLabel', { - defaultMessage: 'share', - }), - description: i18n.translate('visualize.topNavMenu.shareVisualizationButtonAriaLabel', { - defaultMessage: 'Share Visualization', - }), - testId: 'shareTopNavButton', - run: (anchorElement) => { - const hasUnappliedChanges = $scope.dirty; - const hasUnsavedChanges = $appStatus.dirty; - share.toggleShareContextMenu({ - anchorElement, - allowEmbed: true, - allowShortUrl: visualizeCapabilities.createShortUrl, - shareableUrl: unhashUrl(window.location.href), - objectId: savedVis.id, - objectType: 'visualization', - sharingData: { - title: savedVis.title, - }, - isDirty: hasUnappliedChanges || hasUnsavedChanges, - }); - }, - // disable the Share button if no action specified - disableButton: !share, - }, - { - id: 'inspector', - label: i18n.translate('visualize.topNavMenu.openInspectorButtonLabel', { - defaultMessage: 'inspect', - }), - description: i18n.translate('visualize.topNavMenu.openInspectorButtonAriaLabel', { - defaultMessage: 'Open Inspector for visualization', - }), - testId: 'openInspectorButton', - disableButton() { - return !embeddableHandler.hasInspector || !embeddableHandler.hasInspector(); - }, - run() { - const inspectorSession = embeddableHandler.openInspector(); - - if (inspectorSession) { - // Close the inspector if this scope is destroyed (e.g. because the user navigates away). - const removeWatch = $scope.$on('$destroy', () => inspectorSession.close()); - // Remove that watch in case the user closes the inspector session herself. - inspectorSession.onClose.finally(removeWatch); - } - }, - tooltip() { - if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) { - return i18n.translate('visualize.topNavMenu.openInspectorDisabledButtonTooltip', { - defaultMessage: `This visualization doesn't support any inspectors.`, - }); - } - }, - }, - ]; - - if (savedVis.id) { - chrome.docTitle.change(savedVis.title); - } - - // sync initial app filters from state to filterManager - filterManager.setAppFilters(_.cloneDeep(stateContainer.getState().filters)); - // setup syncing of app filters between appState and filterManager - const stopSyncingAppFilters = connectToQueryState( - queryService, - { - set: ({ filters }) => stateContainer.transitions.set('filters', filters), - get: () => ({ filters: stateContainer.getState().filters }), - state$: stateContainer.state$.pipe(map((state) => ({ filters: state.filters }))), - }, - { - filters: esFilters.FilterStateStore.APP_STATE, - } - ); - - const stopAllSyncing = () => { - stopStateSync(); - stopSyncingQueryServiceStateWithUrl(); - stopSyncingAppFilters(); - }; - - // The savedVis is pulled from elasticsearch, but the appState is pulled from the url, with the - // defaults applied. If the url was from a previous session which included modifications to the - // appState then they won't be equal. - if (!_.isEqual(stateContainer.getState().vis, stateDefaults.vis)) { - try { - const { aggs, ...visState } = stateContainer.getState().vis; - vis.setState({ ...visState, data: { aggs } }); - } catch (error) { - // stop syncing url updtes with the state to prevent extra syncing - stopAllSyncing(); - - toastNotifications.addWarning({ - title: i18n.translate('visualize.visualizationTypeInvalidNotificationMessage', { - defaultMessage: 'Invalid visualization type', - }), - text: toMountPoint({error.message}), - }); - - history.replace(`${VisualizeConstants.LANDING_PAGE_PATH}?notFound=visualization`); - - // prevent further controller execution - return; - } - } - - $scope.filters = filterManager.getFilters(); - - $scope.onFiltersUpdated = (filters) => { - // The filters will automatically be set when the filterManager emits an update event (see below) - filterManager.setFilters(filters); - }; - - $scope.showSaveQuery = visualizeCapabilities.saveQuery; - - $scope.$watch( - () => visualizeCapabilities.saveQuery, - (newCapability) => { - $scope.showSaveQuery = newCapability; - } - ); - - const updateSavedQueryFromUrl = (savedQueryId) => { - if (!savedQueryId) { - delete $scope.savedQuery; - - return; - } - - if ($scope.savedQuery && $scope.savedQuery.id === savedQueryId) { - return; - } - - queryService.savedQueries.getSavedQuery(savedQueryId).then((savedQuery) => { - $scope.$evalAsync(() => { - $scope.updateSavedQuery(savedQuery); - }); - }); - }; - - function init() { - if (vis.data.indexPattern) { - $scope.indexPattern = vis.data.indexPattern; - } else { - indexPatterns.getDefault().then((defaultIndexPattern) => { - $scope.indexPattern = defaultIndexPattern; - }); - } - - const initialState = stateContainer.getState(); - - const handleLinkedSearch = (linked) => { - if (linked && !savedVis.savedSearchId && savedSearch) { - savedVis.savedSearchId = savedSearch.id; - vis.data.savedSearchId = savedSearch.id; - searchSource.setParent(savedSearch.searchSource); - } else if (!linked && savedVis.savedSearchId) { - delete savedVis.savedSearchId; - delete vis.data.savedSearchId; - } - }; - - // Create a PersistedState instance for uiState. - const { persistedState, unsubscribePersisted, persistOnChange } = makeStateful( - 'uiState', - stateContainer - ); - vis.uiState = persistedState; - vis.uiState.on('reload', embeddableHandler.reload); - $scope.uiState = persistedState; - $scope.savedVis = savedVis; - $scope.query = initialState.query; - $scope.searchSource = searchSource; - $scope.refreshInterval = timefilter.getRefreshInterval(); - handleLinkedSearch(initialState.linked); - - $scope.showFilterBar = () => { - return vis.type.options.showFilterBar; - }; - - $scope.showQueryInput = () => { - return vis.type.requiresSearch && vis.type.options.showQueryBar; - }; - - $scope.showQueryBarTimePicker = () => { - // tsvb loads without an indexPattern initially (TODO investigate). - // hide timefilter only if timeFieldName is explicitly undefined. - const hasTimeField = vis.data.indexPattern ? !!vis.data.indexPattern.timeFieldName : true; - return vis.type.options.showTimePicker && hasTimeField; - }; - - $scope.timeRange = timefilter.getTime(); - - const unsubscribeStateUpdates = stateContainer.subscribe((state) => { - const newQuery = migrateLegacyQuery(state.query); - if (!_.isEqual(state.query, newQuery)) { - stateContainer.transitions.set('query', newQuery); - } - persistOnChange(state); - updateSavedQueryFromUrl(state.savedQuery); - - // if the browser history was changed manually we need to reflect changes in the editor - if ( - !_.isEqual( - { - ...visualizations.convertFromSerializedVis(vis.serialize()).visState, - title: vis.title, - }, - state.vis - ) - ) { - const { aggs, ...visState } = state.vis; - vis.setState({ - ...visState, - data: { - aggs, - }, - }); - embeddableHandler.reload(); - $scope.eventEmitter.emit('updateEditor'); - } - - $appStatus.dirty = true; - $scope.fetch(); - }); - - const updateTimeRange = () => { - $scope.timeRange = timefilter.getTime(); - $scope.$broadcast('render'); - }; - - // update the query if savedQuery is stored - updateSavedQueryFromUrl(initialState.savedQuery); - - const subscriptions = new Subscription(); - - subscriptions.add( - subscribeWithScope( - $scope, - timefilter.getRefreshIntervalUpdate$(), - { - next: () => { - $scope.refreshInterval = timefilter.getRefreshInterval(); - }, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - subscriptions.add( - subscribeWithScope( - $scope, - timefilter.getTimeUpdate$(), - { - next: updateTimeRange, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - - subscriptions.add( - chrome.getIsVisible$().subscribe((isVisible) => { - $scope.$evalAsync(() => { - $scope.isVisible = isVisible; - }); - }) - ); - - // update the searchSource when query updates - $scope.fetch = function () { - const { query, linked, filters } = stateContainer.getState(); - $scope.query = query; - handleLinkedSearch(linked); - vis.data.searchSource.setField('query', query); - vis.data.searchSource.setField('filter', filters); - $scope.$broadcast('render'); - }; - - // update the searchSource when filters update - subscriptions.add( - subscribeWithScope( - $scope, - filterManager.getUpdates$(), - { - next: () => { - $scope.filters = filterManager.getFilters(); - }, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - subscriptions.add( - subscribeWithScope( - $scope, - filterManager.getFetches$(), - { - next: $scope.fetch, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - - $scope.$on('$destroy', () => { - if ($scope._handler) { - $scope._handler.destroy(); - } - savedVis.destroy(); - subscriptions.unsubscribe(); - $scope.eventEmitter.off('apply', _applyVis); - - unsubscribePersisted(); - vis.uiState.off('reload', embeddableHandler.reload); - unsubscribeStateUpdates(); - - stopAllSyncing(); - }); - - $timeout(() => { - $scope.$broadcast('render'); - }); - } - - $scope.updateQueryAndFetch = function ({ query, dateRange }) { - const isUpdate = - (query && !_.isEqual(query, stateContainer.getState().query)) || - (dateRange && !_.isEqual(dateRange, $scope.timeRange)); - - stateContainer.transitions.set('query', query); - timefilter.setTime(dateRange); - - // If nothing has changed, trigger the fetch manually, otherwise it will happen as a result of the changes - if (!isUpdate) { - embeddableHandler.reload(); - } - }; - - $scope.onRefreshChange = function ({ isPaused, refreshInterval }) { - timefilter.setRefreshInterval({ - pause: isPaused, - value: refreshInterval ? refreshInterval : $scope.refreshInterval.value, - }); - }; - - $scope.onClearSavedQuery = () => { - delete $scope.savedQuery; - stateContainer.transitions.removeSavedQuery(defaultQuery); - filterManager.setFilters(filterManager.getGlobalFilters()); - }; - - const updateStateFromSavedQuery = (savedQuery) => { - stateContainer.transitions.updateFromSavedQuery(savedQuery); - - const savedQueryFilters = savedQuery.attributes.filters || []; - const globalFilters = filterManager.getGlobalFilters(); - filterManager.setFilters([...globalFilters, ...savedQueryFilters]); - - if (savedQuery.attributes.timefilter) { - timefilter.setTime({ - from: savedQuery.attributes.timefilter.from, - to: savedQuery.attributes.timefilter.to, - }); - if (savedQuery.attributes.timefilter.refreshInterval) { - timefilter.setRefreshInterval(savedQuery.attributes.timefilter.refreshInterval); - } - } - }; - - $scope.updateSavedQuery = (savedQuery) => { - $scope.savedQuery = savedQuery; - updateStateFromSavedQuery(savedQuery); - }; - - /** - * Called when the user clicks "Save" button. - */ - function doSave(saveOptions) { - // vis.title was not bound and it's needed to reflect title into visState - const newlyCreated = !Boolean(savedVis.id) || savedVis.copyOnSave; - stateContainer.transitions.setVis({ - title: savedVis.title, - type: savedVis.type || stateContainer.getState().vis.type, - }); - savedVis.searchSourceFields = searchSource.getSerializedFields(); - savedVis.visState = stateContainer.getState().vis; - savedVis.uiStateJSON = angular.toJson($scope.uiState.toJSON()); - $appStatus.dirty = false; - - return savedVis.save(saveOptions).then( - function (id) { - $scope.$evalAsync(() => { - if (id) { - toastNotifications.addSuccess({ - title: i18n.translate( - 'visualize.topNavMenu.saveVisualization.successNotificationText', - { - defaultMessage: `Saved '{visTitle}'`, - values: { - visTitle: savedVis.title, - }, - } - ), - 'data-test-subj': 'saveVisualizationSuccess', - }); - - if ($scope.getOriginatingApp() && saveOptions.returnToOrigin) { - const appPath = `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`; - - // Manually insert a new url so the back button will open the saved visualization. - history.replace(appPath); - setActiveUrl(appPath); - if (newlyCreated && embeddable) { - embeddable - .getStateTransfer() - .navigateToWithEmbeddablePackage($scope.getOriginatingApp(), { - state: { id: savedVis.id, type: VISUALIZE_EMBEDDABLE_TYPE }, - }); - } else { - application.navigateToApp($scope.getOriginatingApp()); - } - } else if (savedVis.id === $route.current.params.id) { - chrome.docTitle.change(savedVis.lastSavedTitle); - chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs)); - savedVis.vis.title = savedVis.title; - savedVis.vis.description = savedVis.description; - } else { - history.replace({ - ...history.location, - pathname: `${VisualizeConstants.EDIT_PATH}/${savedVis.id}`, - }); - } - } - }); - return { id }; - }, - (error) => { - // eslint-disable-next-line - console.error(error); - toastNotifications.addDanger({ - title: i18n.translate('visualize.topNavMenu.saveVisualization.failureNotificationText', { - defaultMessage: `Error on saving '{visTitle}'`, - values: { - visTitle: savedVis.title, - }, - }), - text: error.message, - 'data-test-subj': 'saveVisualizationError', - }); - return { error }; - } - ); - } - - const unlinkFromSavedSearch = () => { - const searchSourceParent = savedSearch.searchSource; - const searchSourceGrandparent = searchSourceParent.getParent(); - const currentIndex = searchSourceParent.getField('index'); - - searchSource.setField('index', currentIndex); - searchSource.setParent(searchSourceGrandparent); - - stateContainer.transitions.unlinkSavedSearch({ - query: searchSourceParent.getField('query'), - parentFilters: searchSourceParent.getOwnField('filter'), - }); - - toastNotifications.addSuccess( - i18n.translate('visualize.linkedToSearch.unlinkSuccessNotificationText', { - defaultMessage: `Unlinked from saved search '{searchTitle}'`, - values: { - searchTitle: savedSearch.title, - }, - }) - ); - }; - - $scope.getAdditionalMessage = () => { - return ( - '' + - i18n.translate('visualize.experimentalVisInfoText', { - defaultMessage: 'This visualization is marked as experimental.', - }) + - ' ' + - vis.type.feedbackMessage - ); - }; - - $scope.eventEmitter.on('unlinkFromSavedSearch', unlinkFromSavedSearch); - - addHelpMenuToAppChrome(chrome, docLinks); - - init(); -} diff --git a/src/plugins/visualize/public/application/editor/lib/make_stateful.ts b/src/plugins/visualize/public/application/editor/lib/make_stateful.ts deleted file mode 100644 index c7163f9b7705d..0000000000000 --- a/src/plugins/visualize/public/application/editor/lib/make_stateful.ts +++ /dev/null @@ -1,58 +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 { PersistedState } from '../../../../../visualizations/public'; -import { ReduxLikeStateContainer } from '../../../../../kibana_utils/public'; -import { VisualizeAppState, VisualizeAppStateTransitions } from '../../types'; - -/** - * @returns Create a PersistedState instance, initialize state changes subscriber/unsubscriber - */ -export function makeStateful( - prop: keyof VisualizeAppState, - stateContainer: ReduxLikeStateContainer -) { - // set up the persistedState state - const persistedState = new PersistedState(); - - // update the appState when the stateful instance changes - const updateOnChange = function () { - stateContainer.transitions.set(prop, persistedState.getChanges()); - }; - - const handlerOnChange = (method: 'on' | 'off') => - persistedState[method]('change', updateOnChange); - - handlerOnChange('on'); - const unsubscribePersisted = () => handlerOnChange('off'); - - // update the stateful object when the app state changes - const persistOnChange = function (state: VisualizeAppState) { - if (state[prop]) { - persistedState.set(state[prop]); - } - }; - - const appState = stateContainer.getState(); - - // if the thing we're making stateful has an appState value, write to persisted state - if (appState[prop]) persistedState.setSilent(appState[prop]); - - return { persistedState, unsubscribePersisted, persistOnChange }; -} diff --git a/src/plugins/visualize/public/application/editor/visualization.js b/src/plugins/visualize/public/application/editor/visualization.js deleted file mode 100644 index 26f61f3f0a2c2..0000000000000 --- a/src/plugins/visualize/public/application/editor/visualization.js +++ /dev/null @@ -1,61 +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. - */ - -export function initVisualizationDirective(app) { - app.directive('visualizationEmbedded', function ($timeout) { - return { - restrict: 'E', - scope: { - embeddableHandler: '=', - uiState: '=?', - timeRange: '=', - filters: '=', - query: '=', - appState: '=', - }, - link: function ($scope, element) { - $scope.renderFunction = async () => { - if (!$scope.rendered) { - $scope.embeddableHandler.render(element[0]); - $scope.rendered = true; - } - - $scope.embeddableHandler.updateInput({ - timeRange: $scope.timeRange, - filters: $scope.filters || [], - query: $scope.query, - }); - }; - - $scope.$on('render', (event) => { - event.preventDefault(); - $timeout(() => { - $scope.renderFunction(); - }); - }); - - $scope.$on('$destroy', () => { - if ($scope.embeddableHandler) { - $scope.embeddableHandler.destroy(); - } - }); - }, - }; - }); -} diff --git a/src/plugins/visualize/public/application/editor/visualization_editor.js b/src/plugins/visualize/public/application/editor/visualization_editor.js deleted file mode 100644 index 4963d9bc5ed72..0000000000000 --- a/src/plugins/visualize/public/application/editor/visualization_editor.js +++ /dev/null @@ -1,71 +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 { DefaultEditorController } from '../../../../vis_default_editor/public'; - -export function initVisEditorDirective(app, deps) { - app.directive('visualizationEditor', function ($timeout) { - return { - restrict: 'E', - scope: { - vis: '=', - uiState: '=?', - timeRange: '=', - filters: '=', - query: '=', - savedSearch: '=', - embeddableHandler: '=', - eventEmitter: '=', - }, - link: function ($scope, element) { - const Editor = $scope.vis.type.editor || DefaultEditorController; - const editor = new Editor( - element[0], - $scope.vis, - $scope.eventEmitter, - $scope.embeddableHandler - ); - - $scope.renderFunction = () => { - editor.render({ - core: deps.core, - data: deps.data, - uiState: $scope.uiState, - timeRange: $scope.timeRange, - filters: $scope.filters, - query: $scope.query, - linked: !!$scope.vis.data.savedSearchId, - savedSearch: $scope.savedSearch, - }); - }; - - $scope.$on('render', (event) => { - event.preventDefault(); - $timeout(() => { - $scope.renderFunction(); - }); - }); - - $scope.$on('$destroy', () => { - editor.destroy(); - }); - }, - }; - }); -} diff --git a/src/plugins/visualize/public/application/help_menu/help_menu_util.js b/src/plugins/visualize/public/application/help_menu/help_menu_util.js deleted file mode 100644 index c297326f2e264..0000000000000 --- a/src/plugins/visualize/public/application/help_menu/help_menu_util.js +++ /dev/null @@ -1,34 +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 { i18n } from '@kbn/i18n'; - -export function addHelpMenuToAppChrome(chrome, docLinks) { - chrome.setHelpExtension({ - appName: i18n.translate('visualize.helpMenu.appName', { - defaultMessage: 'Visualize', - }), - links: [ - { - linkType: 'documentation', - href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`, - }, - ], - }); -} diff --git a/src/plugins/visualize/public/application/index.tsx b/src/plugins/visualize/public/application/index.tsx new file mode 100644 index 0000000000000..4bec244e6efc9 --- /dev/null +++ b/src/plugins/visualize/public/application/index.tsx @@ -0,0 +1,51 @@ +/* + * 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 ReactDOM from 'react-dom'; +import { Router } from 'react-router-dom'; + +import { AppMountParameters } from 'kibana/public'; +import { KibanaContextProvider } from '../../../kibana_react/public'; +import { VisualizeApp } from './app'; +import { VisualizeServices } from './types'; +import { addHelpMenuToAppChrome, addBadgeToAppChrome } from './utils'; + +export const renderApp = ({ element }: AppMountParameters, services: VisualizeServices) => { + // add help link to visualize docs into app chrome menu + addHelpMenuToAppChrome(services.chrome, services.docLinks); + // add readonly badge if saving restricted + if (!services.visualizeCapabilities.save) { + addBadgeToAppChrome(services.chrome); + } + + const app = ( + + + + + + + + ); + + ReactDOM.render(app, element); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/src/plugins/visualize/public/application/legacy_app.js b/src/plugins/visualize/public/application/legacy_app.js deleted file mode 100644 index 452118f8097da..0000000000000 --- a/src/plugins/visualize/public/application/legacy_app.js +++ /dev/null @@ -1,261 +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 { find } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { createHashHistory } from 'history'; - -import { createKbnUrlStateStorage, redirectWhenMissing } from '../../../kibana_utils/public'; -import { createSavedSearchesLoader } from '../../../discover/public'; - -import editorTemplate from './editor/editor.html'; -import visualizeListingTemplate from './listing/visualize_listing.html'; - -import { initVisualizeAppDirective } from './visualize_app'; -import { VisualizeConstants } from './visualize_constants'; -import { VisualizeListingController } from './listing/visualize_listing'; - -import { - getLandingBreadcrumbs, - getWizardStep1Breadcrumbs, - getCreateBreadcrumbs, - getEditBreadcrumbs, -} from './breadcrumbs'; - -const getResolvedResults = (deps) => { - const { core, data, visualizations, createVisEmbeddableFromObject } = deps; - - const results = {}; - - return (savedVis) => { - results.savedVis = savedVis; - const serializedVis = visualizations.convertToSerializedVis(savedVis); - return visualizations - .createVis(serializedVis.type, serializedVis) - .then((vis) => { - if (vis.type.setup) { - return vis.type.setup(vis).catch(() => vis); - } - return vis; - }) - .then((vis) => { - results.vis = vis; - return createVisEmbeddableFromObject(vis, { - timeRange: data.query.timefilter.timefilter.getTime(), - filters: data.query.filterManager.getFilters(), - }); - }) - .then((embeddableHandler) => { - results.embeddableHandler = embeddableHandler; - - embeddableHandler.getOutput$().subscribe((output) => { - if (output.error) { - core.notifications.toasts.addError(output.error, { - title: i18n.translate('visualize.error.title', { - defaultMessage: 'Visualization error', - }), - }); - } - }); - - if (results.vis.data.savedSearchId) { - return createSavedSearchesLoader({ - savedObjectsClient: core.savedObjects.client, - indexPatterns: data.indexPatterns, - search: data.search, - chrome: core.chrome, - overlays: core.overlays, - }).get(results.vis.data.savedSearchId); - } - }) - .then((savedSearch) => { - if (savedSearch) { - results.savedSearch = savedSearch; - } - return results; - }); - }; -}; - -export function initVisualizeApp(app, deps) { - initVisualizeAppDirective(app, deps); - - app.factory('history', () => createHashHistory()); - app.factory('kbnUrlStateStorage', (history) => - createKbnUrlStateStorage({ - history, - useHash: deps.core.uiSettings.get('state:storeInSessionStorage'), - }) - ); - - app.config(function ($routeProvider) { - const defaults = { - reloadOnSearch: false, - requireUICapability: 'visualize.show', - badge: () => { - if (deps.visualizeCapabilities.save) { - return undefined; - } - - return { - text: i18n.translate('visualize.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('visualize.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save visualizations', - }), - iconType: 'glasses', - }; - }, - }; - - $routeProvider - .when(VisualizeConstants.LANDING_PAGE_PATH, { - ...defaults, - template: visualizeListingTemplate, - k7Breadcrumbs: getLandingBreadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => false, - hasDefaultIndex: (history) => deps.data.indexPatterns.ensureDefaultIndexPattern(history), - }, - }) - .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { - ...defaults, - template: visualizeListingTemplate, - k7Breadcrumbs: getWizardStep1Breadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => true, - hasDefaultIndex: (history) => deps.data.indexPatterns.ensureDefaultIndexPattern(history), - }, - }) - .when(VisualizeConstants.CREATE_PATH, { - ...defaults, - template: editorTemplate, - k7Breadcrumbs: getCreateBreadcrumbs, - resolve: { - resolved: function ($route, history) { - const { data, savedVisualizations, visualizations, toastNotifications } = deps; - const visTypes = visualizations.all(); - const visType = find(visTypes, { name: $route.current.params.type }); - const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection; - const hasIndex = - $route.current.params.indexPattern || $route.current.params.savedSearchId; - if (shouldHaveIndex && !hasIndex) { - throw new Error( - i18n.translate( - 'visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage', - { - defaultMessage: 'You must provide either an indexPattern or a savedSearchId', - } - ) - ); - } - - // This delay is needed to prevent some navigation issues in Firefox/Safari. - // see https://github.com/elastic/kibana/issues/65161 - const delay = (res) => { - return new Promise((resolve) => { - setTimeout(() => resolve(res), 0); - }); - }; - - return data.indexPatterns - .ensureDefaultIndexPattern(history) - .then(() => savedVisualizations.get($route.current.params)) - .then((savedVis) => { - savedVis.searchSourceFields = { index: $route.current.params.indexPattern }; - return savedVis; - }) - .then(getResolvedResults(deps)) - .then(delay) - .catch( - redirectWhenMissing({ - history, - mapping: VisualizeConstants.LANDING_PAGE_PATH, - toastNotifications, - }) - ); - }, - }, - }) - .when(`${VisualizeConstants.EDIT_PATH}/:id`, { - ...defaults, - template: editorTemplate, - k7Breadcrumbs: getEditBreadcrumbs, - resolve: { - resolved: function ($route, history) { - const { chrome, data, savedVisualizations, toastNotifications } = deps; - - return data.indexPatterns - .ensureDefaultIndexPattern(history) - .then(() => savedVisualizations.get($route.current.params.id)) - .then((savedVis) => { - chrome.recentlyAccessed.add(savedVis.getFullPath(), savedVis.title, savedVis.id); - return savedVis; - }) - .then(getResolvedResults(deps)) - .catch( - redirectWhenMissing({ - history, - navigateToApp: deps.core.application.navigateToApp, - basePath: deps.core.http.basePath, - mapping: { - visualization: VisualizeConstants.LANDING_PAGE_PATH, - search: { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - 'index-pattern': { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - 'index-pattern-field': { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - }, - toastNotifications, - onBeforeRedirect() { - deps.setActiveUrl(VisualizeConstants.LANDING_PAGE_PATH); - }, - }) - ); - }, - }, - }) - .otherwise({ - resolveRedirectTo: function ($rootScope) { - const path = window.location.hash.substr(1); - deps.restorePreviousUrl(); - $rootScope.$applyAsync(() => { - const { navigated } = deps.kibanaLegacy.navigateToLegacyKibanaUrl(path); - if (!navigated) { - deps.kibanaLegacy.navigateToDefaultApp(); - } - }); - // prevent angular from completing the navigation - return new Promise(() => {}); - }, - }); - }); -} diff --git a/src/plugins/visualize/public/application/listing/_index.scss b/src/plugins/visualize/public/application/listing/_index.scss deleted file mode 100644 index 924c164e467d8..0000000000000 --- a/src/plugins/visualize/public/application/listing/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'listing'; diff --git a/src/plugins/visualize/public/application/listing/visualize_listing.html b/src/plugins/visualize/public/application/listing/visualize_listing.html deleted file mode 100644 index 8838348e0b679..0000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
diff --git a/src/plugins/visualize/public/application/listing/visualize_listing.js b/src/plugins/visualize/public/application/listing/visualize_listing.js deleted file mode 100644 index e8e8d92034113..0000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing.js +++ /dev/null @@ -1,174 +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 { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; -import { withI18nContext } from './visualize_listing_table'; - -import { VisualizeConstants } from '../visualize_constants'; -import { i18n } from '@kbn/i18n'; - -import { getServices } from '../../kibana_services'; -import { syncQueryStateWithUrl } from '../../../../data/public'; -import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; - -import { EuiLink } from '@elastic/eui'; -import React from 'react'; - -export function initListingDirective(app, I18nContext) { - app.directive('visualizeListingTable', (reactDirective) => - reactDirective(withI18nContext(I18nContext)) - ); -} - -export function VisualizeListingController($scope, createNewVis, kbnUrlStateStorage, history) { - const { - addBasePath, - chrome, - savedObjectsClient, - savedVisualizations, - data: { query }, - toastNotifications, - visualizations, - core: { docLinks, savedObjects, uiSettings, application }, - savedObjects: savedObjectsPublic, - } = getServices(); - - chrome.docTitle.change( - i18n.translate('visualize.listingPageTitle', { defaultMessage: 'Visualize' }) - ); - - // syncs `_g` portion of url with query services - const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( - query, - kbnUrlStateStorage - ); - - const { - timefilter: { timefilter }, - } = query; - - timefilter.disableAutoRefreshSelector(); - timefilter.disableTimeRangeSelector(); - - this.addBasePath = addBasePath; - this.uiSettings = uiSettings; - this.savedObjects = savedObjects; - - this.createNewVis = () => { - this.closeNewVisModal = visualizations.showNewVisModal(); - }; - - this.editItem = ({ editUrl, editApp }) => { - if (editApp) { - application.navigateToApp(editApp, { path: editUrl }); - return; - } - // for visualizations the edit and view URLs are the same - window.location.href = addBasePath(editUrl); - }; - - this.getViewElement = (field, record) => { - const dataTestSubj = `visListingTitleLink-${record.title.split(' ').join('-')}`; - if (record.editApp) { - return ( - { - application.navigateToApp(record.editApp, { path: record.editUrl }); - }} - data-test-subj={dataTestSubj} - > - {field} - - ); - } else if (record.editUrl) { - return ( - - {field} - - ); - } else { - return {field}; - } - }; - - if (createNewVis) { - // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately - this.closeNewVisModal = visualizations.showNewVisModal({ - onClose: () => { - // In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal - history.push({ - // Should preserve querystring part so the global state is preserved. - ...history.location, - pathname: VisualizeConstants.LANDING_PAGE_PATH, - }); - }, - }); - } - - this.fetchItems = (filter) => { - const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING); - return savedVisualizations - .findListItems(filter, savedObjectsPublic.settings.getListingLimit()) - .then((result) => { - this.totalItems = result.total; - - return { - total: result.total, - hits: result.hits.filter( - (result) => isLabsEnabled || result.type.stage !== 'experimental' - ), - }; - }); - }; - - this.deleteSelectedItems = function deleteSelectedItems(selectedItems) { - return Promise.all( - selectedItems.map((item) => { - return savedObjectsClient.delete(item.savedObjectType, item.id); - }) - ).catch((error) => { - toastNotifications.addError(error, { - title: i18n.translate('visualize.visualizeListingDeleteErrorTitle', { - defaultMessage: 'Error deleting visualization', - }), - }); - }); - }; - - chrome.setBreadcrumbs([ - { - text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', { - defaultMessage: 'Visualize', - }), - }, - ]); - - this.listingLimit = savedObjectsPublic.settings.getListingLimit(); - this.initialPageSize = savedObjectsPublic.settings.getPerPage(); - - addHelpMenuToAppChrome(chrome, docLinks); - - $scope.$on('$destroy', () => { - if (this.closeNewVisModal) { - this.closeNewVisModal(); - } - - stopSyncingQueryServiceStateWithUrl(); - }); -} diff --git a/src/plugins/visualize/public/application/listing/visualize_listing_table.js b/src/plugins/visualize/public/application/listing/visualize_listing_table.js deleted file mode 100644 index fcd62d7ddee73..0000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing_table.js +++ /dev/null @@ -1,233 +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 React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { TableListView } from '../../../../kibana_react/public'; - -import { EuiIcon, EuiBetaBadge, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; - -import { getServices } from '../../kibana_services'; - -class VisualizeListingTable extends Component { - constructor(props) { - super(props); - } - - render() { - const { visualizeCapabilities, core, toastNotifications } = getServices(); - return ( - item.canDelete} - initialFilter={''} - noItemsFragment={this.getNoItemsMessage()} - entityName={i18n.translate('visualize.listing.table.entityName', { - defaultMessage: 'visualization', - })} - entityNamePlural={i18n.translate('visualize.listing.table.entityNamePlural', { - defaultMessage: 'visualizations', - })} - tableListTitle={i18n.translate('visualize.listing.table.listTitle', { - defaultMessage: 'Visualizations', - })} - toastNotifications={toastNotifications} - uiSettings={core.uiSettings} - /> - ); - } - - getTableColumns() { - const tableColumns = [ - { - field: 'title', - name: i18n.translate('visualize.listing.table.titleColumnName', { - defaultMessage: 'Title', - }), - sortable: true, - render: (field, record) => this.props.getViewElement(field, record), - }, - { - field: 'typeTitle', - name: i18n.translate('visualize.listing.table.typeColumnName', { - defaultMessage: 'Type', - }), - sortable: true, - render: (field, record) => ( - - {this.renderItemTypeIcon(record)} - {record.typeTitle} - {this.getBadge(record)} - - ), - }, - { - field: 'description', - name: i18n.translate('visualize.listing.table.descriptionColumnName', { - defaultMessage: 'Description', - }), - sortable: true, - render: (field, record) => {record.description}, - }, - ]; - - return tableColumns; - } - - getNoItemsMessage() { - if (this.props.hideWriteControls) { - return ( -
- - - - } - /> -
- ); - } - - return ( -
- - - - } - body={ - -

- -

-
- } - actions={ - - - - } - /> -
- ); - } - - renderItemTypeIcon(item) { - let icon; - if (item.image) { - icon = ( - - ); - } else { - icon = ( -