Defining Ports
Ports are the connection points of your component. They define what data your component can receive and send.
Port Structure
go
type Port struct {
Name string // Unique identifier
Label string // Display name in UI
Source bool // true = input, false = output
Position Position // Left, Right, Top, Bottom
Schema schema.Schema // Data structure definition
Configuration Configuration // Additional settings
Status Status // Runtime status
}Basic Port Definition
go
func (c *MyComponent) Ports() []module.Port {
return []module.Port{
// Input port
{
Name: "input",
Label: "Input",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(InputMessage{}),
},
// Output port
{
Name: "output",
Label: "Output",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(OutputMessage{}),
},
}
}Port Positions
PositionTop
│
┌─────────────┴─────────────┐
│ │
│ │
PositionLeft Component PositionRight
│ │
│ │
└─────────────┬─────────────┘
│
PositionBottom| Position | Constant | Typical Use |
|---|---|---|
| Left | module.PositionLeft | Input ports (data flowing in) |
| Right | module.PositionRight | Output ports (data flowing out) |
| Top | module.PositionTop | Control inputs, settings |
| Bottom | module.PositionBottom | Error outputs, status |
Port Types
Input Ports (Source = true)
Input ports receive data from other components:
go
{
Name: "request",
Label: "Request",
Source: true, // This is an input
Position: module.PositionLeft,
Schema: schema.FromGo(Request{}),
}Output Ports (Source = false)
Output ports send data to connected components:
go
{
Name: "response",
Label: "Response",
Source: false, // This is an output
Position: module.PositionRight,
Schema: schema.FromGo(Response{}),
}Schema Definition
Ports use JSON Schema for data validation. The schema.FromGo() function generates schemas from Go structs:
go
type Request struct {
Method string `json:"method" title:"HTTP Method" enum:"GET,POST,PUT,DELETE"`
URL string `json:"url" title:"URL" format:"uri" required:"true"`
Body any `json:"body,omitempty" title:"Request Body"`
}
// In Ports()
Schema: schema.FromGo(Request{})Schema Tags
| Tag | Description | Example |
|---|---|---|
json | JSON field name | json:"fieldName" |
title | Human-readable label | title:"Field Name" |
description | Help text | description:"Enter the value" |
required | Mark as required | required:"true" |
enum | Allowed values | enum:"a,b,c" |
format | Validation format | format:"email" |
default | Default value | default:"hello" |
minLength | Minimum string length | minLength:"1" |
maxLength | Maximum string length | maxLength:"100" |
minimum | Minimum number | minimum:"0" |
maximum | Maximum number | maximum:"100" |
Format Values
| Format | Validates |
|---|---|
email | Email addresses |
uri | URLs |
uri-reference | Relative URLs |
date | ISO date (YYYY-MM-DD) |
date-time | ISO datetime |
time | ISO time |
duration | ISO duration |
ipv4 | IPv4 addresses |
ipv6 | IPv6 addresses |
uuid | UUIDs |
regex | Regular expressions |
Multiple Ports Example
go
func (c *Router) Ports() []module.Port {
return []module.Port{
// Single input
{
Name: "input",
Label: "Input",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(Message{}),
},
// Multiple outputs
{
Name: "route_a",
Label: "Route A",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(Message{}),
},
{
Name: "route_b",
Label: "Route B",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(Message{}),
},
{
Name: "default",
Label: "Default",
Source: false,
Position: module.PositionBottom,
Schema: schema.FromGo(Message{}),
},
}
}Port Configuration
Additional configuration options for ports:
go
{
Name: "settings",
Label: "Settings",
Source: true,
Configuration: module.Configuration{
Async: true, // Don't wait for completion
ArrayItemKey: "id", // Key for array deduplication
SchemaSource: "data", // Source for dynamic schema
},
}| Field | Description |
|---|---|
Async | Message handling doesn't block sender |
ArrayItemKey | Field used to identify array items |
SchemaSource | Field containing dynamic schema |
Dynamic Ports
Ports can be generated dynamically based on settings:
go
type Router struct {
settings Settings
}
type Settings struct {
Routes []string `json:"routes" title:"Route Names"`
}
func (r *Router) Ports() []module.Port {
ports := []module.Port{
{
Name: "input",
Label: "Input",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(Message{}),
},
}
// Generate output ports based on settings
for _, route := range r.settings.Routes {
ports = append(ports, module.Port{
Name: route,
Label: route,
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(Message{}),
})
}
return ports
}Port Status
Runtime status information for ports:
go
{
Name: "server",
Label: "Server",
Source: true,
Status: module.Status{
Label: "Listening",
Description: "Port 8080",
State: module.StateRunning,
},
}| State | Description |
|---|---|
StateIdle | Not active |
StateRunning | Active/running |
StateError | Error condition |
Common Port Patterns
Request/Response
go
func (c *HTTPClient) Ports() []module.Port {
return []module.Port{
{
Name: "request",
Label: "Request",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(HTTPRequest{}),
},
{
Name: "response",
Label: "Response",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(HTTPResponse{}),
},
{
Name: "error",
Label: "Error",
Source: false,
Position: module.PositionBottom,
Schema: schema.FromGo(HTTPError{}),
},
}
}Filter/Split
go
func (c *Filter) Ports() []module.Port {
return []module.Port{
{
Name: "input",
Label: "Input",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(Item{}),
},
{
Name: "match",
Label: "Match",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(Item{}),
},
{
Name: "no_match",
Label: "No Match",
Source: false,
Position: module.PositionBottom,
Schema: schema.FromGo(Item{}),
},
}
}Aggregator
go
func (c *Aggregator) Ports() []module.Port {
return []module.Port{
{
Name: "item",
Label: "Item",
Source: true,
Position: module.PositionLeft,
Schema: schema.FromGo(Item{}),
},
{
Name: "flush",
Label: "Flush",
Source: true,
Position: module.PositionTop,
Schema: schema.FromGo(FlushSignal{}),
},
{
Name: "batch",
Label: "Batch",
Source: false,
Position: module.PositionRight,
Schema: schema.FromGo(Batch{}),
},
}
}Next Steps
- Handling Messages - Process port messages
- Schema Definition - Schema details
- System Ports - Built-in ports