diff --git a/.eslintrc.js b/.eslintrc.js
index 14567f43430060..ce4aea3c023092 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -510,6 +510,10 @@ module.exports = {
// typescript and javascript for front and back end
files: ['x-pack/legacy/plugins/siem/**/*.{js,ts,tsx}'],
plugins: ['eslint-plugin-node', 'react'],
+ env: {
+ mocha: true,
+ jest: true,
+ },
rules: {
'accessor-pairs': 'error',
'array-callback-return': 'error',
@@ -564,8 +568,7 @@ module.exports = {
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-this-before-super': 'error',
- // This will be turned on after bug fixes are mostly complete
- // 'no-undef': 'warn',
+ 'no-undef': 'error',
'no-unreachable': 'error',
'no-unsafe-finally': 'error',
'no-useless-call': 'error',
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 516f5e71577e6d..bea2f4e74297e8 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -13,6 +13,8 @@
# APM
/x-pack/legacy/plugins/apm/ @elastic/apm-ui
+/x-pack/test/functional/apps/apm/ @elastic/apm-ui
+/src/legacy/core_plugins/apm_oss/ @elastic/apm-ui
# Beats
/x-pack/legacy/plugins/beats_management/ @elastic/beats
diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md
index 152a0e2c488712..5fd3ef5e8ff4bf 100644
--- a/STYLEGUIDE.md
+++ b/STYLEGUIDE.md
@@ -141,6 +141,39 @@ function addBar(foos, foo) {
}
```
+### Avoid `any` whenever possible
+
+Since TypeScript 3.0 and the introduction of the
+[`unknown` type](https://mariusschulz.com/blog/the-unknown-type-in-typescript) there are rarely any
+reasons to use `any` as a type. Nearly all places of former `any` usage can be replace by either a
+generic or `unknown` (in cases the type is really not known).
+
+You should always prefer using those mechanisms over using `any`, since they are stricter typed and
+less likely to introduce bugs in the future due to insufficient types.
+
+If you’re not having `any` in your plugin or are starting a new plugin, you should enable the
+[`@typescript-eslint/no-explicit-any`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-explicit-any.md)
+linting rule for your plugin via the [`.eslintrc.js`](https://github.com/elastic/kibana/blob/master/.eslintrc.js) config.
+
+### Avoid non-null assertions
+
+You should try avoiding non-null assertions (`!.`) wherever possible. By using them you tell
+TypeScript, that something is not null even though by it’s type it could be. Usage of non-null
+assertions is most often a side-effect of you actually checked that the variable is not `null`
+but TypeScript doesn’t correctly carry on that information till the usage of the variable.
+
+In most cases it’s possible to replace the non-null assertion by structuring your code/checks slightly different
+or using [user defined type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)
+to properly tell TypeScript what type a variable has.
+
+Using non-null assertion increases the risk for future bugs. In case the condition under which we assumed that the
+variable can’t be null has changed (potentially even due to changes in compeltely different files), the non-null
+assertion would now wrongly disable proper type checking for us.
+
+If you’re not using non-null assertions in your plugin or are starting a new plugin, consider enabling the
+[`@typescript-eslint/no-non-null-assertion`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md)
+linting rule for you plugin in the [`.eslintrc.js`](https://github.com/elastic/kibana/blob/master/.eslintrc.js) config.
+
### Return/throw early from functions
To avoid deep nesting of if-statements, always return a function's value as early
diff --git a/config/kibana.yml b/config/kibana.yml
index 7d49fb37e03208..9525a6423d90a0 100644
--- a/config/kibana.yml
+++ b/config/kibana.yml
@@ -18,10 +18,6 @@
# default to `true` starting in Kibana 7.0.
#server.rewriteBasePath: false
-# Specifies the default route when opening Kibana. You can use this setting to modify
-# the landing page when opening Kibana.
-#server.defaultRoute: /app/kibana
-
# The maximum payload size in bytes for incoming server requests.
#server.maxPayloadBytes: 1048576
diff --git a/docs/api/saved-objects/find.asciidoc b/docs/api/saved-objects/find.asciidoc
index fd80951b1c9f25..f20ded78e07434 100644
--- a/docs/api/saved-objects/find.asciidoc
+++ b/docs/api/saved-objects/find.asciidoc
@@ -41,6 +41,11 @@ experimental[] Retrieve a paginated set of {kib} saved objects by various condit
`has_reference`::
(Optional, object) Filters to objects that have a relationship with the type and ID combination.
+`filter`::
+ (Optional, string) The filter is a KQL string with the caveat that if you filter with an attribute from your type saved object.
+ It should look like that savedObjectType.attributes.title: "myTitle". However, If you used a direct attribute of a saved object like `updatedAt`,
+ you will have to define your filter like that savedObjectType.updatedAt > 2018-12-22.
+
NOTE: As objects change in {kib}, the results on each page of the response also
change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.
diff --git a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md
index 0b5bd8eeb36eca..f264ba500ed6ef 100644
--- a/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md
+++ b/docs/development/core/public/kibana-plugin-public.applicationsetup.registermountcontext.md
@@ -9,7 +9,7 @@ Register a context provider for application mounting. Will only be available to
Signature:
```typescript
-registerMountContext(contextName: T, provider: IContextProvider): void;
+registerMountContext(contextName: T, provider: IContextProvider): void;
```
## Parameters
@@ -17,7 +17,7 @@ registerMountContext(contextName: T, provider:
| Parameter | Type | Description |
| --- | --- | --- |
| contextName | T
| The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. |
-| provider | IContextProvider<AppMountContext, T>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
+| provider | IContextProvider<App['mount'], T>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
Returns:
diff --git a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md
index fc86aaf658b681..62821fcbb92bad 100644
--- a/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md
+++ b/docs/development/core/public/kibana-plugin-public.applicationstart.registermountcontext.md
@@ -9,7 +9,7 @@ Register a context provider for application mounting. Will only be available to
Signature:
```typescript
-registerMountContext(contextName: T, provider: IContextProvider): void;
+registerMountContext(contextName: T, provider: IContextProvider): void;
```
## Parameters
@@ -17,7 +17,7 @@ registerMountContext(contextName: T, provider:
| Parameter | Type | Description |
| --- | --- | --- |
| contextName | T
| The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. |
-| provider | IContextProvider<AppMountContext, T>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
+| provider | IContextProvider<App['mount'], T>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
Returns:
diff --git a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md
index 2644596354e383..5334eee8425779 100644
--- a/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md
+++ b/docs/development/core/public/kibana-plugin-public.contextsetup.createcontextcontainer.md
@@ -9,9 +9,9 @@ Creates a new [IContextContainer](./kibana-plugin-public.icontextcontainer.md) f
Signature:
```typescript
-createContextContainer(): IContextContainer;
+createContextContainer>(): IContextContainer;
```
Returns:
-`IContextContainer`
+`IContextContainer`
diff --git a/docs/development/core/public/kibana-plugin-public.handlercontexttype.md b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md
new file mode 100644
index 00000000000000..b083449d2b703f
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.handlercontexttype.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerContextType](./kibana-plugin-public.handlercontexttype.md)
+
+## HandlerContextType type
+
+Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context.
+
+Signature:
+
+```typescript
+export declare type HandlerContextType> = T extends HandlerFunction ? U : never;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.handlerfunction.md b/docs/development/core/public/kibana-plugin-public.handlerfunction.md
new file mode 100644
index 00000000000000..98c342c17691d9
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.handlerfunction.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerFunction](./kibana-plugin-public.handlerfunction.md)
+
+## HandlerFunction type
+
+A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md)
+
+Signature:
+
+```typescript
+export declare type HandlerFunction = (context: T, ...args: any[]) => any;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.handlerparameters.md b/docs/development/core/public/kibana-plugin-public.handlerparameters.md
new file mode 100644
index 00000000000000..f46c4b649e9436
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.handlerparameters.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HandlerParameters](./kibana-plugin-public.handlerparameters.md)
+
+## HandlerParameters type
+
+Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md).
+
+Signature:
+
+```typescript
+export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md
index 2a995df45757f3..af3b5e3fc2eb65 100644
--- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md
+++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md
@@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin.
Signature:
```typescript
-createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise;
+createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>;
```
## Parameters
@@ -17,11 +17,11 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandlerPluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. |
-| handler | IContextHandler<TContext, THandlerReturn, THandlerParameters>
| Handler function to pass context object to. |
+| handler | THandler
| Handler function to pass context object to. |
Returns:
-`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise`
+`(...rest: HandlerParameters) => ShallowPromise>`
A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value.
diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md
index 0bc7c8f3808d16..f16c07b3d7906d 100644
--- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.md
+++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.md
@@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler
Signature:
```typescript
-export interface IContextContainer
+export interface IContextContainer>
```
## Methods
diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md
index 2cf10a6ec841d6..775f95bd7affaa 100644
--- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md
+++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.registercontext.md
@@ -9,7 +9,7 @@ Register a new context provider.
Signature:
```typescript
-registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
+registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
```
## Parameters
@@ -18,7 +18,7 @@ registerContext(pluginOpaqueId: PluginOpaqu
| --- | --- | --- |
| pluginOpaqueId | PluginOpaqueId
| The plugin opaque ID for the plugin that registers this context. |
| contextName | TContextName
| The key of the TContext
object this provider supplies the value for. |
-| provider | IContextProvider<TContext, TContextName, THandlerParameters>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. |
+| provider | IContextProvider<THandler, TContextName>
| A [IContextProvider](./kibana-plugin-public.icontextprovider.md) to be called each time a new context is created. |
Returns:
diff --git a/docs/development/core/public/kibana-plugin-public.icontexthandler.md b/docs/development/core/public/kibana-plugin-public.icontexthandler.md
deleted file mode 100644
index 2251b1131c3138..00000000000000
--- a/docs/development/core/public/kibana-plugin-public.icontexthandler.md
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IContextHandler](./kibana-plugin-public.icontexthandler.md)
-
-## IContextHandler type
-
-A function registered by a plugin to perform some action.
-
-Signature:
-
-```typescript
-export declare type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn;
-```
-
-## Remarks
-
-A new `TContext` will be built for each handler before invoking.
-
diff --git a/docs/development/core/public/kibana-plugin-public.icontextprovider.md b/docs/development/core/public/kibana-plugin-public.icontextprovider.md
index a84917d6e14420..40f0ee3782f6da 100644
--- a/docs/development/core/public/kibana-plugin-public.icontextprovider.md
+++ b/docs/development/core/public/kibana-plugin-public.icontextprovider.md
@@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type
Signature:
```typescript
-export declare type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName];
+export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName];
```
## Remarks
diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md
index e2ef807a75018c..7531cf9a063336 100644
--- a/docs/development/core/public/kibana-plugin-public.md
+++ b/docs/development/core/public/kibana-plugin-public.md
@@ -91,11 +91,13 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. |
| [ChromeHelpExtension](./kibana-plugin-public.chromehelpextension.md) | |
| [ChromeNavLinkUpdateableFields](./kibana-plugin-public.chromenavlinkupdateablefields.md) | |
+| [HandlerContextType](./kibana-plugin-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md) to represent the type of the context. |
+| [HandlerFunction](./kibana-plugin-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-public.icontextcontainer.md) |
+| [HandlerParameters](./kibana-plugin-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-public.handlercontexttype.md). |
| [HttpBody](./kibana-plugin-public.httpbody.md) | |
| [HttpHandler](./kibana-plugin-public.httphandler.md) | |
| [HttpSetup](./kibana-plugin-public.httpsetup.md) | |
| [HttpStart](./kibana-plugin-public.httpstart.md) | |
-| [IContextHandler](./kibana-plugin-public.icontexthandler.md) | A function registered by a plugin to perform some action. |
| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
| [OverlayBannerMount](./kibana-plugin-public.overlaybannermount.md) | A function that will mount the banner inside the provided element. |
| [OverlayBannerUnmount](./kibana-plugin-public.overlaybannerunmount.md) | A function that will unmount the banner from the element. |
diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md
index 80ddb1aea18d15..a4fa3f17d0d94f 100644
--- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md
+++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.find.md
@@ -9,5 +9,5 @@ Search for objects
Signature:
```typescript
-find: (options: Pick) => Promise>;
+find: (options: Pick) => Promise>;
```
diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md
index 2ad9591426ab26..00a71d25cea38a 100644
--- a/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md
+++ b/docs/development/core/public/kibana-plugin-public.savedobjectsclient.md
@@ -20,7 +20,7 @@ export declare class SavedObjectsClient
| [bulkGet](./kibana-plugin-public.savedobjectsclient.bulkget.md) | | (objects?: {
id: string;
type: string;
}[]) => Promise<SavedObjectsBatchResponse<SavedObjectAttributes>>
| Returns an array of objects by id |
| [create](./kibana-plugin-public.savedobjectsclient.create.md) | | <T extends SavedObjectAttributes>(type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise<SimpleSavedObject<T>>
| Persists an object |
| [delete](./kibana-plugin-public.savedobjectsclient.delete.md) | | (type: string, id: string) => Promise<{}>
| Deletes an object |
-| [find](./kibana-plugin-public.savedobjectsclient.find.md) | | <T extends SavedObjectAttributes>(options: Pick<SavedObjectFindOptionsServer, "search" | "type" | "defaultSearchOperator" | "searchFields" | "sortField" | "hasReference" | "page" | "perPage" | "fields">) => Promise<SavedObjectsFindResponsePublic<T>>
| Search for objects |
+| [find](./kibana-plugin-public.savedobjectsclient.find.md) | | <T extends SavedObjectAttributes>(options: Pick<SavedObjectFindOptionsServer, "search" | "filter" | "type" | "page" | "perPage" | "sortField" | "fields" | "searchFields" | "hasReference" | "defaultSearchOperator">) => Promise<SavedObjectsFindResponsePublic<T>>
| Search for objects |
| [get](./kibana-plugin-public.savedobjectsclient.get.md) | | <T extends SavedObjectAttributes>(type: string, id: string) => Promise<SimpleSavedObject<T>>
| Fetches a single object |
## Methods
diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md
new file mode 100644
index 00000000000000..82237134e0b22c
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.filter.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [SavedObjectsFindOptions](./kibana-plugin-public.savedobjectsfindoptions.md) > [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md)
+
+## SavedObjectsFindOptions.filter property
+
+Signature:
+
+```typescript
+filter?: string;
+```
diff --git a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md
index f90c60ebdd0dc1..4c916431d4333f 100644
--- a/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md
+++ b/docs/development/core/public/kibana-plugin-public.savedobjectsfindoptions.md
@@ -17,6 +17,7 @@ export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions
| --- | --- | --- |
| [defaultSearchOperator](./kibana-plugin-public.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR'
| |
| [fields](./kibana-plugin-public.savedobjectsfindoptions.fields.md) | string[]
| An array of fields to include in the results |
+| [filter](./kibana-plugin-public.savedobjectsfindoptions.filter.md) | string
| |
| [hasReference](./kibana-plugin-public.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
}
| |
| [page](./kibana-plugin-public.savedobjectsfindoptions.page.md) | number
| |
| [perPage](./kibana-plugin-public.savedobjectsfindoptions.perpage.md) | number
| |
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.get.md b/docs/development/core/server/kibana-plugin-server.basepath.get.md
new file mode 100644
index 00000000000000..04feca7ccc5a87
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.get.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [get](./kibana-plugin-server.basepath.get.md)
+
+## BasePath.get property
+
+returns `basePath` value, specific for an incoming request.
+
+Signature:
+
+```typescript
+get: (request: LegacyRequest | KibanaRequest) => string;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.md b/docs/development/core/server/kibana-plugin-server.basepath.md
new file mode 100644
index 00000000000000..bfa1ea02aec178
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.md
@@ -0,0 +1,28 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md)
+
+## BasePath class
+
+Access or manipulate the Kibana base path
+
+Signature:
+
+```typescript
+export declare class BasePath
+```
+
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [get](./kibana-plugin-server.basepath.get.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown>) => string
| returns basePath
value, specific for an incoming request. |
+| [prepend](./kibana-plugin-server.basepath.prepend.md) | | (path: string) => string
| returns a new basePath
value, prefixed with passed url
. |
+| [remove](./kibana-plugin-server.basepath.remove.md) | | (path: string) => string
| returns a new basePath
value, cleaned up from passed url
. |
+| [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md) | | string
| returns the server's basePathSee [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request |
+| [set](./kibana-plugin-server.basepath.set.md) | | (request: LegacyRequest | KibanaRequest<unknown, unknown, unknown>, requestSpecificBasePath: string) => void
| sets basePath
value, specific for an incoming request. |
+
+## Remarks
+
+The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `BasePath` class.
+
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.prepend.md b/docs/development/core/server/kibana-plugin-server.basepath.prepend.md
new file mode 100644
index 00000000000000..113e8d9bf48803
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.prepend.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [prepend](./kibana-plugin-server.basepath.prepend.md)
+
+## BasePath.prepend property
+
+returns a new `basePath` value, prefixed with passed `url`.
+
+Signature:
+
+```typescript
+prepend: (path: string) => string;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.remove.md b/docs/development/core/server/kibana-plugin-server.basepath.remove.md
new file mode 100644
index 00000000000000..c5f1092d2969d9
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.remove.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [remove](./kibana-plugin-server.basepath.remove.md)
+
+## BasePath.remove property
+
+returns a new `basePath` value, cleaned up from passed `url`.
+
+Signature:
+
+```typescript
+remove: (path: string) => string;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md b/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md
new file mode 100644
index 00000000000000..d7e45a92dba6d7
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.serverbasepath.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [serverBasePath](./kibana-plugin-server.basepath.serverbasepath.md)
+
+## BasePath.serverBasePath property
+
+returns the server's basePath
+
+See [BasePath.get](./kibana-plugin-server.basepath.get.md) for getting the basePath value for a specific request
+
+Signature:
+
+```typescript
+readonly serverBasePath: string;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.basepath.set.md b/docs/development/core/server/kibana-plugin-server.basepath.set.md
new file mode 100644
index 00000000000000..cec70ee853bfa4
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.basepath.set.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [BasePath](./kibana-plugin-server.basepath.md) > [set](./kibana-plugin-server.basepath.set.md)
+
+## BasePath.set property
+
+sets `basePath` value, specific for an incoming request.
+
+Signature:
+
+```typescript
+set: (request: LegacyRequest | KibanaRequest, requestSpecificBasePath: string) => void;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md
index f44e6a3d7640b7..7096bfc43a520b 100644
--- a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md
+++ b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md
@@ -9,9 +9,9 @@ Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) f
Signature:
```typescript
-createContextContainer(): IContextContainer;
+createContextContainer>(): IContextContainer;
```
Returns:
-`IContextContainer`
+`IContextContainer`
diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.http.md b/docs/development/core/server/kibana-plugin-server.coresetup.http.md
index 254f2728abef16..8474f4ef940dc6 100644
--- a/docs/development/core/server/kibana-plugin-server.coresetup.http.md
+++ b/docs/development/core/server/kibana-plugin-server.coresetup.http.md
@@ -14,7 +14,7 @@ http: {
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
- registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer;
+ registerRouteHandlerContext: (name: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer;
createRouter: () => IRouter;
};
```
diff --git a/docs/development/core/server/kibana-plugin-server.coresetup.md b/docs/development/core/server/kibana-plugin-server.coresetup.md
index ed487a570f2863..528557e91bd17f 100644
--- a/docs/development/core/server/kibana-plugin-server.coresetup.md
+++ b/docs/development/core/server/kibana-plugin-server.coresetup.md
@@ -18,5 +18,5 @@ export interface CoreSetup
| --- | --- | --- |
| [context](./kibana-plugin-server.coresetup.context.md) | {
createContextContainer: ContextSetup['createContextContainer'];
}
| |
| [elasticsearch](./kibana-plugin-server.coresetup.elasticsearch.md) | {
adminClient$: Observable<ClusterClient>;
dataClient$: Observable<ClusterClient>;
createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ClusterClient;
}
| |
-| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(name: T, provider: RequestHandlerContextProvider<RequestHandlerContext>) => RequestHandlerContextContainer<RequestHandlerContext>;
createRouter: () => IRouter;
}
| |
+| [http](./kibana-plugin-server.coresetup.http.md) | {
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
registerOnPreAuth: HttpServiceSetup['registerOnPreAuth'];
registerAuth: HttpServiceSetup['registerAuth'];
registerOnPostAuth: HttpServiceSetup['registerOnPostAuth'];
basePath: HttpServiceSetup['basePath'];
isTlsEnabled: HttpServiceSetup['isTlsEnabled'];
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(name: T, provider: RequestHandlerContextProvider<T>) => RequestHandlerContextContainer;
createRouter: () => IRouter;
}
| |
diff --git a/docs/development/core/server/kibana-plugin-server.handlercontexttype.md b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md
new file mode 100644
index 00000000000000..e8f1f346e8b8e7
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.handlercontexttype.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerContextType](./kibana-plugin-server.handlercontexttype.md)
+
+## HandlerContextType type
+
+Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context.
+
+Signature:
+
+```typescript
+export declare type HandlerContextType> = T extends HandlerFunction ? U : never;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.handlerfunction.md b/docs/development/core/server/kibana-plugin-server.handlerfunction.md
new file mode 100644
index 00000000000000..97acd37946fc94
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.handlerfunction.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerFunction](./kibana-plugin-server.handlerfunction.md)
+
+## HandlerFunction type
+
+A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md)
+
+Signature:
+
+```typescript
+export declare type HandlerFunction = (context: T, ...args: any[]) => any;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.handlerparameters.md b/docs/development/core/server/kibana-plugin-server.handlerparameters.md
new file mode 100644
index 00000000000000..3dd7998a71a1f2
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.handlerparameters.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [HandlerParameters](./kibana-plugin-server.handlerparameters.md)
+
+## HandlerParameters type
+
+Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md).
+
+Signature:
+
+```typescript
+export declare type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.httpserversetup.basepath.md b/docs/development/core/server/kibana-plugin-server.httpserversetup.basepath.md
index 5cfb2f5c4e8b43..173262de10494f 100644
--- a/docs/development/core/server/kibana-plugin-server.httpserversetup.basepath.md
+++ b/docs/development/core/server/kibana-plugin-server.httpserversetup.basepath.md
@@ -4,13 +4,10 @@
## HttpServerSetup.basePath property
+[BasePath](./kibana-plugin-server.basepath.md)
+
Signature:
```typescript
-basePath: {
- get: (request: KibanaRequest | LegacyRequest) => string;
- set: (request: KibanaRequest | LegacyRequest, basePath: string) => void;
- prepend: (url: string) => string;
- remove: (url: string) => string;
- };
+basePath: IBasePath;
```
diff --git a/docs/development/core/server/kibana-plugin-server.httpserversetup.md b/docs/development/core/server/kibana-plugin-server.httpserversetup.md
index f495de850aff5e..7a126383116e7b 100644
--- a/docs/development/core/server/kibana-plugin-server.httpserversetup.md
+++ b/docs/development/core/server/kibana-plugin-server.httpserversetup.md
@@ -17,7 +17,7 @@ export interface HttpServerSetup
| Property | Type | Description |
| --- | --- | --- |
| [auth](./kibana-plugin-server.httpserversetup.auth.md) | {
get: GetAuthState;
isAuthenticated: IsAuthenticated;
getAuthHeaders: GetAuthHeaders;
}
| |
-| [basePath](./kibana-plugin-server.httpserversetup.basepath.md) | {
get: (request: KibanaRequest | LegacyRequest) => string;
set: (request: KibanaRequest | LegacyRequest, basePath: string) => void;
prepend: (url: string) => string;
remove: (url: string) => string;
}
| |
+| [basePath](./kibana-plugin-server.httpserversetup.basepath.md) | IBasePath
| [BasePath](./kibana-plugin-server.basepath.md) |
| [createCookieSessionStorageFactory](./kibana-plugin-server.httpserversetup.createcookiesessionstoragefactory.md) | <T>(cookieOptions: SessionStorageCookieOptions<T>) => Promise<SessionStorageFactory<T>>
| Creates cookie based session storage factory [SessionStorageFactory](./kibana-plugin-server.sessionstoragefactory.md) |
| [isTlsEnabled](./kibana-plugin-server.httpserversetup.istlsenabled.md) | boolean
| Flag showing whether a server was configured to use TLS connection. |
| [registerAuth](./kibana-plugin-server.httpserversetup.registerauth.md) | (handler: AuthenticationHandler) => void
| To define custom authentication and/or authorization mechanism for incoming requests. A handler should return a state to associate with the incoming request. The state can be retrieved later via http.auth.get(..) Only one AuthenticationHandler can be registered. |
diff --git a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md
index 92bf158ad33129..eec63cf5c80931 100644
--- a/docs/development/core/server/kibana-plugin-server.httpservicesetup.md
+++ b/docs/development/core/server/kibana-plugin-server.httpservicesetup.md
@@ -10,6 +10,6 @@
```typescript
export declare type HttpServiceSetup = Omit & {
createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter;
- registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer;
+ registerRouteHandlerContext: (pluginOpaqueId: PluginOpaqueId, contextName: T, provider: RequestHandlerContextProvider) => RequestHandlerContextContainer;
};
```
diff --git a/docs/development/core/server/kibana-plugin-server.ibasepath.md b/docs/development/core/server/kibana-plugin-server.ibasepath.md
new file mode 100644
index 00000000000000..2baa8d623ce97b
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.ibasepath.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IBasePath](./kibana-plugin-server.ibasepath.md)
+
+## IBasePath type
+
+Access or manipulate the Kibana base path
+
+[BasePath](./kibana-plugin-server.basepath.md)
+
+Signature:
+
+```typescript
+export declare type IBasePath = Pick;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md
index c5549ab017e530..09a9e28d6d0fe8 100644
--- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md
+++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md
@@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin.
Signature:
```typescript
-createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise;
+createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>;
```
## Parameters
@@ -17,11 +17,11 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandlerPluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. |
-| handler | IContextHandler<TContext, THandlerReturn, THandlerParameters>
| Handler function to pass context object to. |
+| handler | THandler
| Handler function to pass context object to. |
Returns:
-`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise`
+`(...rest: HandlerParameters) => ShallowPromise>`
A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value.
diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md
index 1ab699be105b4b..114da31442ff9b 100644
--- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md
+++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md
@@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler
Signature:
```typescript
-export interface IContextContainer
+export interface IContextContainer>
```
## Methods
diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md
index 1a63f63dc91b46..30d3fc154d1e93 100644
--- a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md
+++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md
@@ -9,7 +9,7 @@ Register a new context provider.
Signature:
```typescript
-registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
+registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
```
## Parameters
@@ -18,7 +18,7 @@ registerContext(pluginOpaqueId: PluginOpaqu
| --- | --- | --- |
| pluginOpaqueId | PluginOpaqueId
| The plugin opaque ID for the plugin that registers this context. |
| contextName | TContextName
| The key of the TContext
object this provider supplies the value for. |
-| provider | IContextProvider<TContext, TContextName, THandlerParameters>
| A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. |
+| provider | IContextProvider<THandler, TContextName>
| A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. |
Returns:
diff --git a/docs/development/core/server/kibana-plugin-server.icontexthandler.md b/docs/development/core/server/kibana-plugin-server.icontexthandler.md
deleted file mode 100644
index c1f5acc22734aa..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.icontexthandler.md
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextHandler](./kibana-plugin-server.icontexthandler.md)
-
-## IContextHandler type
-
-A function registered by a plugin to perform some action.
-
-Signature:
-
-```typescript
-export declare type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn;
-```
-
-## Remarks
-
-A new `TContext` will be built for each handler before invoking.
-
diff --git a/docs/development/core/server/kibana-plugin-server.icontextprovider.md b/docs/development/core/server/kibana-plugin-server.icontextprovider.md
index 250e6a2be3f6ae..39ace8b9bc57ee 100644
--- a/docs/development/core/server/kibana-plugin-server.icontextprovider.md
+++ b/docs/development/core/server/kibana-plugin-server.icontextprovider.md
@@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type
Signature:
```typescript
-export declare type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName];
+export declare type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName];
```
## Remarks
diff --git a/docs/development/core/server/kibana-plugin-server.internalcorestart.md b/docs/development/core/server/kibana-plugin-server.internalcorestart.md
deleted file mode 100644
index 4943249d284b04..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.internalcorestart.md
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [InternalCoreStart](./kibana-plugin-server.internalcorestart.md)
-
-## InternalCoreStart interface
-
-
-Signature:
-
-```typescript
-export interface InternalCoreStart
-```
diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md
index baecb180096de9..3c01e7aeef325b 100644
--- a/docs/development/core/server/kibana-plugin-server.md
+++ b/docs/development/core/server/kibana-plugin-server.md
@@ -16,12 +16,11 @@ The plugin integrates with the core system via lifecycle events: `setup`
| Class | Description |
| --- | --- |
+| [BasePath](./kibana-plugin-server.basepath.md) | Access or manipulate the Kibana base path |
| [ClusterClient](./kibana-plugin-server.clusterclient.md) | Represents an Elasticsearch cluster API client and allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)
). |
| [ElasticsearchErrorHelpers](./kibana-plugin-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-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. |
| [SavedObjectsErrorHelpers](./kibana-plugin-server.savedobjectserrorhelpers.md) | |
-| [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) | |
-| [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) | |
| [ScopedClusterClient](./kibana-plugin-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 |
## Enumerations
@@ -51,7 +50,6 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) | |
| [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. |
| [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) | A tiny abstraction for TCP socket. |
-| [InternalCoreStart](./kibana-plugin-server.internalcorestart.md) | |
| [IRouter](./kibana-plugin-server.irouter.md) | Registers route handlers for specified resource path and method. |
| [KibanaRequestRoute](./kibana-plugin-server.kibanarequestroute.md) | Request specific route information exposed to a handler. |
| [LegacyRequest](./kibana-plugin-server.legacyrequest.md) | |
@@ -95,7 +93,6 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [SavedObjectsMigrationVersion](./kibana-plugin-server.savedobjectsmigrationversion.md) | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. |
| [SavedObjectsRawDoc](./kibana-plugin-server.savedobjectsrawdoc.md) | A raw document as represented directly in the saved object index. |
| [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. |
-| [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) | |
| [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) | |
| [SavedObjectsUpdateResponse](./kibana-plugin-server.savedobjectsupdateresponse.md) | |
| [SessionStorage](./kibana-plugin-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. |
@@ -119,10 +116,13 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [ElasticsearchClientConfig](./kibana-plugin-server.elasticsearchclientconfig.md) | |
| [GetAuthHeaders](./kibana-plugin-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. |
| [GetAuthState](./kibana-plugin-server.getauthstate.md) | Get authentication state for a request. Returned by auth
interceptor. |
+| [HandlerContextType](./kibana-plugin-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md) to represent the type of the context. |
+| [HandlerFunction](./kibana-plugin-server.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-server.icontextcontainer.md) |
+| [HandlerParameters](./kibana-plugin-server.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-server.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-server.handlercontexttype.md). |
| [Headers](./kibana-plugin-server.headers.md) | Http request headers to read. |
| [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) | Data send to the client as a response payload. |
| [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | |
-| [IContextHandler](./kibana-plugin-server.icontexthandler.md) | A function registered by a plugin to perform some action. |
+| [IBasePath](./kibana-plugin-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-server.basepath.md) |
| [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
| [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. |
| [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. |
@@ -138,8 +138,6 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [RequestHandler](./kibana-plugin-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-server.kibanaresponsefactory.md) functions. |
| [RequestHandlerContextContainer](./kibana-plugin-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. |
| [RequestHandlerContextProvider](./kibana-plugin-server.requesthandlercontextprovider.md) | Context provider for request handler. Extends request context object with provided functionality or data. |
-| [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md) | Parameters passed to the request handler function. |
-| [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md) | Expected outcome the request handler function. |
| [ResponseError](./kibana-plugin-server.responseerror.md) | Error message and optional data send to the client in case of error. |
| [ResponseErrorAttributes](./kibana-plugin-server.responseerrorattributes.md) | Additional data to provide error details. |
| [ResponseHeaders](./kibana-plugin-server.responseheaders.md) | Http response headers to set. |
diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md
index afdb4885970696..b76a9ce7d235ca 100644
--- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md
+++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextcontainer.md
@@ -9,5 +9,5 @@ An object that handles registration of http request context providers.
Signature:
```typescript
-export declare type RequestHandlerContextContainer = IContextContainer, RequestHandlerParams>;
+export declare type RequestHandlerContextContainer = IContextContainer>;
```
diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md
index 0d9cc6b70b80c0..ea7294b721aabd 100644
--- a/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md
+++ b/docs/development/core/server/kibana-plugin-server.requesthandlercontextprovider.md
@@ -9,5 +9,5 @@ Context provider for request handler. Extends request context object with provid
Signature:
```typescript
-export declare type RequestHandlerContextProvider = IContextProvider;
+export declare type RequestHandlerContextProvider = IContextProvider, TContextName>;
```
diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md b/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md
deleted file mode 100644
index 7f466845b4d460..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.requesthandlerparams.md
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerParams](./kibana-plugin-server.requesthandlerparams.md)
-
-## RequestHandlerParams type
-
-Parameters passed to the request handler function.
-
-Signature:
-
-```typescript
-export declare type RequestHandlerParams = [KibanaRequest, KibanaResponseFactory];
-```
diff --git a/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md b/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md
deleted file mode 100644
index 6c01e21b6ecbe9..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.requesthandlerreturn.md
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [RequestHandlerReturn](./kibana-plugin-server.requesthandlerreturn.md)
-
-## RequestHandlerReturn type
-
-Expected outcome the request handler function.
-
-Signature:
-
-```typescript
-export declare type RequestHandlerReturn = KibanaResponse;
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md
new file mode 100644
index 00000000000000..308bebbeaf60b8
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.filter.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) > [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md)
+
+## SavedObjectsFindOptions.filter property
+
+Signature:
+
+```typescript
+filter?: string;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md
index ad81c439d902c0..dfd51d480db926 100644
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md
+++ b/docs/development/core/server/kibana-plugin-server.savedobjectsfindoptions.md
@@ -17,6 +17,7 @@ export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions
| --- | --- | --- |
| [defaultSearchOperator](./kibana-plugin-server.savedobjectsfindoptions.defaultsearchoperator.md) | 'AND' | 'OR'
| |
| [fields](./kibana-plugin-server.savedobjectsfindoptions.fields.md) | string[]
| An array of fields to include in the results |
+| [filter](./kibana-plugin-server.savedobjectsfindoptions.filter.md) | string
| |
| [hasReference](./kibana-plugin-server.savedobjectsfindoptions.hasreference.md) | {
type: string;
id: string;
}
| |
| [page](./kibana-plugin-server.savedobjectsfindoptions.page.md) | number
| |
| [perPage](./kibana-plugin-server.savedobjectsfindoptions.perpage.md) | number
| |
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema._constructor_.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema._constructor_.md
deleted file mode 100644
index f4fb88fa6d4f11..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema._constructor_.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) > [(constructor)](./kibana-plugin-server.savedobjectsschema._constructor_.md)
-
-## SavedObjectsSchema.(constructor)
-
-Constructs a new instance of the `SavedObjectsSchema` class
-
-Signature:
-
-```typescript
-constructor(schemaDefinition?: SavedObjectsSchemaDefinition);
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| schemaDefinition | SavedObjectsSchemaDefinition
| |
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getconverttoaliasscript.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getconverttoaliasscript.md
deleted file mode 100644
index 5baf075463558a..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getconverttoaliasscript.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) > [getConvertToAliasScript](./kibana-plugin-server.savedobjectsschema.getconverttoaliasscript.md)
-
-## SavedObjectsSchema.getConvertToAliasScript() method
-
-Signature:
-
-```typescript
-getConvertToAliasScript(type: string): string | undefined;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| type | string
| |
-
-Returns:
-
-`string | undefined`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getindexfortype.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getindexfortype.md
deleted file mode 100644
index ba1c439c8c6b4e..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.getindexfortype.md
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) > [getIndexForType](./kibana-plugin-server.savedobjectsschema.getindexfortype.md)
-
-## SavedObjectsSchema.getIndexForType() method
-
-Signature:
-
-```typescript
-getIndexForType(config: Config, type: string): string | undefined;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| config | Config
| |
-| type | string
| |
-
-Returns:
-
-`string | undefined`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.ishiddentype.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema.ishiddentype.md
deleted file mode 100644
index f67b12a4d14c3d..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.ishiddentype.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) > [isHiddenType](./kibana-plugin-server.savedobjectsschema.ishiddentype.md)
-
-## SavedObjectsSchema.isHiddenType() method
-
-Signature:
-
-```typescript
-isHiddenType(type: string): boolean;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| type | string
| |
-
-Returns:
-
-`boolean`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.isnamespaceagnostic.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema.isnamespaceagnostic.md
deleted file mode 100644
index 2ca0abd7e4aa7e..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.isnamespaceagnostic.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md) > [isNamespaceAgnostic](./kibana-plugin-server.savedobjectsschema.isnamespaceagnostic.md)
-
-## SavedObjectsSchema.isNamespaceAgnostic() method
-
-Signature:
-
-```typescript
-isNamespaceAgnostic(type: string): boolean;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| type | string
| |
-
-Returns:
-
-`boolean`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.md b/docs/development/core/server/kibana-plugin-server.savedobjectsschema.md
deleted file mode 100644
index 0808811804eaf5..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsschema.md
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSchema](./kibana-plugin-server.savedobjectsschema.md)
-
-## SavedObjectsSchema class
-
-Signature:
-
-```typescript
-export declare class SavedObjectsSchema
-```
-
-## Constructors
-
-| Constructor | Modifiers | Description |
-| --- | --- | --- |
-| [(constructor)(schemaDefinition)](./kibana-plugin-server.savedobjectsschema._constructor_.md) | | Constructs a new instance of the SavedObjectsSchema
class |
-
-## Methods
-
-| Method | Modifiers | Description |
-| --- | --- | --- |
-| [getConvertToAliasScript(type)](./kibana-plugin-server.savedobjectsschema.getconverttoaliasscript.md) | | |
-| [getIndexForType(config, type)](./kibana-plugin-server.savedobjectsschema.getindexfortype.md) | | |
-| [isHiddenType(type)](./kibana-plugin-server.savedobjectsschema.ishiddentype.md) | | |
-| [isNamespaceAgnostic(type)](./kibana-plugin-server.savedobjectsschema.isnamespaceagnostic.md) | | |
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer._constructor_.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer._constructor_.md
deleted file mode 100644
index c05e97d3dbcdf8..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer._constructor_.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) > [(constructor)](./kibana-plugin-server.savedobjectsserializer._constructor_.md)
-
-## SavedObjectsSerializer.(constructor)
-
-Constructs a new instance of the `SavedObjectsSerializer` class
-
-Signature:
-
-```typescript
-constructor(schema: SavedObjectsSchema);
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| schema | SavedObjectsSchema
| |
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.generaterawid.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.generaterawid.md
deleted file mode 100644
index 4705f48a201aee..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.generaterawid.md
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) > [generateRawId](./kibana-plugin-server.savedobjectsserializer.generaterawid.md)
-
-## SavedObjectsSerializer.generateRawId() method
-
-Given a saved object type and id, generates the compound id that is stored in the raw document.
-
-Signature:
-
-```typescript
-generateRawId(namespace: string | undefined, type: string, id?: string): string;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| namespace | string | undefined
| |
-| type | string
| |
-| id | string
| |
-
-Returns:
-
-`string`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.israwsavedobject.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.israwsavedobject.md
deleted file mode 100644
index e190e7bce8c011..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.israwsavedobject.md
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) > [isRawSavedObject](./kibana-plugin-server.savedobjectsserializer.israwsavedobject.md)
-
-## SavedObjectsSerializer.isRawSavedObject() method
-
-Determines whether or not the raw document can be converted to a saved object.
-
-Signature:
-
-```typescript
-isRawSavedObject(rawDoc: RawDoc): any;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| rawDoc | RawDoc
| |
-
-Returns:
-
-`any`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.md
deleted file mode 100644
index dd3f52554a81ea..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.md
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md)
-
-## SavedObjectsSerializer class
-
-Signature:
-
-```typescript
-export declare class SavedObjectsSerializer
-```
-
-## Constructors
-
-| Constructor | Modifiers | Description |
-| --- | --- | --- |
-| [(constructor)(schema)](./kibana-plugin-server.savedobjectsserializer._constructor_.md) | | Constructs a new instance of the SavedObjectsSerializer
class |
-
-## Methods
-
-| Method | Modifiers | Description |
-| --- | --- | --- |
-| [generateRawId(namespace, type, id)](./kibana-plugin-server.savedobjectsserializer.generaterawid.md) | | Given a saved object type and id, generates the compound id that is stored in the raw document. |
-| [isRawSavedObject(rawDoc)](./kibana-plugin-server.savedobjectsserializer.israwsavedobject.md) | | Determines whether or not the raw document can be converted to a saved object. |
-| [rawToSavedObject(doc)](./kibana-plugin-server.savedobjectsserializer.rawtosavedobject.md) | | Converts a document from the format that is stored in elasticsearch to the saved object client format. |
-| [savedObjectToRaw(savedObj)](./kibana-plugin-server.savedobjectsserializer.savedobjecttoraw.md) | | Converts a document from the saved object client format to the format that is stored in elasticsearch. |
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.rawtosavedobject.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.rawtosavedobject.md
deleted file mode 100644
index b36cdb3be64da9..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.rawtosavedobject.md
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) > [rawToSavedObject](./kibana-plugin-server.savedobjectsserializer.rawtosavedobject.md)
-
-## SavedObjectsSerializer.rawToSavedObject() method
-
-Converts a document from the format that is stored in elasticsearch to the saved object client format.
-
-Signature:
-
-```typescript
-rawToSavedObject(doc: RawDoc): SanitizedSavedObjectDoc;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| doc | RawDoc
| |
-
-Returns:
-
-`SanitizedSavedObjectDoc`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.savedobjecttoraw.md b/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.savedobjecttoraw.md
deleted file mode 100644
index 4854a97a845b89..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsserializer.savedobjecttoraw.md
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsSerializer](./kibana-plugin-server.savedobjectsserializer.md) > [savedObjectToRaw](./kibana-plugin-server.savedobjectsserializer.savedobjecttoraw.md)
-
-## SavedObjectsSerializer.savedObjectToRaw() method
-
-Converts a document from the saved object client format to the format that is stored in elasticsearch.
-
-Signature:
-
-```typescript
-savedObjectToRaw(savedObj: SanitizedSavedObjectDoc): RawDoc;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| savedObj | SanitizedSavedObjectDoc
| |
-
-Returns:
-
-`RawDoc`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.addscopedsavedobjectsclientwrapperfactory.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.addscopedsavedobjectsclientwrapperfactory.md
deleted file mode 100644
index 6e0d1a827750cf..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.addscopedsavedobjectsclientwrapperfactory.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [addScopedSavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsservice.addscopedsavedobjectsclientwrapperfactory.md)
-
-## SavedObjectsService.addScopedSavedObjectsClientWrapperFactory property
-
-Signature:
-
-```typescript
-addScopedSavedObjectsClientWrapperFactory: ScopedSavedObjectsClientProvider['addClientWrapperFactory'];
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getsavedobjectsrepository.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getsavedobjectsrepository.md
deleted file mode 100644
index 13ccad7ed01ae5..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getsavedobjectsrepository.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [getSavedObjectsRepository](./kibana-plugin-server.savedobjectsservice.getsavedobjectsrepository.md)
-
-## SavedObjectsService.getSavedObjectsRepository() method
-
-Signature:
-
-```typescript
-getSavedObjectsRepository(...rest: any[]): any;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| rest | any[]
| |
-
-Returns:
-
-`any`
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getscopedsavedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getscopedsavedobjectsclient.md
deleted file mode 100644
index c762de041edf5f..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.getscopedsavedobjectsclient.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [getScopedSavedObjectsClient](./kibana-plugin-server.savedobjectsservice.getscopedsavedobjectsclient.md)
-
-## SavedObjectsService.getScopedSavedObjectsClient property
-
-Signature:
-
-```typescript
-getScopedSavedObjectsClient: ScopedSavedObjectsClientProvider['getClient'];
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.importexport.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.importexport.md
deleted file mode 100644
index f9b4e46712f4a1..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.importexport.md
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [importExport](./kibana-plugin-server.savedobjectsservice.importexport.md)
-
-## SavedObjectsService.importExport property
-
-Signature:
-
-```typescript
-importExport: {
- objectLimit: number;
- importSavedObjects(options: SavedObjectsImportOptions): Promise;
- resolveImportErrors(options: SavedObjectsResolveImportErrorsOptions): Promise;
- getSortedObjectsForExport(options: SavedObjectsExportOptions): Promise;
- };
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.md
deleted file mode 100644
index d9e23e6f15928e..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.md
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md)
-
-## SavedObjectsService interface
-
-
-Signature:
-
-```typescript
-export interface SavedObjectsService
-```
-
-## Properties
-
-| Property | Type | Description |
-| --- | --- | --- |
-| [addScopedSavedObjectsClientWrapperFactory](./kibana-plugin-server.savedobjectsservice.addscopedsavedobjectsclientwrapperfactory.md) | ScopedSavedObjectsClientProvider<Request>['addClientWrapperFactory']
| |
-| [getScopedSavedObjectsClient](./kibana-plugin-server.savedobjectsservice.getscopedsavedobjectsclient.md) | ScopedSavedObjectsClientProvider<Request>['getClient']
| |
-| [importExport](./kibana-plugin-server.savedobjectsservice.importexport.md) | {
objectLimit: number;
importSavedObjects(options: SavedObjectsImportOptions): Promise<SavedObjectsImportResponse>;
resolveImportErrors(options: SavedObjectsResolveImportErrorsOptions): Promise<SavedObjectsImportResponse>;
getSortedObjectsForExport(options: SavedObjectsExportOptions): Promise<Readable>;
}
| |
-| [SavedObjectsClient](./kibana-plugin-server.savedobjectsservice.savedobjectsclient.md) | typeof SavedObjectsClient
| |
-| [schema](./kibana-plugin-server.savedobjectsservice.schema.md) | SavedObjectsSchema
| |
-| [types](./kibana-plugin-server.savedobjectsservice.types.md) | string[]
| |
-
-## Methods
-
-| Method | Description |
-| --- | --- |
-| [getSavedObjectsRepository(rest)](./kibana-plugin-server.savedobjectsservice.getsavedobjectsrepository.md) | |
-
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.savedobjectsclient.md
deleted file mode 100644
index 4a7722928e85e0..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.savedobjectsclient.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [SavedObjectsClient](./kibana-plugin-server.savedobjectsservice.savedobjectsclient.md)
-
-## SavedObjectsService.SavedObjectsClient property
-
-Signature:
-
-```typescript
-SavedObjectsClient: typeof SavedObjectsClient;
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.schema.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.schema.md
deleted file mode 100644
index be5682e6f034e4..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.schema.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [schema](./kibana-plugin-server.savedobjectsservice.schema.md)
-
-## SavedObjectsService.schema property
-
-Signature:
-
-```typescript
-schema: SavedObjectsSchema;
-```
diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.types.md b/docs/development/core/server/kibana-plugin-server.savedobjectsservice.types.md
deleted file mode 100644
index a783ef4270f186..00000000000000
--- a/docs/development/core/server/kibana-plugin-server.savedobjectsservice.types.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsService](./kibana-plugin-server.savedobjectsservice.md) > [types](./kibana-plugin-server.savedobjectsservice.types.md)
-
-## SavedObjectsService.types property
-
-Signature:
-
-```typescript
-types: string[];
-```
diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc
index 25c07dc5024840..8d9ef515108eda 100644
--- a/docs/management/index-patterns.asciidoc
+++ b/docs/management/index-patterns.asciidoc
@@ -35,8 +35,11 @@ image:management/index-patterns/images/rollup-index-pattern.png["Menu with rollu
{kib} makes it easy for you to create an index pattern by walking you through
the process. Just start typing in the *Index pattern* field, and {kib} looks for
-the names of {es} indices that match your input. If you want to include
-system indices in your search, toggle the switch in the upper right.
+the names of {es} indices that match your input. Make sure that the name of the
+index pattern is unique.
+
+If you want to include system indices in your search, toggle the switch in the
+upper right.
[role="screenshot"]
image:management/index-patterns/images/create-index-pattern.png["Create index pattern"]
diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc
index 7330c7e144b60e..97fb891c95bdba 100644
--- a/docs/settings/monitoring-settings.asciidoc
+++ b/docs/settings/monitoring-settings.asciidoc
@@ -21,7 +21,7 @@ To control how data is collected from your {es} nodes, you configure
{ref}/monitoring-settings.html[`xpack.monitoring.collection`
settings] in `elasticsearch.yml`. To control how monitoring data is collected
from Logstash, you configure
-{logstash-ref}/configuring-logstash.html#monitoring-settings[`xpack.monitoring` settings]
+{logstash-ref}/monitoring-internal-collection.html#monitoring-settings[`xpack.monitoring` settings]
in `logstash.yml`.
For more information, see
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index 7f9034c48e232f..5b3db22a39ea64 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -256,10 +256,6 @@ deprecation warning at startup. This setting cannot end in a slash (`/`).
`server.customResponseHeaders:`:: *Default: `{}`* Header names and values to
send on all responses to the client from the Kibana server.
-[[server-default]]`server.defaultRoute:`:: *Default: "/app/kibana"* This setting
-specifies the default route when opening Kibana. You can use this setting to
-modify the landing page when opening Kibana. Supported on {ece}.
-
`server.host:`:: *Default: "localhost"* This setting specifies the host of the
back end server.
diff --git a/kibana.d.ts b/kibana.d.ts
index e0b20f6fa28af6..d242965e9bdd5a 100644
--- a/kibana.d.ts
+++ b/kibana.d.ts
@@ -42,7 +42,7 @@ export namespace Legacy {
export type Request = LegacyKibanaServer.Request;
export type ResponseToolkit = LegacyKibanaServer.ResponseToolkit;
export type SavedObjectsClient = LegacyKibanaServer.SavedObjectsClient;
- export type SavedObjectsService = LegacyKibanaServer.SavedObjectsService;
+ export type SavedObjectsService = LegacyKibanaServer.SavedObjectsLegacyService;
export type Server = LegacyKibanaServer.Server;
export type InitPluginFunction = LegacyKibanaPluginSpec.InitPluginFunction;
diff --git a/package.json b/package.json
index b8aca7cf2c4092..e60819102eb918 100644
--- a/package.json
+++ b/package.json
@@ -105,9 +105,9 @@
"dependencies": {
"@babel/core": "^7.5.5",
"@babel/register": "^7.5.5",
- "@elastic/charts": "^12.0.2",
+ "@elastic/charts": "^12.1.0",
"@elastic/datemath": "5.0.2",
- "@elastic/eui": "14.3.0",
+ "@elastic/eui": "14.4.0",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "8.1.1-kibana2",
"@elastic/numeral": "2.3.3",
@@ -160,7 +160,6 @@
"expiry-js": "0.1.7",
"file-loader": "4.2.0",
"font-awesome": "4.7.0",
- "fp-ts": "^2.0.5",
"getos": "^3.1.0",
"glob": "^7.1.2",
"glob-all": "^3.1.0",
@@ -177,7 +176,6 @@
"https-proxy-agent": "^2.2.2",
"inert": "^5.1.0",
"inline-style": "^2.0.0",
- "io-ts": "^2.0.1",
"joi": "^13.5.2",
"jquery": "^3.4.1",
"js-yaml": "3.13.1",
@@ -242,7 +240,7 @@
"style-loader": "0.23.1",
"symbol-observable": "^1.2.0",
"tar": "4.4.13",
- "terser-webpack-plugin": "^1.4.1",
+ "terser-webpack-plugin": "^2.1.2",
"thread-loader": "^2.1.3",
"tinygradient": "0.4.3",
"tinymath": "1.2.1",
@@ -375,10 +373,11 @@
"eslint-config-prettier": "6.3.0",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-ban": "1.3.0",
+ "eslint-plugin-cypress": "^2.6.1",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-jest": "22.17.0",
"eslint-plugin-jsx-a11y": "6.2.3",
- "eslint-plugin-mocha": "5.3.0",
+ "eslint-plugin-mocha": "6.1.1",
"eslint-plugin-no-unsanitized": "3.0.2",
"eslint-plugin-node": "9.2.0",
"eslint-plugin-prefer-object-spread": "1.2.1",
@@ -421,7 +420,7 @@
"license-checker": "^16.0.0",
"listr": "^0.14.1",
"load-grunt-config": "^3.0.1",
- "mocha": "3.5.3",
+ "mocha": "6.2.1",
"multistream": "^2.1.1",
"murmurhash3js": "3.0.1",
"mutation-observer": "^1.0.3",
diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json
index 8c6359e66a7a5d..da2a37cc41ad3c 100644
--- a/packages/eslint-config-kibana/package.json
+++ b/packages/eslint-config-kibana/package.json
@@ -24,7 +24,7 @@
"eslint-plugin-jsx-a11y": "6.2.3",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-jest": "^22.17.0",
- "eslint-plugin-mocha": "^5.3.0",
+ "eslint-plugin-mocha": "^6.1.1",
"eslint-plugin-no-unsanitized": "3.0.2",
"eslint-plugin-prefer-object-spread": "1.2.1",
"eslint-plugin-react": "7.13.0",
diff --git a/packages/kbn-babel-code-parser/src/can_require.js b/packages/kbn-babel-code-parser/src/can_require.js
index e590c249e9806f..4d85910abe6ed6 100644
--- a/packages/kbn-babel-code-parser/src/can_require.js
+++ b/packages/kbn-babel-code-parser/src/can_require.js
@@ -17,18 +17,18 @@
* under the License.
*/
-export function canRequire(cwd, entry) {
+export function canRequire(entry, cwd = require.resolve.paths(entry) || []) {
try {
// We will try to test if we can resolve
// this entry through the require.resolve
// setting as the start looking path the
- // given cwd. Require.resolve will keep
+ // given cwd. That cwd variable could be
+ // a path or an array of paths
+ // from where Require.resolve will keep
// looking recursively as normal starting
- // from that location.
+ // from those locations.
return require.resolve(entry, {
- paths: [
- cwd
- ]
+ paths: [].concat(cwd)
});
} catch (e) {
return false;
diff --git a/packages/kbn-babel-code-parser/src/code_parser.js b/packages/kbn-babel-code-parser/src/code_parser.js
index 8d76b1032561ac..0f53bd249bb5cc 100644
--- a/packages/kbn-babel-code-parser/src/code_parser.js
+++ b/packages/kbn-babel-code-parser/src/code_parser.js
@@ -79,7 +79,7 @@ export async function parseEntries(cwd, entries, strategy, results, wasParsed =
const sanitizedCwd = cwd || process.cwd();
// Test each entry against canRequire function
- const entriesQueue = entries.map(entry => canRequire(sanitizedCwd, entry));
+ const entriesQueue = entries.map(entry => canRequire(entry));
while(entriesQueue.length) {
// Get the first element in the queue as
diff --git a/packages/kbn-babel-code-parser/src/strategies.js b/packages/kbn-babel-code-parser/src/strategies.js
index 317ded014210b1..89621bc53bd534 100644
--- a/packages/kbn-babel-code-parser/src/strategies.js
+++ b/packages/kbn-babel-code-parser/src/strategies.js
@@ -62,8 +62,12 @@ export async function dependenciesParseStrategy(cwd, parseSingleFile, mainEntry,
// new dependencies
return dependencies.reduce((filteredEntries, entry) => {
const absEntryPath = resolve(cwd, dirname(mainEntry), entry);
- const requiredPath = canRequire(cwd, absEntryPath);
- const requiredRelativePath = canRequire(cwd, entry);
+
+ // NOTE: cwd for following canRequires is absEntryPath
+ // because we should start looking from there
+ const requiredPath = canRequire(absEntryPath, absEntryPath);
+ const requiredRelativePath = canRequire(entry, absEntryPath);
+
const isRelativeFile = !isAbsolute(entry);
const isNodeModuleDep = isRelativeFile && !requiredPath && requiredRelativePath;
const isNewEntry = isRelativeFile && requiredPath;
diff --git a/packages/kbn-babel-code-parser/src/strategies.test.js b/packages/kbn-babel-code-parser/src/strategies.test.js
index 5a84edf560af13..d7caa8b95d4a22 100644
--- a/packages/kbn-babel-code-parser/src/strategies.test.js
+++ b/packages/kbn-babel-code-parser/src/strategies.test.js
@@ -59,8 +59,8 @@ describe('Code Parser Strategies', () => {
cb(null, `require('dep_from_node_modules')`);
});
- canRequire.mockImplementation((mockCwd, entry) => {
- if (entry === `${mockCwd}dep1/dep_from_node_modules`) {
+ canRequire.mockImplementation((entry, cwd) => {
+ if (entry === `${cwd}dep1/dep_from_node_modules`) {
return false;
}
@@ -78,7 +78,7 @@ describe('Code Parser Strategies', () => {
cb(null, `require('./relative_dep')`);
});
- canRequire.mockImplementation((mockCwd, entry) => {
+ canRequire.mockImplementation((entry) => {
if (entry === `${mockCwd}dep1/relative_dep`) {
return `${entry}/index.js`;
}
diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts
index 6d3914eb56218b..5c69036a4b13ae 100644
--- a/packages/kbn-dev-utils/src/index.ts
+++ b/packages/kbn-dev-utils/src/index.ts
@@ -23,3 +23,4 @@ export { createAbsolutePathSerializer } from './serializers';
export { CA_CERT_PATH, ES_KEY_PATH, ES_CERT_PATH } from './certs';
export { run, createFailError, createFlagError, combineErrors, isFailError, Flags } from './run';
export { REPO_ROOT } from './constants';
+export { KbnClient } from './kbn_client';
diff --git a/packages/kbn-dev-utils/src/kbn_client/errors.ts b/packages/kbn-dev-utils/src/kbn_client/errors.ts
new file mode 100644
index 00000000000000..068c68555b62ae
--- /dev/null
+++ b/packages/kbn-dev-utils/src/kbn_client/errors.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 { AxiosError, AxiosResponse } from 'axios';
+
+export interface AxiosRequestError extends AxiosError {
+ response: undefined;
+}
+
+export interface AxiosResponseError extends AxiosError {
+ response: AxiosResponse;
+}
+
+export const isAxiosRequestError = (error: any): error is AxiosRequestError => {
+ return error && error.code === undefined && error.response === undefined;
+};
+
+export const isAxiosResponseError = (error: any): error is AxiosResponseError => {
+ return error && error.code !== undefined && error.response !== undefined;
+};
+
+export const isConcliftOnGetError = (error: any) => {
+ return (
+ isAxiosResponseError(error) && error.config.method === 'GET' && error.response.status === 409
+ );
+};
diff --git a/src/legacy/ui/ui_settings/__tests__/lib/index.js b/packages/kbn-dev-utils/src/kbn_client/index.ts
similarity index 88%
rename from src/legacy/ui/ui_settings/__tests__/lib/index.js
rename to packages/kbn-dev-utils/src/kbn_client/index.ts
index 29b1adbcba5760..72214b6c617462 100644
--- a/src/legacy/ui/ui_settings/__tests__/lib/index.js
+++ b/packages/kbn-dev-utils/src/kbn_client/index.ts
@@ -17,7 +17,5 @@
* under the License.
*/
-export {
- createObjectsClientStub,
- savedObjectsClientErrors,
-} from './create_objects_client_stub';
+export { KbnClient } from './kbn_client';
+export { uriencode } from './kbn_client_requester';
diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts
new file mode 100644
index 00000000000000..2eb6c6cc5aac6b
--- /dev/null
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ToolingLog } from '../tooling_log';
+import { KbnClientRequester, ReqOptions } from './kbn_client_requester';
+import { KbnClientStatus } from './kbn_client_status';
+import { KbnClientPlugins } from './kbn_client_plugins';
+import { KbnClientVersion } from './kbn_client_version';
+import { KbnClientSavedObjects } from './kbn_client_saved_objects';
+import { KbnClientUiSettings, UiSettingValues } from './kbn_client_ui_settings';
+
+export class KbnClient {
+ private readonly requester = new KbnClientRequester(this.log, this.kibanaUrls);
+ readonly status = new KbnClientStatus(this.requester);
+ readonly plugins = new KbnClientPlugins(this.status);
+ readonly version = new KbnClientVersion(this.status);
+ readonly savedObjects = new KbnClientSavedObjects(this.log, this.requester);
+ readonly uiSettings = new KbnClientUiSettings(this.log, this.requester, this.uiSettingDefaults);
+
+ /**
+ * Basic Kibana server client that implements common behaviors for talking
+ * to the Kibana server from dev tooling.
+ *
+ * @param log ToolingLog
+ * @param kibanaUrls Array of kibana server urls to send requests to
+ * @param uiSettingDefaults Map of uiSetting values that will be merged with all uiSetting resets
+ */
+ constructor(
+ private readonly log: ToolingLog,
+ private readonly kibanaUrls: string[],
+ private readonly uiSettingDefaults?: UiSettingValues
+ ) {
+ if (!kibanaUrls.length) {
+ throw new Error('missing Kibana urls');
+ }
+ }
+
+ /**
+ * Make a direct request to the Kibana server
+ */
+ async request(options: ReqOptions) {
+ return await this.requester.request(options);
+ }
+
+ resolveUrl(relativeUrl: string) {
+ return this.requester.resolveUrl(relativeUrl);
+ }
+}
diff --git a/test/common/services/kibana_server/version.js b/packages/kbn-dev-utils/src/kbn_client/kbn_client_plugins.ts
similarity index 57%
rename from test/common/services/kibana_server/version.js
rename to packages/kbn-dev-utils/src/kbn_client/kbn_client_plugins.ts
index b7efb01c63449a..80285caf365a0b 100644
--- a/test/common/services/kibana_server/version.js
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_plugins.ts
@@ -17,23 +17,28 @@
* under the License.
*/
-export class KibanaServerVersion {
- constructor(kibanaStatus) {
- this.kibanaStatus = kibanaStatus;
- this._cachedVersionNumber;
- }
+import { KbnClientStatus } from './kbn_client_status';
- async get() {
- if (this._cachedVersionNumber) {
- return this._cachedVersionNumber;
- }
+const PLUGIN_STATUS_ID = /^plugin:(.+?)@/;
+
+export class KbnClientPlugins {
+ constructor(private readonly status: KbnClientStatus) {}
+ /**
+ * Get a list of plugin ids that are enabled on the server
+ */
+ public async getEnabledIds() {
+ const pluginIds: string[] = [];
+ const apiResp = await this.status.get();
- const status = await this.kibanaStatus.get();
- if (status && status.version && status.version.number) {
- this._cachedVersionNumber = status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : '');
- return this._cachedVersionNumber;
+ for (const status of apiResp.status.statuses) {
+ if (status.id) {
+ const match = status.id.match(PLUGIN_STATUS_ID);
+ if (match) {
+ pluginIds.push(match[1]);
+ }
+ }
}
- throw new Error(`Unable to fetch Kibana Server status, received ${JSON.stringify(status)}`);
+ return pluginIds;
}
}
diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts
new file mode 100644
index 00000000000000..56d4d7f99e0b80
--- /dev/null
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_requester.ts
@@ -0,0 +1,124 @@
+/*
+ * 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 Url from 'url';
+
+import Axios from 'axios';
+
+import { isAxiosRequestError, isConcliftOnGetError } from './errors';
+import { ToolingLog } from '../tooling_log';
+
+export const uriencode = (
+ strings: TemplateStringsArray,
+ ...values: Array
+) => {
+ const queue = strings.slice();
+
+ if (queue.length === 0) {
+ throw new Error('how could strings passed to `uriencode` template tag be empty?');
+ }
+
+ if (queue.length !== values.length + 1) {
+ throw new Error('strings and values passed to `uriencode` template tag are unbalanced');
+ }
+
+ // pull the first string off the queue, there is one less item in `values`
+ // since the values are always wrapped in strings, so we shift the extra string
+ // off the queue to balance the queue and values array.
+ const leadingString = queue.shift()!;
+ return queue.reduce(
+ (acc, string, i) => `${acc}${encodeURIComponent(values[i])}${string}`,
+ leadingString
+ );
+};
+
+const DEFAULT_MAX_ATTEMPTS = 5;
+
+export interface ReqOptions {
+ description?: string;
+ path: string;
+ query?: Record;
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
+ body?: any;
+ attempt?: number;
+ maxAttempts?: number;
+}
+
+const delay = (ms: number) =>
+ new Promise(resolve => {
+ setTimeout(resolve, ms);
+ });
+
+export class KbnClientRequester {
+ constructor(private readonly log: ToolingLog, private readonly kibanaUrls: string[]) {}
+
+ private pickUrl() {
+ const url = this.kibanaUrls.shift()!;
+ this.kibanaUrls.push(url);
+ return url;
+ }
+
+ public resolveUrl(relativeUrl: string = '/') {
+ return Url.resolve(this.pickUrl(), relativeUrl);
+ }
+
+ async request(options: ReqOptions): Promise {
+ const url = Url.resolve(this.pickUrl(), options.path);
+ const description = options.description || `${options.method} ${url}`;
+ const attempt = options.attempt === undefined ? 1 : options.attempt;
+ const maxAttempts =
+ options.maxAttempts === undefined ? DEFAULT_MAX_ATTEMPTS : options.maxAttempts;
+
+ try {
+ const response = await Axios.request({
+ method: options.method,
+ url,
+ data: options.body,
+ params: options.query,
+ headers: {
+ 'kbn-xsrf': 'kbn-client',
+ },
+ });
+
+ return response.data;
+ } catch (error) {
+ let retryErrorMsg: string | undefined;
+ if (isAxiosRequestError(error)) {
+ retryErrorMsg = `[${description}] request failed (attempt=${attempt})`;
+ } else if (isConcliftOnGetError(error)) {
+ retryErrorMsg = `Conflict on GET (path=${options.path}, attempt=${attempt})`;
+ }
+
+ if (retryErrorMsg) {
+ if (attempt < maxAttempts) {
+ this.log.error(retryErrorMsg);
+ await delay(1000 * attempt);
+ return await this.request({
+ ...options,
+ attempt: attempt + 1,
+ });
+ }
+
+ throw new Error(retryErrorMsg + ' and ran out of retries');
+ }
+
+ throw error;
+ }
+ }
+}
diff --git a/test/common/services/kibana_server/saved_objects.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts
similarity index 64%
rename from test/common/services/kibana_server/saved_objects.ts
rename to packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts
index 0e4a9a34bf2e40..51fa19c140bf05 100644
--- a/test/common/services/kibana_server/saved_objects.ts
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_saved_objects.ts
@@ -17,16 +17,9 @@
* under the License.
*/
-import Url from 'url';
+import { ToolingLog } from '../tooling_log';
-import Axios, { AxiosRequestConfig } from 'axios';
-import { ToolingLog } from '@kbn/dev-utils';
-
-const joinPath = (...components: Array) =>
- `/${components
- .filter((s): s is string => !!s)
- .map(c => encodeURIComponent(c))
- .join('/')}`;
+import { KbnClientRequester, uriencode } from './kbn_client_requester';
type MigrationVersion = Record;
@@ -64,15 +57,8 @@ interface UpdateOptions extends IndexOptions {
id: string;
}
-export class KibanaServerSavedObjects {
- private readonly x = Axios.create({
- baseURL: Url.resolve(this.url, '/api/saved_objects/'),
- headers: {
- 'kbn-xsrf': 'KibanaServerSavedObjects',
- },
- });
-
- constructor(private readonly url: string, private readonly log: ToolingLog) {}
+export class KbnClientSavedObjects {
+ constructor(private readonly log: ToolingLog, private readonly requester: KbnClientRequester) {}
/**
* Get an object
@@ -80,8 +66,9 @@ export class KibanaServerSavedObjects {
public async get>(options: GetOptions) {
this.log.debug('Gettings saved object: %j', options);
- return await this.request>('get saved object', {
- url: joinPath(options.type, options.id),
+ return await this.requester.request>({
+ description: 'get saved object',
+ path: uriencode`/api/saved_objects/${options.type}/${options.id}`,
method: 'GET',
});
}
@@ -92,13 +79,16 @@ export class KibanaServerSavedObjects {
public async create>(options: IndexOptions) {
this.log.debug('Creating saved object: %j', options);
- return await this.request>('update saved object', {
- url: joinPath(options.type, options.id),
- params: {
+ return await this.requester.request>({
+ description: 'update saved object',
+ path: options.id
+ ? uriencode`/api/saved_objects/${options.type}/${options.id}`
+ : uriencode`/api/saved_objects/${options.type}`,
+ query: {
overwrite: options.overwrite,
},
method: 'POST',
- data: {
+ body: {
attributes: options.attributes,
migrationVersion: options.migrationVersion,
references: options.references,
@@ -112,13 +102,14 @@ export class KibanaServerSavedObjects {
public async update>(options: UpdateOptions) {
this.log.debug('Updating saved object: %j', options);
- return await this.request>('update saved object', {
- url: joinPath(options.type, options.id),
- params: {
+ return await this.requester.request>({
+ description: 'update saved object',
+ path: uriencode`/api/saved_objects/${options.type}/${options.id}`,
+ query: {
overwrite: options.overwrite,
},
method: 'PUT',
- data: {
+ body: {
attributes: options.attributes,
migrationVersion: options.migrationVersion,
references: options.references,
@@ -132,22 +123,10 @@ export class KibanaServerSavedObjects {
public async delete(options: GetOptions) {
this.log.debug('Deleting saved object %s/%s', options);
- return await this.request('delete saved object', {
- url: joinPath(options.type, options.id),
+ return await this.requester.request({
+ description: 'delete saved object',
+ path: uriencode`/api/saved_objects/${options.type}/${options.id}`,
method: 'DELETE',
});
}
-
- private async request(desc: string, options: AxiosRequestConfig) {
- try {
- const resp = await this.x.request(options);
- return resp.data;
- } catch (error) {
- if (error.response) {
- throw new Error(`Failed to ${desc}:\n${JSON.stringify(error.response.data, null, 2)}`);
- }
-
- throw error;
- }
- }
}
diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_status.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_status.ts
new file mode 100644
index 00000000000000..22baf4a3304168
--- /dev/null
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_status.ts
@@ -0,0 +1,68 @@
+/*
+ * 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 { KbnClientRequester } from './kbn_client_requester';
+
+interface Status {
+ state: 'green' | 'red' | 'yellow';
+ title?: string;
+ id?: string;
+ icon: string;
+ message: string;
+ uiColor: string;
+ since: string;
+}
+
+interface ApiResponseStatus {
+ name: string;
+ uuid: string;
+ version: {
+ number: string;
+ build_hash: string;
+ build_number: number;
+ build_snapshot: boolean;
+ };
+ status: {
+ overall: Status;
+ statuses: Status[];
+ };
+ metrics: unknown;
+}
+
+export class KbnClientStatus {
+ constructor(private readonly requester: KbnClientRequester) {}
+
+ /**
+ * Get the full server status
+ */
+ async get() {
+ return await this.requester.request({
+ method: 'GET',
+ path: 'api/status',
+ });
+ }
+
+ /**
+ * Get the overall/merged state
+ */
+ public async getOverallState() {
+ const status = await this.get();
+ return status.status.overall.state;
+ }
+}
diff --git a/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts b/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts
new file mode 100644
index 00000000000000..03033bc5c2ccc4
--- /dev/null
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_ui_settings.ts
@@ -0,0 +1,113 @@
+/*
+ * 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 { ToolingLog } from '../tooling_log';
+
+import { KbnClientRequester, uriencode } from './kbn_client_requester';
+
+export type UiSettingValues = Record;
+interface UiSettingsApiResponse {
+ settings: {
+ [key: string]: {
+ userValue: string | number | boolean;
+ isOverridden: boolean | undefined;
+ };
+ };
+}
+
+export class KbnClientUiSettings {
+ constructor(
+ private readonly log: ToolingLog,
+ private readonly requester: KbnClientRequester,
+ private readonly defaults?: UiSettingValues
+ ) {}
+
+ async get(setting: string) {
+ const all = await this.getAll();
+ const value = all.settings[setting] ? all.settings[setting].userValue : undefined;
+
+ this.log.verbose('uiSettings.value: %j', value);
+ return value;
+ }
+
+ /**
+ * Gets defaultIndex from the config doc.
+ */
+ async getDefaultIndex() {
+ return await this.get('defaultIndex');
+ }
+
+ /**
+ * Unset a uiSetting
+ */
+ async unset(setting: string) {
+ return await this.requester.request({
+ path: uriencode`/api/kibana/settings/${setting}`,
+ method: 'DELETE',
+ });
+ }
+
+ /**
+ * Replace all uiSettings with the `doc` values, `doc` is merged
+ * with some defaults
+ */
+ async replace(doc: UiSettingValues) {
+ const all = await this.getAll();
+ for (const [name, { isOverridden }] of Object.entries(all.settings)) {
+ if (!isOverridden) {
+ await this.unset(name);
+ }
+ }
+
+ this.log.debug('replacing kibana config doc: %j', doc);
+
+ await this.requester.request({
+ method: 'POST',
+ path: '/api/kibana/settings',
+ body: {
+ changes: {
+ ...this.defaults,
+ ...doc,
+ },
+ },
+ });
+ }
+
+ /**
+ * Add fields to the config doc (like setting timezone and defaultIndex)
+ */
+ async update(updates: UiSettingValues) {
+ this.log.debug('applying update to kibana config: %j', updates);
+
+ await this.requester.request({
+ path: '/api/kibana/settings',
+ method: 'POST',
+ body: {
+ changes: updates,
+ },
+ });
+ }
+
+ private async getAll() {
+ return await this.requester.request({
+ path: '/api/kibana/settings',
+ method: 'GET',
+ });
+ }
+}
diff --git a/src/legacy/ui/ui_exports/ui_exports_mixin.js b/packages/kbn-dev-utils/src/kbn_client/kbn_client_version.ts
similarity index 63%
rename from src/legacy/ui/ui_exports/ui_exports_mixin.js
rename to packages/kbn-dev-utils/src/kbn_client/kbn_client_version.ts
index ea2a07f3b265e0..1aacb857f12f67 100644
--- a/src/legacy/ui/ui_exports/ui_exports_mixin.js
+++ b/packages/kbn-dev-utils/src/kbn_client/kbn_client_version.ts
@@ -17,22 +17,20 @@
* under the License.
*/
-import { collectUiExports } from './collect_ui_exports';
+import { KbnClientStatus } from './kbn_client_status';
-export function uiExportsMixin(kbnServer) {
- kbnServer.uiExports = collectUiExports(
- kbnServer.pluginSpecs
- );
+export class KbnClientVersion {
+ private versionCache: string | undefined;
- // check for unknown uiExport types
- const { unknown = [] } = kbnServer.uiExports;
- if (!unknown.length) {
- return;
- }
+ constructor(private readonly status: KbnClientStatus) {}
+
+ async get() {
+ if (this.versionCache !== undefined) {
+ return this.versionCache;
+ }
- throw new Error(`Unknown uiExport types: ${
- unknown
- .map(({ pluginSpec, type }) => `${type} from ${pluginSpec.getId()}`)
- .join(', ')
- }`);
+ const status = await this.status.get();
+ this.versionCache = status.version.number + (status.version.build_snapshot ? '-SNAPSHOT' : '');
+ return this.versionCache;
+ }
}
diff --git a/packages/kbn-es-query/src/es_query/index.d.ts b/packages/kbn-es-query/src/es_query/index.d.ts
new file mode 100644
index 00000000000000..9510a18441e53c
--- /dev/null
+++ b/packages/kbn-es-query/src/es_query/index.d.ts
@@ -0,0 +1,39 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export function buildQueryFromFilters(filters: unknown[], indexPattern: unknown): unknown;
+export function buildEsQuery(
+ indexPattern: unknown,
+ queries: unknown,
+ filters: unknown,
+ config?: {
+ allowLeadingWildcards: boolean;
+ queryStringOptions: unknown;
+ ignoreFilterIfFieldNotInIndex: boolean;
+ dateFormatTZ?: string | null;
+ }
+): unknown;
+export function getEsQueryConfig(config: {
+ get: (name: string) => unknown;
+}): {
+ allowLeadingWildcards: boolean;
+ queryStringOptions: unknown;
+ ignoreFilterIfFieldNotInIndex: boolean;
+ dateFormatTZ?: string | null;
+};
diff --git a/packages/kbn-es-query/src/index.d.ts b/packages/kbn-es-query/src/index.d.ts
index 873636a28889fd..ca4455da33f45d 100644
--- a/packages/kbn-es-query/src/index.d.ts
+++ b/packages/kbn-es-query/src/index.d.ts
@@ -17,5 +17,6 @@
* under the License.
*/
+export * from './es_query';
export * from './kuery';
export * from './filters';
diff --git a/packages/kbn-es-query/src/kuery/ast/ast.d.ts b/packages/kbn-es-query/src/kuery/ast/ast.d.ts
index 915c024f2ab48d..448ef0e9cca750 100644
--- a/packages/kbn-es-query/src/kuery/ast/ast.d.ts
+++ b/packages/kbn-es-query/src/kuery/ast/ast.d.ts
@@ -17,6 +17,8 @@
* under the License.
*/
+import { JsonObject } from '..';
+
/**
* WARNING: these typings are incomplete
*/
@@ -30,15 +32,6 @@ export interface KueryParseOptions {
startRule: string;
}
-type JsonValue = null | boolean | number | string | JsonObject | JsonArray;
-
-interface JsonObject {
- [key: string]: JsonValue;
-}
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-interface JsonArray extends Array {}
-
export function fromKueryExpression(
expression: string,
parseOptions?: KueryParseOptions
diff --git a/packages/kbn-es-query/src/kuery/functions/is.js b/packages/kbn-es-query/src/kuery/functions/is.js
index 0338671e9b3fe4..690f98b08ba827 100644
--- a/packages/kbn-es-query/src/kuery/functions/is.js
+++ b/packages/kbn-es-query/src/kuery/functions/is.js
@@ -32,7 +32,6 @@ export function buildNodeParams(fieldName, value, isPhrase = false) {
if (_.isUndefined(value)) {
throw new Error('value is a required argument');
}
-
const fieldNode = typeof fieldName === 'string' ? ast.fromLiteralExpression(fieldName) : literal.buildNode(fieldName);
const valueNode = typeof value === 'string' ? ast.fromLiteralExpression(value) : literal.buildNode(value);
const isPhraseNode = literal.buildNode(isPhrase);
@@ -42,7 +41,7 @@ export function buildNodeParams(fieldName, value, isPhrase = false) {
}
export function toElasticsearchQuery(node, indexPattern = null, config = {}) {
- const { arguments: [ fieldNameArg, valueArg, isPhraseArg ] } = node;
+ const { arguments: [fieldNameArg, valueArg, isPhraseArg] } = node;
const fieldName = ast.toElasticsearchQuery(fieldNameArg);
const value = !_.isUndefined(valueArg) ? ast.toElasticsearchQuery(valueArg) : valueArg;
const type = isPhraseArg.value ? 'phrase' : 'best_fields';
diff --git a/packages/kbn-es-query/src/kuery/index.d.ts b/packages/kbn-es-query/src/kuery/index.d.ts
index 9d797406420d41..b01a8914f68ef3 100644
--- a/packages/kbn-es-query/src/kuery/index.d.ts
+++ b/packages/kbn-es-query/src/kuery/index.d.ts
@@ -18,3 +18,13 @@
*/
export * from './ast';
+export { nodeTypes } from './node_types';
+
+export type JsonValue = null | boolean | number | string | JsonObject | JsonArray;
+
+export interface JsonObject {
+ [key: string]: JsonValue;
+}
+
+// eslint-disable-next-line @typescript-eslint/no-empty-interface
+export interface JsonArray extends Array {}
diff --git a/packages/kbn-es-query/src/kuery/index.js b/packages/kbn-es-query/src/kuery/index.js
index 84c6a205b42ce6..08fa9829d4a566 100644
--- a/packages/kbn-es-query/src/kuery/index.js
+++ b/packages/kbn-es-query/src/kuery/index.js
@@ -19,5 +19,5 @@
export * from './ast';
export * from './filter_migration';
-export * from './node_types';
+export { nodeTypes } from './node_types';
export * from './errors';
diff --git a/packages/kbn-es-query/src/kuery/node_types/index.d.ts b/packages/kbn-es-query/src/kuery/node_types/index.d.ts
new file mode 100644
index 00000000000000..0d1f2c28e39f08
--- /dev/null
+++ b/packages/kbn-es-query/src/kuery/node_types/index.d.ts
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/**
+ * WARNING: these typings are incomplete
+ */
+
+import { JsonObject, JsonValue } from '..';
+
+type FunctionName =
+ | 'is'
+ | 'and'
+ | 'or'
+ | 'not'
+ | 'range'
+ | 'exists'
+ | 'geoBoundingBox'
+ | 'geoPolygon';
+
+interface FunctionTypeBuildNode {
+ type: 'function';
+ function: FunctionName;
+ // TODO -> Need to define a better type for DSL query
+ arguments: any[];
+}
+
+interface FunctionType {
+ buildNode: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode;
+ buildNodeWithArgumentNodes: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode;
+ toElasticsearchQuery: (node: any, indexPattern: any, config: JsonObject) => JsonValue;
+}
+
+interface LiteralType {
+ buildNode: (
+ value: null | boolean | number | string
+ ) => { type: 'literal'; value: null | boolean | number | string };
+ toElasticsearchQuery: (node: any) => null | boolean | number | string;
+}
+
+interface NamedArgType {
+ buildNode: (name: string, value: any) => { type: 'namedArg'; name: string; value: any };
+ toElasticsearchQuery: (node: any) => string;
+}
+
+interface WildcardType {
+ buildNode: (value: string) => { type: 'wildcard'; value: string };
+ test: (node: any, string: string) => boolean;
+ toElasticsearchQuery: (node: any) => string;
+ toQueryStringQuery: (node: any) => string;
+ hasLeadingWildcard: (node: any) => boolean;
+}
+
+interface NodeTypes {
+ function: FunctionType;
+ literal: LiteralType;
+ namedArg: NamedArgType;
+ wildcard: WildcardType;
+}
+
+export const nodeTypes: NodeTypes;
diff --git a/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js
index 18e161e0ce925e..523317ab63e85b 100644
--- a/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js
+++ b/packages/kbn-plugin-generator/integration_tests/generate_plugin.test.js
@@ -88,7 +88,12 @@ describe(`running the plugin-generator via 'node scripts/generate_plugin.js plug
await withProcRunner(log, async proc => {
await proc.run('kibana', {
cmd: 'yarn',
- args: ['start', '--optimize.enabled=false', '--logging.json=false'],
+ args: [
+ 'start',
+ '--optimize.enabled=false',
+ '--logging.json=false',
+ '--migrations.skip=true',
+ ],
cwd: generatedPath,
wait: /ispec_plugin.+Status changed from uninitialized to green - Ready/,
});
diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js
index fb1ca192c5fd37..9901f62ae71cf3 100644
--- a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js
+++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites_by_tags.test.js
@@ -95,16 +95,16 @@ it('only runs hooks of parents and tests in level1a', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1a' ]",
- "suite: ",
- "suite: level 1",
- "suite: level 1 level 1a",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1a test 1a",
-]
-`);
+ Array [
+ "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1a' ]",
+ "suite: ",
+ "suite: level 1",
+ "suite: level 1 level 1a",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1a test 1a",
+ ]
+ `);
});
it('only runs hooks of parents and tests in level1b', async () => {
@@ -114,16 +114,16 @@ it('only runs hooks of parents and tests in level1b', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1b' ]",
- "suite: ",
- "suite: level 1",
- "suite: level 1 level 1b",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1b test 1b",
-]
-`);
+ Array [
+ "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1b' ]",
+ "suite: ",
+ "suite: level 1",
+ "suite: level 1 level 1b",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1b test 1b",
+ ]
+ `);
});
it('only runs hooks of parents and tests in level1a and level1b', async () => {
@@ -133,20 +133,20 @@ it('only runs hooks of parents and tests in level1a and level1b', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1a', 'level1b' ]",
- "suite: ",
- "suite: level 1",
- "suite: level 1 level 1a",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1a test 1a",
- "suite: level 1 level 1b",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1b test 1b",
-]
-`);
+ Array [
+ "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1a', 'level1b' ]",
+ "suite: ",
+ "suite: level 1",
+ "suite: level 1 level 1a",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1a test 1a",
+ "suite: level 1 level 1b",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1b test 1b",
+ ]
+ `);
});
it('only runs level1a if including level1 and excluding level1b', async () => {
@@ -156,17 +156,17 @@ it('only runs level1a if including level1 and excluding level1b', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1' ]",
- "info: Filtering out any suites that include the tag(s): [ 'level1b' ]",
- "suite: ",
- "suite: level 1",
- "suite: level 1 level 1a",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1a test 1a",
-]
-`);
+ Array [
+ "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1' ]",
+ "info: Filtering out any suites that include the tag(s): [ 'level1b' ]",
+ "suite: ",
+ "suite: level 1",
+ "suite: level 1 level 1a",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1a test 1a",
+ ]
+ `);
});
it('only runs level1b if including level1 and excluding level1a', async () => {
@@ -176,17 +176,17 @@ it('only runs level1b if including level1 and excluding level1a', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1' ]",
- "info: Filtering out any suites that include the tag(s): [ 'level1a' ]",
- "suite: ",
- "suite: level 1",
- "suite: level 1 level 1b",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "hook: level 1 \\"before each\\" hook: level1BeforeEach",
- "test: level 1 level 1b test 1b",
-]
-`);
+ Array [
+ "info: Only running suites (and their sub-suites) if they include the tag(s): [ 'level1' ]",
+ "info: Filtering out any suites that include the tag(s): [ 'level1a' ]",
+ "suite: ",
+ "suite: level 1",
+ "suite: level 1 level 1b",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "hook: level 1 \\"before each\\" hook: level1BeforeEach",
+ "test: level 1 level 1b test 1b",
+ ]
+ `);
});
it('only runs level2 if excluding level1', async () => {
@@ -196,15 +196,15 @@ it('only runs level2 if excluding level1', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Filtering out any suites that include the tag(s): [ 'level1' ]",
- "suite: ",
- "suite: level 2",
- "suite: level 2 level 2a",
- "hook: \\"before each\\" hook: rootBeforeEach",
- "test: level 2 level 2a test 2a",
-]
-`);
+ Array [
+ "info: Filtering out any suites that include the tag(s): [ 'level1' ]",
+ "suite: ",
+ "suite: level 2",
+ "suite: level 2 level 2a",
+ "hook: \\"before each\\" hook: rootBeforeEach",
+ "test: level 2 level 2a test 2a",
+ ]
+ `);
});
it('does nothing if everything excluded', async () => {
@@ -214,8 +214,8 @@ it('does nothing if everything excluded', async () => {
});
expect(history).toMatchInlineSnapshot(`
-Array [
- "info: Filtering out any suites that include the tag(s): [ 'level1', 'level2a' ]",
-]
-`);
+ Array [
+ "info: Filtering out any suites that include the tag(s): [ 'level1', 'level2a' ]",
+ ]
+ `);
});
diff --git a/renovate.json5 b/renovate.json5
index e5dd29aa631908..cd836762b817f8 100644
--- a/renovate.json5
+++ b/renovate.json5
@@ -67,6 +67,17 @@
'(\\b|_)jest(\\b|_)',
],
},
+ {
+ groupSlug: '@elastic/charts',
+ groupName: '@elastic/charts related packages',
+ packageNames: [
+ '@elastic/charts',
+ '@types/elastic__charts',
+ ],
+ reviewers: [
+ 'markov00',
+ ],
+ },
{
groupSlug: 'mocha',
groupName: 'mocha related packages',
diff --git a/rfcs/text/0006_management_section_service.md b/rfcs/text/0006_management_section_service.md
new file mode 100644
index 00000000000000..bcb74b1bcd8da7
--- /dev/null
+++ b/rfcs/text/0006_management_section_service.md
@@ -0,0 +1,332 @@
+- Start Date: 2019-08-20
+- RFC PR: TBD
+- Kibana Issue: [#43499](https://github.com/elastic/kibana/issues/43499)
+
+# Summary
+Management is one of the four primary "domains" covered by @elastic/kibana-app-arch (along with Data, Embeddables, and Visualizations). There are two main purposes for this service:
+
+1. Own the management "framework" -- the UI that displays the management sidebar nav, the landing page, and handles rendering each of the sections
+2. Expose a registry for other plugins to add their own registry sections to the UI and add nested links to them in the sidebar.
+
+The purpose of this RFC is to consider item 2 above -- the service for registering sections to the nav & loading them up.
+
+# Motivation
+
+## Why now?
+The main driver for considering this now is that the Management API moving to the new platform is going to block other teams from completing migration, so we need to have an answer to what the new platform version of the API looks like as soon as possible in `7.x`.
+
+## Why not just keep the current API and redesign later?
+The answer to that has to do with the items that are currently used in the management implementation which must be removed in order to migrate to NP: the framework currently registers a `uiExport`, and relies on `IndexedArray`, `uiRegistry`, and `ui/routes`.
+
+This means that we will basically need to rebuild the service anyway in order to migrate to the new platform. So if we are going to invest that time, we might as well invest it in building the API the way we want it to be longer term, rather than creating more work for ourselves later.
+
+## Technical goals
+- Remove another usage of `IndexedArray` & `uiRegistry` (required for migration)
+- Remove dependency on `ui/routes` (required for migration)
+- Remove management section `uiExport` (required for migration)
+- Simple API that is designed in keeping with new platform principles
+ - This includes being rendering-framework-agnostic... You should be able to build your management section UI however you'd like
+- Clear separation of app/UI code and service code, even if both live within the same plugin
+- Flexibility to potentially support alternate layouts in the future (see mockups in [reference section](#reference) below)
+
+# Basic example
+This API is influenced heavily by the [application service mounting RFC](https://github.com/elastic/kibana/blob/master/rfcs/text/0004_application_service_mounting.md). The intent is to make the experience consistent with that service; the Management section is basically one big app with a bunch of registered "subapps".
+
+```ts
+// my_plugin/public/plugin.ts
+
+export class MyPlugin {
+ setup(core, { management }) {
+ // Registering a new app to a new section
+ const mySection = management.sections.register({
+ id: 'my-section',
+ title: 'My Main Section', // display name
+ order: 10,
+ euiIconType: 'iconName',
+ });
+ mySection.registerApp({
+ id: 'my-management-app',
+ title: 'My Management App', // display name
+ order: 20,
+ async mount(context, params) {
+ const { renderApp } = await import('./my-section');
+ return renderApp(context, params);
+ }
+ });
+
+ // Registering a new app to an existing section
+ const kibanaSection = management.sections.get('kibana');
+ kibanaSection.registerApp({ id: 'my-kibana-management-app', ... });
+ }
+
+ start(core, { management }) {
+ // access all registered sections, filtered based on capabilities
+ const sections = management.sections.getAvailable();
+ sections.forEach(section => console.log(`${section.id} - ${section.title}`));
+ // automatically navigate to any app by id
+ management.sections.navigateToApp('my-kibana-management-app');
+ }
+}
+
+// my_plugin/public/my-section.tsx
+
+export function renderApp(context, { sectionBasePath, element }) {
+ ReactDOM.render(
+ // `sectionBasePath` would be `/app/management/my-section/my-management-app`
+ ,
+ element
+ );
+
+ // return value must be a function that unmounts (just like Core Application Service)
+ return () => ReactDOM.unmountComponentAtNode(element);
+}
+```
+
+We can also create a utility in `kibana_react` to make it easy for folks to `mount` a React app:
+```ts
+// src/plugins/kibana_react/public/mount_with_react.tsx
+import { KibanaContextProvider } from './context';
+
+export const mountWithReact = (
+ Component: React.ComponentType<{ basename: string }>,
+ context: AppMountContext,
+ params: ManagementSectionMountParams,
+) => {
+ ReactDOM.render(
+ (
+
+
+
+ ),
+ params.element
+ );
+
+ return () => ReactDOM.unmountComponentAtNode(params.element);
+}
+
+// my_plugin/public/plugin.ts
+import { mountWithReact } from 'src/plugins/kibana_react/public';
+
+export class MyPlugin {
+ setup(core, { management }) {
+ const kibanaSection = management.sections.get('kibana');
+ kibanaSection.registerApp({
+ id: 'my-other-kibana-management-app',
+ ...,
+ async mount(context, params) {
+ const { MySection } = await import('./components/my-section');
+ const unmountCallback = mountWithReact(MySection, context, params);
+ return () => unmountCallback();
+ }
+ });
+ }
+}
+```
+
+# Detailed design
+
+```ts
+interface ManagementSetup {
+ sections: SectionsServiceSetup;
+}
+
+interface ManagementStart {
+ sections: SectionsServiceStart;
+}
+
+interface SectionsServiceSetup {
+ get: (sectionId: string) => Section;
+ getAvailable: () => Section[]; // filtered based on capabilities
+ register: RegisterSection;
+}
+
+interface SectionsServiceStart {
+ getAvailable: () => Array>; // filtered based on capabilities
+ // uses `core.application.navigateToApp` under the hood, automatically prepending the `path` for the link
+ navigateToApp: (appId: string, options?: { path?: string; state?: any }) => void;
+}
+
+type RegisterSection = (
+ id: string,
+ title: string,
+ order?: number,
+ euiIconType?: string, // takes precedence over `icon` property.
+ icon?: string, // URL to image file; fallback if no `euiIconType`
+) => Section;
+
+type RegisterManagementApp = (
+ id: string;
+ title: string;
+ order?: number;
+ mount: ManagementSectionMount;
+) => ManagementApp;
+
+type Unmount = () => Promise | void;
+
+interface ManagementSectionMountParams {
+ sectionBasePath: string; // base path for setting up your router
+ element: HTMLElement; // element the section should render into
+}
+
+type ManagementSectionMount = (
+ context: AppMountContext, // provided by core.ApplicationService
+ params: ManagementSectionMountParams,
+) => Unmount | Promise;
+
+interface ManagementApp {
+ id: string;
+ title: string;
+ basePath: string;
+ sectionId: string;
+ order?: number;
+}
+
+interface Section {
+ id: string;
+ title: string;
+ apps: ManagementApp[];
+ registerApp: RegisterManagementApp;
+ order?: number;
+ euiIconType?: string;
+ icon?: string;
+}
+```
+
+# Legacy service (what this would be replacing)
+
+Example of how this looks today:
+```js
+// myplugin/index
+new Kibana.Plugin({
+ uiExports: {
+ managementSections: ['myplugin/management'],
+ }
+});
+
+// myplugin/public/management
+import { management } from 'ui/management';
+
+// completely new section
+const newSection = management.register('mypluginsection', {
+ name: 'mypluginsection',
+ order: 10,
+ display: 'My Plugin',
+ icon: 'iconName',
+});
+newSection.register('mypluginlink', {
+ name: 'mypluginlink',
+ order: 10,
+ display: 'My sublink',
+ url: `#/management/myplugin`,
+});
+
+// new link in existing section
+const kibanaSection = management.getSection('kibana');
+kibanaSection.register('mypluginlink', {
+ name: 'mypluginlink',
+ order: 10,
+ display: 'My sublink',
+ url: `#/management/myplugin`,
+});
+
+// use ui/routes to render component
+import routes from 'ui/routes';
+
+const renderReact = (elem) => {
+ render(, elem);
+};
+
+routes.when('management/myplugin', {
+ controller($scope, $http, kbnUrl) {
+ $scope.$on('$destroy', () => {
+ const elem = document.getElementById('usersReactRoot');
+ if (elem) unmountComponentAtNode(elem);
+ });
+ $scope.$$postDigest(() => {
+ const elem = document.getElementById('usersReactRoot');
+ const changeUrl = (url) => {
+ kbnUrl.change(url);
+ $scope.$apply();
+ };
+ renderReact(elem, $http, changeUrl);
+ });
+ },
+});
+```
+Current public contracts owned by the legacy service:
+```js
+// ui/management/index
+interface API {
+ PAGE_TITLE_COMPONENT: string; // actually related to advanced settings?
+ PAGE_SUBTITLE_COMPONENT: string; // actually related to advanced settings?
+ PAGE_FOOTER_COMPONENT: string; // actually related to advanced settings?
+ SidebarNav: React.SFC;
+ registerSettingsComponent: (
+ id: string,
+ component: string | React.SFC,
+ allowOverride: boolean
+ ) => void;
+ management: new ManagementSection();
+ MANAGEMENT_BREADCRUMB: {
+ text: string;
+ href: string;
+ };
+}
+
+// ui/management/section
+class ManagementSection {
+ get visibleItems,
+ addListener: (fn: function) => void,
+ register: (id: string, options: Options) => ManagementSection,
+ deregister: (id: string) => void,
+ hasItem: (id: string) => boolean,
+ getSection: (id: string) => ManagementSection,
+ hide: () => void,
+ show: () => void,
+ disable: () => void,
+ enable: () => void,
+}
+
+interface Options {
+ order: number | null;
+ display: string | null; // defaults to id
+ url: string | null; // defaults to ''
+ visible: boolean | null; // defaults to true
+ disabled: boolean | null; // defaults to false
+ tooltip: string | null; // defaults to ''
+ icon: string | null; // defaults to ''
+}
+```
+
+# Notes
+
+- The hide/show/disable/enable options were dropped with the assumption that we will be working with uiCapabilities to determine this instead... so people shouldn't need to manage it manually as they can look up a pre-filtered list of sections.
+- This was updated to add flexibility for custom (non-EUI) icons as outlined in [#32661](https://github.com/elastic/kibana/issues/32661). Much like the Core Application Service, you either choose an EUI icon, or provide a URL to an icon.
+
+# Drawbacks
+
+- This removes the ability to infinitely nest sections within each other by making a distinction between a section header and a nav link.
+ - So far we didn't seem to be using this feature anyway, but would like feedback on any use cases for it.
+
+# Reference
+
+- Issues about Global vs Spaces-based management sections: https://github.com/elastic/kibana/issues/37285 https://github.com/elastic/kibana/issues/37283
+- Mockups related to above issues: https://marvelapp.com/52b8616/screen/57582729
+
+# Alternatives
+
+An alternative design would be making everything React-specific and simply requiring consumers of the service to provide a React component to render when a route is hit, or giving them a react-router instance to work with.
+
+This would require slightly less work for folks using the service as it would eliminate the need for a `mount` function. However, it comes at the cost of forcing folks into a specific rendering framework, which ultimately provides less flexibility.
+
+# Adoption strategy
+
+Our strategy for implementing this should be to build the service entirely in the new platform in a `management` plugin, so that plugins can gradually cut over to the new service as they prepare to migrate to the new platform.
+
+One thing we would need to figure out is how to bridge the gap between the new plugin and the legacy `ui/management` service. Ideally we would find a way to integrate the two, such that the management nav could display items registered via both services. This is a strategy we'd need to work out in more detail as we got closer to implementation.
+
+# How we teach this
+
+The hope is that this will already feel familiar to Kibana application developers, as most will have already been exposed to the Core Application Service and how it handles mounting.
+
+A guide could also be added to the "Management" section of the Kibana docs (the legacy service is not even formally documented).
diff --git a/src/cli/serve/integration_tests/invalid_config.test.js b/src/cli/serve/integration_tests/invalid_config.test.js
index a3f44697281090..e86fb03ad79546 100644
--- a/src/cli/serve/integration_tests/invalid_config.test.js
+++ b/src/cli/serve/integration_tests/invalid_config.test.js
@@ -25,9 +25,12 @@ const INVALID_CONFIG_PATH = resolve(__dirname, '__fixtures__/invalid_config.yml'
describe('cli invalid config support', function () {
it('exits with statusCode 64 and logs a single line when config is invalid', function () {
+ // Unused keys only throw once LegacyService starts, so disable migrations so that Core
+ // will finish the start lifecycle without a running Elasticsearch instance.
const { error, status, stdout } = spawnSync(process.execPath, [
'src/cli',
- '--config', INVALID_CONFIG_PATH
+ '--config', INVALID_CONFIG_PATH,
+ '--migrations.skip=true'
], {
cwd: ROOT_DIR
});
diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.js b/src/cli/serve/integration_tests/reload_logging_config.test.js
index 2b6f229ca9dae4..206118d2d1be85 100644
--- a/src/cli/serve/integration_tests/reload_logging_config.test.js
+++ b/src/cli/serve/integration_tests/reload_logging_config.test.js
@@ -83,7 +83,7 @@ describe('Server logging configuration', function () {
it('should be reloadable via SIGHUP process signaling', async function () {
expect.assertions(3);
- child = spawn(process.execPath, [kibanaPath, '--config', testConfigFile, '--oss'], {
+ child = spawn(process.execPath, [kibanaPath, '--config', testConfigFile, '--oss', '--verbose'], {
stdio: 'pipe'
});
@@ -114,7 +114,9 @@ describe('Server logging configuration', function () {
const data = JSON.parse(line);
sawJson = true;
- if (data.tags.includes('listening')) {
+ // We know the sighup handler will be registered before
+ // root.setup() is called
+ if (data.message.includes('setting up root')) {
isJson = false;
setLoggingJson(false);
@@ -128,10 +130,9 @@ describe('Server logging configuration', function () {
// the switch yet, so we ignore before switching over.
} else {
// Kibana has successfully stopped logging json, so kill the server.
-
sawNonjson = true;
- child.kill();
+ child && child.kill();
child = undefined;
}
})
@@ -178,10 +179,11 @@ describe('Server logging configuration', function () {
'--config', testConfigFile,
'--logging.dest', logPath,
'--plugins.initialize', 'false',
- '--logging.json', 'false'
+ '--logging.json', 'false',
+ '--verbose'
]);
- watchFileUntil(logPath, /http server running/, 2 * minute)
+ watchFileUntil(logPath, /starting server/, 2 * minute)
.then(() => {
// once the server is running, archive the log file and issue SIGHUP
fs.renameSync(logPath, logPathArchived);
@@ -190,8 +192,8 @@ describe('Server logging configuration', function () {
.then(() => watchFileUntil(logPath, /Reloaded logging configuration due to SIGHUP/, 10 * second))
.then(contents => {
const lines = contents.toString().split('\n');
- // should be the first and only new line of the log file
- expect(lines).toHaveLength(2);
+ // should be the first line of the new log file
+ expect(lines[0]).toMatch(/Reloaded logging configuration due to SIGHUP/);
child.kill();
})
.then(done, done);
diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js
index 7f479a7e118e02..1f7593d788304b 100644
--- a/src/cli/serve/serve.js
+++ b/src/cli/serve/serve.js
@@ -194,7 +194,6 @@ export default function (program) {
.option('--plugins ', 'an alias for --plugin-dir', pluginDirCollector)
.option('--optimize', 'Optimize and then stop the server');
-
if (CAN_REPL) {
command.option('--repl', 'Run the server with a REPL prompt and access to the server object');
}
@@ -240,7 +239,7 @@ export default function (program) {
repl: !!opts.repl,
basePath: !!opts.basePath,
optimize: !!opts.optimize,
- oss: !!opts.oss,
+ oss: !!opts.oss
},
features: {
isClusterModeSupported: CAN_CLUSTER,
diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx
index d1855a0370f002..935844baddf86a 100644
--- a/src/core/public/application/application_service.tsx
+++ b/src/core/public/application/application_service.tsx
@@ -27,12 +27,9 @@ import { AppRouter } from './ui';
import { HttpStart } from '../http';
import { ContextSetup, IContextContainer } from '../context';
import {
- AppMountContext,
App,
LegacyApp,
AppMounter,
- AppUnmount,
- AppMountParameters,
InternalApplicationSetup,
InternalApplicationStart,
} from './types';
@@ -64,11 +61,7 @@ export class ApplicationService {
private readonly apps$ = new BehaviorSubject>(new Map());
private readonly legacyApps$ = new BehaviorSubject>(new Map());
private readonly capabilities = new CapabilitiesService();
- private mountContext?: IContextContainer<
- AppMountContext,
- AppUnmount | Promise,
- [AppMountParameters]
- >;
+ private mountContext?: IContextContainer;
public setup({ context }: SetupDeps): InternalApplicationSetup {
this.mountContext = context.createContextContainer();
@@ -98,7 +91,7 @@ export class ApplicationService {
this.legacyApps$.next(new Map([...this.legacyApps$.value.entries(), [app.id, app]]));
},
- registerMountContext: this.mountContext.registerContext,
+ registerMountContext: this.mountContext!.registerContext,
};
}
diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts
index 018d7569ce411b..b2d0aff26b8b09 100644
--- a/src/core/public/application/types.ts
+++ b/src/core/public/application/types.ts
@@ -193,7 +193,7 @@ export interface ApplicationSetup {
*/
registerMountContext(
contextName: T,
- provider: IContextProvider
+ provider: IContextProvider
): void;
}
@@ -224,7 +224,7 @@ export interface InternalApplicationSetup {
registerMountContext(
pluginOpaqueId: PluginOpaqueId,
contextName: T,
- provider: IContextProvider
+ provider: IContextProvider
): void;
}
@@ -261,7 +261,7 @@ export interface ApplicationStart {
*/
registerMountContext(
contextName: T,
- provider: IContextProvider
+ provider: IContextProvider
): void;
}
@@ -291,7 +291,7 @@ export interface InternalApplicationStart
registerMountContext(
pluginOpaqueId: PluginOpaqueId,
contextName: T,
- provider: IContextProvider
+ provider: IContextProvider
): void;
// Internal APIs
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index afd9f8e4a38209..f24b0ed1681aab 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -19,7 +19,7 @@
import Url from 'url';
-import React, { Component, createRef, Fragment } from 'react';
+import React, { Component, createRef } from 'react';
import * as Rx from 'rxjs';
import {
@@ -376,7 +376,7 @@ class HeaderUI extends Component {
];
return (
-
+
@@ -407,11 +407,13 @@ class HeaderUI extends Component {
isLocked={isLocked}
onIsLockedUpdate={onIsLockedUpdate}
>
-
-
-
+
-
+
);
}
diff --git a/src/core/public/chrome/ui/header/header_breadcrumbs.tsx b/src/core/public/chrome/ui/header/header_breadcrumbs.tsx
index f4b1c1d49cd27f..68eb6a54f48a3c 100644
--- a/src/core/public/chrome/ui/header/header_breadcrumbs.tsx
+++ b/src/core/public/chrome/ui/header/header_breadcrumbs.tsx
@@ -64,7 +64,11 @@ export class HeaderBreadcrumbs extends Component {
public render() {
return (
-
+
);
}
diff --git a/src/core/public/context/context_service.ts b/src/core/public/context/context_service.ts
index 704524d8386367..dadc509c97821e 100644
--- a/src/core/public/context/context_service.ts
+++ b/src/core/public/context/context_service.ts
@@ -18,7 +18,7 @@
*/
import { PluginOpaqueId } from '../../server';
-import { IContextContainer, ContextContainer } from '../../utils/context';
+import { IContextContainer, ContextContainer, HandlerFunction } from '../../utils/context';
import { CoreContext } from '../core_system';
interface StartDeps {
@@ -31,15 +31,8 @@ export class ContextService {
public setup({ pluginDependencies }: StartDeps): ContextSetup {
return {
- createContextContainer: <
- TContext extends {},
- THandlerReturn,
- THandlerParameters extends any[] = []
- >() =>
- new ContextContainer(
- pluginDependencies,
- this.core.coreId
- ),
+ createContextContainer: >() =>
+ new ContextContainer(pluginDependencies, this.core.coreId),
};
}
}
@@ -111,9 +104,5 @@ export interface ContextSetup {
/**
* Creates a new {@link IContextContainer} for a service owner.
*/
- createContextContainer<
- TContext extends {},
- THandlerReturn,
- THandlerParmaters extends any[] = []
- >(): IContextContainer;
+ createContextContainer>(): IContextContainer;
}
diff --git a/src/core/public/context/index.ts b/src/core/public/context/index.ts
index 28b2641b2a5a74..f22c4168d75448 100644
--- a/src/core/public/context/index.ts
+++ b/src/core/public/context/index.ts
@@ -18,4 +18,10 @@
*/
export { ContextService, ContextSetup } from './context_service';
-export { IContextContainer, IContextProvider, IContextHandler } from '../../utils/context';
+export {
+ IContextContainer,
+ IContextProvider,
+ HandlerFunction,
+ HandlerContextType,
+ HandlerParameters,
+} from '../../utils/context';
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 393a7076759e86..1e2dfde7496ea2 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -67,7 +67,14 @@ import { UiSettingsClient, UiSettingsState, UiSettingsClientContract } from './u
import { ApplicationSetup, Capabilities, ApplicationStart } from './application';
import { DocLinksStart } from './doc_links';
import { SavedObjectsStart } from './saved_objects';
-import { IContextContainer, IContextProvider, ContextSetup, IContextHandler } from './context';
+import {
+ IContextContainer,
+ IContextProvider,
+ ContextSetup,
+ HandlerFunction,
+ HandlerContextType,
+ HandlerParameters,
+} from './context';
export { CoreContext, CoreSystem } from './core_system';
export { RecursiveReadonly } from '../utils';
@@ -217,7 +224,9 @@ export {
ChromeRecentlyAccessedHistoryItem,
ChromeStart,
IContextContainer,
- IContextHandler,
+ HandlerFunction,
+ HandlerContextType,
+ HandlerParameters,
IContextProvider,
ContextSetup,
DocLinksStart,
diff --git a/src/core/public/notifications/notifications_service.ts b/src/core/public/notifications/notifications_service.ts
index 2dc2b2ef06094f..33221522fa83ca 100644
--- a/src/core/public/notifications/notifications_service.ts
+++ b/src/core/public/notifications/notifications_service.ts
@@ -48,7 +48,7 @@ export class NotificationsService {
public setup({ uiSettings }: SetupDeps): NotificationsSetup {
const notificationSetup = { toasts: this.toasts.setup({ uiSettings }) };
- this.uiSettingsErrorSubscription = uiSettings.getUpdateErrors$().subscribe(error => {
+ this.uiSettingsErrorSubscription = uiSettings.getUpdateErrors$().subscribe((error: Error) => {
notificationSetup.toasts.addDanger({
title: i18n.translate('core.notifications.unableUpdateUISettingNotificationMessageTitle', {
defaultMessage: 'Unable to update UI setting',
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index b2d730d7fa4670..e6c8f116e5782a 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -9,6 +9,7 @@ import { MouseEventHandler } from 'react';
import { Observable } from 'rxjs';
import React from 'react';
import * as Rx from 'rxjs';
+import { ShallowPromise } from '@kbn/utility-types';
import { EuiGlobalToastListToast as Toast } from '@elastic/eui';
// @public
@@ -31,7 +32,7 @@ export interface AppBase {
// @public (undocumented)
export interface ApplicationSetup {
register(app: App): void;
- registerMountContext(contextName: T, provider: IContextProvider): void;
+ registerMountContext(contextName: T, provider: IContextProvider): void;
}
// @public (undocumented)
@@ -44,7 +45,7 @@ export interface ApplicationStart {
path?: string;
state?: any;
}): void;
- registerMountContext(contextName: T, provider: IContextProvider): void;
+ registerMountContext(contextName: T, provider: IContextProvider): void;
}
// @public
@@ -213,7 +214,7 @@ export interface ChromeStart {
// @public
export interface ContextSetup {
- createContextContainer(): IContextContainer;
+ createContextContainer>(): IContextContainer;
}
// @internal (undocumented)
@@ -389,6 +390,15 @@ export interface FatalErrorsSetup {
get$: () => Rx.Observable;
}
+// @public
+export type HandlerContextType> = T extends HandlerFunction ? U : never;
+
+// @public
+export type HandlerFunction = (context: T, ...args: any[]) => any;
+
+// @public
+export type HandlerParameters> = T extends (context: any, ...args: infer U) => any ? U : never;
+
// @public (undocumented)
export type HttpBody = BodyInit | null | any;
@@ -551,16 +561,13 @@ export interface I18nStart {
}
// @public
-export interface IContextContainer {
- createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise;
- registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
+export interface IContextContainer> {
+ createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>;
+ registerContext>(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this;
}
// @public
-export type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn;
-
-// @public
-export type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName];
+export type IContextProvider, TContextName extends keyof HandlerContextType> = (context: Partial>, ...rest: HandlerParameters) => Promise[TContextName]> | HandlerContextType[TContextName];
// @public @deprecated
export interface LegacyCoreSetup extends CoreSetup {
@@ -752,7 +759,7 @@ export class SavedObjectsClient {
}[]) => Promise>;
create: (type: string, attributes: T, options?: SavedObjectsCreateOptions) => Promise>;
delete: (type: string, id: string) => Promise<{}>;
- find: (options: Pick) => Promise>;
+ find: (options: Pick) => Promise>;
get: (type: string, id: string) => Promise>;
update(type: string, id: string, attributes: T, { version, migrationVersion, references }?: SavedObjectsUpdateOptions): Promise>;
}
@@ -775,6 +782,8 @@ export interface SavedObjectsFindOptions extends SavedObjectsBaseOptions {
defaultSearchOperator?: 'AND' | 'OR';
fields?: string[];
// (undocumented)
+ filter?: string;
+ // (undocumented)
hasReference?: {
type: string;
id: string;
diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts
index dc13d001643a31..cf0300157aece3 100644
--- a/src/core/public/saved_objects/saved_objects_client.ts
+++ b/src/core/public/saved_objects/saved_objects_client.ts
@@ -297,6 +297,7 @@ export class SavedObjectsClient {
searchFields: 'search_fields',
sortField: 'sort_field',
type: 'type',
+ filter: 'filter',
};
const renamedQuery = renameKeys(renameMap, options);
diff --git a/src/core/server/bootstrap.ts b/src/core/server/bootstrap.ts
index 6a4bfc7c581df8..2dff4430b4dbef 100644
--- a/src/core/server/bootstrap.ts
+++ b/src/core/server/bootstrap.ts
@@ -70,6 +70,22 @@ export async function bootstrap({
const root = new Root(rawConfigService.getConfig$(), env, onRootShutdown);
+ process.on('SIGHUP', () => {
+ const cliLogger = root.logger.get('cli');
+ cliLogger.info('Reloading logging configuration due to SIGHUP.', { tags: ['config'] });
+
+ try {
+ rawConfigService.reloadConfig();
+ } catch (err) {
+ return shutdown(err);
+ }
+
+ cliLogger.info('Reloaded logging configuration due to SIGHUP.', { tags: ['config'] });
+ });
+
+ process.on('SIGINT', () => shutdown());
+ process.on('SIGTERM', () => shutdown());
+
function shutdown(reason?: Error) {
rawConfigService.stop();
return root.shutdown(reason);
@@ -87,22 +103,6 @@ export async function bootstrap({
cliLogger.info('Optimization done.');
await shutdown();
}
-
- process.on('SIGHUP', () => {
- const cliLogger = root.logger.get('cli');
- cliLogger.info('Reloading logging configuration due to SIGHUP.', { tags: ['config'] });
-
- try {
- rawConfigService.reloadConfig();
- } catch (err) {
- return shutdown(err);
- }
-
- cliLogger.info('Reloaded logging configuration due to SIGHUP.', { tags: ['config'] });
- });
-
- process.on('SIGINT', () => shutdown());
- process.on('SIGTERM', () => shutdown());
}
function onRootShutdown(reason?: any) {
diff --git a/src/core/server/config/config_service.mock.ts b/src/core/server/config/config_service.mock.ts
index b9c4fa91ae7028..e87869e92deebc 100644
--- a/src/core/server/config/config_service.mock.ts
+++ b/src/core/server/config/config_service.mock.ts
@@ -20,11 +20,13 @@
import { BehaviorSubject } from 'rxjs';
import { ObjectToConfigAdapter } from './object_to_config_adapter';
-import { ConfigService } from './config_service';
+import { IConfigService } from './config_service';
-type ConfigServiceContract = PublicMethodsOf;
-const createConfigServiceMock = () => {
- const mocked: jest.Mocked = {
+const createConfigServiceMock = ({
+ atPath = {},
+ getConfig$ = {},
+}: { atPath?: Record; getConfig$?: Record } = {}) => {
+ const mocked: jest.Mocked = {
atPath: jest.fn(),
getConfig$: jest.fn(),
optionalAtPath: jest.fn(),
@@ -33,8 +35,8 @@ const createConfigServiceMock = () => {
isEnabledAtPath: jest.fn(),
setSchema: jest.fn(),
};
- mocked.atPath.mockReturnValue(new BehaviorSubject({}));
- mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter({})));
+ mocked.atPath.mockReturnValue(new BehaviorSubject(atPath));
+ mocked.getConfig$.mockReturnValue(new BehaviorSubject(new ObjectToConfigAdapter(getConfig$)));
mocked.getUsedPaths.mockResolvedValue([]);
mocked.getUnusedPaths.mockResolvedValue([]);
mocked.isEnabledAtPath.mockResolvedValue(true);
diff --git a/src/core/server/config/config_service.ts b/src/core/server/config/config_service.ts
index fff19aa3af0f04..8d3cc733cf250c 100644
--- a/src/core/server/config/config_service.ts
+++ b/src/core/server/config/config_service.ts
@@ -26,6 +26,9 @@ import { Config, ConfigPath, Env } from '.';
import { Logger, LoggerFactory } from '../logging';
import { hasConfigPathIntersection } from './config';
+/** @internal */
+export type IConfigService = PublicMethodsOf;
+
/** @internal */
export class ConfigService {
private readonly log: Logger;
diff --git a/src/core/server/config/index.ts b/src/core/server/config/index.ts
index 257263069cabd8..d27462a86a9c8e 100644
--- a/src/core/server/config/index.ts
+++ b/src/core/server/config/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-export { ConfigService } from './config_service';
+export { ConfigService, IConfigService } from './config_service';
export { RawConfigService } from './raw_config_service';
export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './config';
export { ObjectToConfigAdapter } from './object_to_config_adapter';
diff --git a/src/core/server/context/context_service.ts b/src/core/server/context/context_service.ts
index 80935840c55360..1c5bd41a01f0f1 100644
--- a/src/core/server/context/context_service.ts
+++ b/src/core/server/context/context_service.ts
@@ -18,7 +18,7 @@
*/
import { PluginOpaqueId } from '../../server';
-import { IContextContainer, ContextContainer } from '../../utils/context';
+import { IContextContainer, ContextContainer, HandlerFunction } from '../../utils/context';
import { CoreContext } from '../core_context';
interface SetupDeps {
@@ -31,15 +31,8 @@ export class ContextService {
public setup({ pluginDependencies }: SetupDeps): ContextSetup {
return {
- createContextContainer: <
- TContext extends {},
- THandlerReturn,
- THandlerParameters extends any[] = []
- >() => {
- return new ContextContainer(
- pluginDependencies,
- this.core.coreId
- );
+ createContextContainer: >() => {
+ return new ContextContainer(pluginDependencies, this.core.coreId);
},
};
}
@@ -112,9 +105,5 @@ export interface ContextSetup {
/**
* Creates a new {@link IContextContainer} for a service owner.
*/
- createContextContainer<
- TContext extends {},
- THandlerReturn,
- THandlerParmaters extends any[] = []
- >(): IContextContainer;
+ createContextContainer>(): IContextContainer;
}
diff --git a/src/core/server/context/index.ts b/src/core/server/context/index.ts
index 28b2641b2a5a74..f22c4168d75448 100644
--- a/src/core/server/context/index.ts
+++ b/src/core/server/context/index.ts
@@ -18,4 +18,10 @@
*/
export { ContextService, ContextSetup } from './context_service';
-export { IContextContainer, IContextProvider, IContextHandler } from '../../utils/context';
+export {
+ IContextContainer,
+ IContextProvider,
+ HandlerFunction,
+ HandlerContextType,
+ HandlerParameters,
+} from '../../utils/context';
diff --git a/src/core/server/core_context.mock.ts b/src/core/server/core_context.mock.ts
new file mode 100644
index 00000000000000..e8c0a0a4830bfb
--- /dev/null
+++ b/src/core/server/core_context.mock.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { CoreContext } from './core_context';
+import { getEnvOptions } from './config/__mocks__/env';
+import { Env, IConfigService } from './config';
+import { loggingServiceMock } from './logging/logging_service.mock';
+import { configServiceMock } from './config/config_service.mock';
+import { ILoggingService } from './logging';
+
+function create({
+ env = Env.createDefault(getEnvOptions()),
+ logger = loggingServiceMock.create(),
+ configService = configServiceMock.create(),
+}: {
+ env?: Env;
+ logger?: jest.Mocked;
+ configService?: jest.Mocked;
+} = {}): CoreContext {
+ return { coreId: Symbol(), env, logger, configService };
+}
+
+export const mockCoreContext = {
+ create,
+};
diff --git a/src/core/server/core_context.ts b/src/core/server/core_context.ts
index 701f5a83a81c20..237fc2e6aafdce 100644
--- a/src/core/server/core_context.ts
+++ b/src/core/server/core_context.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { ConfigService, Env } from './config';
+import { IConfigService, Env } from './config';
import { LoggerFactory } from './logging';
/** @internal */
@@ -31,6 +31,6 @@ export type CoreId = symbol;
export interface CoreContext {
coreId: CoreId;
env: Env;
- configService: ConfigService;
+ configService: IConfigService;
logger: LoggerFactory;
}
diff --git a/src/core/server/elasticsearch/retry_call_cluster.test.ts b/src/core/server/elasticsearch/retry_call_cluster.test.ts
new file mode 100644
index 00000000000000..e2c6415a08c56d
--- /dev/null
+++ b/src/core/server/elasticsearch/retry_call_cluster.test.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 elasticsearch from 'elasticsearch';
+import { retryCallCluster } from './retry_call_cluster';
+
+describe('retryCallCluster', () => {
+ it('retries ES API calls that rejects with NoConnection errors', () => {
+ expect.assertions(1);
+ const callEsApi = jest.fn();
+ let i = 0;
+ callEsApi.mockImplementation(() => {
+ return i++ <= 2
+ ? Promise.reject(new elasticsearch.errors.NoConnections())
+ : Promise.resolve('success');
+ });
+ const retried = retryCallCluster(callEsApi);
+ return expect(retried('endpoint')).resolves.toMatchInlineSnapshot(`"success"`);
+ });
+
+ it('rejects when ES API calls reject with other errors', async () => {
+ expect.assertions(3);
+ const callEsApi = jest.fn();
+ let i = 0;
+ callEsApi.mockImplementation(() => {
+ i++;
+
+ return i === 1
+ ? Promise.reject(new Error('unknown error'))
+ : i === 2
+ ? Promise.resolve('success')
+ : i === 3 || i === 4
+ ? Promise.reject(new elasticsearch.errors.NoConnections())
+ : i === 5
+ ? Promise.reject(new Error('unknown error'))
+ : null;
+ });
+ const retried = retryCallCluster(callEsApi);
+ await expect(retried('endpoint')).rejects.toMatchInlineSnapshot(`[Error: unknown error]`);
+ await expect(retried('endpoint')).resolves.toMatchInlineSnapshot(`"success"`);
+ return expect(retried('endpoint')).rejects.toMatchInlineSnapshot(`[Error: unknown error]`);
+ });
+});
diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/retry_call_cluster.ts
new file mode 100644
index 00000000000000..4b74dffebbef9d
--- /dev/null
+++ b/src/core/server/elasticsearch/retry_call_cluster.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 { retryWhen, concatMap } from 'rxjs/operators';
+import { defer, throwError, iif, timer } from 'rxjs';
+import elasticsearch from 'elasticsearch';
+import { CallAPIOptions } from '.';
+
+/**
+ * Retries the provided Elasticsearch API call when a `NoConnections` error is
+ * encountered. The API call will be retried once a second, indefinitely, until
+ * a successful response or a different error is received.
+ *
+ * @param apiCaller
+ */
+
+// TODO: Replace with APICaller from './scoped_cluster_client' once #46668 is merged
+export function retryCallCluster(
+ apiCaller: (
+ endpoint: string,
+ clientParams: Record,
+ options?: CallAPIOptions
+ ) => Promise
+) {
+ return (endpoint: string, clientParams: Record = {}, options?: CallAPIOptions) => {
+ return defer(() => apiCaller(endpoint, clientParams, options))
+ .pipe(
+ retryWhen(errors =>
+ errors.pipe(
+ concatMap((error, i) =>
+ iif(
+ () => error instanceof elasticsearch.errors.NoConnections,
+ timer(1000),
+ throwError(error)
+ )
+ )
+ )
+ )
+ )
+ .toPromise();
+ };
+}
diff --git a/src/core/server/http/base_path_service.test.ts b/src/core/server/http/base_path_service.test.ts
index ffbbe158cb2d4d..01790b7c77e064 100644
--- a/src/core/server/http/base_path_service.test.ts
+++ b/src/core/server/http/base_path_service.test.ts
@@ -22,6 +22,18 @@ import { KibanaRequest } from './router';
import { httpServerMock } from './http_server.mocks';
describe('BasePath', () => {
+ describe('serverBasePath', () => {
+ it('defaults to an empty string', () => {
+ const basePath = new BasePath();
+ expect(basePath.serverBasePath).toBe('');
+ });
+
+ it('returns the server base path', () => {
+ const basePath = new BasePath('/server');
+ expect(basePath.serverBasePath).toBe('/server');
+ });
+ });
+
describe('#get()', () => {
it('returns base path associated with an incoming Legacy.Request request', () => {
const request = httpServerMock.createRawRequest();
diff --git a/src/core/server/http/base_path_service.ts b/src/core/server/http/base_path_service.ts
index 951463a2c9919f..916419cac212a1 100644
--- a/src/core/server/http/base_path_service.ts
+++ b/src/core/server/http/base_path_service.ts
@@ -20,18 +20,39 @@ import { ensureRawRequest, KibanaRequest, LegacyRequest } from './router';
import { modifyUrl } from '../../utils';
+/**
+ * Access or manipulate the Kibana base path
+ *
+ * @public
+ */
export class BasePath {
private readonly basePathCache = new WeakMap();
- constructor(private readonly serverBasePath?: string) {}
+ /**
+ * returns the server's basePath
+ *
+ * See {@link BasePath.get} for getting the basePath value for a specific request
+ */
+ public readonly serverBasePath: string;
+
+ /** @internal */
+ constructor(serverBasePath: string = '') {
+ this.serverBasePath = serverBasePath;
+ }
+ /**
+ * returns `basePath` value, specific for an incoming request.
+ */
public get = (request: KibanaRequest | LegacyRequest) => {
const requestScopePath = this.basePathCache.get(ensureRawRequest(request)) || '';
- const serverBasePath = this.serverBasePath || '';
- return `${serverBasePath}${requestScopePath}`;
+ return `${this.serverBasePath}${requestScopePath}`;
};
- // should work only for KibanaRequest as soon as spaces migrate to NP
+ /**
+ * sets `basePath` value, specific for an incoming request.
+ *
+ * @privateRemarks should work only for KibanaRequest as soon as spaces migrate to NP
+ */
public set = (request: KibanaRequest | LegacyRequest, requestSpecificBasePath: string) => {
const rawRequest = ensureRawRequest(request);
@@ -43,8 +64,11 @@ export class BasePath {
this.basePathCache.set(rawRequest, requestSpecificBasePath);
};
+ /**
+ * returns a new `basePath` value, prefixed with passed `url`.
+ */
public prepend = (path: string): string => {
- if (!this.serverBasePath) return path;
+ if (this.serverBasePath === '') return path;
return modifyUrl(path, parts => {
if (!parts.hostname && parts.pathname && parts.pathname.startsWith('/')) {
parts.pathname = `${this.serverBasePath}${parts.pathname}`;
@@ -52,8 +76,11 @@ export class BasePath {
});
};
+ /**
+ * returns a new `basePath` value, cleaned up from passed `url`.
+ */
public remove = (path: string): string => {
- if (!this.serverBasePath) {
+ if (this.serverBasePath === '') {
return path;
}
@@ -68,3 +95,11 @@ export class BasePath {
return path;
};
}
+
+/**
+ * Access or manipulate the Kibana base path
+ *
+ * {@link BasePath}
+ * @public
+ */
+export type IBasePath = Pick;
diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts
index cb6906379c4ef3..b56fef5f65c2a9 100644
--- a/src/core/server/http/http_server.ts
+++ b/src/core/server/http/http_server.ts
@@ -26,7 +26,7 @@ import { adoptToHapiAuthFormat, AuthenticationHandler } from './lifecycle/auth';
import { adoptToHapiOnPostAuthFormat, OnPostAuthHandler } from './lifecycle/on_post_auth';
import { adoptToHapiOnPreAuthFormat, OnPreAuthHandler } from './lifecycle/on_pre_auth';
-import { KibanaRequest, LegacyRequest, ResponseHeaders, IRouter } from './router';
+import { ResponseHeaders, IRouter } from './router';
import {
SessionStorageCookieOptions,
createCookieSessionStorageFactory,
@@ -34,7 +34,7 @@ import {
import { SessionStorageFactory } from './session_storage';
import { AuthStateStorage, GetAuthState, IsAuthenticated } from './auth_state_storage';
import { AuthHeadersStorage, GetAuthHeaders } from './auth_headers_storage';
-import { BasePath } from './base_path_service';
+import { BasePath, IBasePath } from './base_path_service';
/**
* Kibana HTTP Service provides own abstraction for work with HTTP stack.
@@ -148,24 +148,8 @@ export interface HttpServerSetup {
* @param handler {@link OnPostAuthHandler} - function to call.
*/
registerOnPostAuth: (handler: OnPostAuthHandler) => void;
- basePath: {
- /**
- * returns `basePath` value, specific for an incoming request.
- */
- get: (request: KibanaRequest | LegacyRequest) => string;
- /**
- * sets `basePath` value, specific for an incoming request.
- */
- set: (request: KibanaRequest | LegacyRequest, basePath: string) => void;
- /**
- * returns a new `basePath` value, prefixed with passed `url`.
- */
- prepend: (url: string) => string;
- /**
- * returns a new `basePath` value, cleaned up from passed `url`.
- */
- remove: (url: string) => string;
- };
+ /** {@link BasePath} */
+ basePath: IBasePath;
auth: {
get: GetAuthState;
isAuthenticated: IsAuthenticated;
diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts
index c5f920dcb360e1..c0658ae8d1e5c4 100644
--- a/src/core/server/http/http_service.mock.ts
+++ b/src/core/server/http/http_service.mock.ts
@@ -30,6 +30,7 @@ type ServiceSetupMockType = jest.Mocked & {
};
const createBasePathMock = (): jest.Mocked => ({
+ serverBasePath: '/mock-server-basepath',
get: jest.fn(),
set: jest.fn(),
prepend: jest.fn(),
diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts
index 5814991a2dd27c..0ac5ad92763537 100644
--- a/src/core/server/http/http_service.ts
+++ b/src/core/server/http/http_service.ts
@@ -83,8 +83,8 @@ export type HttpServiceSetup = Omit & {
registerRouteHandlerContext: (
pluginOpaqueId: PluginOpaqueId,
contextName: T,
- provider: RequestHandlerContextProvider