///|
/// The plugin protocol round-trip (goctl's `api plugin`). mctl writes goctl's
/// request — `{Api, ApiFilePath, Style, Dir}` — to the plugin's stdin
/// (`plugin_request`); the plugin reads it back (`plugin_from_json`, or
/// `spec_from_json` when it wants nothing but the spec), emits the files it wants
/// written, and serialises them (`gen_files_to_json`); mctl reads that reply
/// (`parse_gen_files`) and writes the files to disk. Every stage here uses mctl's
/// own (de)serialisers, so the whole symmetric contract runs in one process — the
/// same one `cmd/demo-plugin` speaks over real pipes.
///
/// moon run src/examples/08-plugin
#coverage.skip
fn run_plugin(request : String) -> String raise {
let req = @moonctl.plugin_from_json(@json.parse(request))
let spec = req.api
let mut md = "# " + spec.service + " routes (style " + req.style + ")\n\n"
for r in spec.routes {
md = md + "- " + r.verb + " " + r.path + " -> " + r.handler + "\n"
}
let files : Array[@moonctl.GenFile] = [
{ path: spec.service + "_routes.md", content: md, },
{
path: spec.service + "_count.txt",
content: spec.routes.length().to_string() + "\n",
},
]
@moonctl.gen_files_to_json(files).stringify(indent=2)
}
///|
#coverage.skip
fn main raise {
let source =
#|service greet {
#| get /ping ping "health check"
#| post /users create_user "create a user"
#|}
let spec = @moonctl.parse(source)
let request = @moonctl.plugin_request(
spec,
api_file_path="greet.api",
style="go_zero",
dir="out",
)
println("==== plugin_request(spec) -> plugin stdin ====\n")
println(request)
// The spec alone cannot tell a plugin where to write or how to spell what it
// writes, so goctl's request carries the file, the style and the directory too.
let req = @moonctl.plugin_from_json(@json.parse(request))
println(
"\nApiFilePath=\{req.api_file_path} Style=\{req.style} Dir=\{req.dir}",
)
try {
let reply = run_plugin(request)
println("\n==== plugin stdout: gen_files_to_json(files) ====\n")
println(reply)
println("\n==== parse_gen_files(reply) -> files mctl writes ====\n")
for f in @moonctl.parse_gen_files(@json.parse(reply)) {
println("---- " + f.path + " ----")
println(f.content)
}
} catch {
_ => println("plugin round-trip failed")
}
}