Refactor: Unify command menu item execution (#18908)

- Makes engineComponentKey non-nullable on CommandMenuItem. Adds two new
engine component keys: TRIGGER_WORKFLOW_VERSION and
FRONT_COMPONENT_RENDERER to cover the former standalone cases.
- Unifies the previously separated engine, front component and workflow
runners into a single `CommandRunner` component with a unified
`useMountCommand` hook that handles all command types.
This commit is contained in:
Raphaël Bosi
2026-03-24 16:59:52 +01:00
committed by GitHub
parent 27c0ca975f
commit 49afe5dbc4
103 changed files with 1296 additions and 1131 deletions
@@ -0,0 +1,78 @@
import { useCallback } from 'react';
import { useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation } from '@/command-menu-item/engine-command/hooks/useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation';
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
import { buildHeadlessCommandContextApi } from '@/command-menu-item/engine-command/utils/buildHeadlessCommandContextApi';
import { useStore } from 'jotai';
import { isDefined } from 'twenty-shared/utils';
import {
type CommandMenuItemAvailabilityType,
type EngineComponentKey,
} from '~/generated-metadata/graphql';
type MountCommandParams = {
engineCommandId: string;
contextStoreInstanceId: string;
engineComponentKey: EngineComponentKey;
frontComponentId?: string;
workflowVersionId?: string;
availabilityType?: CommandMenuItemAvailabilityType;
availabilityObjectMetadataId?: string | null;
};
export const useMountCommand = () => {
const store = useStore();
const {
enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation,
} = useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation();
const mountCommand = useCallback(
async ({
engineCommandId,
contextStoreInstanceId,
engineComponentKey,
frontComponentId,
workflowVersionId,
availabilityType,
availabilityObjectMetadataId,
}: MountCommandParams) => {
const headlessEngineCommandContextApi = buildHeadlessCommandContextApi({
store,
contextStoreInstanceId,
engineComponentKey,
});
const commandState = isDefined(frontComponentId)
? { ...headlessEngineCommandContextApi, frontComponentId }
: isDefined(workflowVersionId) && isDefined(availabilityType)
? await enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation(
{
headlessEngineCommandContextApi,
workflowVersionId,
availabilityType,
availabilityObjectMetadataId,
},
)
: headlessEngineCommandContextApi;
if (!isDefined(commandState)) {
return;
}
store.set(headlessCommandContextApisState.atom, (previousMap) => {
const newMap = new Map(previousMap);
newMap.set(engineCommandId, commandState);
return newMap;
});
},
[
store,
enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation,
],
);
return mountCommand;
};