More strict plugin type definitions (#205232)

Stricter defaults for plugin types: `Plugin` and `CoreSetup` now have
empty objects as defaults instead of `object` which is assignable to
anything basically. This catches some type errors, but my motivation for
this is to allow something like:

```ts
function createPlugin ():Plugin<MySetupContract, MyStartContract, MySetupDependencies, MyStartDependencies> {
	return {
		// look ma, no additional typing necessary
		setup ( coreSetup, pluginsSetup ) {
		},
		start ( coreStart, pluginsStart ) {
		}
	}
}
```
This commit is contained in:
Dario Gieselaar 2025-01-07 16:41:15 +01:00 committed by GitHub
parent c3c6bfba08
commit 98ce312ba3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 133 additions and 59 deletions

View file

@ -61,7 +61,10 @@ export interface EsoModelVersionExamplePluginsStart {
encryptedSavedObjects: EncryptedSavedObjectsPluginStart;
}
export class EsoModelVersionExample implements Plugin<void, void> {
export class EsoModelVersionExample
implements
Plugin<void, void, EsoModelVersionExamplePluginSetup, EsoModelVersionExamplePluginsStart>
{
public setup(
core: CoreSetup<EsoModelVersionExamplePluginsStart>,
plugins: EsoModelVersionExamplePluginSetup

View file

@ -36,7 +36,7 @@ import type { CoreStart } from './core_start';
* navigation in the generated docs until there's a fix for
* https://github.com/Microsoft/web-build-tools/issues/1237
*/
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
export interface CoreSetup<TPluginsStart extends Record<string, any> = {}, TStart = unknown> {
/** {@link AnalyticsServiceSetup} */
analytics: AnalyticsServiceSetup;
/** {@link ApplicationSetup} */

View file

@ -40,7 +40,7 @@ import type { CoreStart } from './core_start';
* consuming {@link Plugin}'s `TStart` type. Used by `getStartServices`.
* @public
*/
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
export interface CoreSetup<TPluginsStart extends Record<string, any> = {}, TStart = unknown> {
/** {@link AnalyticsServiceSetup} */
analytics: AnalyticsServiceSetup;
/** {@link CapabilitiesSetup} */

View file

@ -18,8 +18,8 @@ import type { CoreStart, CoreSetup } from '@kbn/core-lifecycle-browser';
export interface Plugin<
TSetup = void,
TStart = void,
TPluginsSetup extends object = object,
TPluginsStart extends object = object
TPluginsSetup extends Record<string, any> = never,
TPluginsStart extends Record<string, any> = never
> {
setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup;

View file

@ -19,10 +19,10 @@ import type { Plugin } from './plugin';
* @public
*/
export type PluginInitializer<
TSetup,
TStart,
TPluginsSetup extends object = object,
TPluginsStart extends object = object
TSetup = void,
TStart = void,
TPluginsSetup extends Record<string, any> = never,
TPluginsStart extends Record<string, any> = never
> = (core: PluginInitializerContext) => Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
/**

View file

@ -98,7 +98,7 @@ export class PluginWrapper<
* is the contract returned by the dependency's `setup` function.
*/
public setup(
setupContext: CoreSetup<TPluginsStart> | CorePreboot,
setupContext: CoreSetup<TPluginsStart, TStart> | CorePreboot,
plugins: TPluginsSetup
): TSetup | Promise<TSetup> {
if (!this.instance) {
@ -109,7 +109,7 @@ export class PluginWrapper<
return this.instance.setup(setupContext as CorePreboot, plugins);
}
return this.instance.setup(setupContext as CoreSetup, plugins);
return this.instance.setup(setupContext as CoreSetup<TPluginsStart, TStart>, plugins);
}
/**

View file

@ -291,10 +291,10 @@ export interface PrebootPlugin<TSetup = void, TPluginsSetup extends object = obj
export interface Plugin<
TSetup = void,
TStart = void,
TPluginsSetup extends object = object,
TPluginsStart extends object = object
TPluginsSetup extends Record<string, any> = {},
TPluginsStart extends Record<string, any> = {}
> {
setup(core: CoreSetup, plugins: TPluginsSetup): TSetup;
setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup;
start(core: CoreStart, plugins: TPluginsStart): TStart;
@ -451,10 +451,10 @@ export interface PluginInitializerContext<ConfigSchema = unknown> {
* @public
*/
export type PluginInitializer<
TSetup,
TStart,
TPluginsSetup extends object = object,
TPluginsStart extends object = object
TSetup = void,
TStart = void,
TPluginsSetup extends Record<string, any> = never,
TPluginsStart extends Record<string, any> = never
> = (
core: PluginInitializerContext
) => Promise<

View file

@ -54,5 +54,7 @@ export class MapsEmsPlugin implements Plugin<MapsEmsPluginServerSetup> {
};
}
public start() {}
public start() {
return {};
}
}

View file

@ -45,7 +45,7 @@ interface StartDeps {
}
export class DashboardPlugin
implements Plugin<DashboardPluginSetup, DashboardPluginStart, SetupDeps>
implements Plugin<DashboardPluginSetup, DashboardPluginStart, SetupDeps, StartDeps>
{
private readonly logger: Logger;
@ -53,7 +53,7 @@ export class DashboardPlugin
this.logger = initializerContext.logger.get();
}
public setup(core: CoreSetup<StartDeps>, plugins: SetupDeps) {
public setup(core: CoreSetup<StartDeps, DashboardPluginStart>, plugins: SetupDeps) {
this.logger.debug('dashboard: Setup');
core.savedObjects.registerType(

View file

@ -15,7 +15,6 @@ import {
CoreStart,
KibanaRequest,
Logger,
Plugin,
PluginInitializerContext,
SharedGlobalConfig,
StartServicesAccessor,
@ -121,7 +120,7 @@ export interface SearchRouteDependencies {
globalConfig$: Observable<SharedGlobalConfig>;
}
export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
export class SearchService {
private readonly aggsService = new AggsService();
private readonly searchSourceService = new SearchSourceService();
private searchStrategies: StrategyMap = {};

View file

@ -25,7 +25,15 @@ export interface UnifiedSearchServerPluginSetupDependencies {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface UnifiedSearchServerPluginStartDependencies {}
export class UnifiedSearchServerPlugin implements Plugin<UnifiedSearchServerPluginSetup> {
export class UnifiedSearchServerPlugin
implements
Plugin<
UnifiedSearchServerPluginSetup,
UnifiedSearchServerPluginStart,
UnifiedSearchServerPluginSetupDependencies,
UnifiedSearchServerPluginStartDependencies
>
{
private readonly autocompleteService: AutocompleteService;
constructor(initializerContext: PluginInitializerContext<ConfigSchema>) {

View file

@ -82,7 +82,15 @@ export interface Framework {
getEsShardTimeout: () => Promise<number>;
}
export class VisTypeTimeseriesPlugin implements Plugin<VisTypeTimeseriesSetup> {
export class VisTypeTimeseriesPlugin
implements
Plugin<
VisTypeTimeseriesSetup,
void,
VisTypeTimeseriesPluginSetupDependencies,
VisTypeTimeseriesPluginStartDependencies
>
{
constructor(private readonly initializerContext: PluginInitializerContext) {
this.initializerContext = initializerContext;
}

View file

@ -26,7 +26,9 @@ interface MessageBody {
messages: Message[];
}
export class GenAiStreamingResponseExamplePlugin implements Plugin<void, void> {
export class GenAiStreamingResponseExamplePlugin
implements Plugin<void, void, {}, GenAiStreamingResponseExamplePluginStart>
{
public setup({ http, getStartServices }: CoreSetup<GenAiStreamingResponseExamplePluginStart>) {
const router = http.createRouter();

View file

@ -15,7 +15,7 @@ interface StartDeps {
screenshotting: ScreenshottingStart;
}
export class ScreenshottingExamplePlugin implements Plugin<void, void> {
export class ScreenshottingExamplePlugin implements Plugin<void, void, {}, StartDeps> {
setup({ http, getStartServices }: CoreSetup<StartDeps>) {
const router = http.createRouter();

View file

@ -40,7 +40,7 @@ interface PluginsStart {
data: DataPluginStart;
}
export class CanvasPlugin implements Plugin {
export class CanvasPlugin implements Plugin<void, void, PluginsSetup, PluginsStart> {
private readonly logger: Logger;
constructor(public readonly initializerContext: PluginInitializerContext) {

View file

@ -17,7 +17,7 @@ import { registerWithCustomIntegrations } from './register_custom_integration';
import { routes } from './routes';
import type { ConfigSchema } from '../common/app';
export class DataVisualizerPlugin implements Plugin {
export class DataVisualizerPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
private readonly _logger: Logger;
constructor(initializerContext: PluginInitializerContext<ConfigSchema>) {

View file

@ -201,7 +201,10 @@ const includedHiddenTypes = [
CONNECTOR_TOKEN_SAVED_OBJECT_TYPE,
];
export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartContract> {
export class ActionsPlugin
implements
Plugin<PluginSetupContract, PluginStartContract, ActionsPluginsSetup, ActionsPluginsStart>
{
private readonly logger: Logger;
private readonly actionsConfig: ActionsConfig;
private taskRunnerFactory?: TaskRunnerFactory;
@ -230,7 +233,7 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
}
public setup(
core: CoreSetup<ActionsPluginsStart>,
core: CoreSetup<ActionsPluginsStart, PluginStartContract>,
plugins: ActionsPluginsSetup
): PluginSetupContract {
this.licenseState = new LicenseState(plugins.licensing.license$);

View file

@ -12,12 +12,21 @@ import { getDatasetQualityServerRouteRepository } from './routes';
import { registerRoutes } from './routes/register_routes';
import { DatasetQualityRouteHandlerResources } from './routes/types';
import {
DatasetQualityPluginSetup,
DatasetQualityPluginSetupDependencies,
DatasetQualityPluginStart,
DatasetQualityPluginStartDependencies,
} from './types';
export class DatasetQualityServerPlugin implements Plugin {
export class DatasetQualityServerPlugin
implements
Plugin<
DatasetQualityPluginSetup,
DatasetQualityPluginStart,
DatasetQualityPluginSetupDependencies,
DatasetQualityPluginStartDependencies
>
{
private readonly logger: Logger;
private readonly dataTelemetryService: DataTelemetryService;

View file

@ -13,29 +13,36 @@ import type {
Logger,
CustomRequestHandlerContext,
} from '@kbn/core/server';
import type { PluginStartContract as ActionsPluginsStart } from '@kbn/actions-plugin/server/plugin';
import { MINIMUM_LICENSE_TYPE } from '../common/constants';
import { registerRoutes } from './routes';
import type {
IntegrationAssistantPluginSetup,
IntegrationAssistantPluginStart,
IntegrationAssistantPluginStartDependencies,
IntegrationAssistantPluginSetupDependencies,
} from './types';
import { parseExperimentalConfigValue } from '../common/experimental_features';
import { IntegrationAssistantConfigType } from './config';
export type IntegrationAssistantRouteHandlerContext = CustomRequestHandlerContext<{
integrationAssistant: {
getStartServices: CoreSetup<{
actions: ActionsPluginsStart;
}>['getStartServices'];
getStartServices: CoreSetup<
IntegrationAssistantPluginStartDependencies,
IntegrationAssistantPluginStart
>['getStartServices'];
isAvailable: () => boolean;
logger: Logger;
};
}>;
export class IntegrationAssistantPlugin
implements Plugin<IntegrationAssistantPluginSetup, IntegrationAssistantPluginStart>
implements
Plugin<
IntegrationAssistantPluginSetup,
IntegrationAssistantPluginStart,
IntegrationAssistantPluginSetupDependencies,
IntegrationAssistantPluginStartDependencies
>
{
private readonly logger: Logger;
private readonly config: IntegrationAssistantConfigType;
@ -50,9 +57,7 @@ export class IntegrationAssistantPlugin
}
public setup(
core: CoreSetup<{
actions: ActionsPluginsStart;
}>
core: CoreSetup<IntegrationAssistantPluginStartDependencies, IntegrationAssistantPluginStart>
): IntegrationAssistantPluginSetup {
core.http.registerRouteHandlerContext<
IntegrationAssistantRouteHandlerContext,

View file

@ -12,6 +12,10 @@ import {
ActionsClientSimpleChatModel,
} from '@kbn/langchain/server';
import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server';
import type {
PluginStartContract as ActionsPluginStart,
PluginSetupContract as ActionsPluginSetup,
} from '@kbn/actions-plugin/server/plugin';
import { ESProcessorItem, SamplesFormat } from '../common';
export interface IntegrationAssistantPluginSetup {
@ -22,9 +26,11 @@ export interface IntegrationAssistantPluginStart {}
export interface IntegrationAssistantPluginSetupDependencies {
licensing: LicensingPluginSetup;
actions: ActionsPluginSetup;
}
export interface IntegrationAssistantPluginStartDependencies {
licensing: LicensingPluginStart;
actions: ActionsPluginStart;
}
export interface SimplifiedProcessor {

View file

@ -35,7 +35,7 @@ import { registerIntegrations } from './register_integrations';
import { StartDeps, SetupDeps } from './types';
import { MapsStorage } from './content_management';
export class MapsPlugin implements Plugin {
export class MapsPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
readonly _initializerContext: PluginInitializerContext<MapsXPackConfig>;
private readonly _logger: Logger;

View file

@ -22,7 +22,9 @@ export interface ConnectorsPluginsStart {
actions: ActionsPluginSetupContract;
}
export class StackConnectorsPlugin implements Plugin<void, void> {
export class StackConnectorsPlugin
implements Plugin<void, void, ConnectorsPluginsSetup, ConnectorsPluginsStart>
{
private readonly logger: Logger;
private config: StackConnectorsConfigType;
readonly experimentalFeatures: ExperimentalFeatures;

View file

@ -12,6 +12,7 @@ import { TaskTypeDictionary } from '../task_type_dictionary';
import { BackgroundTaskNode } from '../saved_objects/schemas/background_task_node';
import { BACKGROUND_TASK_NODE_SO_NAME } from '../saved_objects';
import { TaskManagerStartContract } from '..';
import { TaskManagerPluginsStart } from '../plugin';
export const TASK_ID = 'delete_inactive_background_task_nodes';
const TASK_TYPE = `task_manager:${TASK_ID}`;
@ -40,7 +41,7 @@ export async function scheduleDeleteInactiveNodesTaskDefinition(
export function registerDeleteInactiveNodesTaskDefinition(
logger: Logger,
coreStartServices: () => Promise<[CoreStart, TaskManagerStartContract, unknown]>,
coreStartServices: () => Promise<[CoreStart, TaskManagerPluginsStart, TaskManagerStartContract]>,
taskTypeDictionary: TaskTypeDictionary
) {
taskTypeDictionary.registerTaskDefinitions({
@ -53,7 +54,7 @@ export function registerDeleteInactiveNodesTaskDefinition(
export function taskRunner(
logger: Logger,
coreStartServices: () => Promise<[CoreStart, TaskManagerStartContract, unknown]>
coreStartServices: () => Promise<[CoreStart, TaskManagerPluginsStart, TaskManagerStartContract]>
) {
return () => {
return {

View file

@ -8,7 +8,11 @@
import { combineLatest, Observable, Subject, BehaviorSubject } from 'rxjs';
import { map, distinctUntilChanged } from 'rxjs';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { UsageCollectionSetup, UsageCounter } from '@kbn/usage-collection-plugin/server';
import type {
UsageCollectionSetup,
UsageCollectionStart,
UsageCounter,
} from '@kbn/usage-collection-plugin/server';
import {
PluginInitializerContext,
Plugin,
@ -18,7 +22,7 @@ import {
ServiceStatusLevels,
CoreStatus,
} from '@kbn/core/server';
import type { CloudStart } from '@kbn/cloud-plugin/server';
import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/server';
import {
registerDeleteInactiveNodesTaskDefinition,
scheduleDeleteInactiveNodesTaskDefinition,
@ -79,14 +83,26 @@ export type TaskManagerStartContract = Pick<
getRegisteredTypes: () => string[];
};
export interface TaskManagerPluginStart {
export interface TaskManagerPluginsStart {
cloud?: CloudStart;
usageCollection?: UsageCollectionStart;
}
export interface TaskManagerPluginsSetup {
cloud?: CloudSetup;
usageCollection?: UsageCollectionSetup;
}
const LogHealthForBackgroundTasksOnlyMinutes = 60;
export class TaskManagerPlugin
implements Plugin<TaskManagerSetupContract, TaskManagerStartContract>
implements
Plugin<
TaskManagerSetupContract,
TaskManagerStartContract,
TaskManagerPluginsSetup,
TaskManagerPluginsStart
>
{
private taskPollingLifecycle?: TaskPollingLifecycle;
private taskManagerId?: string;
@ -125,8 +141,8 @@ export class TaskManagerPlugin
}
public setup(
core: CoreSetup<TaskManagerStartContract, unknown>,
plugins: { usageCollection?: UsageCollectionSetup }
core: CoreSetup<TaskManagerPluginsStart, TaskManagerStartContract>,
plugins: TaskManagerPluginsSetup
): TaskManagerSetupContract {
this.elasticsearchAndSOAvailability$ = getElasticsearchAndSOAvailability(core.status.core$);
@ -253,7 +269,7 @@ export class TaskManagerPlugin
public start(
{ savedObjects, elasticsearch, executionContext, docLinks }: CoreStart,
{ cloud }: TaskManagerPluginStart
{ cloud }: TaskManagerPluginsStart
): TaskManagerStartContract {
const savedObjectsRepository = savedObjects.createInternalRepository([
TASK_SO_NAME,

View file

@ -15,6 +15,7 @@ import { ConcreteTaskInstance, TaskManagerStartContract } from '..';
import { TaskStatus } from '../task';
import { REMOVED_TYPES } from '../task_type_dictionary';
import { TASK_MANAGER_INDEX } from '../constants';
import { TaskManagerPluginsStart } from '../plugin';
export const TASK_ID = 'mark_removed_tasks_as_unrecognized';
const TASK_TYPE = `task_manager:${TASK_ID}`;
@ -40,7 +41,7 @@ export async function scheduleMarkRemovedTasksAsUnrecognizedDefinition(
export function registerMarkRemovedTasksAsUnrecognizedDefinition(
logger: Logger,
coreStartServices: () => Promise<[CoreStart, TaskManagerStartContract, unknown]>,
coreStartServices: () => Promise<[CoreStart, TaskManagerPluginsStart, TaskManagerStartContract]>,
taskTypeDictionary: TaskTypeDictionary
) {
taskTypeDictionary.registerTaskDefinitions({
@ -53,7 +54,7 @@ export function registerMarkRemovedTasksAsUnrecognizedDefinition(
export function taskRunner(
logger: Logger,
coreStartServices: () => Promise<[CoreStart, TaskManagerStartContract, unknown]>
coreStartServices: () => Promise<[CoreStart, TaskManagerPluginsStart, TaskManagerStartContract]>
) {
return () => {
return {

View file

@ -34,7 +34,10 @@ export class TriggersActionsPlugin implements Plugin<void, PluginStartContract>
this.data = getService();
}
public setup(core: CoreSetup<TriggersActionsPluginStart>, plugins: PluginsSetup): void {
public setup(
core: CoreSetup<TriggersActionsPluginStart, PluginStartContract>,
plugins: PluginsSetup
): void {
const router = core.http.createRouter();
registerDataService({
logger: this.logger,

View file

@ -61,7 +61,9 @@ export interface LensServerPluginSetup {
) => void;
}
export class LensServerPlugin implements Plugin<LensServerPluginSetup, {}, {}, {}> {
export class LensServerPlugin
implements Plugin<LensServerPluginSetup, {}, PluginSetupContract, PluginStartContract>
{
private customVisualizationMigrations: CustomVisualizationMigrations = {};
constructor(private initializerContext: PluginInitializerContext) {}

View file

@ -18,7 +18,9 @@ import { KibanaFramework } from './lib/adapters/framework/kibana_framework_adapt
import { initMetricExplorerRoute } from './routes/metrics_explorer';
import { initMetricIndicesRoute } from './routes/metric_indices';
export class MetricsDataPlugin implements Plugin<MetricsDataPluginSetup, {}, {}, {}> {
export class MetricsDataPlugin
implements Plugin<MetricsDataPluginSetup, {}, {}, MetricsDataPluginStartDeps>
{
private metricsClient: MetricsDataClient | null = null;
constructor(context: PluginInitializerContext) {}

View file

@ -78,7 +78,9 @@ const alertingFeatures = OBSERVABILITY_RULE_TYPE_IDS_WITH_SUPPORTED_STACK_RULE_T
})
);
export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
export class ObservabilityPlugin
implements Plugin<ObservabilityPluginSetup, void, PluginSetup, PluginStart>
{
private logger: Logger;
constructor(private readonly initContext: PluginInitializerContext) {
@ -86,7 +88,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
this.logger = initContext.logger.get();
}
public setup(core: CoreSetup<PluginStart>, plugins: PluginSetup) {
public setup(core: CoreSetup<PluginStart, void>, plugins: PluginSetup) {
const casesCapabilities = createCasesUICapabilities();
const casesApiTags = getCasesApiTags(observabilityFeatureId);

View file

@ -132,7 +132,7 @@ export interface RouteDependencies {
router: IRouter;
}
export class EnterpriseSearchPlugin implements Plugin {
export class EnterpriseSearchPlugin implements Plugin<void, void, PluginsSetup, PluginsStart> {
private readonly config: ConfigType;
private readonly logger: Logger;
private readonly globalConfigService: GlobalConfigService;