import { produce } from 'immer' import type { Edge, Node } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types' import type { PluginTriggerNodeType } from '@/app/components/workflow/nodes/trigger-plugin/types' import type { FetchWorkflowDraftResponse } from '@/types/workflow' export type TriggerPluginNodePayload = { title: string desc: string plugin_id: string provider_id: string event_name: string subscription_id: string plugin_unique_identifier: string event_parameters: Record } export type WorkflowDraftSyncParams = Pick< FetchWorkflowDraftResponse, 'graph' | 'features' | 'environment_variables' | 'conversation_variables' > const removeTempProperties = (data: Record): void => { Object.keys(data).forEach((key) => { if (key.startsWith('_')) delete data[key] }) } type TriggerParameterSchema = Record type TriggerPluginHydratePayload = (PluginTriggerNodeType & { paramSchemas?: TriggerParameterSchema[] parameters_schema?: TriggerParameterSchema[] }) const sanitizeTriggerPluginNode = (node: Node): Node => { const data = node.data if (!data || data.type !== BlockEnum.TriggerPlugin) return node const sanitizedData: TriggerPluginNodePayload & { type: BlockEnum.TriggerPlugin } = { type: BlockEnum.TriggerPlugin, title: data.title ?? '', desc: data.desc ?? '', plugin_id: data.plugin_id ?? '', provider_id: data.provider_id ?? '', event_name: data.event_name ?? '', subscription_id: data.subscription_id ?? '', plugin_unique_identifier: data.plugin_unique_identifier ?? '', event_parameters: (typeof data.event_parameters === 'object' && data.event_parameters !== null) ? data.event_parameters as Record : {}, } return { ...node, data: sanitizedData, } } export const sanitizeWorkflowDraftPayload = (params: WorkflowDraftSyncParams): WorkflowDraftSyncParams => { const { graph } = params if (!graph?.nodes?.length) return params const sanitizedNodes = graph.nodes.map(node => sanitizeTriggerPluginNode(node as Node)) return { ...params, graph: { ...graph, nodes: sanitizedNodes, }, } } const isTriggerPluginNode = (node: Node): node is Node => { const data = node.data as unknown if (!data || typeof data !== 'object') return false const payload = data as Partial & { type?: BlockEnum } if (payload.type !== BlockEnum.TriggerPlugin) return false return 'event_parameters' in payload } const hydrateTriggerPluginNode = (node: Node): Node => { if (!isTriggerPluginNode(node)) return node const typedNode = node as Node const data = typedNode.data const eventParameters = data.event_parameters ?? {} const parametersSchema = data.parameters_schema ?? data.paramSchemas ?? [] const config = data.config ?? eventParameters ?? {} const nextData: typeof data = { ...data, config, paramSchemas: data.paramSchemas ?? parametersSchema, parameters_schema: parametersSchema, } return { ...typedNode, data: nextData, } } export const hydrateWorkflowDraftResponse = (draft: FetchWorkflowDraftResponse): FetchWorkflowDraftResponse => { return produce(draft, (mutableDraft) => { if (!mutableDraft?.graph) return if (mutableDraft.graph.nodes) { mutableDraft.graph.nodes = mutableDraft.graph.nodes .filter((node: Node) => !node.data?._isTempNode) .map((node: Node) => { if (node.data) removeTempProperties(node.data as Record) return hydrateTriggerPluginNode(node) }) } if (mutableDraft.graph.edges) { mutableDraft.graph.edges = mutableDraft.graph.edges .filter((edge: Edge) => !edge.data?._isTemp) .map((edge: Edge) => { if (edge.data) removeTempProperties(edge.data as Record) return edge }) } if (mutableDraft.environment_variables) { mutableDraft.environment_variables = mutableDraft.environment_variables.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env, ) } }) }