Skip to main content

jellyflow_core/core/model/
port.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::core::ids::{NodeId, PortKey};
5use crate::types::TypeDesc;
6
7use super::edge::EdgeKind;
8
9/// Port direction.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum PortDirection {
13    /// Input port.
14    In,
15    /// Output port.
16    Out,
17}
18
19/// Port kind.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
21#[serde(rename_all = "snake_case")]
22pub enum PortKind {
23    /// Data port.
24    Data,
25    /// Exec port (control flow).
26    Exec,
27}
28
29impl PortKind {
30    pub fn edge_kind(self) -> EdgeKind {
31        match self {
32            Self::Data => EdgeKind::Data,
33            Self::Exec => EdgeKind::Exec,
34        }
35    }
36}
37
38/// Connection capacity for a port.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[serde(rename_all = "snake_case")]
41pub enum PortCapacity {
42    /// Single connection.
43    Single,
44    /// Multiple connections.
45    Multi,
46}
47
48/// Port instance.
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct Port {
51    /// Owning node.
52    pub node: NodeId,
53    /// Schema key for stable migrations.
54    pub key: PortKey,
55    /// Port direction.
56    pub dir: PortDirection,
57    /// Port kind.
58    pub kind: PortKind,
59    /// Capacity rule.
60    pub capacity: PortCapacity,
61
62    /// Whether this port can be used for creating/accepting connections via editor interactions.
63    ///
64    /// This mirrors XyFlow handle-level `isConnectable`. When omitted, the owning node's
65    /// `Node.connectable` / global `NodeGraphInteractionState.nodes_connectable` decides.
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub connectable: Option<bool>,
68
69    /// Dictates whether a connection can start from this port.
70    ///
71    /// This mirrors XyFlow handle-level `isConnectableStart`. When omitted, the port is treated as
72    /// start-connectable (subject to `connectable`).
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub connectable_start: Option<bool>,
75
76    /// Dictates whether a connection can end on this port.
77    ///
78    /// This mirrors XyFlow handle-level `isConnectableEnd`. When omitted, the port is treated as
79    /// end-connectable (subject to `connectable`).
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    pub connectable_end: Option<bool>,
82
83    /// Optional type descriptor.
84    ///
85    /// Profiles may choose to infer or override this via concretization.
86    #[serde(default, skip_serializing_if = "Option::is_none")]
87    pub ty: Option<TypeDesc>,
88
89    /// Opaque port payload (domain-owned).
90    #[serde(default)]
91    pub data: Value,
92}