Migrate output schema to V2 (#14311)

Previous refacto was creating output schema V2 which has more specific
schemas based on the step type. Before we were using one common schema,
which was too complex when searching for variable informations.

This PR migrate the deprecated schemas and remove the old code:
- mark previous `BaseOutputSchema` as deprecated
- remove other previous schemas
- use V2 everywhere
- icon should not be stored in schema. Instead it should be generated
based on the fieldmetadata or the item type
This commit is contained in:
Thomas Trompette
2025-09-09 18:37:00 +02:00
committed by GitHub
parent e787dadde8
commit 2b59198a1b
57 changed files with 589 additions and 1256 deletions
@@ -4,10 +4,7 @@ import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/ste
import { type InputSchemaPropertyType } from '@/workflow/types/InputSchema';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { getPreviousSteps } from '@/workflow/workflow-steps/utils/getWorkflowPreviousSteps';
import {
type OutputSchema,
type StepOutputSchema,
} from '@/workflow/workflow-variables/types/StepOutputSchema';
import { type StepOutputSchemaV2 } from '@/workflow/workflow-variables/types/StepOutputSchemaV2';
import { filterOutputSchema } from '@/workflow/workflow-variables/utils/filterOutputSchema';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -22,7 +19,7 @@ export const useAvailableVariablesInWorkflowStep = ({
shouldDisplayRecordFields: boolean;
shouldDisplayRecordObjects: boolean;
fieldTypesToExclude?: InputSchemaPropertyType[];
}): StepOutputSchema[] => {
}): StepOutputSchemaV2[] => {
const workflowSelectedNode = useRecoilComponentValue(
workflowSelectedNodeComponentState,
);
@@ -33,7 +30,7 @@ export const useAvailableVariablesInWorkflowStep = ({
? getPreviousSteps(steps, workflowSelectedNode).map((step) => step.id)
: [];
const availableStepsOutputSchema: StepOutputSchema[] = useRecoilValue(
const availableStepsOutputSchema: StepOutputSchemaV2[] = useRecoilValue(
stepsOutputSchemaFamilySelector({
workflowVersionId: flow.workflowVersionId,
stepIds: [TRIGGER_STEP_ID, ...previousStepIds],
@@ -47,7 +44,7 @@ export const useAvailableVariablesInWorkflowStep = ({
shouldDisplayRecordObjects,
outputSchema: stepOutputSchema.outputSchema,
fieldTypesToExclude,
}) as OutputSchema;
});
if (!isDefined(outputSchema) || isEmptyObject(outputSchema)) {
return undefined;
@@ -57,6 +54,7 @@ export const useAvailableVariablesInWorkflowStep = ({
id: stepOutputSchema.id,
name: stepOutputSchema.name,
icon: stepOutputSchema.icon,
type: stepOutputSchema.type,
outputSchema,
};
})
@@ -1,18 +1,7 @@
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { useWorkflowVersionIdOrThrow } from '@/workflow/hooks/useWorkflowVersionIdOrThrow';
import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector';
import type { BaseOutputSchemaV2 } from '@/workflow/workflow-variables/types/BaseOutputSchemaV2';
import type { CodeOutputSchema } from '@/workflow/workflow-variables/types/CodeOutputSchema';
import type { FindRecordsOutputSchema } from '@/workflow/workflow-variables/types/FindRecordsOutputSchema';
import type { FormOutputSchema } from '@/workflow/workflow-variables/types/FormOutputSchema';
import { type RecordOutputSchemaV2 } from '@/workflow/workflow-variables/types/RecordOutputSchemaV2';
import { getOutputSchemaType } from '@/workflow/workflow-variables/utils/getOutputSchemaType';
import { searchVariableThroughBaseOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughBaseOutputSchema';
import { searchVariableThroughCodeOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughCodeOutputSchema';
import { searchVariableThroughFindRecordsOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughFindRecordsOutputSchema';
import { searchVariableThroughFormOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughFormOutputSchema';
import { searchVariableThroughRecordEventOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughRecordEventOutputSchema';
import { searchVariableThroughRecordOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughRecordOutputSchema';
import { searchVariableThroughOutputSchemaV2 } from '@/workflow/workflow-variables/utils/searchVariableThroughOutputSchemaV2';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { TRIGGER_STEP_ID } from 'twenty-shared/workflow';
@@ -62,59 +51,9 @@ export const useSearchVariable = ({
};
}
const outputSchemaType = getOutputSchemaType(stepType);
if (outputSchemaType === 'RECORD') {
return searchVariableThroughRecordOutputSchema({
stepName: stepOutputSchema.name,
recordOutputSchema: stepOutputSchema.outputSchema as RecordOutputSchemaV2,
rawVariableName,
isFullRecord,
});
}
if (outputSchemaType === 'DATABASE_EVENT') {
return searchVariableThroughRecordEventOutputSchema({
stepName: stepOutputSchema.name,
recordOutputSchema: stepOutputSchema.outputSchema as RecordOutputSchemaV2,
rawVariableName,
isFullRecord,
});
}
if (outputSchemaType === 'FIND_RECORDS') {
return searchVariableThroughFindRecordsOutputSchema({
stepName: stepOutputSchema.name,
searchRecordOutputSchema:
stepOutputSchema.outputSchema as unknown as FindRecordsOutputSchema,
rawVariableName,
isFullRecord,
});
}
if (outputSchemaType === 'FORM') {
return searchVariableThroughFormOutputSchema({
stepName: stepOutputSchema.name,
formOutputSchema:
stepOutputSchema.outputSchema as unknown as FormOutputSchema,
rawVariableName,
isFullRecord,
});
}
if (outputSchemaType === 'CODE') {
return searchVariableThroughCodeOutputSchema({
stepName: stepOutputSchema.name,
codeOutputSchema:
stepOutputSchema.outputSchema as unknown as CodeOutputSchema,
rawVariableName,
isFullRecord,
});
}
return searchVariableThroughBaseOutputSchema({
stepName: stepOutputSchema.name,
baseOutputSchema: stepOutputSchema.outputSchema as BaseOutputSchemaV2,
return searchVariableThroughOutputSchemaV2({
stepOutputSchema,
stepType,
rawVariableName,
isFullRecord,
});
@@ -6,23 +6,22 @@ import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { type BaseOutputSchemaV2 } from '@/workflow/workflow-variables/types/BaseOutputSchemaV2';
import { type LinkOutputSchema } from '@/workflow/workflow-variables/types/LinkOutputSchema';
import { type FieldOutputSchemaV2 } from '@/workflow/workflow-variables/types/RecordOutputSchemaV2';
import { type StepOutputSchemaV2 } from '@/workflow/workflow-variables/types/StepOutputSchemaV2';
import { getVariableTemplateFromPath } from '@/workflow/workflow-variables/utils/getVariableTemplateFromPath';
import { useState } from 'react';
import { useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import {
type BaseOutputSchema,
type LinkOutputSchema,
type StepOutputSchema,
} from '../types/StepOutputSchema';
import { isBaseOutputSchemaV2 } from '../types/guards/isBaseOutputSchemaV2';
import { isLinkOutputSchema } from '../types/guards/isLinkOutputSchema';
import { isRecordOutputSchemaV2 } from '../types/guards/isRecordOutputSchemaV2';
import { getCurrentSubStepFromPath } from '../utils/getCurrentSubStepFromPath';
import { isBaseOutputSchema } from '../utils/isBaseOutputSchema';
import { isLinkOutputSchema } from '../utils/isLinkOutputSchema';
import { isRecordOutputSchema } from '../utils/isRecordOutputSchema';
type UseVariableDropdownProps = {
step: StepOutputSchema;
step: StepOutputSchemaV2;
onSelect: (value: string) => void;
onBack: () => void;
};
@@ -72,9 +71,9 @@ export const useVariableDropdown = ({
if (isLinkOutputSchema(currentSubStep)) {
return { link: currentSubStep.link };
} else if (isRecordOutputSchema(currentSubStep)) {
} else if (isRecordOutputSchemaV2(currentSubStep)) {
return currentSubStep.fields;
} else if (isBaseOutputSchema(currentSubStep)) {
} else if (isBaseOutputSchemaV2(currentSubStep)) {
return currentSubStep;
}
};
@@ -83,7 +82,9 @@ export const useVariableDropdown = ({
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
const handleSelectBaseOutputSchema = (
baseOutputSchema: BaseOutputSchema,
baseOutputSchema:
| BaseOutputSchemaV2
| Record<string, FieldOutputSchemaV2>,
) => {
if (!baseOutputSchema[key]?.isLeaf) {
setCurrentPath([...currentPath, key]);
@@ -136,9 +137,9 @@ export const useVariableDropdown = ({
if (isLinkOutputSchema(currentSubStep)) {
handleSelectLinkOutputSchema(currentSubStep);
} else if (isRecordOutputSchema(currentSubStep)) {
} else if (isRecordOutputSchemaV2(currentSubStep)) {
handleSelectBaseOutputSchema(currentSubStep.fields);
} else if (isBaseOutputSchema(currentSubStep)) {
} else if (isBaseOutputSchemaV2(currentSubStep)) {
handleSelectBaseOutputSchema(currentSubStep);
}
};