Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Blocks

A block is the primary structural unit of a WCL file. Blocks group attributes and nested blocks under a named type, and can carry optional identity and metadata.

Full Syntax

[decorators] [partial] type [inline-id] [inline-args...] { body }

Every component except type and { body } is optional.

Components

Block Type

The block type is a plain identifier that names the kind of configuration node. Types are user-defined unless they are one of the reserved names listed below.

server { }
database { }
endpoint { }
my_custom_type { }

Inline ID

An inline ID uniquely identifies a block within its scope. It may contain letters, digits, and hyphens (unlike attribute names, which forbid hyphens):

server web-1 { }
database primary-db { }
endpoint get-users { }

Inline IDs must be unique per block type within their scope. The only exception is partial blocks, which share an ID with the block they extend (see Partial Declarations).

Inline Arguments

Inline arguments are positional values placed between the inline ID (or block type) and the opening {. They accept any primary expression: integers, floats, strings, booleans, null, and lists.

server web 8080 "prod" { }
endpoint api true 3 { }
service worker [1, 2, 3] { }

Without a schema, inline args are collected into a synthetic _args list attribute:

server web 8080 "prod" {
  host = "localhost"
}
// Evaluates to: { _args: [8080, "prod"], host: "localhost" }

With a schema, fields decorated with @inline(N) map positional args to named attributes:

schema "server" {
    port: int @inline(0)
    env: string @inline(1)
    host: string
}

server web 8080 "prod" {
    host = "localhost"
}
// Evaluates to: { port: 8080, env: "prod", host: "localhost" }

Any args not mapped by @inline remain in _args.

Decorators

Decorators are annotations that modify or validate a block. They are placed before the block type, one per line, each starting with @:

@deprecated
@env("production")
server legacy { }

@required
server primary { }

See Decorators for the full decorator system.

The partial Keyword

The partial keyword marks a block as a partial declaration, meaning it will be merged into another block with the same type and ID. This allows spreading a block’s definition across multiple files:

partial server web-1 {
  host = "0.0.0.0"
}

partial server web-1 {
  port = 8080
}

See Partial Declarations for merge semantics.

Body

The body is a { }-delimited sequence of attributes, nested blocks, let bindings, for loops, and if/else expressions.

Reserved Block Types

The following block types have special semantics and are handled by the WCL pipeline:

TypePurpose
schemaDefines a schema for validating user blocks
decorator_schemaDefines the parameter schema for a decorator
tableTabular data with typed columns
validationInline validation assertions
macroDefines a reusable macro (function or attribute form)

Examples

Minimal Block

server { }

Block with Attributes

server {
  host = "0.0.0.0"
  port = 8080
}

Block with Inline ID

server web-1 {
  host = "0.0.0.0"
  port = 8080
}

Block with Inline Arguments

server 8080 "production" {
  host = "prod.example.com"
}

Block with Inline ID and Arguments

server web-1 8080 "production" {
  host = "prod.example.com"
}

Decorated Block

@env("production")
server primary {
  host = "prod.example.com"
  port = 443
}

Nested Blocks

application my-app {
  name    = "my-app"
  version = "1.0.0"

  server {
    host = "0.0.0.0"
    port = 8080

    tls {
      cert = "/etc/certs/server.crt"
      key  = "/etc/certs/server.key"
    }
  }

  database primary {
    host = "db.internal"
    port = 5432
  }
}

Multiple Sibling Blocks of the Same Type

server web-1 {
  host = "10.0.0.1"
  port = 8080
}

server web-2 {
  host = "10.0.0.2"
  port = 8080
}

server web-3 {
  host = "10.0.0.3"
  port = 8080
}

Blocks without IDs in the same scope are not required to be unique by the evaluator, but schemas may impose additional uniqueness constraints.