// =====================================================================
// json_out.sx — `--json` mode output for `dist`, built with `std.json`.
//
// The machine-readable JSON object a `--json` run writes to stdout is
// built here, keeping the `std.json` writer in one place, separate from
// the `std.cli` dispatch in dist.sx.
// =====================================================================

#import "modules/std.sx";
#import "modules/std/json.sx";

// A machine-readable command failure: a stable dotted `code` naming the
// failing stage and sub-reason (e.g. "validation.digest_mismatch") plus a
// human sentence. Pipelines fill one of these at the raise site, so the
// CLI can report precisely what failed without the error channel having to
// carry data.
CliFailure :: struct {
    code: string = "";
    message: string = "";
}

// Serialize a failure as the `--json` error object — `{ "status": "error",
// "error": { "code": <code>, "message": <message> } }` — into the
// caller-owned `dst`, returning the bytes written. Overflow surfaces on
// the error channel.
write_error :: (f: CliFailure, dst: []u8) -> (i64, !JsonError) {
    gpa := GPA.init();
    obj : Object = .{};
    obj.put("status", .str("error"), xx gpa);
    eo : Object = .{};
    eo.put("code",    .str(f.code),    xx gpa);
    eo.put("message", .str(f.message), xx gpa);
    obj.put("error", .object(eo), xx gpa);
    root : Value = .object(obj);
    n := try write_to_buffer(root, dst);
    return n;
}
