Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pageLoadAssetSize:
dataVisualizer: 32727
developerToolbar: 4467
devTools: 8109
discover: 31186
discover: 30501
discoverEnhanced: 5509
discoverShared: 2322
elasticAssistant: 301540
Expand Down Expand Up @@ -115,7 +115,7 @@ pageLoadAssetSize:
maps: 45917
mapsEms: 6734
metricsDataAccess: 44950
ml: 89000
ml: 102091
Copy link
Copy Markdown
Member

@tylersmalley tylersmalley Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a skill if you want to give it a try to reduce this. https://github.com/elastic/kibana/blob/main/.agents/skills/optimize-bundle-size/SKILL.md

/optimize-bundle-size pluginId=ml

mockIdpPlugin: 7463
monitoring: 28983
navigation: 11814
Expand Down Expand Up @@ -184,7 +184,7 @@ pageLoadAssetSize:
timelines: 131503
transform: 16515
triggersActionsUi: 123512
uiActions: 35278
uiActions: 35180
unifiedDocViewer: 15000
unifiedSearch: 19500
upgradeAssistant: 6898
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ import { discoverServiceMock } from '../../__mocks__/services';
import React from 'react';
import { createEsqlDataSource } from '../../../common/data_sources';
import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield';
import type {
Action,
ActionDefinition,
ActionExecutionContext,
} from '@kbn/ui-actions-plugin/public/actions';
import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public/actions';
import { type AdditionalCellAction, type DiscoverCellActionExecutionContext } from '../types';
import { createContextAwarenessMocks } from '../__mocks__';
import { type ScopedProfilesManager } from '../profiles_manager';
Expand All @@ -38,12 +34,11 @@ let mockUuid = 0;

jest.mock('uuid', () => ({ ...jest.requireActual('uuid'), v4: jest.fn() }));

const mockActions: Array<ActionDefinition<DiscoverCellActionExecutionContext>> = [];
const mockActions: string[] = [];
const mockTriggerActions: Record<string, string[]> = { [DISCOVER_CELL_ACTIONS_TRIGGER_ID]: [] };

jest.spyOn(discoverServiceMock.uiActions, 'registerAction').mockImplementation((action) => {
mockActions.push(action as ActionDefinition<DiscoverCellActionExecutionContext>);
return action as Action;
jest.spyOn(discoverServiceMock.uiActions, 'registerActionAsync').mockImplementation((actionId) => {
mockActions.push(actionId);
});

jest
Expand All @@ -54,7 +49,7 @@ jest

jest.spyOn(discoverServiceMock.uiActions, 'unregisterAction').mockImplementation((id) => {
mockActions.splice(
mockActions.findIndex((action) => action.id === id),
mockActions.findIndex((actionId) => actionId === id),
1
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const useAdditionalCellActions = ({
);

actions.forEach((action) => {
uiActions.registerAction(action);
uiActions.registerActionAsync(action.id, async () => action);
uiActions.attachAction(DISCOVER_CELL_ACTIONS_TRIGGER_ID, action.id);
});

Expand Down
4 changes: 0 additions & 4 deletions src/platform/plugins/shared/ui_actions/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ export type Start = jest.Mocked<UiActionsPublicStart>;

const createSetupContract = (): Setup => {
const setupContract: Setup = {
addTriggerAction: jest.fn(),
addTriggerActionAsync: jest.fn(),
attachAction: jest.fn(),
detachAction: jest.fn(),
registerAction: jest.fn(),
registerActionAsync: jest.fn(),
unregisterAction: jest.fn(),
};
Expand All @@ -33,7 +31,6 @@ const createStartContract = (): Start => {
const startContract: Start = {
attachAction: jest.fn(),
unregisterAction: jest.fn(),
addTriggerAction: jest.fn(),
addTriggerActionAsync: jest.fn(),
clear: jest.fn(),
detachAction: jest.fn(),
Expand All @@ -50,7 +47,6 @@ const createStartContract = (): Start => {
async (triggerId: string, context: object) =>
[] as Array<FrequentCompatibilityChangeAction<object>>
),
registerAction: jest.fn(),
registerActionAsync: jest.fn(),
};

Expand Down
2 changes: 0 additions & 2 deletions src/platform/plugins/shared/ui_actions/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ import { setAnalytics, setI18n, setNotifications, setTheme, setUserProfile } fro

export type UiActionsPublicSetup = Pick<
UiActionsService,
| 'addTriggerAction'
| 'addTriggerActionAsync'
| 'attachAction'
| 'detachAction'
| 'registerAction'
| 'registerActionAsync'
| 'unregisterAction'
>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type { ActionRegistry } from '../types';
import { coreMock } from '@kbn/core/public/mocks';
import { ON_OPEN_PANEL_MENU } from '../../common/trigger_ids';
import { triggers } from '../triggers';
import { ACTION_HELLO_WORLD } from '../tests/test_samples/hello_world_action';

const testAction1: ActionDefinition = {
id: 'action1',
Expand Down Expand Up @@ -62,29 +63,14 @@ describe('UiActionsService', () => {
describe('.registerAction()', () => {
test('can register an action', () => {
const service = new UiActionsService();
service.registerAction({
service.registerActionAsync('test', async () => ({
id: 'test',
execute: async () => {},
getDisplayName: () => 'test',
getIconType: () => '',
isCompatible: async () => true,
type: 'test',
});
});

test('return action instance', () => {
const service = new UiActionsService();
const action = service.registerAction({
id: 'test',
execute: async () => {},
getDisplayName: () => 'test',
getIconType: () => '',
isCompatible: async () => true,
type: 'test',
});

expect(action).toBeInstanceOf(ActionInternal);
expect(action.id).toBe('test');
}));
});
});

Expand All @@ -111,21 +97,21 @@ describe('UiActionsService', () => {
test('returns actions set on trigger', async () => {
const service = new UiActionsService();

service.registerAction(action1);
service.registerAction(action2);
service.registerActionAsync('action1', async () => action1);
service.registerActionAsync('action2', async () => action2);

const list0 = await service.getTriggerActions(ON_OPEN_PANEL_MENU);

expect(list0).toHaveLength(0);

service.addTriggerAction(ON_OPEN_PANEL_MENU, action1);
service.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action1', async () => action1);
const list1 = await service.getTriggerActions(ON_OPEN_PANEL_MENU);

expect(list1).toHaveLength(1);
expect(list1[0]).toBeInstanceOf(ActionInternal);
expect(list1[0].id).toBe(action1.id);

service.addTriggerAction(ON_OPEN_PANEL_MENU, action2);
service.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action2', async () => action2);
const list2 = await service.getTriggerActions(ON_OPEN_PANEL_MENU);

expect(list2).toHaveLength(2);
Expand All @@ -143,7 +129,7 @@ describe('UiActionsService', () => {
const helloWorldAction = createHelloWorldAction(coreStart);
const length = actions.size;

service.registerAction(helloWorldAction);
service.registerActionAsync(ACTION_HELLO_WORLD, async () => helloWorldAction);

expect(actions.size - length).toBe(1);
const action = await actions.get(helloWorldAction.id)?.();
Expand All @@ -154,9 +140,13 @@ describe('UiActionsService', () => {
const service = new UiActionsService();
const helloWorldAction = createHelloWorldAction(coreStart);

service.registerAction(helloWorldAction);
service.registerActionAsync(ACTION_HELLO_WORLD, async () => helloWorldAction);

service.addTriggerAction(ON_OPEN_PANEL_MENU, helloWorldAction);
service.addTriggerActionAsync(
ON_OPEN_PANEL_MENU,
ACTION_HELLO_WORLD,
async () => helloWorldAction
);

const compatibleActions = await service.getTriggerCompatibleActions(ON_OPEN_PANEL_MENU, {
hi: 'there',
Expand All @@ -175,9 +165,9 @@ describe('UiActionsService', () => {
execute: () => Promise.resolve(),
};

service.registerAction(action);
service.registerActionAsync('test', async () => action);

service.addTriggerAction(ON_OPEN_PANEL_MENU, action);
service.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'test', async () => action);

const compatibleActions1 = await service.getTriggerCompatibleActions(ON_OPEN_PANEL_MENU, {
accept: true,
Expand Down Expand Up @@ -221,8 +211,8 @@ describe('UiActionsService', () => {
test('forked service preserves trigger-to-actions mapping', async () => {
const service1 = new UiActionsService();

service1.registerAction(testAction1);
service1.addTriggerAction(ON_OPEN_PANEL_MENU, testAction1);
service1.registerActionAsync('action1', async () => testAction1);
service1.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action1', async () => testAction1);

const service2 = service1.fork();

Expand All @@ -238,16 +228,16 @@ describe('UiActionsService', () => {
test('new attachments in fork do not appear in original service', async () => {
const service1 = new UiActionsService();

service1.registerAction(testAction1);
service1.registerAction(testAction2);
service1.addTriggerAction(ON_OPEN_PANEL_MENU, testAction1);
service1.registerActionAsync('action1', async () => testAction1);
service1.registerActionAsync('action2', async () => testAction2);
service1.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action1', async () => testAction1);

const service2 = service1.fork();

expect(await service1.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);
expect(await service2.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);

service2.addTriggerAction(ON_OPEN_PANEL_MENU, testAction2);
service2.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action2', async () => testAction2);

expect(await service1.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);
expect(await service2.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(2);
Expand All @@ -256,33 +246,35 @@ describe('UiActionsService', () => {
test('new attachments in original service do not appear in fork', async () => {
const service1 = new UiActionsService();

service1.registerAction(testAction1);
service1.registerAction(testAction2);
service1.addTriggerAction(ON_OPEN_PANEL_MENU, testAction1);
service1.registerActionAsync('action1', async () => testAction1);
service1.registerActionAsync('action2', async () => testAction2);
service1.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action1', async () => testAction1);

const service2 = service1.fork();

expect(await service1.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);
expect(await service2.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);

service1.addTriggerAction(ON_OPEN_PANEL_MENU, testAction2);
service1.addTriggerActionAsync(ON_OPEN_PANEL_MENU, 'action2', async () => testAction2);

expect(await service1.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(2);
expect(await service2.getTriggerActions(ON_OPEN_PANEL_MENU)).toHaveLength(1);
});
});

describe('registries', () => {
const ACTION_HELLO_WORLD = 'ACTION_HELLO_WORLD';

test('can register action', async () => {
const actions: ActionRegistry = new Map();
const service = new UiActionsService({ actions });

service.registerAction({
id: ACTION_HELLO_WORLD,
order: 13,
} as unknown as ActionDefinition);
service.registerActionAsync(
ACTION_HELLO_WORLD,
async () =>
({
id: ACTION_HELLO_WORLD,
order: 13,
} as unknown as ActionDefinition)
);

expect(await actions.get(ACTION_HELLO_WORLD)?.()).toMatchObject({
id: ACTION_HELLO_WORLD,
Expand All @@ -298,7 +290,7 @@ describe('UiActionsService', () => {
order: 25,
} as unknown as ActionDefinition;

service.addTriggerAction(ON_OPEN_PANEL_MENU, action);
service.addTriggerActionAsync(ON_OPEN_PANEL_MENU, ACTION_HELLO_WORLD, async () => action);

const actions = await service.getTriggerActions(ON_OPEN_PANEL_MENU);

Expand All @@ -314,8 +306,8 @@ describe('UiActionsService', () => {
order: 25,
} as unknown as ActionDefinition;

service.registerAction(action);
service.addTriggerAction(ON_OPEN_PANEL_MENU, action);
service.registerActionAsync(ACTION_HELLO_WORLD, async () => action);
service.addTriggerActionAsync(ON_OPEN_PANEL_MENU, ACTION_HELLO_WORLD, async () => action);
service.detachAction(ON_OPEN_PANEL_MENU, action.id);

const actions2 = await service.getTriggerActions(ON_OPEN_PANEL_MENU);
Expand All @@ -330,7 +322,7 @@ describe('UiActionsService', () => {
order: 25,
} as unknown as ActionDefinition;

service.registerAction(action);
service.registerActionAsync(ACTION_HELLO_WORLD, async () => action);
expect(() => service.detachAction('i do not exist', ACTION_HELLO_WORLD)).toThrowError(
'No trigger [triggerId = i do not exist] exists, for detaching action [actionId = ACTION_HELLO_WORLD].'
);
Expand All @@ -344,8 +336,10 @@ describe('UiActionsService', () => {
order: 25,
} as unknown as ActionDefinition;

service.registerAction(action);
expect(() => service.addTriggerAction('i do not exist', action)).toThrowError(
service.registerActionAsync(ACTION_HELLO_WORLD, async () => action);
expect(() =>
service.addTriggerActionAsync('i do not exist', ACTION_HELLO_WORLD, async () => action)
).toThrowError(
'No trigger [triggerId = i do not exist] exists, for attaching action [actionId = ACTION_HELLO_WORLD].'
);
});
Expand All @@ -358,10 +352,10 @@ describe('UiActionsService', () => {
order: 25,
} as unknown as ActionDefinition;

service.registerAction(action);
expect(() => service.registerAction(action)).toThrowError(
'Action [action.id = ACTION_HELLO_WORLD] already registered.'
);
service.registerActionAsync(ACTION_HELLO_WORLD, async () => action);
expect(() =>
service.registerActionAsync(ACTION_HELLO_WORLD, async () => action)
).toThrowError('Action [action.id = ACTION_HELLO_WORLD] already registered.');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,6 @@ export class UiActionsService {
return trigger;
};

/**
* @deprecated
*
* Use `plugins.uiActions.registerActionAsync` instead.
*/
public readonly registerAction = <Context extends object>(
definition: ActionDefinition<Context>
): Action<Context> => {
if (this.actions.has(definition.id)) {
throw new Error(`Action [action.id = ${definition.id}] already registered.`);
}

const action = new ActionInternal(definition);

this.actions.set(action.id, async () => action as unknown as ActionInternal<object>);

return action;
};

public readonly registerActionAsync = <Context extends object>(
id: string,
getDefinition: () => Promise<ActionDefinition<Context>>
Expand Down Expand Up @@ -122,17 +103,7 @@ export class UiActionsService {
};

/**
* @deprecated
*
* Use `plugins.uiActions.addTriggerActionAsync` instead.
*/
public readonly addTriggerAction = (triggerId: string, action: ActionDefinition<any>): void => {
if (!this.actions.has(action.id)) this.registerAction(action);
this.attachAction(triggerId, action.id);
};

/**
* `addTriggerAction` is similar to `attachAction` as it attaches action to a
* `addTriggerActionAsync` is similar to `attachAction` as it attaches action to a
* trigger, but it also registers the action, if it has not been registered, yet.
*/
public readonly addTriggerActionAsync = (
Expand Down
Loading
Loading