Types¶
Types define data schemas for validation. Attach them to flows to validate data before processing (input) or before writing to the target (output). Validation failures return HTTP 422 with field-level error details.
Defining a Type¶
type "user" {
email = string {
format = "email"
required = true
}
age = number {
min = 0
max = 150
}
role = string { enum = ["admin", "user", "guest"] }
username = string {
min_length = 3
max_length = 50
pattern = "^[a-zA-Z0-9_]+$"
}
}
Using a Type in a Flow¶
Use the validate block in a flow to apply type validation:
flow "create_user" {
from {
connector = "api"
operation = "POST /users"
}
validate {
input = "user" # Validates request body against type "user"
output = "user" # Validates transform result before writing
}
transform {
id = "uuid()"
email = "lower(input.email)"
created_at = "now()"
}
to {
connector = "db"
target = "users"
}
}
Both input and output accept a type name or a type.name reference:
Base Types¶
| Type | Description |
|---|---|
string |
Text value |
number |
Numeric value (integer or float) |
boolean |
true or false |
object |
Nested map |
array |
List of values |
Constraints¶
String Constraints¶
| Constraint | Type | Description |
|---|---|---|
required |
bool | Field must be present and non-null (default: true) |
format |
string | Validate string format |
min_length |
int | Minimum string length |
max_length |
int | Maximum string length |
pattern |
string | Regular expression the value must match |
enum |
list | Value must be one of these strings |
validate |
string | Reference to a custom validator |
Number Constraints¶
| Constraint | Type | Description |
|---|---|---|
required |
bool | Field must be present (default: true) |
min |
number | Minimum value (inclusive) |
max |
number | Maximum value (inclusive) |
enum |
list | Value must be one of these numbers |
Format Values¶
The format constraint validates well-known string formats:
| Format | Description |
|---|---|
"email" |
Valid email address |
"url" |
Valid URL |
"uuid" |
UUID v4 format |
"date" |
ISO date (YYYY-MM-DD) |
"datetime" |
ISO datetime (RFC3339) |
"phone" |
Phone number |
"ip" |
IP address (v4 or v6) |
type "contact" {
email = string { format = "email" }
phone = string {
format = "phone"
required = false
}
url = string {
format = "url"
required = false
}
}
Optional Fields¶
By default, all fields are required. Use required = false to make a field optional:
type "user_input" {
email = string {
required = true
format = "email"
}
name = string {
required = true
min_length = 1
}
nickname = string {
required = false
max_length = 50
}
avatar_url = string {
required = false
format = "url"
}
age = number {
required = false
min = 0
max = 150
}
}
This is especially useful for auto-generated fields like id or created_at — you define the type for documentation and output validation, but mark the field as optional for input:
type "user" {
id = string { required = false } # Auto-generated by transform
email = string { format = "email" }
created_at = string { required = false } # Set by transform
}
Custom Validators¶
Reference a custom validator for field-level validation beyond built-in constraints:
validator "cuit_validator" {
type = "cel"
expr = "value.matches('[0-9]{2}-[0-9]{8}-[0-9]')"
message = "Must be a valid CUIT (XX-XXXXXXXX-X)"
}
type "company" {
name = string { required = true }
cuit = string { validate = "cuit_validator" }
}
Validators can be cel, regex, or wasm. See Extending Mycel for details.
Enum Constraints¶
type "order" {
status = string { enum = ["pending", "paid", "shipped", "delivered", "cancelled"] }
priority = number { enum = [1, 2, 3] }
}
Pattern Constraints¶
type "product" {
sku = string { pattern = "^[A-Z]{3}-[0-9]{4}$" } # e.g., "PRD-0001"
slug = string { pattern = "^[a-z0-9-]+$" }
}
Complete Example¶
type "create_order_input" {
user_id = string { format = "uuid" }
product_id = string { format = "uuid" }
quantity = number {
min = 1
max = 1000
}
notes = string {
required = false
max_length = 500
}
priority = string {
required = false
enum = ["low", "normal", "high"]
}
}
type "order" {
id = string { required = false } # Generated
user_id = string { format = "uuid" }
product_id = string { format = "uuid" }
quantity = number { min = 1 }
status = string { enum = ["pending", "processing", "shipped", "cancelled"] }
created_at = string { required = false } # Generated
}
flow "create_order" {
from {
connector = "api"
operation = "POST /orders"
}
validate {
input = "create_order_input"
}
transform {
id = "uuid()"
user_id = "input.user_id"
product_id = "input.product_id"
quantity = "input.quantity"
status = "'pending'"
created_at = "now()"
}
validate {
output = "order"
}
to {
connector = "db"
target = "orders"
}
}
Federation Types¶
Types used in GraphQL Federation can include federation directives using underscore-prefixed attributes:
type "Product" {
_key = "sku" # @key(fields: "sku") — entity key
_shareable = true # @shareable — multiple subgraphs can resolve this type
sku = string { required = true }
name = string {}
price = number {}
}
| Attribute | GraphQL Directive | Description |
|---|---|---|
_key = "id" |
@key(fields: "id") |
Marks type as a federation entity |
_shareable = true |
@shareable |
Multiple subgraphs can resolve this type |
_description = "..." |
Type description | Appears in schema docs |
_implements = ["Node"] |
Implements interface | Interface implementations |
Field-level federation directives: