diff --git a/api_docs/core.json b/api_docs/core.json index 4d0f9dac3bf96..856dbb7e3737f 100644 --- a/api_docs/core.json +++ b/api_docs/core.json @@ -7985,22 +7985,11 @@ "id": "def-server.IContextContainer", "type": "Interface", "label": "IContextContainer", - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.IContextContainer", - "text": "IContextContainer" - }, - "" - ], "description": [ "\nAn object that handles registration of context providers and configuring handlers with context.\n" ], "tags": [ "remarks", - "typeParam", "public" ], "children": [ @@ -8043,8 +8032,8 @@ ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 154, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L154" + "lineNumber": 151, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L151" } }, { @@ -8059,8 +8048,8 @@ ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 155, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L155" + "lineNumber": 152, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L152" } }, { @@ -8082,8 +8071,8 @@ ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 156, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L156" + "lineNumber": 153, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L153" } } ], @@ -8095,8 +8084,8 @@ ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 153, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L153" + "lineNumber": 150, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L150" } }, { @@ -8104,17 +8093,40 @@ "type": "Function", "label": "createHandler", "signature": [ - "(pluginOpaqueId: symbol, handler: THandler) => (...rest: ", + "(pluginOpaqueId: symbol, handler: ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.RequestHandler", + "text": "RequestHandler" + }, + " | Error | { message: string | Error; attributes?: Record | undefined; } | Buffer | ", + "Stream", + " | undefined>(options: ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.CustomHttpResponseOptions", + "text": "CustomHttpResponseOptions" }, - ") => ", - "ShallowPromise", - ">" + ") => ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.KibanaResponse", + "text": "KibanaResponse" + } ], "description": [ "\nCreate a new handler function pre-wired to context for the plugin.\n" @@ -8132,8 +8144,8 @@ ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 168, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L168" + "lineNumber": 165, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L165" } }, { @@ -8141,33 +8153,65 @@ "label": "handler", "isRequired": true, "signature": [ - "THandler" + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.RequestHandler", + "text": "RequestHandler" + }, + " | Error | { message: string | Error; attributes?: Record | undefined; } | Buffer | ", + "Stream", + " | undefined>(options: ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.CustomHttpResponseOptions", + "text": "CustomHttpResponseOptions" + }, + ") => ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.KibanaResponse", + "text": "KibanaResponse" + } ], "description": [ "- Handler function to pass context object to." ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 169, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L169" + "lineNumber": 166, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L166" } } ], "tags": [], "returnComment": [ - "A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of\nthe `handler` return value." + "A function that takes `RequestHandler` parameters, calls `handler` with a new context, and returns a Promise of\nthe `handler` return value." ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 167, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L167" + "lineNumber": 164, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L164" } } ], "source": { "path": "src/core/server/context/container/context.ts", - "lineNumber": 138, - "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L138" + "lineNumber": 135, + "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/context/container/context.ts#L135" }, "initialIsOpen": false }, @@ -16631,23 +16675,14 @@ "type": "Function", "label": "createContextContainer", "signature": [ - ">() => ", + "() => ", { "pluginId": "core", "scope": "server", "docId": "kibCorePluginApi", "section": "def-server.IContextContainer", "text": "IContextContainer" - }, - "" + } ], "description": [ "\nCreates a new {@link IContextContainer} for a service owner." diff --git a/api_docs/core_http.json b/api_docs/core_http.json index 8e3a753da3a0b..284c2efc4cc38 100644 --- a/api_docs/core_http.json +++ b/api_docs/core_http.json @@ -3725,9 +3725,9 @@ { "pluginId": "core", "scope": "server", - "docId": "kibCoreHttpPluginApi", - "section": "def-server.RequestHandlerContextContainer", - "text": "RequestHandlerContextContainer" + "docId": "kibCorePluginApi", + "section": "def-server.IContextContainer", + "text": "IContextContainer" } ] }, @@ -6509,28 +6509,7 @@ "link": "https://github.com/elastic/kibana/tree/mastersrc/core/server/http/types.ts#L30" }, "signature": [ - "IContextContainer | Error | { message: string | Error; attributes?: Record | undefined; } | Buffer | ", - "Stream", - " | undefined>(options: ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.CustomHttpResponseOptions", - "text": "CustomHttpResponseOptions" - }, - ") => ", - "KibanaResponse", - "; badRequest: (options?: ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.ErrorHttpResponseOptions", - "text": "ErrorHttpResponseOptions" - }, - ") => ", - "KibanaResponse" + "IContextContainer" ], "initialIsOpen": false }, diff --git a/docs/development/core/server/kibana-plugin-core-server.contextsetup.createcontextcontainer.md b/docs/development/core/server/kibana-plugin-core-server.contextsetup.createcontextcontainer.md index d19eec9ae5015..0d12fc16af423 100644 --- a/docs/development/core/server/kibana-plugin-core-server.contextsetup.createcontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-core-server.contextsetup.createcontextcontainer.md @@ -9,9 +9,9 @@ Creates a new [IContextContainer](./kibana-plugin-core-server.icontextcontainer. Signature: ```typescript -createContextContainer>(): IContextContainer; +createContextContainer(): IContextContainer; ``` Returns: -`IContextContainer` +`IContextContainer` diff --git a/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.createhandler.md b/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.createhandler.md index 8fbc6b8b73697..7d7368426b1c2 100644 --- a/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.createhandler.md +++ b/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.createhandler.md @@ -9,7 +9,7 @@ Create a new handler function pre-wired to context for the plugin. Signature: ```typescript -createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; +createHandler(pluginOpaqueId: PluginOpaqueId, handler: RequestHandler): (...rest: HandlerParameters) => ShallowPromise>; ``` ## Parameters @@ -17,11 +17,11 @@ createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: Hand | Parameter | Type | Description | | --- | --- | --- | | pluginOpaqueId | PluginOpaqueId | The plugin opaque ID for the plugin that registers this handler. | -| handler | THandler | Handler function to pass context object to. | +| handler | RequestHandler | Handler function to pass context object to. | Returns: -`(...rest: HandlerParameters) => ShallowPromise>` +`(...rest: HandlerParameters) => ShallowPromise>` -A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of the `handler` return value. +A function that takes `RequestHandler` parameters, calls `handler` with a new context, and returns a Promise of the `handler` return value. diff --git a/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.md b/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.md index 3b390e3aaa117..8b4d3f39e345e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-core-server.icontextcontainer.md @@ -9,7 +9,7 @@ An object that handles registration of context providers and configuring handler Signature: ```typescript -export interface IContextContainer +export interface IContextContainer ``` ## Remarks diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontextcontainer.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontextcontainer.md index 6966deb9d7cc7..09e7ff261b795 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontextcontainer.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontextcontainer.md @@ -9,5 +9,5 @@ An object that handles registration of http request context providers. Signature: ```typescript -export declare type RequestHandlerContextContainer = IContextContainer; +export declare type RequestHandlerContextContainer = IContextContainer; ``` diff --git a/src/core/server/context/container/context.mock.ts b/src/core/server/context/container/context.mock.ts index 0a2530dfc345e..2a43006301c03 100644 --- a/src/core/server/context/container/context.mock.ts +++ b/src/core/server/context/container/context.mock.ts @@ -8,16 +8,16 @@ import { IContextContainer } from './context'; -export type ContextContainerMock = jest.Mocked>; +export type ContextContainerMock = jest.Mocked; -const createContextMock = (mockContext = {}) => { +const createContextMock = (mockContext: any = {}) => { const contextMock: ContextContainerMock = { - // @ts-expect-error tsc cannot infer ContextName and uses never + // @ts-expect-error since ContextContainerMock cannot infer ContextName and fallsback to never registerContext: jest.fn(), createHandler: jest.fn(), }; contextMock.createHandler.mockImplementation((pluginId, handler) => (...args) => - handler(mockContext, ...args) + Promise.resolve(handler(mockContext, ...args)) ); return contextMock; }; diff --git a/src/core/server/context/container/context.test.ts b/src/core/server/context/container/context.test.ts index 693eed7873754..25fab2e3f0bfb 100644 --- a/src/core/server/context/container/context.test.ts +++ b/src/core/server/context/container/context.test.ts @@ -65,6 +65,30 @@ describe('ContextContainer', () => { `"Cannot register context for unknown plugin: Symbol(unknown)"` ); }); + + 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'>( + pluginA, + 'ctxFromA', + // @ts-expect-error expected string, returned number + async () => 1 + ) + ).not.toThrow(); + }); + + it('reports a TS error if registers a context for unknown property name', async () => { + const contextContainer = new ContextContainer(plugins, coreId); + await expect(() => + // @ts-expect-error expects ctxFromB, but given ctxFromC + contextContainer.registerContext<{ ctxFromB: string; core: any }, 'ctxFromC'>( + pluginB, + 'ctxFromC', + async () => 1 + ) + ).not.toThrow(); + }); }); describe('context building', () => { diff --git a/src/core/server/context/container/context.ts b/src/core/server/context/container/context.ts index 98b87ee888c75..f3d91e268bd1c 100644 --- a/src/core/server/context/container/context.ts +++ b/src/core/server/context/container/context.ts @@ -130,12 +130,9 @@ export type HandlerParameters> = T extends ( * } * ``` * - * @typeParam THandler - the type of {@link HandlerFunction} this container should manage. The first argument of this - * function will be used as the context type. - * * @public */ -export interface IContextContainer { +export interface IContextContainer { /** * Register a new context provider. * @@ -161,18 +158,17 @@ export interface IContextContainer { * * @param pluginOpaqueId - The plugin opaque ID for the plugin that registers this handler. * @param handler - Handler function to pass context object to. - * @returns A function that takes `THandlerParameters`, calls `handler` with a new context, and returns a Promise of + * @returns A function that takes `RequestHandler` parameters, calls `handler` with a new context, and returns a Promise of * the `handler` return value. */ createHandler( pluginOpaqueId: PluginOpaqueId, - handler: THandler - ): (...rest: HandlerParameters) => ShallowPromise>; + handler: RequestHandler + ): (...rest: HandlerParameters) => ShallowPromise>; } /** @internal */ -export class ContextContainer - implements IContextContainer { +export class ContextContainer implements IContextContainer { /** * Used to map contexts to their providers and associated plugin. In registration order which is tightly coupled to * plugin load order. @@ -222,22 +218,23 @@ export class ContextContainer return this; }; - public createHandler = (source: symbol, handler: THandler) => { + public createHandler = (source: symbol, handler: RequestHandler) => { if (source !== this.coreId && !this.pluginDependencies.has(source)) { throw new Error(`Cannot create handler for unknown plugin: ${source.toString()}`); } - return (async (...args: HandlerParameters) => { + return (async (...args: HandlerParameters) => { const context = await this.buildContext(source, ...args); - // @ts-expect-error requires explicit handler arity return handler(context, ...args); - }) as (...args: HandlerParameters) => ShallowPromise>; + }) as ( + ...args: HandlerParameters + ) => ShallowPromise>; }; private async buildContext( source: symbol, - ...contextArgs: HandlerParameters - ): Promise> { + ...contextArgs: HandlerParameters + ): Promise> { const contextsToBuild = new Set(this.getContextNamesForSource(source)); return [...this.contextProviders] @@ -254,10 +251,9 @@ export class ContextContainer return { ...resolvedContext, - // @ts-expect-error requires explicit provider arity [contextName]: await provider(exposedContext, ...contextArgs), }; - }, Promise.resolve({}) as Promise>); + }, Promise.resolve({}) as Promise>); } private getContextNamesForSource(source: symbol): ReadonlySet { diff --git a/src/core/server/context/context_service.ts b/src/core/server/context/context_service.ts index 536b10b750b7b..68a99ed3d4156 100644 --- a/src/core/server/context/context_service.ts +++ b/src/core/server/context/context_service.ts @@ -7,7 +7,7 @@ */ import { PluginOpaqueId } from '../../server'; -import { IContextContainer, ContextContainer, HandlerFunction } from './container'; +import { IContextContainer, ContextContainer } from './container'; import { CoreContext } from '../core_context'; interface SetupDeps { @@ -20,8 +20,8 @@ export class ContextService { public setup({ pluginDependencies }: SetupDeps): ContextSetup { return { - createContextContainer: >() => { - return new ContextContainer(pluginDependencies, this.core.coreId); + createContextContainer: () => { + return new ContextContainer(pluginDependencies, this.core.coreId); }, }; } @@ -93,5 +93,5 @@ export interface ContextSetup { /** * Creates a new {@link IContextContainer} for a service owner. */ - createContextContainer>(): IContextContainer; + createContextContainer(): IContextContainer; } diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts index 8cb23e9d67f57..f007a77a2a21a 100644 --- a/src/core/server/http/types.ts +++ b/src/core/server/http/types.ts @@ -10,7 +10,7 @@ import { IContextProvider, IContextContainer } from '../context'; import { ICspConfig } from '../csp'; import { GetAuthState, IsAuthenticated } from './auth_state_storage'; import { GetAuthHeaders } from './auth_headers_storage'; -import { RequestHandler, IRouter } from './router'; +import { IRouter } from './router'; import { HttpServerSetup } from './http_server'; import { SessionStorageCookieOptions } from './cookie_session_storage'; import { SessionStorageFactory } from './session_storage'; @@ -27,7 +27,7 @@ import type { PluginOpaqueId, RequestHandlerContext } from '..'; * An object that handles registration of http request context providers. * @public */ -export type RequestHandlerContextContainer = IContextContainer; +export type RequestHandlerContextContainer = IContextContainer; /** * Context provider for request handler. diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 15adae32cca6d..a1a774e8721c8 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -383,7 +383,7 @@ export { ConfigService } // @public export interface ContextSetup { - createContextContainer>(): IContextContainer; + createContextContainer(): IContextContainer; } // @internal @@ -1063,8 +1063,8 @@ export interface IClusterClient { } // @public -export interface IContextContainer { - createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; +export interface IContextContainer { + createHandler(pluginOpaqueId: PluginOpaqueId, handler: RequestHandler): (...rest: HandlerParameters) => ShallowPromise>; registerContext(pluginOpaqueId: PluginOpaqueId, contextName: ContextName, provider: IContextProvider): this; } @@ -1932,7 +1932,7 @@ export interface RequestHandlerContext { } // @public -export type RequestHandlerContextContainer = IContextContainer; +export type RequestHandlerContextContainer = IContextContainer; // @public export type RequestHandlerContextProvider = IContextProvider;