Files
dify/web/app/components/workflow/nodes/loop/use-single-run-form-params.helpers.ts
Coding On Star a408a5d87e test(workflow): add helper specs and raise targeted workflow coverage (#33995)
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-03-24 17:51:07 +08:00

132 lines
3.9 KiB
TypeScript

import type { InputVar, Node, ValueSelector, Variable } from '../../types'
import type { CaseItem, Condition, LoopVariable } from './types'
import { ValueType } from '@/app/components/workflow/types'
import { VALUE_SELECTOR_DELIMITER as DELIMITER } from '@/config'
import { getNodeInfoById, getNodeUsedVarPassToServerKey, getNodeUsedVars, isSystemVar } from '../_base/components/variable/utils'
export function getVarSelectorsFromCase(caseItem: CaseItem): ValueSelector[] {
const vars: ValueSelector[] = []
caseItem.conditions?.forEach((condition) => {
vars.push(...getVarSelectorsFromCondition(condition))
})
return vars
}
export function getVarSelectorsFromCondition(condition: Condition): ValueSelector[] {
const vars: ValueSelector[] = []
if (condition.variable_selector)
vars.push(condition.variable_selector)
if (condition.sub_variable_condition?.conditions?.length)
vars.push(...getVarSelectorsFromCase(condition.sub_variable_condition))
return vars
}
export const createInputVarValues = (runInputData: Record<string, unknown>) => {
const vars: Record<string, unknown> = {}
Object.keys(runInputData).forEach((key) => {
vars[key] = runInputData[key]
})
return vars
}
export const dedupeInputVars = (inputVars: InputVar[]) => {
const seen: Record<string, boolean> = {}
const uniqueInputVars: InputVar[] = []
inputVars.forEach((input) => {
if (!input || seen[input.variable])
return
seen[input.variable] = true
uniqueInputVars.push(input)
})
return uniqueInputVars
}
export const buildUsedOutVars = ({
loopChildrenNodes,
currentNodeId,
canChooseVarNodes,
isNodeInLoop,
toVarInputs,
}: {
loopChildrenNodes: Node[]
currentNodeId: string
canChooseVarNodes: Node[]
isNodeInLoop: (nodeId: string) => boolean
toVarInputs: (variables: Variable[]) => InputVar[]
}) => {
const vars: ValueSelector[] = []
const seenVarSelectors: Record<string, boolean> = {}
const allVarObject: Record<string, { inSingleRunPassedKey: string }> = {}
loopChildrenNodes.forEach((node) => {
const nodeVars = getNodeUsedVars(node).filter(item => item && item.length > 0)
nodeVars.forEach((varSelector) => {
if (varSelector[0] === currentNodeId)
return
if (isNodeInLoop(varSelector[0]))
return
const varSelectorStr = varSelector.join('.')
if (!seenVarSelectors[varSelectorStr]) {
seenVarSelectors[varSelectorStr] = true
vars.push(varSelector)
}
let passToServerKeys = getNodeUsedVarPassToServerKey(node, varSelector)
if (typeof passToServerKeys === 'string')
passToServerKeys = [passToServerKeys]
passToServerKeys.forEach((key: string, index: number) => {
allVarObject[[varSelectorStr, node.id, index].join(DELIMITER)] = {
inSingleRunPassedKey: key,
}
})
})
})
const usedOutVars = toVarInputs(vars.map((valueSelector) => {
const varInfo = getNodeInfoById(canChooseVarNodes, valueSelector[0])
return {
label: {
nodeType: varInfo?.data.type,
nodeName: varInfo?.data.title || canChooseVarNodes[0]?.data.title,
variable: isSystemVar(valueSelector) ? valueSelector.join('.') : valueSelector[valueSelector.length - 1],
},
variable: valueSelector.join('.'),
value_selector: valueSelector,
}
}))
return { usedOutVars, allVarObject }
}
export const getDependentVarsFromLoopPayload = ({
nodeId,
usedOutVars,
breakConditions,
loopVariables,
}: {
nodeId: string
usedOutVars: InputVar[]
breakConditions?: Condition[]
loopVariables?: LoopVariable[]
}) => {
const vars: ValueSelector[] = usedOutVars.map(item => item.variable.split('.'))
breakConditions?.forEach((condition) => {
vars.push(...getVarSelectorsFromCondition(condition))
})
loopVariables?.forEach((loopVariable) => {
if (loopVariable.value_type === ValueType.variable)
vars.push(loopVariable.value)
})
return vars.filter(item => item[0] !== nodeId)
}