mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Change ContextContainer to lazily initialize providers (#129896)
* Change ContextContainer to lazily initialize providers * Introduce CustomRequestHandlerContext, start adapting usages * adapt IContextProvider's return type * start fixing violations * fixing violations - 2 * adapt home routes * fix remaining core violation * fix violations on core tests * fixing more violations * fixing more violations * update generated doc... * fix more violations * adapt remaining RequestHandlerContext * fix more violations * fix non-async method * more fixes * fix another await in non async method * add yet another missing async * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * add yet yet another missing async * update fleet's endpoints * fix telemetry endpoints * fix event_log endpoints * fix some security unit tests * adapt canvas routes * adapt alerting routes * adapt more so_tagging routes * fix data_enhanced routes * fix license_management routes * fix file_upload routes * fix index_management routes * fix lists routes * fix snapshot_restore routes * fix rule_registry routes * fix ingest_pipelines routes * fix remote_clusters routes * fix index_lifecycle_management routes * improve and fix the lazy implementation * fix triggers_actions_ui endpoints * start fixing unit tests * fix cases routes * fix transform routes * fix upgrade_assistant routes * fix uptime route wrapper * fix uptime route wrapper bis * update osquery routes * update cross_cluster_replication routes * fix some ML routes / wrappers * adapt maps routes * adapt rollup routes * fix some canvas unit tests * fix more canvas unit tests * fix observability wrapper * fix (?) infra type hell * start fixing monitoring * fix a few test plugins * woups * fix yet more violations * fixing UA tests * fix logstash handlers * fix fleet unit tests * lint? * one more batch * update security_solution endpoints * start fixing security_solution mocks * start fixing security_solution tests * fix more security_solution tests * fix more security_solution tests * just one more * fix last (?) security_solution tests * fix timelion javascript file * fix more test plugins * fix transforms context type * fix ml context type * fix context tests * fix securitySolution withEndpointAuthz tests * fix features unit tests * fix actions unit tests * fix imports * fix duplicate import * fix some merge problems * fix new usage * fix new test * introduces context.resolve * down the rabbit hole again * start fixing test type failures * more test type failures fixes * move import comment back to correct place * more test type failures fixes, bis * use context.resolve for security solution rules routes * fix new violations due to master merge * remove comment Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
706d9268ef
commit
a02c00b8a3
699 changed files with 4508 additions and 3170 deletions
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md) > [deprecations](./kibana-plugin-core-server.corerequesthandlercontext.deprecations.md)
|
||||
|
||||
## CoreRequestHandlerContext.deprecations property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md) > [elasticsearch](./kibana-plugin-core-server.corerequesthandlercontext.elasticsearch.md)
|
||||
|
||||
## CoreRequestHandlerContext.elasticsearch property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md)
|
||||
|
||||
## CoreRequestHandlerContext interface
|
||||
|
||||
The `core` context provided to route handler.
|
||||
|
||||
Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface CoreRequestHandlerContext
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [deprecations](./kibana-plugin-core-server.corerequesthandlercontext.deprecations.md) | { client: DeprecationsClient; } | |
|
||||
| [elasticsearch](./kibana-plugin-core-server.corerequesthandlercontext.elasticsearch.md) | { client: IScopedClusterClient; } | |
|
||||
| [savedObjects](./kibana-plugin-core-server.corerequesthandlercontext.savedobjects.md) | { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; } | |
|
||||
| [uiSettings](./kibana-plugin-core-server.corerequesthandlercontext.uisettings.md) | { client: IUiSettingsClient; } | |
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md) > [savedObjects](./kibana-plugin-core-server.corerequesthandlercontext.savedobjects.md)
|
||||
|
||||
## CoreRequestHandlerContext.savedObjects property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md) > [uiSettings](./kibana-plugin-core-server.corerequesthandlercontext.uisettings.md)
|
||||
|
||||
## CoreRequestHandlerContext.uiSettings property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,14 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CustomRequestHandlerContext](./kibana-plugin-core-server.customrequesthandlercontext.md)
|
||||
|
||||
## CustomRequestHandlerContext type
|
||||
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type CustomRequestHandlerContext<T> = RequestHandlerContext & {
|
||||
[Key in keyof T]: T[Key] extends Promise<unknown> ? T[Key] : Promise<T[Key]>;
|
||||
};
|
||||
```
|
|
@ -87,5 +87,5 @@ async (context, request, response) => {
|
|||
| [registerOnPreAuth](./kibana-plugin-core-server.httpservicesetup.registeronpreauth.md) | (handler: OnPreAuthHandler) => void | To define custom logic to perform for incoming requests before the Auth interceptor performs a check that user has access to requested resources. |
|
||||
| [registerOnPreResponse](./kibana-plugin-core-server.httpservicesetup.registeronpreresponse.md) | (handler: OnPreResponseHandler) => void | To define custom logic to perform for the server response. |
|
||||
| [registerOnPreRouting](./kibana-plugin-core-server.httpservicesetup.registeronprerouting.md) | (handler: OnPreRoutingHandler) => void | To define custom logic to perform for incoming requests before server performs a route lookup. |
|
||||
| [registerRouteHandlerContext](./kibana-plugin-core-server.httpservicesetup.registerroutehandlercontext.md) | <Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer | Register a context provider for a route handler. |
|
||||
| [registerRouteHandlerContext](./kibana-plugin-core-server.httpservicesetup.registerroutehandlercontext.md) | <Context extends RequestHandlerContext, ContextName extends keyof Omit<Context, 'resolve'>>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer | Register a context provider for a route handler. |
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Register a context provider for a route handler.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Omit<Context, 'resolve'>>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
|
|
@ -9,7 +9,7 @@ A function that returns a context value for a specific key of given context type
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
export declare type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => MaybePromise<Awaited<Context[ContextName]>>;
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
|
|
@ -60,6 +60,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [ConfigDeprecationDetails](./kibana-plugin-core-server.configdeprecationdetails.md) | |
|
||||
| [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. |
|
||||
| [CorePreboot](./kibana-plugin-core-server.corepreboot.md) | Context passed to the <code>setup</code> method of <code>preboot</code> plugins. |
|
||||
| [CoreRequestHandlerContext](./kibana-plugin-core-server.corerequesthandlercontext.md) | The <code>core</code> context provided to route handler.<!-- -->Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request |
|
||||
| [CoreSetup](./kibana-plugin-core-server.coresetup.md) | Context passed to the <code>setup</code> method of <code>standard</code> plugins. |
|
||||
| [CoreStart](./kibana-plugin-core-server.corestart.md) | Context passed to the plugins <code>start</code> method. |
|
||||
| [CoreStatus](./kibana-plugin-core-server.corestatus.md) | Status of core services. |
|
||||
|
@ -133,7 +134,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [PrebootPlugin](./kibana-plugin-core-server.prebootplugin.md) | The interface that should be returned by a <code>PluginInitializer</code> for a <code>preboot</code> plugin. |
|
||||
| [PrebootServicePreboot](./kibana-plugin-core-server.prebootservicepreboot.md) | Kibana Preboot Service allows to control the boot flow of Kibana. Preboot plugins can use it to hold the boot until certain condition is met. |
|
||||
| [RegisterDeprecationsConfig](./kibana-plugin-core-server.registerdeprecationsconfig.md) | |
|
||||
| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.<!-- -->Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request |
|
||||
| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Base context passed to a route handler. |
|
||||
| [RequestHandlerContextBase](./kibana-plugin-core-server.requesthandlercontextbase.md) | \* |
|
||||
| [ResolveCapabilitiesOptions](./kibana-plugin-core-server.resolvecapabilitiesoptions.md) | Defines a set of additional options for the <code>resolveCapabilities</code> method of [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md)<!-- -->. |
|
||||
| [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. |
|
||||
| [RouteConfigOptions](./kibana-plugin-core-server.routeconfigoptions.md) | Additional route options. |
|
||||
|
@ -262,6 +264,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [AuthResult](./kibana-plugin-core-server.authresult.md) | |
|
||||
| [CapabilitiesProvider](./kibana-plugin-core-server.capabilitiesprovider.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) |
|
||||
| [CapabilitiesSwitcher](./kibana-plugin-core-server.capabilitiesswitcher.md) | See [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) |
|
||||
| [CustomRequestHandlerContext](./kibana-plugin-core-server.customrequesthandlercontext.md) | |
|
||||
| [DeprecationsDetails](./kibana-plugin-core-server.deprecationsdetails.md) | |
|
||||
| [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. |
|
||||
| [DocLinksServiceStart](./kibana-plugin-core-server.doclinksservicestart.md) | |
|
||||
|
|
|
@ -7,22 +7,5 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
core: {
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
};
|
||||
core: Promise<CoreRequestHandlerContext>;
|
||||
```
|
||||
|
|
|
@ -4,19 +4,18 @@
|
|||
|
||||
## RequestHandlerContext interface
|
||||
|
||||
Plugin specific context passed to a route handler.
|
||||
|
||||
Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.client](./kibana-plugin-core-server.iscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request
|
||||
Base context passed to a route handler.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface RequestHandlerContext
|
||||
export interface RequestHandlerContext extends RequestHandlerContextBase
|
||||
```
|
||||
<b>Extends:</b> RequestHandlerContextBase
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; }; uiSettings: { client: IUiSettingsClient; }; deprecations: { client: DeprecationsClient; }; } | |
|
||||
| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | Promise<CoreRequestHandlerContext> | |
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RequestHandlerContextBase](./kibana-plugin-core-server.requesthandlercontextbase.md)
|
||||
|
||||
## RequestHandlerContextBase interface
|
||||
|
||||
\*
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface RequestHandlerContextBase
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [resolve](./kibana-plugin-core-server.requesthandlercontextbase.resolve.md) | <T extends keyof Omit<this, 'resolve'>>(parts: T\[\]) => Promise<AwaitedProperties<Pick<this, T>>> | Await all the specified context parts and return them. |
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RequestHandlerContextBase](./kibana-plugin-core-server.requesthandlercontextbase.md) > [resolve](./kibana-plugin-core-server.requesthandlercontextbase.resolve.md)
|
||||
|
||||
## RequestHandlerContextBase.resolve property
|
||||
|
||||
Await all the specified context parts and return them.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
resolve: <T extends keyof Omit<this, 'resolve'>>(parts: T[]) => Promise<AwaitedProperties<Pick<this, T>>>;
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
const resolved = await context.resolve(['core', 'pluginA']);
|
||||
const esClient = resolved.core.elasticsearch.client;
|
||||
const pluginAService = resolved.pluginA.someService;
|
||||
```
|
||||
|
|
@ -14,7 +14,7 @@ export const registerRoutes = ({ router, log, screenshotMode }: RouteDependencie
|
|||
{ path: `${BASE_API_ROUTE}/check_is_screenshot`, validate: false },
|
||||
async (ctx, req, res) => {
|
||||
log.info(`Reading screenshot mode from a request: ${screenshotMode.isScreenshotMode(req)}`);
|
||||
log.info(`Reading is screenshot mode from ctx: ${ctx.screenshotMode.isScreenshot}`);
|
||||
log.info(`Reading is screenshot mode from ctx: ${(await ctx.screenshotMode).isScreenshot}`);
|
||||
return res.ok();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -33,8 +33,9 @@ export function registerServerSearchRoute(router: IRouter<DataRequestHandlerCont
|
|||
const abortSignal = getRequestAbortedSignal(request.events.aborted$);
|
||||
|
||||
try {
|
||||
const res = await context
|
||||
.search!.search(
|
||||
const search = await context.search;
|
||||
const res = await search
|
||||
.search(
|
||||
{
|
||||
params: {
|
||||
index,
|
||||
|
|
|
@ -26,6 +26,13 @@ export type MaybePromise<T> = T | Promise<T>;
|
|||
*/
|
||||
export type ShallowPromise<T> = T extends Promise<infer U> ? Promise<U> : Promise<T>;
|
||||
|
||||
/**
|
||||
* Unwrap all promise attributes of the given type
|
||||
*/
|
||||
export type AwaitedProperties<T> = {
|
||||
[K in keyof T]: Awaited<T[K]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Minimal interface for an object resembling an `Observable`.
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { ContextContainer } from './context';
|
||||
import { PluginOpaqueId } from '../..';
|
||||
import type { PluginOpaqueId, RequestHandlerContextBase } from '../..';
|
||||
import { httpServerMock } from '../../http/http_server.mocks';
|
||||
|
||||
const pluginA = Symbol('pluginA');
|
||||
|
@ -22,7 +22,7 @@ const plugins: ReadonlyMap<PluginOpaqueId, PluginOpaqueId[]> = new Map([
|
|||
]);
|
||||
const coreId = Symbol();
|
||||
|
||||
interface MyContext {
|
||||
interface MyContext extends RequestHandlerContextBase {
|
||||
core: any;
|
||||
core1: string;
|
||||
core2: number;
|
||||
|
@ -32,31 +32,47 @@ interface MyContext {
|
|||
ctxFromD: object;
|
||||
}
|
||||
|
||||
describe('ContextContainer', () => {
|
||||
it('does not allow the same context to be registered twice', () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
coreId,
|
||||
'ctxFromA',
|
||||
() => 'aString'
|
||||
);
|
||||
type TestContext<T> = T & RequestHandlerContextBase;
|
||||
|
||||
expect(() =>
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
describe('ContextContainer', () => {
|
||||
describe('registerContext', () => {
|
||||
it('throws an error if the same context is registered twice', () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
coreId,
|
||||
'ctxFromA',
|
||||
() => 'aString'
|
||||
)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Context provider for ctxFromA has already been registered."`
|
||||
);
|
||||
});
|
||||
);
|
||||
|
||||
expect(() =>
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
coreId,
|
||||
'ctxFromA',
|
||||
() => 'aString'
|
||||
)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Context provider for ctxFromA has already been registered."`
|
||||
);
|
||||
});
|
||||
|
||||
it('throws an error if a `resolve` context is registered', () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
expect(() =>
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
coreId,
|
||||
// @ts-expect-error protected with typing too
|
||||
'resolve',
|
||||
() => 'aString'
|
||||
)
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Cannot register a provider for resolve, it is a reserved keyword."`
|
||||
);
|
||||
});
|
||||
|
||||
describe('registerContext', () => {
|
||||
it('throws error if called with an unknown symbol', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
await expect(() =>
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
Symbol('unknown'),
|
||||
'ctxFromA',
|
||||
jest.fn()
|
||||
|
@ -69,7 +85,7 @@ describe('ContextContainer', () => {
|
|||
it('reports a TS error if returned contract does not satisfy the Context interface', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
await expect(() =>
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
// @ts-expect-error expected string, returned number
|
||||
|
@ -82,7 +98,7 @@ describe('ContextContainer', () => {
|
|||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
await expect(() =>
|
||||
// @ts-expect-error expects ctxFromB, but given ctxFromC
|
||||
contextContainer.registerContext<{ ctxFromB: string; core: any }, 'ctxFromC'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromB: string; core: any }>, 'ctxFromC'>(
|
||||
pluginB,
|
||||
'ctxFromC',
|
||||
async () => 1
|
||||
|
@ -92,39 +108,216 @@ describe('ContextContainer', () => {
|
|||
});
|
||||
|
||||
describe('context building', () => {
|
||||
it('resolves dependencies', async () => {
|
||||
const resolveAllContexts = async (ctx: Record<string, any>): Promise<unknown> => {
|
||||
const resolved = {} as Record<string, any>;
|
||||
for (const key of Object.getOwnPropertyNames(ctx)) {
|
||||
if (key === 'resolve') {
|
||||
continue;
|
||||
}
|
||||
resolved[key] = await ctx[key];
|
||||
}
|
||||
return resolved;
|
||||
};
|
||||
|
||||
it('lazily loads the providers when accessed', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
expect.assertions(8);
|
||||
contextContainer.registerContext<{ core1: string; core: any }, 'core1'>(
|
||||
|
||||
const core1provider = jest.fn().mockReturnValue('core1');
|
||||
const ctxFromAProvider = jest.fn().mockReturnValue('ctxFromA');
|
||||
|
||||
contextContainer.registerContext<TestContext<{ core1: string; core: any }>, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
(context) => {
|
||||
expect(context).toEqual({});
|
||||
core1provider
|
||||
);
|
||||
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
ctxFromAProvider
|
||||
);
|
||||
|
||||
let context: any;
|
||||
const rawHandler1 = jest.fn((ctx) => {
|
||||
context = ctx;
|
||||
return 'rawHandler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
|
||||
expect(core1provider).not.toHaveBeenCalled();
|
||||
expect(ctxFromAProvider).not.toHaveBeenCalled();
|
||||
|
||||
await context!.core1;
|
||||
|
||||
expect(core1provider).toHaveBeenCalledTimes(1);
|
||||
expect(ctxFromAProvider).not.toHaveBeenCalled();
|
||||
|
||||
await context!.ctxFromA;
|
||||
|
||||
expect(core1provider).toHaveBeenCalledTimes(1);
|
||||
expect(ctxFromAProvider).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it(`does not eagerly loads a provider's dependencies`, async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const core1provider = jest.fn().mockReturnValue('core1');
|
||||
const ctxFromAProvider = jest.fn().mockReturnValue('ctxFromA');
|
||||
|
||||
contextContainer.registerContext<TestContext<{ core1: string; core: any }>, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
core1provider
|
||||
);
|
||||
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
ctxFromAProvider
|
||||
);
|
||||
|
||||
let context: any;
|
||||
const rawHandler1 = jest.fn((ctx) => {
|
||||
context = ctx;
|
||||
return 'rawHandler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
|
||||
expect(core1provider).not.toHaveBeenCalled();
|
||||
expect(ctxFromAProvider).not.toHaveBeenCalled();
|
||||
|
||||
await context!.ctxFromA;
|
||||
|
||||
expect(core1provider).not.toHaveBeenCalled();
|
||||
expect(ctxFromAProvider).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it(`allows to load a dependency from a provider`, async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const core1provider = jest.fn().mockReturnValue('core1');
|
||||
const ctxFromAProvider = jest.fn().mockImplementation(async (ctx: any) => {
|
||||
const core1 = await ctx.core1;
|
||||
return `${core1}-ctxFromA`;
|
||||
});
|
||||
|
||||
contextContainer.registerContext<TestContext<{ core1: string; core: any }>, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
core1provider
|
||||
);
|
||||
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
ctxFromAProvider
|
||||
);
|
||||
|
||||
let context: any;
|
||||
const rawHandler1 = jest.fn((ctx) => {
|
||||
context = ctx;
|
||||
return 'rawHandler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
|
||||
expect(core1provider).not.toHaveBeenCalled();
|
||||
expect(ctxFromAProvider).not.toHaveBeenCalled();
|
||||
|
||||
const contextValue = await context!.ctxFromA;
|
||||
|
||||
expect(contextValue).toEqual('core1-ctxFromA');
|
||||
expect(core1provider).toHaveBeenCalledTimes(1);
|
||||
expect(ctxFromAProvider).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it(`only calls a provider once and caches the returned value`, async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const core1provider = jest.fn().mockReturnValue('core1');
|
||||
const ctxFromAProvider = jest.fn().mockImplementation(async (ctx: any) => {
|
||||
const core1 = await ctx.core1;
|
||||
return `${core1}-ctxFromA`;
|
||||
});
|
||||
|
||||
contextContainer.registerContext<TestContext<{ core1: string; core: any }>, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
core1provider
|
||||
);
|
||||
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
ctxFromAProvider
|
||||
);
|
||||
|
||||
let context: any;
|
||||
const rawHandler1 = jest.fn((ctx) => {
|
||||
context = ctx;
|
||||
return 'rawHandler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
|
||||
expect(core1provider).not.toHaveBeenCalled();
|
||||
expect(ctxFromAProvider).not.toHaveBeenCalled();
|
||||
|
||||
await context!.core1;
|
||||
await context!.ctxFromA;
|
||||
await context!.core1;
|
||||
|
||||
expect(core1provider).toHaveBeenCalledTimes(1);
|
||||
expect(ctxFromAProvider).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('resolves dependencies', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
expect.assertions(10);
|
||||
contextContainer.registerContext<TestContext<{ core1: string; core: any }>, 'core1'>(
|
||||
coreId,
|
||||
'core1',
|
||||
async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({});
|
||||
return 'core';
|
||||
}
|
||||
);
|
||||
|
||||
contextContainer.registerContext<{ ctxFromA: string; core: any }, 'ctxFromA'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromA: string; core: any }>, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({ core1: 'core' });
|
||||
return 'aString';
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromB: number; core: any }, 'ctxFromB'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromB: number; core: any }>, 'ctxFromB'>(
|
||||
pluginB,
|
||||
'ctxFromB',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core', ctxFromA: 'aString' });
|
||||
async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({ core1: 'core', ctxFromA: 'aString' });
|
||||
return 299;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromC: boolean; core: any }, 'ctxFromC'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromC: boolean; core: any }>, 'ctxFromC'>(
|
||||
pluginC,
|
||||
'ctxFromC',
|
||||
(context) => {
|
||||
expect(context).toEqual({
|
||||
async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
|
@ -132,19 +325,34 @@ describe('ContextContainer', () => {
|
|||
return false;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<{ ctxFromD: {}; core: any }, 'ctxFromD'>(
|
||||
contextContainer.registerContext<TestContext<{ ctxFromD: {}; core: any }>, 'ctxFromD'>(
|
||||
pluginD,
|
||||
'ctxFromD',
|
||||
(context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({ core1: 'core' });
|
||||
return {};
|
||||
}
|
||||
);
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
ctxFromC: false,
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const rawHandler2 = jest.fn(() => 'handler2' as any);
|
||||
const rawHandler2 = jest.fn(async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromD: {},
|
||||
});
|
||||
return 'handler2' as any;
|
||||
});
|
||||
|
||||
const handler2 = contextContainer.createHandler(pluginD, rawHandler2);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
|
@ -154,41 +362,25 @@ describe('ContextContainer', () => {
|
|||
await handler2(request, response);
|
||||
|
||||
// Should have context from pluginC, its deps, and core
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
ctxFromC: false,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
|
||||
// Should have context from pluginD, and core
|
||||
expect(rawHandler2).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromD: {},
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
expect(rawHandler2).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
|
||||
it('exposes all core context to all providers regardless of registration order', async () => {
|
||||
expect.assertions(4);
|
||||
expect.assertions(5);
|
||||
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
contextContainer
|
||||
.registerContext<MyContext, 'ctxFromA'>(pluginA, 'ctxFromA', (context) => {
|
||||
expect(context).toEqual({ core1: 'core', core2: 101 });
|
||||
return `aString ${context.core1} ${context.core2}`;
|
||||
.registerContext<MyContext, 'ctxFromA'>(pluginA, 'ctxFromA', async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({ core1: 'core', core2: 101 });
|
||||
return `aString ${await context.core1} ${await context.core2}`;
|
||||
})
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', () => 'core')
|
||||
.registerContext<MyContext, 'core2'>(coreId, 'core2', () => 101)
|
||||
.registerContext<MyContext, 'ctxFromB'>(pluginB, 'ctxFromB', (context) => {
|
||||
expect(context).toEqual({
|
||||
.registerContext<MyContext, 'ctxFromB'>(pluginB, 'ctxFromB', async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
|
@ -196,40 +388,45 @@ describe('ContextContainer', () => {
|
|||
return 277;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
ctxFromB: 277,
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginB, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
ctxFromA: 'aString core 101',
|
||||
ctxFromB: 277,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
|
||||
it('exposes all core context to core providers', async () => {
|
||||
expect.assertions(4);
|
||||
expect.assertions(5);
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
contextContainer
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', (context) => {
|
||||
expect(context).toEqual({});
|
||||
.registerContext<MyContext, 'core1'>(coreId, 'core1', async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({});
|
||||
return 'core';
|
||||
})
|
||||
.registerContext<MyContext, 'core2'>(coreId, 'core2', (context) => {
|
||||
expect(context).toEqual({ core1: 'core' });
|
||||
.registerContext<MyContext, 'core2'>(coreId, 'core2', async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({ core1: 'core' });
|
||||
return 101;
|
||||
});
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginA, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
|
@ -237,14 +434,7 @@ describe('ContextContainer', () => {
|
|||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
// If no context is registered for pluginA, only core contexts should be exposed
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
core2: 101,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
|
||||
it('does not expose plugin contexts to core handler', async () => {
|
||||
|
@ -254,24 +444,24 @@ describe('ContextContainer', () => {
|
|||
.registerContext<MyContext, 'core1'>(coreId, 'core1', (context) => 'core')
|
||||
.registerContext<MyContext, 'ctxFromA'>(pluginA, 'ctxFromA', (context) => 'aString');
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
// pluginA context should not be present in a core handler
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(coreId, rawHandler1);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
// pluginA context should not be present in a core handler
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
|
||||
it('passes additional arguments to providers', async () => {
|
||||
expect.assertions(6);
|
||||
expect.assertions(7);
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
|
@ -292,19 +482,102 @@ describe('ContextContainer', () => {
|
|||
}
|
||||
);
|
||||
|
||||
const rawHandler1 = jest.fn(() => 'handler1' as any);
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
expect(await resolveAllContexts(context)).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromB: 77,
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginD, rawHandler1);
|
||||
|
||||
expect(await handler1(request, response)).toEqual('handler1');
|
||||
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{
|
||||
core1: 'core',
|
||||
ctxFromB: 77,
|
||||
},
|
||||
request,
|
||||
response
|
||||
);
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
|
||||
describe('#resolve', () => {
|
||||
it('resolves dependencies', async () => {
|
||||
const contextContainer = new ContextContainer(plugins, coreId);
|
||||
expect.assertions(10);
|
||||
contextContainer.registerContext<MyContext, 'core1'>(coreId, 'core1', async (context) => {
|
||||
expect(await context.resolve([])).toEqual({});
|
||||
return 'core';
|
||||
});
|
||||
|
||||
contextContainer.registerContext<MyContext, 'ctxFromA'>(
|
||||
pluginA,
|
||||
'ctxFromA',
|
||||
async (context) => {
|
||||
expect(await context.resolve(['core1'])).toEqual({ core1: 'core' });
|
||||
return 'aString';
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<MyContext, 'ctxFromB'>(
|
||||
pluginB,
|
||||
'ctxFromB',
|
||||
async (context) => {
|
||||
expect(await context.resolve(['core1', 'ctxFromA'])).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
});
|
||||
return 299;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<MyContext, 'ctxFromC'>(
|
||||
pluginC,
|
||||
'ctxFromC',
|
||||
async (context) => {
|
||||
expect(await context.resolve(['core1', 'ctxFromA', 'ctxFromB'])).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
);
|
||||
contextContainer.registerContext<MyContext, 'ctxFromD'>(
|
||||
pluginD,
|
||||
'ctxFromD',
|
||||
async (context) => {
|
||||
expect(await context.resolve(['core1'])).toEqual({ core1: 'core' });
|
||||
return {};
|
||||
}
|
||||
);
|
||||
|
||||
const rawHandler1 = jest.fn(async (context) => {
|
||||
expect(await context.resolve(['core1', 'ctxFromA', 'ctxFromB', 'ctxFromC'])).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromA: 'aString',
|
||||
ctxFromB: 299,
|
||||
ctxFromC: false,
|
||||
});
|
||||
return 'handler1' as any;
|
||||
});
|
||||
const handler1 = contextContainer.createHandler(pluginC, rawHandler1);
|
||||
|
||||
const rawHandler2 = jest.fn(async (context) => {
|
||||
expect(await context.resolve(['core1', 'ctxFromD'])).toEqual({
|
||||
core1: 'core',
|
||||
ctxFromD: {},
|
||||
});
|
||||
return 'handler2' as any;
|
||||
});
|
||||
|
||||
const handler2 = contextContainer.createHandler(pluginD, rawHandler2);
|
||||
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
|
||||
await handler1(request, response);
|
||||
await handler2(request, response);
|
||||
|
||||
// Should have context from pluginC, its deps, and core
|
||||
expect(rawHandler1).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
|
||||
// Should have context from pluginD, and core
|
||||
expect(rawHandler2).toHaveBeenCalledWith(expect.any(Object), request, response);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -337,7 +610,11 @@ describe('ContextContainer', () => {
|
|||
const request = httpServerMock.createKibanaRequest();
|
||||
const response = httpServerMock.createResponseFactory();
|
||||
await handler1(request, response);
|
||||
expect(rawHandler1).toHaveBeenCalledWith({}, request, response);
|
||||
expect(rawHandler1).toHaveBeenCalledWith(
|
||||
{ resolve: expect.any(Function) },
|
||||
request,
|
||||
response
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
*/
|
||||
|
||||
import { flatten } from 'lodash';
|
||||
import { ShallowPromise } from '@kbn/utility-types';
|
||||
import { pick } from 'lodash';
|
||||
import { ShallowPromise, MaybePromise } from '@kbn/utility-types';
|
||||
import type { CoreId, PluginOpaqueId, RequestHandler, RequestHandlerContext } from '../..';
|
||||
|
||||
/**
|
||||
|
@ -31,7 +30,7 @@ export type IContextProvider<
|
|||
// context.core will always be available, but plugin contexts are typed as optional
|
||||
context: Omit<Context, ContextName>,
|
||||
...rest: HandlerParameters<RequestHandler>
|
||||
) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
) => MaybePromise<Awaited<Context[ContextName]>>;
|
||||
|
||||
/**
|
||||
* A function that accepts a context object and an optional number of additional arguments. Used for the generic types
|
||||
|
@ -202,6 +201,9 @@ export class ContextContainer implements IContextContainer {
|
|||
provider: IContextProvider<Context, ContextName>
|
||||
): this => {
|
||||
const contextName = name as string;
|
||||
if (contextName === 'resolve') {
|
||||
throw new Error(`Cannot register a provider for ${contextName}, it is a reserved keyword.`);
|
||||
}
|
||||
if (this.contextProviders.has(contextName)) {
|
||||
throw new Error(`Context provider for ${contextName} has already been registered.`);
|
||||
}
|
||||
|
@ -224,36 +226,51 @@ export class ContextContainer implements IContextContainer {
|
|||
}
|
||||
|
||||
return (async (...args: HandlerParameters<RequestHandler>) => {
|
||||
const context = await this.buildContext(source, ...args);
|
||||
const context = this.buildContext(source, ...args);
|
||||
return handler(context, ...args);
|
||||
}) as (
|
||||
...args: HandlerParameters<RequestHandler>
|
||||
) => ShallowPromise<ReturnType<RequestHandler>>;
|
||||
};
|
||||
|
||||
private async buildContext(
|
||||
private buildContext(
|
||||
source: symbol,
|
||||
...contextArgs: HandlerParameters<RequestHandler>
|
||||
): Promise<HandlerContextType<RequestHandler>> {
|
||||
): HandlerContextType<RequestHandler> {
|
||||
const contextsToBuild = new Set(this.getContextNamesForSource(source));
|
||||
const builtContextPromises: Record<string, Promise<unknown>> = {};
|
||||
|
||||
const builtContext = {} as HandlerContextType<RequestHandler>;
|
||||
(builtContext as unknown as RequestHandlerContext).resolve = async (keys) => {
|
||||
const resolved = await Promise.all(
|
||||
keys.map(async (key) => {
|
||||
return [key, await builtContext[key]];
|
||||
})
|
||||
);
|
||||
return Object.fromEntries(resolved);
|
||||
};
|
||||
|
||||
return [...this.contextProviders]
|
||||
.sort(sortByCoreFirst(this.coreId))
|
||||
.filter(([contextName]) => contextsToBuild.has(contextName))
|
||||
.reduce(async (contextPromise, [contextName, { provider, source: providerSource }]) => {
|
||||
const resolvedContext = await contextPromise;
|
||||
.reduce((contextAccessors, [contextName, { provider, source: providerSource }]) => {
|
||||
const exposedContext = createExposedContext({
|
||||
currentContextName: contextName,
|
||||
exposedContextNames: [...this.getContextNamesForSource(providerSource)],
|
||||
contextAccessors,
|
||||
});
|
||||
Object.defineProperty(contextAccessors, contextName, {
|
||||
get: async () => {
|
||||
const contextKey = contextName as keyof HandlerContextType<RequestHandler>;
|
||||
if (!builtContextPromises[contextKey]) {
|
||||
builtContextPromises[contextKey] = provider(exposedContext, ...contextArgs);
|
||||
}
|
||||
return await builtContextPromises[contextKey];
|
||||
},
|
||||
});
|
||||
|
||||
// For the next provider, only expose the context available based on the dependencies of the plugin that
|
||||
// registered that provider.
|
||||
const exposedContext = pick(resolvedContext, [
|
||||
...this.getContextNamesForSource(providerSource),
|
||||
]);
|
||||
|
||||
return {
|
||||
...resolvedContext,
|
||||
[contextName]: await provider(exposedContext, ...contextArgs),
|
||||
};
|
||||
}, Promise.resolve({}) as Promise<HandlerContextType<RequestHandler>>);
|
||||
return contextAccessors;
|
||||
}, builtContext);
|
||||
}
|
||||
|
||||
private getContextNamesForSource(source: symbol): ReadonlySet<string> {
|
||||
|
@ -299,3 +316,28 @@ const sortByCoreFirst =
|
|||
return rightProvider.source === coreId ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
const createExposedContext = ({
|
||||
currentContextName,
|
||||
exposedContextNames,
|
||||
contextAccessors,
|
||||
}: {
|
||||
currentContextName: string;
|
||||
exposedContextNames: string[];
|
||||
contextAccessors: Partial<HandlerContextType<RequestHandler>>;
|
||||
}) => {
|
||||
const exposedContext: Partial<HandlerContextType<RequestHandler>> = {};
|
||||
exposedContext.resolve = contextAccessors.resolve;
|
||||
|
||||
for (const contextName of exposedContextNames) {
|
||||
if (contextName === currentContextName) {
|
||||
continue;
|
||||
}
|
||||
const descriptor = Object.getOwnPropertyDescriptor(contextAccessors, contextName);
|
||||
if (descriptor) {
|
||||
Object.defineProperty(exposedContext, contextName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return exposedContext;
|
||||
};
|
||||
|
|
|
@ -89,7 +89,8 @@ export class CoreApp {
|
|||
const resources = coreSetup.httpResources.createRegistrar(router);
|
||||
|
||||
router.get({ path: '/', validate: false }, async (context, req, res) => {
|
||||
const defaultRoute = await context.core.uiSettings.client.get<string>('defaultRoute');
|
||||
const { uiSettings } = await context.core;
|
||||
const defaultRoute = await uiSettings.client.get<string>('defaultRoute');
|
||||
const basePath = httpSetup.basePath.get(req);
|
||||
const url = `${basePath}${defaultRoute}`;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ export const registerGetRoute = (router: IRouter) => {
|
|||
validate: false,
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const deprecationsClient = context.core.deprecations.client;
|
||||
const deprecationsClient = (await context.core).deprecations.client;
|
||||
|
||||
const body: DeprecationsGetResponse = {
|
||||
deprecations: await deprecationsClient.getAllDeprecations(),
|
||||
|
|
|
@ -65,10 +65,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asInternalUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asInternalUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -90,10 +88,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -115,10 +111,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asInternalUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asInternalUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -136,10 +130,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -157,7 +149,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asInternalUser.ping(
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asInternalUser.ping(
|
||||
{},
|
||||
{
|
||||
opaqueId: 'new-opaque-id',
|
||||
|
@ -203,10 +196,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -229,10 +220,8 @@ describe('trace', () => {
|
|||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
executionContext.set(parentContext);
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({
|
||||
body: {
|
||||
context: executionContext.get()?.toJSON(),
|
||||
|
@ -345,10 +334,8 @@ describe('trace', () => {
|
|||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
executionContext.set(parentContext);
|
||||
await delay(id-- * 100);
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -397,10 +384,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -487,10 +472,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -511,10 +494,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asInternalUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asInternalUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -535,10 +516,8 @@ describe('trace', () => {
|
|||
|
||||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -561,10 +540,8 @@ describe('trace', () => {
|
|||
const router = createRouter('');
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
executionContext.set(parentContext);
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -593,10 +570,8 @@ describe('trace', () => {
|
|||
};
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
executionContext.set(ctx);
|
||||
const { headers } = await context.core.elasticsearch.client.asCurrentUser.ping(
|
||||
{},
|
||||
{ meta: true }
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await esClient.asCurrentUser.ping({}, { meta: true });
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
@ -663,9 +638,10 @@ describe('trace', () => {
|
|||
description: 'new-description',
|
||||
};
|
||||
router.get({ path: '/execution-context', validate: false }, async (context, req, res) => {
|
||||
const { headers } = await executionContext.withContext(newContext, () =>
|
||||
context.core.elasticsearch.client.asCurrentUser.ping({}, { meta: true })
|
||||
);
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const { headers } = await executionContext.withContext(newContext, () => {
|
||||
return esClient.asCurrentUser.ping({}, { meta: true });
|
||||
});
|
||||
return res.ok({ body: headers || {} });
|
||||
});
|
||||
|
||||
|
|
|
@ -366,7 +366,7 @@ export interface HttpServiceSetup {
|
|||
*/
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
ContextName extends keyof Omit<Context, 'resolve'>
|
||||
>(
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
|
@ -393,7 +393,7 @@ export interface InternalHttpServiceSetup
|
|||
authRequestHeaders: IAuthHeadersStorage;
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
ContextName extends keyof Omit<Context, 'resolve'>
|
||||
>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: ContextName,
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('HttpResources service', () => {
|
|||
let setupDeps: SetupDeps;
|
||||
let router: jest.Mocked<IRouter>;
|
||||
const kibanaRequest = httpServerMock.createKibanaRequest();
|
||||
const context = { core: coreMock.createRequestHandlerContext() };
|
||||
const context = coreMock.createCustomRequestHandlerContext({});
|
||||
const apmConfig = { mockApmConfig: true };
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -71,7 +71,7 @@ describe('HttpResources service', () => {
|
|||
await routeHandler(context, kibanaRequest, responseFactory);
|
||||
expect(getDeps().rendering.render).toHaveBeenCalledWith(
|
||||
kibanaRequest,
|
||||
context.core.uiSettings.client,
|
||||
(await context.core).uiSettings.client,
|
||||
{
|
||||
isAnonymousPage: false,
|
||||
vars: {
|
||||
|
@ -117,7 +117,7 @@ describe('HttpResources service', () => {
|
|||
await routeHandler(context, kibanaRequest, responseFactory);
|
||||
expect(getDeps().rendering.render).toHaveBeenCalledWith(
|
||||
kibanaRequest,
|
||||
context.core.uiSettings.client,
|
||||
(await context.core).uiSettings.client,
|
||||
{
|
||||
isAnonymousPage: true,
|
||||
vars: {
|
||||
|
|
|
@ -93,7 +93,8 @@ export class HttpResourcesService implements CoreService<InternalHttpResourcesSe
|
|||
return {
|
||||
async renderCoreApp(options: HttpResourcesRenderOptions = {}) {
|
||||
const apmConfig = getApmConfig(request.url.pathname);
|
||||
const body = await deps.rendering.render(request, context.core.uiSettings.client, {
|
||||
const { uiSettings } = await context.core;
|
||||
const body = await deps.rendering.render(request, uiSettings.client, {
|
||||
isAnonymousPage: false,
|
||||
vars: {
|
||||
apmConfig,
|
||||
|
@ -108,7 +109,8 @@ export class HttpResourcesService implements CoreService<InternalHttpResourcesSe
|
|||
},
|
||||
async renderAnonymousCoreApp(options: HttpResourcesRenderOptions = {}) {
|
||||
const apmConfig = getApmConfig(request.url.pathname);
|
||||
const body = await deps.rendering.render(request, context.core.uiSettings.client, {
|
||||
const { uiSettings } = await context.core;
|
||||
const body = await deps.rendering.render(request, uiSettings.client, {
|
||||
isAnonymousPage: true,
|
||||
vars: {
|
||||
apmConfig,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
import { AwaitedProperties } from '@kbn/utility-types';
|
||||
import { Type } from '@kbn/config-schema';
|
||||
import {
|
||||
ElasticsearchServiceSetup,
|
||||
|
@ -465,8 +466,39 @@ export type {
|
|||
} from './analytics';
|
||||
export { TelemetryCounterType } from './analytics';
|
||||
|
||||
/** @public **/
|
||||
export interface RequestHandlerContextBase {
|
||||
/**
|
||||
* Await all the specified context parts and return them.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const resolved = await context.resolve(['core', 'pluginA']);
|
||||
* const esClient = resolved.core.elasticsearch.client;
|
||||
* const pluginAService = resolved.pluginA.someService;
|
||||
* ```
|
||||
*/
|
||||
resolve: <T extends keyof Omit<this, 'resolve'>>(
|
||||
parts: T[]
|
||||
) => Promise<AwaitedProperties<Pick<this, T>>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin specific context passed to a route handler.
|
||||
* Base context passed to a route handler.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface RequestHandlerContext extends RequestHandlerContextBase {
|
||||
core: Promise<CoreRequestHandlerContext>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type CustomRequestHandlerContext<T> = RequestHandlerContext & {
|
||||
[Key in keyof T]: T[Key] extends Promise<unknown> ? T[Key] : Promise<T[Key]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The `core` context provided to route handler.
|
||||
*
|
||||
* Provides the following clients and services:
|
||||
* - {@link SavedObjectsClient | savedObjects.client} - Saved Objects client
|
||||
|
@ -477,27 +509,24 @@ export { TelemetryCounterType } from './analytics';
|
|||
* data client which uses the credentials of the incoming request
|
||||
* - {@link IUiSettingsClient | uiSettings.client} - uiSettings client
|
||||
* which uses the credentials of the incoming request
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface RequestHandlerContext {
|
||||
core: {
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
export interface CoreRequestHandlerContext {
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import { of } from 'rxjs';
|
||||
import { duration } from 'moment';
|
||||
import { ByteSizeValue } from '@kbn/config-schema';
|
||||
import { isPromise } from '@kbn/std';
|
||||
import type { MockedKeys } from '@kbn/utility-types/jest';
|
||||
import type {
|
||||
PluginInitializerContext,
|
||||
|
@ -66,7 +67,11 @@ export { executionContextServiceMock } from './execution_context/execution_conte
|
|||
export { docLinksServiceMock } from './doc_links/doc_links_service.mock';
|
||||
export { analyticsServiceMock } from './analytics/analytics_service.mock';
|
||||
|
||||
export type { ElasticsearchClientMock } from './elasticsearch/client/mocks';
|
||||
export type {
|
||||
ElasticsearchClientMock,
|
||||
ClusterClientMock,
|
||||
ScopedClusterClientMock,
|
||||
} from './elasticsearch/client/mocks';
|
||||
|
||||
type MockedPluginInitializerConfig<T> = jest.Mocked<PluginInitializerContext<T>['config']>;
|
||||
|
||||
|
@ -280,6 +285,40 @@ function createCoreRequestHandlerContextMock() {
|
|||
};
|
||||
}
|
||||
|
||||
export type CustomRequestHandlerMock<T> = {
|
||||
core: Promise<ReturnType<typeof createCoreRequestHandlerContextMock>>;
|
||||
resolve: jest.MockedFunction<any>;
|
||||
} & {
|
||||
[Key in keyof T]: T[Key] extends Promise<unknown> ? T[Key] : Promise<T[Key]>;
|
||||
};
|
||||
|
||||
const createCustomRequestHandlerContextMock = <T>(contextParts: T): CustomRequestHandlerMock<T> => {
|
||||
const mock = Object.entries(contextParts).reduce(
|
||||
(context, [key, value]) => {
|
||||
// @ts-expect-error type matching from inferred types is hard
|
||||
context[key] = isPromise(value) ? value : Promise.resolve(value);
|
||||
return context;
|
||||
},
|
||||
{
|
||||
core: Promise.resolve(createCoreRequestHandlerContextMock()),
|
||||
} as CustomRequestHandlerMock<T>
|
||||
);
|
||||
|
||||
mock.resolve = jest.fn().mockImplementation(async () => {
|
||||
const resolved = {};
|
||||
for (const propName of Object.keys(mock)) {
|
||||
if (propName === 'resolve') {
|
||||
continue;
|
||||
}
|
||||
// @ts-expect-error type matching from inferred types is hard
|
||||
resolved[propName] = await mock[propName];
|
||||
}
|
||||
return resolved;
|
||||
});
|
||||
|
||||
return mock;
|
||||
};
|
||||
|
||||
export const coreMock = {
|
||||
createPreboot: createCorePrebootMock,
|
||||
createSetup: createCoreSetupMock,
|
||||
|
@ -289,4 +328,5 @@ export const coreMock = {
|
|||
createInternalStart: createInternalCoreStartMock,
|
||||
createPluginInitializerContext: pluginInitializerContextMock,
|
||||
createRequestHandlerContext: createCoreRequestHandlerContextMock,
|
||||
createCustomRequestHandlerContext: createCustomRequestHandlerContextMock,
|
||||
};
|
||||
|
|
|
@ -185,7 +185,7 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
|
|||
createCookieSessionStorageFactory: deps.http.createCookieSessionStorageFactory,
|
||||
registerRouteHandlerContext: <
|
||||
Context extends RequestHandlerContext,
|
||||
ContextName extends keyof Context
|
||||
ContextName extends keyof Omit<Context, 'resolve'>
|
||||
>(
|
||||
contextName: ContextName,
|
||||
provider: RequestHandlerContextProvider<Context, ContextName>
|
||||
|
|
|
@ -25,7 +25,7 @@ export const registerBootstrapRoute = ({
|
|||
validate: false,
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
const uiSettingsClient = ctx.core.uiSettings.client;
|
||||
const uiSettingsClient = (await ctx.core).uiSettings.client;
|
||||
const { body, etag } = await renderer({ uiSettingsClient, request: req });
|
||||
|
||||
return res.ok({
|
||||
|
@ -48,7 +48,7 @@ export const registerBootstrapRoute = ({
|
|||
validate: false,
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
const uiSettingsClient = ctx.core.uiSettings.client;
|
||||
const uiSettingsClient = (await ctx.core).uiSettings.client;
|
||||
const { body, etag } = await renderer({
|
||||
uiSettingsClient,
|
||||
request: req,
|
||||
|
|
|
@ -51,7 +51,8 @@ export const registerBulkCreateRoute = (router: IRouter, { coreUsageData }: Rout
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsBulkCreate({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.bulkCreate(req.body, { overwrite });
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.bulkCreate(req.body, { overwrite });
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -34,7 +34,8 @@ export const registerBulkGetRoute = (router: IRouter, { coreUsageData }: RouteDe
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsBulkGet({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.bulkGet(req.body);
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.bulkGet(req.body);
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -32,7 +32,8 @@ export const registerBulkResolveRoute = (router: IRouter, { coreUsageData }: Rou
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsBulkResolve({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.bulkResolve(req.body);
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.bulkResolve(req.body);
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -44,7 +44,8 @@ export const registerBulkUpdateRoute = (router: IRouter, { coreUsageData }: Rout
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsBulkUpdate({ request: req }).catch(() => {});
|
||||
|
||||
const savedObject = await context.core.savedObjects.client.bulkUpdate(req.body);
|
||||
const { savedObjects } = await context.core;
|
||||
const savedObject = await savedObjects.client.bulkUpdate(req.body);
|
||||
return res.ok({ body: savedObject });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -61,7 +61,8 @@ export const registerCreateRoute = (router: IRouter, { coreUsageData }: RouteDep
|
|||
references,
|
||||
initialNamespaces,
|
||||
};
|
||||
const result = await context.core.savedObjects.client.create(type, attributes, options);
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.create(type, attributes, options);
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -32,7 +32,7 @@ export const registerDeleteRoute = (router: IRouter, { coreUsageData }: RouteDep
|
|||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const { type, id } = req.params;
|
||||
const { force } = req.query;
|
||||
const { getClient } = context.core.savedObjects;
|
||||
const { getClient } = (await context.core).savedObjects;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsDelete({ request: req }).catch(() => {});
|
||||
|
|
|
@ -25,9 +25,10 @@ export const registerDeleteUnknownTypesRoute = (
|
|||
validate: false,
|
||||
},
|
||||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const { elasticsearch, savedObjects } = await context.core;
|
||||
await deleteUnknownTypeObjects({
|
||||
esClient: context.core.elasticsearch.client,
|
||||
typeRegistry: context.core.savedObjects.typeRegistry,
|
||||
esClient: elasticsearch.client,
|
||||
typeRegistry: savedObjects.typeRegistry,
|
||||
kibanaIndex,
|
||||
kibanaVersion,
|
||||
});
|
||||
|
|
|
@ -165,7 +165,7 @@ export const registerExportRoute = (
|
|||
},
|
||||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const cleaned = cleanOptions(req.body);
|
||||
const { typeRegistry, getExporter, getClient } = context.core.savedObjects;
|
||||
const { typeRegistry, getExporter, getClient } = (await context.core).savedObjects;
|
||||
const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((t) => t.name);
|
||||
|
||||
let options: EitherExportOptions;
|
||||
|
|
|
@ -73,8 +73,8 @@ export const registerFindRoute = (router: IRouter, { coreUsageData }: RouteDepen
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
const result = await context.core.savedObjects.client.find({
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.find({
|
||||
perPage: query.per_page,
|
||||
page: query.page,
|
||||
type: Array.isArray(query.type) ? query.type : [query.type],
|
||||
|
|
|
@ -32,8 +32,9 @@ export const registerGetRoute = (router: IRouter, { coreUsageData }: RouteDepend
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsGet({ request: req }).catch(() => {});
|
||||
|
||||
const savedObject = await context.core.savedObjects.client.get(type, id);
|
||||
return res.ok({ body: savedObject });
|
||||
const { savedObjects } = await context.core;
|
||||
const object = await savedObjects.client.get(type, id);
|
||||
return res.ok({ body: object });
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -63,7 +63,7 @@ export const registerImportRoute = (
|
|||
},
|
||||
catchAndReturnBoomErrors(async (context, req, res) => {
|
||||
const { overwrite, createNewCopies } = req.query;
|
||||
const { getClient, getImporter, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, getImporter, typeRegistry } = (await context.core).savedObjects;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient
|
||||
|
|
|
@ -38,7 +38,7 @@ export const registerLegacyExportRoute = (
|
|||
);
|
||||
|
||||
const ids = Array.isArray(req.query.dashboard) ? req.query.dashboard : [req.query.dashboard];
|
||||
const { client } = ctx.core.savedObjects;
|
||||
const { client } = (await ctx.core).savedObjects;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementLegacyDashboardsExport({ request: req }).catch(() => {});
|
||||
|
|
|
@ -46,7 +46,7 @@ export const registerLegacyImportRoute = (
|
|||
"The import dashboard API '/api/kibana/dashboards/import' is deprecated. Use the saved objects import objects API '/api/saved_objects/_import' instead."
|
||||
);
|
||||
|
||||
const { client } = ctx.core.savedObjects;
|
||||
const { client } = (await ctx.core).savedObjects;
|
||||
const objects = req.body.objects as SavedObject[];
|
||||
const { force, exclude } = req.query;
|
||||
|
||||
|
|
|
@ -27,11 +27,12 @@ export const registerResolveRoute = (router: IRouter, { coreUsageData }: RouteDe
|
|||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { type, id } = req.params;
|
||||
const { savedObjects } = await context.core;
|
||||
|
||||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsResolve({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.resolve(type, id);
|
||||
const result = await savedObjects.client.resolve(type, id);
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -92,7 +92,7 @@ export const registerResolveImportErrorsRoute = (
|
|||
});
|
||||
}
|
||||
|
||||
const { getClient, getImporter, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, getImporter, typeRegistry } = (await context.core).savedObjects;
|
||||
|
||||
const includedHiddenTypes = chain(req.body.retries)
|
||||
.map('type')
|
||||
|
|
|
@ -49,7 +49,8 @@ export const registerUpdateRoute = (router: IRouter, { coreUsageData }: RouteDep
|
|||
const usageStatsClient = coreUsageData.getClient();
|
||||
usageStatsClient.incrementSavedObjectsUpdate({ request: req }).catch(() => {});
|
||||
|
||||
const result = await context.core.savedObjects.client.update(type, id, attributes, options);
|
||||
const { savedObjects } = await context.core;
|
||||
const result = await savedObjects.client.update(type, id, attributes, options);
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import { AddConfigDeprecation } from '@kbn/config';
|
||||
import { AnalyticsClient } from '@kbn/analytics-client';
|
||||
import apm from 'elastic-apm-node';
|
||||
import { AwaitedProperties } from '@kbn/utility-types';
|
||||
import Boom from '@hapi/boom';
|
||||
import { ByteSizeValue } from '@kbn/config-schema';
|
||||
import { CliArgs } from '@kbn/config';
|
||||
|
@ -446,6 +447,30 @@ export interface CorePreboot {
|
|||
preboot: PrebootServicePreboot;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface CoreRequestHandlerContext {
|
||||
// (undocumented)
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
// (undocumented)
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
// (undocumented)
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
// (undocumented)
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
}
|
||||
|
||||
// @internal
|
||||
export interface CoreServicesUsageData {
|
||||
// (undocumented)
|
||||
|
@ -840,6 +865,11 @@ export interface CustomHttpResponseOptions<T extends HttpResponsePayload | Respo
|
|||
statusCode: number;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type CustomRequestHandlerContext<T> = RequestHandlerContext & {
|
||||
[Key in keyof T]: T[Key] extends Promise<unknown> ? T[Key] : Promise<T[Key]>;
|
||||
};
|
||||
|
||||
// @internal (undocumented)
|
||||
export const DEFAULT_APP_CATEGORIES: Record<string, AppCategory>;
|
||||
|
||||
|
@ -1189,7 +1219,7 @@ export interface HttpServiceSetup {
|
|||
registerOnPreAuth: (handler: OnPreAuthHandler) => void;
|
||||
registerOnPreResponse: (handler: OnPreResponseHandler) => void;
|
||||
registerOnPreRouting: (handler: OnPreRoutingHandler) => void;
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Context>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
registerRouteHandlerContext: <Context extends RequestHandlerContext, ContextName extends keyof Omit<Context, 'resolve'>>(contextName: ContextName, provider: RequestHandlerContextProvider<Context, ContextName>) => RequestHandlerContextContainer;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -1221,7 +1251,7 @@ export interface IContextContainer {
|
|||
}
|
||||
|
||||
// @public
|
||||
export type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => Promise<Context[ContextName]> | Context[ContextName];
|
||||
export type IContextProvider<Context extends RequestHandlerContext, ContextName extends keyof Context> = (context: Omit<Context, ContextName>, ...rest: HandlerParameters<RequestHandler>) => MaybePromise<Awaited<Context[ContextName]>>;
|
||||
|
||||
// @public
|
||||
export interface ICspConfig {
|
||||
|
@ -1840,26 +1870,14 @@ export interface RegisterDeprecationsConfig {
|
|||
export type RequestHandler<P = unknown, Q = unknown, B = unknown, Context extends RequestHandlerContext = RequestHandlerContext, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory> = (context: Context, request: KibanaRequest<P, Q, B, Method>, response: ResponseFactory) => IKibanaResponse<any> | Promise<IKibanaResponse<any>>;
|
||||
|
||||
// @public
|
||||
export interface RequestHandlerContext {
|
||||
export interface RequestHandlerContext extends RequestHandlerContextBase {
|
||||
// (undocumented)
|
||||
core: {
|
||||
savedObjects: {
|
||||
client: SavedObjectsClientContract;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
|
||||
getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
|
||||
getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
|
||||
};
|
||||
elasticsearch: {
|
||||
client: IScopedClusterClient;
|
||||
};
|
||||
uiSettings: {
|
||||
client: IUiSettingsClient;
|
||||
};
|
||||
deprecations: {
|
||||
client: DeprecationsClient;
|
||||
};
|
||||
};
|
||||
core: Promise<CoreRequestHandlerContext>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RequestHandlerContextBase {
|
||||
resolve: <T extends keyof Omit<this, 'resolve'>>(parts: T[]) => Promise<AwaitedProperties<Pick<this, T>>>;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
|
|
@ -42,7 +42,6 @@ import { config as uiSettingsConfig } from './ui_settings';
|
|||
import { config as statusConfig } from './status';
|
||||
import { config as i18nConfig } from './i18n';
|
||||
import { ContextService } from './context';
|
||||
import { RequestHandlerContext } from '.';
|
||||
import {
|
||||
InternalCorePreboot,
|
||||
InternalCoreSetup,
|
||||
|
@ -372,13 +371,9 @@ export class Server {
|
|||
}
|
||||
|
||||
private registerCoreContext(coreSetup: InternalCoreSetup) {
|
||||
coreSetup.http.registerRouteHandlerContext(
|
||||
coreId,
|
||||
'core',
|
||||
(context, req, res): RequestHandlerContext['core'] => {
|
||||
return new CoreRouteHandlerContext(this.coreStart!, req);
|
||||
}
|
||||
);
|
||||
coreSetup.http.registerRouteHandlerContext(coreId, 'core', async (context, req, res) => {
|
||||
return new CoreRouteHandlerContext(this.coreStart!, req);
|
||||
});
|
||||
}
|
||||
|
||||
public setupCoreConfig() {
|
||||
|
|
|
@ -23,7 +23,7 @@ export function registerDeleteRoute(router: IRouter) {
|
|||
{ path: '/api/kibana/settings/{key}', validate },
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const uiSettingsClient = context.core.uiSettings.client;
|
||||
const uiSettingsClient = (await context.core).uiSettings.client;
|
||||
|
||||
await uiSettingsClient.remove(request.params.key);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ export function registerGetRoute(router: IRouter) {
|
|||
{ path: '/api/kibana/settings', validate: false },
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const uiSettingsClient = context.core.uiSettings.client;
|
||||
const uiSettingsClient = (await context.core).uiSettings.client;
|
||||
return response.ok({
|
||||
body: {
|
||||
settings: await uiSettingsClient.getUserProvided(),
|
||||
|
|
|
@ -26,7 +26,7 @@ export function registerSetRoute(router: IRouter) {
|
|||
{ path: '/api/kibana/settings/{key}', validate },
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const uiSettingsClient = context.core.uiSettings.client;
|
||||
const uiSettingsClient = (await context.core).uiSettings.client;
|
||||
|
||||
const { key } = request.params;
|
||||
const { value } = request.body;
|
||||
|
|
|
@ -21,7 +21,7 @@ const validate = {
|
|||
export function registerSetManyRoute(router: IRouter) {
|
||||
router.post({ path: '/api/kibana/settings', validate }, async (context, request, response) => {
|
||||
try {
|
||||
const uiSettingsClient = context.core.uiSettings.client;
|
||||
const uiSettingsClient = (await context.core).uiSettings.client;
|
||||
|
||||
const { changes } = request.body;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ export const setupOptionsListSuggestionsRoute = (
|
|||
try {
|
||||
const suggestionRequest: OptionsListRequestBody = request.body;
|
||||
const { index } = request.params;
|
||||
const esClient = context.core.elasticsearch.client.asCurrentUser;
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const suggestionsResponse = await getOptionsListSuggestions({
|
||||
abortedEvent$: request.events.aborted$,
|
||||
request: suggestionRequest,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { coreMock } from '@kbn/core/server/mocks';
|
||||
import {
|
||||
createFieldFormatsSetupMock,
|
||||
createFieldFormatsStartMock,
|
||||
|
@ -17,7 +18,6 @@ import {
|
|||
} from './search/mocks';
|
||||
import { createIndexPatternsStartMock } from './data_views/mocks';
|
||||
import { createDatatableUtilitiesMock } from './datatable_utilities/mock';
|
||||
import { DataRequestHandlerContext } from './search';
|
||||
|
||||
function createSetupContract() {
|
||||
return {
|
||||
|
@ -43,8 +43,9 @@ function createStartContract() {
|
|||
|
||||
function createRequestHandlerContext() {
|
||||
return {
|
||||
core: coreMock.createRequestHandlerContext(),
|
||||
search: createSearchRequestHandlerContext(),
|
||||
} as unknown as jest.Mocked<DataRequestHandlerContext>;
|
||||
};
|
||||
}
|
||||
|
||||
export const dataPluginMock = {
|
||||
|
|
|
@ -20,7 +20,6 @@ const {
|
|||
savedObjects: { client: mockSavedObjectsClient },
|
||||
},
|
||||
} = mockContext;
|
||||
const context = registerSavedQueryRouteHandlerContext(mockContext);
|
||||
|
||||
const savedQueryAttributes: SavedQueryAttributes = {
|
||||
title: 'foo',
|
||||
|
@ -73,7 +72,15 @@ const savedQueryReferences = [
|
|||
];
|
||||
|
||||
describe('saved query route handler context', () => {
|
||||
beforeEach(() => {
|
||||
let context: Awaited<ReturnType<typeof registerSavedQueryRouteHandlerContext>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
context = await registerSavedQueryRouteHandlerContext(
|
||||
coreMock.createCustomRequestHandlerContext({
|
||||
core: mockContext.core,
|
||||
})
|
||||
);
|
||||
|
||||
mockSavedObjectsClient.create.mockClear();
|
||||
mockSavedObjectsClient.resolve.mockClear();
|
||||
mockSavedObjectsClient.find.mockClear();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { RequestHandlerContext, SavedObject } from '@kbn/core/server';
|
||||
import { CustomRequestHandlerContext, RequestHandlerContext, SavedObject } from '@kbn/core/server';
|
||||
import { isFilters } from '@kbn/es-query';
|
||||
import { isQuery, SavedQueryAttributes } from '../../common';
|
||||
import { extract, inject } from '../../common/query/persistable_state';
|
||||
|
@ -66,18 +66,16 @@ function verifySavedQuery({ title, query, filters = [] }: SavedQueryAttributes)
|
|||
}
|
||||
}
|
||||
|
||||
export function registerSavedQueryRouteHandlerContext(context: RequestHandlerContext) {
|
||||
export async function registerSavedQueryRouteHandlerContext(context: RequestHandlerContext) {
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
|
||||
const createSavedQuery = async (attrs: SavedQueryAttributes) => {
|
||||
verifySavedQuery(attrs);
|
||||
const { attributes, references } = extractReferences(attrs);
|
||||
|
||||
const savedObject = await context.core.savedObjects.client.create<SavedQueryAttributes>(
|
||||
'query',
|
||||
attributes,
|
||||
{
|
||||
references,
|
||||
}
|
||||
);
|
||||
const savedObject = await soClient.create<SavedQueryAttributes>('query', attributes, {
|
||||
references,
|
||||
});
|
||||
|
||||
// TODO: Handle properly
|
||||
if (savedObject.error) throw new Error(savedObject.error.message);
|
||||
|
@ -89,14 +87,9 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
verifySavedQuery(attrs);
|
||||
const { attributes, references } = extractReferences(attrs);
|
||||
|
||||
const savedObject = await context.core.savedObjects.client.update<SavedQueryAttributes>(
|
||||
'query',
|
||||
id,
|
||||
attributes,
|
||||
{
|
||||
references,
|
||||
}
|
||||
);
|
||||
const savedObject = await soClient.update<SavedQueryAttributes>('query', id, attributes, {
|
||||
references,
|
||||
});
|
||||
|
||||
// TODO: Handle properly
|
||||
if (savedObject.error) throw new Error(savedObject.error.message);
|
||||
|
@ -105,8 +98,10 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
};
|
||||
|
||||
const getSavedQuery = async (id: string) => {
|
||||
const { saved_object: savedObject, outcome } =
|
||||
await context.core.savedObjects.client.resolve<SavedQueryAttributes>('query', id);
|
||||
const { saved_object: savedObject, outcome } = await soClient.resolve<SavedQueryAttributes>(
|
||||
'query',
|
||||
id
|
||||
);
|
||||
if (outcome === 'conflict') {
|
||||
throw new Error(`Multiple saved queries found with ID: ${id} (legacy URL alias conflict)`);
|
||||
} else if (savedObject.error) {
|
||||
|
@ -116,20 +111,19 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
};
|
||||
|
||||
const getSavedQueriesCount = async () => {
|
||||
const { total } = await context.core.savedObjects.client.find<SavedQueryAttributes>({
|
||||
const { total } = await soClient.find<SavedQueryAttributes>({
|
||||
type: 'query',
|
||||
});
|
||||
return total;
|
||||
};
|
||||
|
||||
const findSavedQueries = async ({ page = 1, perPage = 50, search = '' } = {}) => {
|
||||
const { total, saved_objects: savedObjects } =
|
||||
await context.core.savedObjects.client.find<SavedQueryAttributes>({
|
||||
type: 'query',
|
||||
page,
|
||||
perPage,
|
||||
search,
|
||||
});
|
||||
const { total, saved_objects: savedObjects } = await soClient.find<SavedQueryAttributes>({
|
||||
type: 'query',
|
||||
page,
|
||||
perPage,
|
||||
search,
|
||||
});
|
||||
|
||||
const savedQueries = savedObjects.map(injectReferences);
|
||||
|
||||
|
@ -137,7 +131,7 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
};
|
||||
|
||||
const getAllSavedQueries = async () => {
|
||||
const finder = context.core.savedObjects.client.createPointInTimeFinder<SavedQueryAttributes>({
|
||||
const finder = soClient.createPointInTimeFinder<SavedQueryAttributes>({
|
||||
type: 'query',
|
||||
perPage: 100,
|
||||
});
|
||||
|
@ -152,8 +146,8 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
return { total: savedQueries.length, savedQueries };
|
||||
};
|
||||
|
||||
const deleteSavedQuery = (id: string) => {
|
||||
return context.core.savedObjects.client.delete('query', id);
|
||||
const deleteSavedQuery = async (id: string) => {
|
||||
return await soClient.delete('query', id);
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -167,6 +161,6 @@ export function registerSavedQueryRouteHandlerContext(context: RequestHandlerCon
|
|||
};
|
||||
}
|
||||
|
||||
export interface SavedQueryRouteHandlerContext extends RequestHandlerContext {
|
||||
savedQuery: ReturnType<typeof registerSavedQueryRouteHandlerContext>;
|
||||
}
|
||||
export type SavedQueryRouteHandlerContext = CustomRequestHandlerContext<{
|
||||
savedQuery: Promise<ReturnType<typeof registerSavedQueryRouteHandlerContext>>;
|
||||
}>;
|
||||
|
|
|
@ -37,7 +37,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
},
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const body = await context.savedQuery.create(request.body);
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.create(request.body);
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -57,7 +58,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
async (context, request, response) => {
|
||||
const { id } = request.params;
|
||||
try {
|
||||
const body = await context.savedQuery.update(id, request.body);
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.update(id, request.body);
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -76,7 +78,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
async (context, request, response) => {
|
||||
const { id } = request.params;
|
||||
try {
|
||||
const body = await context.savedQuery.get(id);
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.get(id);
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -92,7 +95,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
},
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const count = await context.savedQuery.count();
|
||||
const savedQuery = await context.savedQuery;
|
||||
const count = await savedQuery.count();
|
||||
return response.ok({ body: `${count}` });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -114,7 +118,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
},
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const body = await context.savedQuery.find(request.body);
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.find(request.body);
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -130,7 +135,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
},
|
||||
async (context, request, response) => {
|
||||
try {
|
||||
const body = await context.savedQuery.getAll();
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.getAll();
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
@ -149,7 +155,8 @@ export function registerSavedQueryRoutes({ http }: CoreSetup): void {
|
|||
async (context, request, response) => {
|
||||
const { id } = request.params;
|
||||
try {
|
||||
const body = await context.savedQuery.delete(id);
|
||||
const savedQuery = await context.savedQuery;
|
||||
const body = await savedQuery.delete(id);
|
||||
return response.ok({ body });
|
||||
} catch (e) {
|
||||
// TODO: Handle properly
|
||||
|
|
|
@ -47,8 +47,9 @@ export function registerSearchRoute(router: DataPluginRouter): void {
|
|||
const abortSignal = getRequestAbortedSignal(request.events.aborted$);
|
||||
|
||||
try {
|
||||
const response = await context
|
||||
.search!.search(
|
||||
const search = await context.search;
|
||||
const response = await search
|
||||
.search(
|
||||
{ ...searchRequest, id },
|
||||
{
|
||||
abortSignal,
|
||||
|
@ -85,7 +86,8 @@ export function registerSearchRoute(router: DataPluginRouter): void {
|
|||
const { strategy, id } = request.params;
|
||||
|
||||
try {
|
||||
await context.search!.cancel(id, { strategy });
|
||||
const search = await context.search;
|
||||
await search.cancel(id, { strategy });
|
||||
return res.ok();
|
||||
} catch (err) {
|
||||
return reportServerError(res, err);
|
||||
|
|
|
@ -143,7 +143,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
|
||||
core.http.registerRouteHandlerContext<DataRequestHandlerContext, 'search'>(
|
||||
'search',
|
||||
async (context, request) => {
|
||||
(context, request) => {
|
||||
return this.asScoped(request);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
IUiSettingsClient,
|
||||
SavedObjectsClientContract,
|
||||
KibanaRequest,
|
||||
RequestHandlerContext,
|
||||
CustomRequestHandlerContext,
|
||||
} from '@kbn/core/server';
|
||||
import {
|
||||
ISearchOptions,
|
||||
|
@ -126,8 +126,8 @@ export interface ISearchStart<
|
|||
|
||||
export type SearchRequestHandlerContext = IScopedSearchClient;
|
||||
|
||||
export interface DataRequestHandlerContext extends RequestHandlerContext {
|
||||
export type DataRequestHandlerContext = CustomRequestHandlerContext<{
|
||||
search: SearchRequestHandlerContext;
|
||||
}
|
||||
}>;
|
||||
|
||||
export type DataPluginRouter = IRouter<DataRequestHandlerContext>;
|
||||
|
|
|
@ -38,7 +38,7 @@ export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void =
|
|||
},
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
const { client } = ctx.core.elasticsearch;
|
||||
const { client } = (await ctx.core).elasticsearch;
|
||||
|
||||
const type = req.body.context.split('_field')[0] as estypes.MappingRuntimeFieldType;
|
||||
const body = {
|
||||
|
|
|
@ -24,7 +24,7 @@ export function registerPreviewScriptedFieldRoute(router: IRouter): void {
|
|||
},
|
||||
},
|
||||
async (context, request, res) => {
|
||||
const client = context.core.elasticsearch.client.asCurrentUser;
|
||||
const client = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const { index, name, script, query, additionalFields } = request.body;
|
||||
|
||||
try {
|
||||
|
|
|
@ -31,7 +31,8 @@ export function registerResolveIndexRoute(router: IRouter): void {
|
|||
},
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const body = await context.core.elasticsearch.client.asCurrentUser.indices.resolveIndex({
|
||||
const esClient = (await context.core).elasticsearch.client;
|
||||
const body = await esClient.asCurrentUser.indices.resolveIndex({
|
||||
name: req.params.query,
|
||||
expand_wildcards: req.query.expand_wildcards || 'open',
|
||||
});
|
||||
|
|
|
@ -94,8 +94,9 @@ const registerCreateDataViewRouteFactory =
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
|
|
|
@ -64,8 +64,9 @@ const manageDefaultIndexPatternRoutesFactory =
|
|||
validate: {},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
@ -103,8 +104,9 @@ const manageDefaultIndexPatternRoutesFactory =
|
|||
},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -58,8 +58,9 @@ const deleteIndexPatternRouteFactory =
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -134,8 +134,9 @@ const updateFieldsActionRouteFactory = (path: string, serviceKey: string) => {
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -63,8 +63,9 @@ const getDataViewRouteFactory =
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -45,8 +45,9 @@ const hasUserDataViewRouteFactory =
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
|
|
|
@ -92,8 +92,9 @@ const runtimeCreateFieldRouteFactory =
|
|||
},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -73,8 +73,9 @@ const deleteRuntimeFieldRouteFactory =
|
|||
},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -80,8 +80,9 @@ const getRuntimeFieldRouteFactory =
|
|||
},
|
||||
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -92,8 +92,9 @@ const putRuntimeFieldRouteFactory =
|
|||
},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -93,8 +93,9 @@ const updateRuntimeFieldRouteFactory =
|
|||
},
|
||||
},
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -42,8 +42,9 @@ export const registerCreateScriptedFieldRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { indexPatternsServiceFactory }] = await getStartServices();
|
||||
const indexPatternsService = await indexPatternsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -43,8 +43,9 @@ export const registerDeleteScriptedFieldRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { indexPatternsServiceFactory }] = await getStartServices();
|
||||
const indexPatternsService = await indexPatternsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -43,8 +43,9 @@ export const registerGetScriptedFieldRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { indexPatternsServiceFactory }] = await getStartServices();
|
||||
const indexPatternsService = await indexPatternsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -42,8 +42,9 @@ export const registerPutScriptedFieldRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { indexPatternsServiceFactory }] = await getStartServices();
|
||||
const indexPatternsService = await indexPatternsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -63,8 +63,9 @@ export const registerUpdateScriptedFieldRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { indexPatternsServiceFactory }] = await getStartServices();
|
||||
const indexPatternsService = await indexPatternsServiceFactory(
|
||||
savedObjectsClient,
|
||||
|
|
|
@ -161,8 +161,9 @@ const updateDataViewRouteFactory =
|
|||
},
|
||||
router.handleLegacyErrors(
|
||||
handleErrors(async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const [, , { dataViewsServiceFactory }] = await getStartServices();
|
||||
|
||||
const dataViewsService = await dataViewsServiceFactory(
|
||||
|
|
|
@ -56,7 +56,7 @@ export function registerRoutes(
|
|||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const { asCurrentUser } = context.core.elasticsearch.client;
|
||||
const { asCurrentUser } = (await context.core).elasticsearch.client;
|
||||
const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
|
||||
const { pattern, interval, look_back: lookBack, meta_fields: metaFields } = request.query;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ const validate: RouteValidatorFullConfig<{}, IQuery, IBody> = {
|
|||
body: schema.maybe(schema.object({ index_filter: schema.any() })),
|
||||
};
|
||||
const handler: RequestHandler<{}, IQuery, IBody> = async (context, request, response) => {
|
||||
const { asCurrentUser } = context.core.elasticsearch.client;
|
||||
const { asCurrentUser } = (await context.core).elasticsearch.client;
|
||||
const indexPatterns = new IndexPatternsFetcher(asCurrentUser);
|
||||
const {
|
||||
pattern,
|
||||
|
|
|
@ -16,8 +16,9 @@ export const registerHasDataViewsRoute = (router: IRouter): void => {
|
|||
validate: {},
|
||||
},
|
||||
async (ctx, req, res) => {
|
||||
const savedObjectsClient = ctx.core.savedObjects.client;
|
||||
const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser;
|
||||
const core = await ctx.core;
|
||||
const savedObjectsClient = core.savedObjects.client;
|
||||
const elasticsearchClient = core.elasticsearch.client.asCurrentUser;
|
||||
const dataViews = await getIndexPattern({
|
||||
esClient: elasticsearchClient,
|
||||
soClient: savedObjectsClient,
|
||||
|
|
|
@ -22,7 +22,7 @@ export const registerHitsStatusRoute = (router: IRouter) => {
|
|||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { index, query } = req.body;
|
||||
const client = context.core.elasticsearch.client;
|
||||
const client = (await context.core).elasticsearch.client;
|
||||
|
||||
try {
|
||||
const body = await client.asCurrentUser.search({
|
||||
|
|
|
@ -38,7 +38,7 @@ export function createInstallRoute(
|
|||
// @ts-ignore Custom query validation used
|
||||
const now = query.now ? new Date(query.now) : new Date();
|
||||
|
||||
const sampleDataInstaller = getSampleDataInstaller({
|
||||
const sampleDataInstaller = await getSampleDataInstaller({
|
||||
datasetId: sampleDataset.id,
|
||||
sampleDatasets,
|
||||
logger,
|
||||
|
|
|
@ -78,7 +78,7 @@ async function findExistingSampleObjects(
|
|||
.map(({ savedObjects }) => savedObjects.map(({ type, id }) => ({ type, id })))
|
||||
.flat();
|
||||
const objectTypes = getUniqueObjectTypes(objects);
|
||||
const client = getSavedObjectsClient(context, objectTypes);
|
||||
const client = await getSavedObjectsClient(context, objectTypes);
|
||||
const findSampleObjectsResult = await findSampleObjects({ client, logger, objects });
|
||||
|
||||
let objectCounter = 0;
|
||||
|
@ -101,18 +101,20 @@ async function getSampleDatasetStatus(
|
|||
return { status: NOT_INSTALLED };
|
||||
}
|
||||
|
||||
const { elasticsearch } = await context.core;
|
||||
|
||||
for (let i = 0; i < sampleDataset.dataIndices.length; i++) {
|
||||
const dataIndexConfig = sampleDataset.dataIndices[i];
|
||||
const index = createIndexName(sampleDataset.id, dataIndexConfig.id);
|
||||
try {
|
||||
const indexExists = await context.core.elasticsearch.client.asCurrentUser.indices.exists({
|
||||
const indexExists = await elasticsearch.client.asCurrentUser.indices.exists({
|
||||
index,
|
||||
});
|
||||
if (!indexExists) {
|
||||
return { status: NOT_INSTALLED };
|
||||
}
|
||||
|
||||
const count = await context.core.elasticsearch.client.asCurrentUser.count({
|
||||
const count = await elasticsearch.client.asCurrentUser.count({
|
||||
index,
|
||||
});
|
||||
if (count.count === 0) {
|
||||
|
|
|
@ -32,7 +32,7 @@ export function createUninstallRoute(
|
|||
return response.notFound();
|
||||
}
|
||||
|
||||
const sampleDataInstaller = getSampleDataInstaller({
|
||||
const sampleDataInstaller = await getSampleDataInstaller({
|
||||
datasetId: sampleDataset.id,
|
||||
sampleDatasets,
|
||||
logger,
|
||||
|
|
|
@ -11,7 +11,7 @@ import type { SampleDatasetSchema } from '../lib/sample_dataset_registry_types';
|
|||
import { SampleDataInstaller } from '../sample_data_installer';
|
||||
import { getUniqueObjectTypes } from '../lib/utils';
|
||||
|
||||
export const getSampleDataInstaller = ({
|
||||
export const getSampleDataInstaller = async ({
|
||||
datasetId,
|
||||
context,
|
||||
sampleDatasets,
|
||||
|
@ -22,14 +22,15 @@ export const getSampleDataInstaller = ({
|
|||
sampleDatasets: SampleDatasetSchema[];
|
||||
logger: Logger;
|
||||
}) => {
|
||||
const core = await context.core;
|
||||
const sampleDataset = sampleDatasets.find(({ id }) => id === datasetId)!;
|
||||
const { getImporter, client: soClient } = context.core.savedObjects;
|
||||
const { getImporter, client: soClient } = core.savedObjects;
|
||||
const objectTypes = getUniqueObjectTypes(sampleDataset.savedObjects);
|
||||
const savedObjectsClient = getSavedObjectsClient(context, objectTypes);
|
||||
const savedObjectsClient = await getSavedObjectsClient(context, objectTypes);
|
||||
const soImporter = getImporter(savedObjectsClient);
|
||||
|
||||
return new SampleDataInstaller({
|
||||
esClient: context.core.elasticsearch.client,
|
||||
esClient: core.elasticsearch.client,
|
||||
soImporter,
|
||||
soClient,
|
||||
logger,
|
||||
|
@ -37,8 +38,11 @@ export const getSampleDataInstaller = ({
|
|||
});
|
||||
};
|
||||
|
||||
export const getSavedObjectsClient = (context: RequestHandlerContext, objectTypes: string[]) => {
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
export const getSavedObjectsClient = async (
|
||||
context: RequestHandlerContext,
|
||||
objectTypes: string[]
|
||||
) => {
|
||||
const { getClient, typeRegistry } = (await context.core).savedObjects;
|
||||
const includedHiddenTypes = objectTypes.filter((supportedType) =>
|
||||
typeRegistry.isHidden(supportedType)
|
||||
);
|
||||
|
|
|
@ -29,7 +29,7 @@ export const registerBulkGetRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const managementService = await managementServicePromise;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = (await context.core).savedObjects;
|
||||
|
||||
const objects = req.body;
|
||||
const uniqueTypes = objects.reduce((acc, { type }) => acc.add(type), new Set<string>());
|
||||
|
|
|
@ -47,7 +47,7 @@ export const registerFindRoute = (
|
|||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { query } = req;
|
||||
const managementService = await managementServicePromise;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = (await context.core).savedObjects;
|
||||
|
||||
const searchTypes = Array.isArray(query.type) ? query.type : [query.type];
|
||||
const includedFields = Array.isArray(query.fields) ? query.fields : [query.fields];
|
||||
|
|
|
@ -25,7 +25,7 @@ export const registerGetAllowedTypesRoute = (router: IRouter) => {
|
|||
validate: false,
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const allowedTypes = context.core.savedObjects.typeRegistry
|
||||
const allowedTypes = (await context.core).savedObjects.typeRegistry
|
||||
.getImportableAndExportableTypes()
|
||||
.filter((type) => type.management!.visibleInManagement ?? true)
|
||||
.map(convertType);
|
||||
|
|
|
@ -32,7 +32,7 @@ export const registerRelationshipsRoute = (
|
|||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const managementService = await managementServicePromise;
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = (await context.core).savedObjects;
|
||||
const { type, id } = req.params;
|
||||
const { size, savedObjectTypes: maybeArraySavedObjectTypes } = req.query;
|
||||
const savedObjectTypes = Array.isArray(maybeArraySavedObjectTypes)
|
||||
|
|
|
@ -31,7 +31,7 @@ export const registerScrollForCountRoute = (router: IRouter) => {
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (context, req, res) => {
|
||||
const { getClient, typeRegistry } = context.core.savedObjects;
|
||||
const { getClient, typeRegistry } = (await context.core).savedObjects;
|
||||
const { typesToInclude, searchString, references } = req.body;
|
||||
|
||||
const includedHiddenTypes = chain(typesToInclude)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { RequestHandlerContext, KibanaRequest } from '@kbn/core/server';
|
||||
import type { CustomRequestHandlerContext, KibanaRequest } from '@kbn/core/server';
|
||||
|
||||
export interface ScreenshotModePluginStart {
|
||||
/**
|
||||
|
@ -32,8 +32,8 @@ export interface ScreenshotModePluginSetup extends ScreenshotModePluginStart {
|
|||
setScreenshotModeEnabled(): void;
|
||||
}
|
||||
|
||||
export interface ScreenshotModeRequestHandlerContext extends RequestHandlerContext {
|
||||
export type ScreenshotModeRequestHandlerContext = CustomRequestHandlerContext<{
|
||||
screenshotMode: {
|
||||
isScreenshot: boolean;
|
||||
};
|
||||
}
|
||||
}>;
|
||||
|
|
|
@ -34,7 +34,7 @@ export const registerCreateRoute = (router: IRouter, url: ServerUrlService) => {
|
|||
},
|
||||
},
|
||||
router.handleLegacyErrors(async (ctx, req, res) => {
|
||||
const savedObjects = ctx.core.savedObjects.client;
|
||||
const savedObjects = (await ctx.core).savedObjects.client;
|
||||
const shortUrls = url.shortUrls.get({ savedObjects });
|
||||
const { locatorId, params, slug, humanReadableSlug } = req.body;
|
||||
const locator = url.locators.get(locatorId);
|
||||
|
|
|
@ -25,7 +25,7 @@ export const registerDeleteRoute = (router: IRouter, url: ServerUrlService) => {
|
|||
},
|
||||
router.handleLegacyErrors(async (ctx, req, res) => {
|
||||
const id = req.params.id;
|
||||
const savedObjects = ctx.core.savedObjects.client;
|
||||
const savedObjects = (await ctx.core).savedObjects.client;
|
||||
const shortUrls = url.shortUrls.get({ savedObjects });
|
||||
|
||||
await shortUrls.delete(id);
|
||||
|
|
|
@ -25,7 +25,7 @@ export const registerGetRoute = (router: IRouter, url: ServerUrlService) => {
|
|||
},
|
||||
router.handleLegacyErrors(async (ctx, req, res) => {
|
||||
const id = req.params.id;
|
||||
const savedObjects = ctx.core.savedObjects.client;
|
||||
const savedObjects = (await ctx.core).savedObjects.client;
|
||||
const shortUrls = url.shortUrls.get({ savedObjects });
|
||||
const shortUrl = await shortUrls.get(id);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ export const registerResolveRoute = (router: IRouter, url: ServerUrlService) =>
|
|||
},
|
||||
router.handleLegacyErrors(async (ctx, req, res) => {
|
||||
const slug = req.params.slug;
|
||||
const savedObjects = ctx.core.savedObjects.client;
|
||||
const savedObjects = (await ctx.core).savedObjects.client;
|
||||
|
||||
try {
|
||||
const shortUrls = url.shortUrls.get({ savedObjects });
|
||||
|
|
|
@ -48,12 +48,13 @@ export function registerTelemetryOptInRoutes({
|
|||
},
|
||||
async (context, req, res) => {
|
||||
const newOptInStatus = req.body.enabled;
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const attributes: TelemetrySavedObjectAttributes = {
|
||||
enabled: newOptInStatus,
|
||||
lastVersionChecked: currentKibanaVersion,
|
||||
};
|
||||
const config = await firstValueFrom(config$);
|
||||
const telemetrySavedObject = await getTelemetrySavedObject(context.core.savedObjects.client);
|
||||
const telemetrySavedObject = await getTelemetrySavedObject(soClient);
|
||||
|
||||
if (telemetrySavedObject === false) {
|
||||
// If we get false, we couldn't get the saved object due to lack of permissions
|
||||
|
@ -96,7 +97,7 @@ export function registerTelemetryOptInRoutes({
|
|||
}
|
||||
|
||||
try {
|
||||
await updateTelemetrySavedObject(context.core.savedObjects.client, attributes);
|
||||
await updateTelemetrySavedObject(soClient, attributes);
|
||||
} catch (e) {
|
||||
if (SavedObjectsErrorHelpers.isForbiddenError(e)) {
|
||||
return res.forbidden();
|
||||
|
|
|
@ -21,7 +21,7 @@ export function registerTelemetryUserHasSeenNotice(router: IRouter) {
|
|||
validate: false,
|
||||
},
|
||||
async (context, req, res) => {
|
||||
const internalRepository = context.core.savedObjects.client;
|
||||
const internalRepository = (await context.core).savedObjects.client;
|
||||
const telemetrySavedObject: TelemetrySavedObject = await getTelemetrySavedObject(
|
||||
internalRepository
|
||||
);
|
||||
|
|
|
@ -45,13 +45,14 @@ export function registerValueSuggestionsRoute(router: IRouter, config$: Observab
|
|||
const { field: fieldName, query, filters, fieldMeta, method } = request.body;
|
||||
const { index } = request.params;
|
||||
const abortSignal = getRequestAbortedSignal(request.events.aborted$);
|
||||
const { savedObjects, elasticsearch } = await context.core;
|
||||
|
||||
try {
|
||||
const fn = method === 'terms_agg' ? termsAggSuggestions : termsEnumSuggestions;
|
||||
const body = await fn(
|
||||
config,
|
||||
context.core.savedObjects.client,
|
||||
context.core.elasticsearch.client.asCurrentUser,
|
||||
savedObjects.client,
|
||||
elasticsearch.client.asCurrentUser,
|
||||
index,
|
||||
fieldName,
|
||||
query,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue