Connections

A connection declaration defines a typed relationship between block instances; arrow statements then populate it. The result is a list of records that hosts can consume — render edges, build dependency graphs, validate references.

Declaring a connection

A connection names a relationship's source type, destination type, and (optionally) a tag drawn from a symbol_set.

symbol_set EdgeKind { uses  depends_on }
connection DependsOn: Service -> Service : EdgeKind

Connection statements

Inside a @connections(SchemaName) field, write source -> destination :tag to populate it. The tag is optional; omit the :kind for an untagged edge.

@document
type Config {
  @connections(DependsOn) edges: list<DependsOn>
}

web   -> db                   // untagged
web   -> cache :uses
api   -> db    :depends_on

Each statement produces a record with source, destination, and kind slots, ready for a host to interpret.

Dynamic endpoints

By default, every operand of an arrow statement must name a literal block in scope; an operand that resolves to nothing is a schema error. Tag the declaration with @dynamic to relax that: an unresolved operand is projected as its raw id string instead of being dropped, and wcl check no longer flags it. This is for endpoints a host materialises at consume time — e.g. ids generated by a repeater — that can't be resolved statically. The resolved side of a partly-dynamic statement is still type-checked.

symbol_set EdgeKind { uses }
@dynamic
connection DependsOn: Service -> Service : EdgeKind

A still-unmatched id is the host's responsibility (wdoc, for instance, drops such an edge with a build warning rather than failing). Leave @dynamic off for connections whose endpoints are always literal, so typos stay caught.