Skip to content

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:

validate {
  input = type.user         # HCL reference syntax
  input = "user"            # String name (equivalent)
}

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:

type "Order" {
  _key = "id"

  id         = string { required = true }
  product_id = string { external = true }    # @external — from another subgraph
  total      = number { requires = "items" } # @requires — needs items from federation
}