Repository: langgenius/dify
File: web/service/workflow-payload.ts (TypeScript)

Code before:
    event_parameters: (typeof data.event_parameters === 'object' && data.event_parameters !== null)
      ? data.event_parameters as Record<string, unknown>
      : {},
  }

  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<TriggerPluginNodePayload>))

  return {
    ...params,
    graph: {
      ...graph,
      nodes: sanitizedNodes,
    },
  }
}

const isTriggerPluginNode = (node: Node): node is Node<TriggerPluginHydratePayload> => {
  const data = node.data as unknown

  if (!data || typeof data !== 'object')
    return false

  const payload = data as Partial<TriggerPluginHydratePayload> & { 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<TriggerPluginHydratePayload>
  const data = typedNode.data
  const eventParameters = data.event_parameters ?? {}
  const parametersSchema = data.parameters_schema ?? data.paramSchemas ?? []
  const config = data.config ?? eventParameters ?? {}

Review comment (refactor):
I'm considering whether we should preserve this logic. AFAIK this is a compatibility logic to ensure  that JSONSchema previously stored as string could be handled properly. However, since the JSONSchema support in UI is not enabled, ordinary users cannot create workflows with JSONSchema validation.

Delete this part could simplify the code.

Another approach would add a comment about the background.

Code after:
    event_parameters: (typeof data.event_parameters === 'object' && data.event_parameters !== null)
      ? data.event_parameters as Record<string, unknown>
      : {},
  }

  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) => {
    // First sanitize known node types (TriggerPlugin)
    const n = sanitizeTriggerPluginNode(node as Node<TriggerPluginNodePayload>) as Node<any>

    // Normalize Start node variable json_schema: ensure dict, not string
    if ((n.data as any)?.type === BlockEnum.Start && Array.isArray((n.data as any).variables)) {
      const next = { ...n, data: { ...n.data } }
      next.data.variables = (n.data as any).variables.map((v: any) => {
        if (v && v.type === 'json_object' && typeof v.json_schema === 'string') {
          try {
            const obj = JSON.parse(v.json_schema)
            return { ...v, json_schema: obj }
          }
          catch {
            return v
          }
        }
        return v
      })
      return next
    }

    return n
  })

  return {
    ...params,
    graph: {
      ...graph,
      nodes: sanitizedNodes,
    },
  }
}