From 8a244223cad387364c3362ddadbda8a00a33579e Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Tue, 13 Aug 2019 10:06:34 -0500 Subject: [PATCH] [7.x] Export missing Context types (#43051) (#43143) --- ...-public.icontextcontainer.createhandler.md | 4 +- ...ver.contextsetup.createcontextcontainer.md | 2 +- .../kibana-plugin-server.contextsetup.md | 63 ++++++++++++++- ...-server.icontextcontainer.createhandler.md | 27 +++++++ .../kibana-plugin-server.icontextcontainer.md | 80 +++++++++++++++++++ ...erver.icontextcontainer.registercontext.md | 34 ++++++++ .../kibana-plugin-server.icontexthandler.md | 18 +++++ .../kibana-plugin-server.icontextprovider.md | 18 +++++ .../core/server/kibana-plugin-server.md | 5 +- src/core/public/public.api.md | 3 +- src/core/server/index.ts | 1 + src/core/server/server.api.md | 18 +++-- src/core/utils/context.ts | 10 ++- 13 files changed, 267 insertions(+), 16 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md create mode 100644 docs/development/core/server/kibana-plugin-server.icontextcontainer.md create mode 100644 docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md create mode 100644 docs/development/core/server/kibana-plugin-server.icontexthandler.md create mode 100644 docs/development/core/server/kibana-plugin-server.icontextprovider.md diff --git a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md index a02cc0f2e0a39..2a995df45757f 100644 --- a/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md +++ b/docs/development/core/public/kibana-plugin-public.icontextcontainer.createhandler.md @@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin. Signature: ```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => Promisify; +createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; ``` ## Parameters @@ -21,7 +21,7 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandlerReturns: -`(...rest: THandlerParameters) => Promisify` +`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise` A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md index e028e1391f284..f44e6a3d7640b 100644 --- a/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-server.contextsetup.createcontextcontainer.md @@ -4,7 +4,7 @@ ## ContextSetup.createContextContainer() method -Creates a new for a service owner. +Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. Signature: diff --git a/docs/development/core/server/kibana-plugin-server.contextsetup.md b/docs/development/core/server/kibana-plugin-server.contextsetup.md index 972266583e336..0b4f5aa5d403b 100644 --- a/docs/development/core/server/kibana-plugin-server.contextsetup.md +++ b/docs/development/core/server/kibana-plugin-server.contextsetup.md @@ -4,6 +4,8 @@ ## ContextSetup interface +An object that handles registration of context providers and configuring handlers with context. + Signature: ```typescript @@ -14,7 +16,66 @@ export interface ContextSetup | Method | Description | | --- | --- | -| [createContextContainer()](./kibana-plugin-server.contextsetup.createcontextcontainer.md) | Creates a new for a service owner. | +| [createContextContainer()](./kibana-plugin-server.contextsetup.createcontextcontainer.md) | Creates a new [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for a service owner. | + +## Remarks + +A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` ## Example diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md new file mode 100644 index 0000000000000..c5549ab017e53 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.createhandler.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [createHandler](./kibana-plugin-server.icontextcontainer.createhandler.md) + +## IContextContainer.createHandler() method + +Create a new handler function pre-wired to context for the plugin. + +Signature: + +```typescript +createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | +| handler | IContextHandler<TContext, THandlerReturn, THandlerParameters> | Handler function to pass context object to. | + +Returns: + +`(...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise` + +A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. + diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md new file mode 100644 index 0000000000000..1ab699be105b4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.md @@ -0,0 +1,80 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) + +## IContextContainer interface + +An object that handles registration of context providers and configuring handlers with context. + +Signature: + +```typescript +export interface IContextContainer +``` + +## Methods + +| Method | Description | +| --- | --- | +| [createHandler(pluginOpaqueId, handler)](./kibana-plugin-server.icontextcontainer.createhandler.md) | Create a new handler function pre-wired to context for the plugin. | +| [registerContext(pluginOpaqueId, contextName, provider)](./kibana-plugin-server.icontextcontainer.registercontext.md) | Register a new context provider. | + +## Remarks + +A [IContextContainer](./kibana-plugin-server.icontextcontainer.md) can be used by any Core service or plugin (known as the "service owner") which wishes to expose APIs in a handler function. The container object will manage registering context providers and configuring a handler with all of the contexts that should be exposed to the handler's plugin. This is dependent on the dependencies that the handler's plugin declares. + +Contexts providers are executed in the order they were registered. Each provider gets access to context values provided by any plugins that it depends on. + +In order to configure a handler with context, you must call the [IContextContainer.createHandler()](./kibana-plugin-server.icontextcontainer.createhandler.md) function and use the returned handler which will automatically build a context object when called. + +When registering context or creating handlers, the \_calling plugin's opaque id\_ must be provided. This id is passed in via the plugin's initializer and can be accessed from the [PluginInitializerContext.opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) Note this should NOT be the context service owner's id, but the plugin that is actually registering the context or handler. + +```ts +// Correct +class MyPlugin { + private readonly handlers = new Map(); + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(pluginOpaqueId, contextName, provider) { + this.contextContainer.registerContext(pluginOpaqueId, contextName, provider); + }, + registerRoute(pluginOpaqueId, path, handler) { + this.handlers.set( + path, + this.contextContainer.createHandler(pluginOpaqueId, handler) + ); + } + } + } +} + +// Incorrect +class MyPlugin { + private readonly handlers = new Map(); + + constructor(private readonly initContext: PluginInitializerContext) {} + + setup(core) { + this.contextContainer = core.context.createContextContainer(); + return { + registerContext(contextName, provider) { + // BUG! + // This would leak this context to all handlers rather that only plugins that depend on the calling plugin. + this.contextContainer.registerContext(this.initContext.opaqueId, contextName, provider); + }, + registerRoute(path, handler) { + this.handlers.set( + path, + // BUG! + // This handler will not receive any contexts provided by other dependencies of the calling plugin. + this.contextContainer.createHandler(this.initContext.opaqueId, handler) + ); + } + } + } +} + +``` + diff --git a/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md new file mode 100644 index 0000000000000..1a63f63dc91b4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.icontextcontainer.registercontext.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextContainer](./kibana-plugin-server.icontextcontainer.md) > [registerContext](./kibana-plugin-server.icontextcontainer.registercontext.md) + +## IContextContainer.registerContext() method + +Register a new context provider. + +Signature: + +```typescript +registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this context. | +| contextName | TContextName | The key of the TContext object this provider supplies the value for. | +| provider | IContextProvider<TContext, TContextName, THandlerParameters> | A [IContextProvider](./kibana-plugin-server.icontextprovider.md) to be called each time a new context is created. | + +Returns: + +`this` + +The [IContextContainer](./kibana-plugin-server.icontextcontainer.md) for method chaining. + +## Remarks + +The value (or resolved Promise value) returned by the `provider` function will be attached to the context object on the key specified by `contextName`. + +Throws an exception if more than one provider is registered for the same `contextName`. + diff --git a/docs/development/core/server/kibana-plugin-server.icontexthandler.md b/docs/development/core/server/kibana-plugin-server.icontexthandler.md new file mode 100644 index 0000000000000..c1f5acc22734a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.icontexthandler.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextHandler](./kibana-plugin-server.icontexthandler.md) + +## IContextHandler type + +A function registered by a plugin to perform some action. + +Signature: + +```typescript +export declare type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; +``` + +## Remarks + +A new `TContext` will be built for each handler before invoking. + diff --git a/docs/development/core/server/kibana-plugin-server.icontextprovider.md b/docs/development/core/server/kibana-plugin-server.icontextprovider.md new file mode 100644 index 0000000000000..250e6a2be3f6a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.icontextprovider.md @@ -0,0 +1,18 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [IContextProvider](./kibana-plugin-server.icontextprovider.md) + +## IContextProvider type + +A function that returns a context value for a specific key of given context type. + +Signature: + +```typescript +export declare type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; +``` + +## Remarks + +This function will be called each time a new context is built for a handler invocation. + diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index e6a51055410d5..7b7e9aee42c01 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -37,7 +37,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AuthResultParams](./kibana-plugin-server.authresultparams.md) | Result of an incoming request authentication. | | [AuthToolkit](./kibana-plugin-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | | [CallAPIOptions](./kibana-plugin-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | -| [ContextSetup](./kibana-plugin-server.contextsetup.md) | | +| [ContextSetup](./kibana-plugin-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. | | [CoreSetup](./kibana-plugin-server.coresetup.md) | Context passed to the plugins setup method. | | [CoreStart](./kibana-plugin-server.corestart.md) | Context passed to the plugins start method. | | [CustomHttpResponseOptions](./kibana-plugin-server.customhttpresponseoptions.md) | HTTP response parameters for a response with adjustable status code. | @@ -48,6 +48,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters | | [HttpServerSetup](./kibana-plugin-server.httpserversetup.md) | Kibana HTTP Service provides own abstraction for work with HTTP stack. Plugins don't have direct access to hapi server and its primitives anymore. Moreover, plugins shouldn't rely on the fact that HTTP Service uses one or another library under the hood. This gives the platform flexibility to upgrade or changing our internal HTTP stack without breaking plugins. If the HTTP Service lacks functionality you need, we are happy to discuss and support your needs. | | [HttpServiceStart](./kibana-plugin-server.httpservicestart.md) | | +| [IContextContainer](./kibana-plugin-server.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | | [IKibanaSocket](./kibana-plugin-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | | [InternalCoreStart](./kibana-plugin-server.internalcorestart.md) | | | [IRouter](./kibana-plugin-server.irouter.md) | Registers route handlers for specified resource path and method. | @@ -118,6 +119,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [Headers](./kibana-plugin-server.headers.md) | Http request headers to read. | | [HttpResponsePayload](./kibana-plugin-server.httpresponsepayload.md) | Data send to the client as a response payload. | | [HttpServiceSetup](./kibana-plugin-server.httpservicesetup.md) | | +| [IContextHandler](./kibana-plugin-server.icontexthandler.md) | A function registered by a plugin to perform some action. | +| [IContextProvider](./kibana-plugin-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | | [IsAuthenticated](./kibana-plugin-server.isauthenticated.md) | Return authentication status for a request. | | [KibanaResponseFactory](./kibana-plugin-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | | [KnownHeaders](./kibana-plugin-server.knownheaders.md) | Set of well-known HTTP headers. | diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 4e45d326aeb80..a5c31e41e0267 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -492,8 +492,7 @@ export interface I18nStart { // @public export interface IContextContainer { - // Warning: (ae-forgotten-export) The symbol "Promisify" needs to be exported by the entry point index.d.ts - createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => Promisify; + createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; } diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 6ad514094c731..5f6a273c8dd8c 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -51,6 +51,7 @@ import { ContextSetup } from './context'; export { bootstrap } from './bootstrap'; export { ConfigPath, ConfigService } from './config'; +export { IContextContainer, IContextProvider, IContextHandler } from './context'; export { CoreId } from './core_context'; export { CallAPIOptions, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index f6945667eeb06..6597fdf0259d4 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -93,12 +93,8 @@ export class ConfigService { setSchema(path: ConfigPath, schema: Type): Promise; } -// Warning: (ae-unresolved-inheritdoc-reference) The @inheritDoc reference could not be resolved: The package "kibana" does not have an export "IContextContainer" -// -// @public (undocumented) +// @public export interface ContextSetup { - // Warning: (ae-forgotten-export) The symbol "IContextContainer" needs to be exported by the entry point index.d.ts - // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "IContextContainer" createContextContainer(): IContextContainer; } @@ -251,6 +247,18 @@ export interface HttpServiceStart { isListening: (port: number) => boolean; } +// @public +export interface IContextContainer { + createHandler(pluginOpaqueId: PluginOpaqueId, handler: IContextHandler): (...rest: THandlerParameters) => THandlerReturn extends Promise ? THandlerReturn : Promise; + registerContext(pluginOpaqueId: PluginOpaqueId, contextName: TContextName, provider: IContextProvider): this; +} + +// @public +export type IContextHandler = (context: TContext, ...rest: THandlerParameters) => TReturn; + +// @public +export type IContextProvider, TContextName extends keyof TContext, TProviderParameters extends any[] = []> = (context: Partial, ...rest: TProviderParameters) => Promise | TContext[TContextName]; + // @public export interface IKibanaSocket { // (undocumented) diff --git a/src/core/utils/context.ts b/src/core/utils/context.ts index 2efe68cc5d764..8c3b5aa163994 100644 --- a/src/core/utils/context.ts +++ b/src/core/utils/context.ts @@ -56,8 +56,6 @@ export type IContextHandler TReturn; -type Promisify = T extends Promise ? Promise : Promise; - /** * An object that handles registration of context providers and configuring handlers with context. * @@ -163,7 +161,9 @@ export interface IContextContainer< createHandler( pluginOpaqueId: PluginOpaqueId, handler: IContextHandler - ): (...rest: THandlerParameters) => Promisify; + ): ( + ...rest: THandlerParameters + ) => THandlerReturn extends Promise ? THandlerReturn : Promise; } /** @internal */ @@ -228,7 +228,9 @@ export class ContextContainer< return (async (...args: THandlerParameters) => { const context = await this.buildContext(source, ...args); return handler(context, ...args); - }) as (...args: THandlerParameters) => Promisify; + }) as ( + ...args: THandlerParameters + ) => THandlerReturn extends Promise ? THandlerReturn : Promise; }; private async buildContext(