///|
/// One spec, four clients and a Markdown reference — what `mctl api ts|dart|kt|java`
/// and `mctl api doc` generate, without touching the disk.
///
/// The spec below is small but not trivial: a body route, a path parameter, a query
/// parameter, a header, an optional field and a nested type. The four clients are
/// generated from it, and the lines printed are the ones each language spells its
/// own way: the call, the model and the error.
///
/// moon run src/examples/14-clients
#coverage.skip
fn main raise {
let source =
#|@server(group: user, prefix: /api/v1)
#|service greet {
#| @doc "create a user"
#| @handler createUser
#| post /users (CreateReq) returns (User)
#|
#| @handler getUser
#| get /users/:id (GetReq) returns (User)
#|}
#|
#|type GetReq {
#| id: int64 `path:"id"`
#| verbose: bool `form:"verbose,optional"`
#|}
#|
#|type CreateReq {
#| name: string `json:"name"`
#| owner: User `json:"owner"`
#|}
#|
#|type User {
#| id: int64 `json:"id"`
#| name: string `json:"name"`
#| nickname: string `json:"nickname,optional"`
#|}
let spec = @moonctl.parse(source)
// formatting is idempotent: the canonical form of the canonical form is itself
let formatted = @moonctl.format(source)
println(
"api format is stable: " +
(formatted == @moonctl.format(formatted)).to_string(),
)
// and a valid spec has nothing to report
println(
"api validate: " +
@moonctl.validate_source(source).length().to_string() +
" finding(s)",
)
println("")
for
(lang, file) in [
(@moonctl.Lang::TypeScript, "greet_client.ts"),
(@moonctl.Lang::Dart, "greet_client.dart"),
(@moonctl.Lang::Kotlin, "greet_client.kt"),
(@moonctl.Lang::Java, "GreetClient.java"),
] {
let (name, text) = @moonctl.client_file(spec, lang)
println(
lang.label() +
" → " +
name +
" (" +
text.length().to_string() +
" bytes)",
)
println(
" " + name + " is named as expected: " + (name == file).to_string(),
)
}
println("")
let doc = @moonctl.generate_markdown(spec)
println("Markdown reference: " + doc.length().to_string() + " bytes")
println("")
// the route table is the part of the reference a reader comes for
let mut header = 0
while header < doc.length() && doc[header] != '#' {
header = header + 1
}
println(doc[if header < doc.length() { header } else { 0 }:].to_owned())
}