///|
/// The `.api` `type` → moonorm model generator. `generate_model` turns each
/// storable `type` block into a model struct, a `@moonorm.Model[T]` (an `id` column
/// is the primary key, plus the `from_row` decoder and `to_columns` projection
/// MoonBit can't synthesise for want of reflection), a `@moonorm.Table` descriptor,
/// and an up/down migration pair. A block with a non-storable field (here `Feed`'s
/// `[]Post` slice) still gets its struct and a plain `Table`.
///
///     moon run src/examples/04-model
#coverage.skip
fn main raise {
  let source =
    #|type User {
    #|  id:    int64  `json:"id"`
    #|  name:  string `json:"name"`
    #|  email: string `json:"email"`
    #|}
    #|
    #|type Post {
    #|  id:     int64  `json:"id"`
    #|  title:  string `json:"title"`
    #|  author: int64  `json:"author"`
    #|}
    #|
    #|type Feed {
    #|  posts: []Post `json:"posts"`
    #|}
    #|
    #|service blog {
    #|  get /users/:id get_user
    #|}
  let spec = @moonctl.parse(source)
  println(
    "parsed \{spec.types.length()} type blocks for service \{spec.service}\n",
  )
  println("==== generate_model(spec) -> moonorm model + migration ====\n")
  println(@moonctl.generate_model(spec))
}