///|
/// Struct tags: where a field binds from, what it is called there, and what it has
/// to look like. A `type` field carries its raw back-tick tag verbatim in
/// `Field::tag`; `Field::bind` reads whether the value comes out of the request body
/// (`json:`), the query string (`form:`), a URL segment (`path:`) or a header
/// (`header:`), `Field::json_name` the name it arrives under there, and
/// `Field::optional` / `default_` / `options` / `range` the constraints that follow
/// that name. `openapi_document` documents each of them where it belongs — a `form:`
/// field as a query parameter, a body field as a schema property with its `default`,
/// `enum` and bounds — and the generated `types.mbt` carries the `with_defaults` and
/// `check` that enforce the same rules at run time.
///
///     moon run src/examples/12-tags
#coverage.skip
fn main raise {
  let source =
    #|type ListAccounts {
    #|  region:    string `path:"region"`
    #|  page:      int    `form:"page,default=1,range=[1:100]"`
    #|  sort:      string `form:"sort,options=asc|desc"`
    #|  trace:     string `header:"X-Trace"`
    #|}
    #|
    #|type Account {
    #|  id:        int64  `json:"account_id"`
    #|  handle:    string `json:"handle"`
    #|  email:     string `json:"email,omitempty"`
    #|  api_token: string `json:"apiToken,optional"`
    #|  note:      string
    #|}
    #|
    #|service accounts {
    #|  @handler list_accounts
    #|  get /regions/:region/accounts (ListAccounts) returns (Account)
    #|}
  let spec = @moonctl.parse(source)
  for t in spec.types {
    println("type \{t.name}:")
    for f in t.fields {
      let where_ = match f.bind() {
        Body => "body"
        Query => "query"
        Path => "path"
        Header => "header"
      }
      let extra = (if f.optional() { " optional" } else { "" }) +
        (match f.default_() {
          Some(d) => " default=" + d
          None => ""
        })
      println(
        "  \{f.name} : \{f.type_}  ->  \{where_} \"\{f.json_name()}\"\{extra}",
      )
    }
  }
  println("\n==== the checks those tags generate ====\n")
  println(@moonctl.generate(spec))
  println("\n==== openapi_document(spec) ====\n")
  println(
    @moonctl.openapi_document(spec, version=OpenApi31).stringify(indent=2),
  )
}