From b25c8cb53998ae20441273aa550a0b435b608bf3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 22:13:16 +0000 Subject: [PATCH 01/31] chore(internal): codegen related update --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3183fac..81083cd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/agentmail-to/agentmail-cli go 1.25 require ( - github.com/agentmail-to/agentmail-go v0.6.0 + github.com/agentmail-to/agentmail-go v0.8.0 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.6 github.com/charmbracelet/lipgloss v1.1.0 diff --git a/go.sum b/go.sum index 550ec0a..1089e67 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/agentmail-to/agentmail-go v0.6.0 h1:CCQtBbYE97KASraV2v4IvSuaaJrjKDn97qH1rhMmJt8= -github.com/agentmail-to/agentmail-go v0.6.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= +github.com/agentmail-to/agentmail-go v0.8.0 h1:7Ek7UHIO0U2rrN6ib2gL1/W3LEkHdQfvQsHu0j3T+CQ= +github.com/agentmail-to/agentmail-go v0.8.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= From fbfe2c1e0e56a779a885443c2d0d4743b512e242 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 03:52:03 +0000 Subject: [PATCH 02/31] chore(cli): fall back to JSON when using default "explore" with non-TTY --- cmd/agentmail/main.go | 2 +- pkg/cmd/agent.go | 6 ++-- pkg/cmd/apikey.go | 6 ++-- pkg/cmd/cmdutil.go | 29 +++++++++++++---- pkg/cmd/cmdutil_test.go | 70 ++++++++++++++++++++++++++++++++++++++++- pkg/cmd/domain.go | 12 ++++--- pkg/cmd/draft.go | 9 ++++-- pkg/cmd/inbox.go | 15 ++++++--- pkg/cmd/inboxapikey.go | 6 ++-- pkg/cmd/inboxdraft.go | 18 +++++++---- pkg/cmd/inboxlist.go | 9 ++++-- pkg/cmd/inboxmessage.go | 27 ++++++++++------ pkg/cmd/inboxthread.go | 9 ++++-- pkg/cmd/list.go | 9 ++++-- pkg/cmd/metric.go | 3 +- pkg/cmd/organization.go | 3 +- pkg/cmd/pod.go | 9 ++++-- pkg/cmd/podapikey.go | 6 ++-- pkg/cmd/poddomain.go | 12 ++++--- pkg/cmd/poddraft.go | 9 ++++-- pkg/cmd/podinbox.go | 12 ++++--- pkg/cmd/podlist.go | 9 ++++-- pkg/cmd/podmetric.go | 3 +- pkg/cmd/podthread.go | 9 ++++-- pkg/cmd/thread.go | 9 ++++-- pkg/cmd/webhook.go | 12 ++++--- 26 files changed, 241 insertions(+), 82 deletions(-) diff --git a/cmd/agentmail/main.go b/cmd/agentmail/main.go index a8702f2..6853420 100644 --- a/cmd/agentmail/main.go +++ b/cmd/agentmail/main.go @@ -43,7 +43,7 @@ func main() { fmt.Fprintf(os.Stderr, "%s %q: %d %s\n", apierr.Request.Method, apierr.Request.URL, apierr.Response.StatusCode, http.StatusText(apierr.Response.StatusCode)) format := app.String("format-error") json := gjson.Parse(apierr.RawJSON()) - show_err := cmd.ShowJSON(os.Stdout, "Error", json, format, app.String("transform-error")) + show_err := cmd.ShowJSON(os.Stdout, os.Stderr, "Error", json, format, app.IsSet("format-error"), app.String("transform-error")) if show_err != nil { // Just print the original error: fmt.Fprintf(os.Stderr, "%s\n", err.Error()) diff --git a/pkg/cmd/agent.go b/pkg/cmd/agent.go index 03ee71b..b446260 100644 --- a/pkg/cmd/agent.go +++ b/pkg/cmd/agent.go @@ -83,8 +83,9 @@ func handleAgentSignUp(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "agent sign-up", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "agent sign-up", obj, format, explicitFormat, transform) } func handleAgentVerify(ctx context.Context, cmd *cli.Command) error { @@ -117,6 +118,7 @@ func handleAgentVerify(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "agent verify", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "agent verify", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/apikey.go b/pkg/cmd/apikey.go index c93f3c8..28a95d6 100644 --- a/pkg/cmd/apikey.go +++ b/pkg/cmd/apikey.go @@ -283,8 +283,9 @@ func handleAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "api-keys create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "api-keys create", obj, format, explicitFormat, transform) } func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -317,8 +318,9 @@ func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "api-keys list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "api-keys list", obj, format, explicitFormat, transform) } func handleAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/cmdutil.go b/pkg/cmd/cmdutil.go index 75c8b90..d0d9826 100644 --- a/pkg/cmd/cmdutil.go +++ b/pkg/cmd/cmdutil.go @@ -366,8 +366,13 @@ func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format } } -// Display JSON to the user in various different formats -func ShowJSON(out *os.File, title string, res gjson.Result, format string, transform string) error { +const warningExploreNotSupported = "Warning: Output format 'explore' not supported for non-terminal output; falling back to 'json'\n" + +// Display JSON to the user in various different formats. The explicitFormat parameter indicates +// whether the format was explicitly set by the user (via --format), which controls whether we +// silently fall back to json when explore is requested on non-terminal output. Warnings are +// written to stderr. +func ShowJSON(out *os.File, stderr io.Writer, title string, res gjson.Result, format string, explicitFormat bool, transform string) error { if transform != "" { transformed := res.Get(transform) if transformed.Exists() { @@ -377,8 +382,14 @@ func ShowJSON(out *os.File, title string, res gjson.Result, format string, trans switch strings.ToLower(format) { case "auto": - return ShowJSON(out, title, res, "json", "") + return ShowJSON(out, stderr, title, res, "json", explicitFormat, "") case "explore": + if !isTerminal(out) { + if explicitFormat { + fmt.Fprint(stderr, warningExploreNotSupported) + } + return ShowJSON(out, stderr, title, res, "json", explicitFormat, transform) + } return jsonview.ExploreJSON(title, res) default: bytes, err := formatJSON(out, title, res, format, transform) @@ -403,9 +414,15 @@ type hasRawJSON interface { // For an iterator over different value types, display its values to the user in // different formats. // -1 is used to signal no limit of items to display -func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterator[T], format string, transform string, itemsToDisplay int64) error { +func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, iter jsonview.Iterator[T], format string, explicitFormat bool, transform string, itemsToDisplay int64) error { if format == "explore" { - return jsonview.ExploreJSONStream(title, iter) + if isTerminal(stdout) { + return jsonview.ExploreJSONStream(title, iter) + } + if explicitFormat { + fmt.Fprint(stderr, warningExploreNotSupported) + } + format = "json" } terminalWidth, terminalHeight, err := term.GetSize(os.Stdout.Fd()) @@ -478,7 +495,7 @@ func ShowJSONIterator[T any](stdout *os.File, title string, iter jsonview.Iterat } obj = gjson.ParseBytes(jsonData) } - if err := ShowJSON(pager, title, obj, format, transform); err != nil { + if err := ShowJSON(pager, stderr, title, obj, format, explicitFormat, transform); err != nil { return err } itemsToDisplay -= 1 diff --git a/pkg/cmd/cmdutil_test.go b/pkg/cmd/cmdutil_test.go index 66e3b07..ba5e3f0 100644 --- a/pkg/cmd/cmdutil_test.go +++ b/pkg/cmd/cmdutil_test.go @@ -231,6 +231,73 @@ func TestShowJSONIterator(t *testing.T) { }) } +func TestExploreFallback(t *testing.T) { + t.Parallel() + + t.Run("ShowJSONFallsBackToJsonOnNonTTY", func(t *testing.T) { + t.Parallel() + + // os.Pipe() produces a *os.File that isn't a terminal, so explore should fall back. + r, w, err := os.Pipe() + require.NoError(t, err) + defer r.Close() + + var stderr bytes.Buffer + res := gjson.Parse(`{"id":"abc"}`) + err = ShowJSON(w, &stderr, "test", res, "explore", false, "") + w.Close() + require.NoError(t, err) + + var buf bytes.Buffer + _, _ = buf.ReadFrom(r) + assert.Contains(t, buf.String(), `"id"`) + assert.Contains(t, buf.String(), `"abc"`) + }) + + t.Run("ShowJSONIteratorFallsBackToJsonOnNonTTY", func(t *testing.T) { + t.Parallel() + + iter := &sliceIterator[map[string]any]{items: []map[string]any{ + {"id": "abc"}, + }} + captured := captureShowJSONIterator(t, iter, "explore", "", -1) + assert.Contains(t, captured, `"id"`) + assert.Contains(t, captured, `"abc"`) + }) + + t.Run("ShowJSONWarnsWhenExplicitFormatOnNonTTY", func(t *testing.T) { + t.Parallel() + + r, w, err := os.Pipe() + require.NoError(t, err) + defer r.Close() + + var stderr bytes.Buffer + res := gjson.Parse(`{"id":"abc"}`) + err = ShowJSON(w, &stderr, "test", res, "explore", true, "") + w.Close() + require.NoError(t, err) + + assert.Equal(t, warningExploreNotSupported, stderr.String()) + }) + + t.Run("ShowJSONSilentWhenDefaultFormatOnNonTTY", func(t *testing.T) { + t.Parallel() + + r, w, err := os.Pipe() + require.NoError(t, err) + defer r.Close() + + var stderr bytes.Buffer + res := gjson.Parse(`{"id":"abc"}`) + err = ShowJSON(w, &stderr, "test", res, "explore", false, "") + w.Close() + require.NoError(t, err) + + assert.Empty(t, stderr.String(), "no warning expected when format was not explicit") + }) +} + // sliceIterator is a simple iterator over a slice for testing. type sliceIterator[T any] struct { index int @@ -260,7 +327,8 @@ func captureShowJSONIterator[T any](t *testing.T, iter jsonview.Iterator[T], for require.NoError(t, err) defer r.Close() - err = ShowJSONIterator(w, "test", iter, format, transform, itemsToDisplay) + var stderr bytes.Buffer + err = ShowJSONIterator(w, &stderr, "test", iter, format, false, transform, itemsToDisplay) w.Close() require.NoError(t, err) diff --git a/pkg/cmd/domain.go b/pkg/cmd/domain.go index df45bb1..62a5dcd 100644 --- a/pkg/cmd/domain.go +++ b/pkg/cmd/domain.go @@ -172,8 +172,9 @@ func handleDomainsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "domains create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "domains create", obj, format, explicitFormat, transform) } func handleDomainsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -214,8 +215,9 @@ func handleDomainsUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "domains update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "domains update", obj, format, explicitFormat, transform) } func handleDomainsList(ctx context.Context, cmd *cli.Command) error { @@ -248,8 +250,9 @@ func handleDomainsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "domains list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "domains list", obj, format, explicitFormat, transform) } func handleDomainsDelete(ctx context.Context, cmd *cli.Command) error { @@ -308,8 +311,9 @@ func handleDomainsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "domains get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "domains get", obj, format, explicitFormat, transform) } func handleDomainsGetZoneFile(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/draft.go b/pkg/cmd/draft.go index e97079a..b7b9ca3 100644 --- a/pkg/cmd/draft.go +++ b/pkg/cmd/draft.go @@ -120,8 +120,9 @@ func handleDraftsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "drafts list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "drafts list", obj, format, explicitFormat, transform) } func handleDraftsGet(ctx context.Context, cmd *cli.Command) error { @@ -155,8 +156,9 @@ func handleDraftsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "drafts get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "drafts get", obj, format, explicitFormat, transform) } func handleDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -199,6 +201,7 @@ func handleDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "drafts get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "drafts get-attachment", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/inbox.go b/pkg/cmd/inbox.go index 5ef6d17..68bb4ae 100644 --- a/pkg/cmd/inbox.go +++ b/pkg/cmd/inbox.go @@ -196,8 +196,9 @@ func handleInboxesCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes create", obj, format, explicitFormat, transform) } func handleInboxesUpdate(ctx context.Context, cmd *cli.Command) error { @@ -238,8 +239,9 @@ func handleInboxesUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes update", obj, format, explicitFormat, transform) } func handleInboxesList(ctx context.Context, cmd *cli.Command) error { @@ -272,8 +274,9 @@ func handleInboxesList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes list", obj, format, explicitFormat, transform) } func handleInboxesDelete(ctx context.Context, cmd *cli.Command) error { @@ -332,8 +335,9 @@ func handleInboxesGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes get", obj, format, explicitFormat, transform) } func handleInboxesListMetrics(ctx context.Context, cmd *cli.Command) error { @@ -374,6 +378,7 @@ func handleInboxesListMetrics(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes list-metrics", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes list-metrics", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/inboxapikey.go b/pkg/cmd/inboxapikey.go index eb44d6d..7a1b8f9 100644 --- a/pkg/cmd/inboxapikey.go +++ b/pkg/cmd/inboxapikey.go @@ -301,8 +301,9 @@ func handleInboxesAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:api-keys create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:api-keys create", obj, format, explicitFormat, transform) } func handleInboxesAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -343,8 +344,9 @@ func handleInboxesAPIKeysList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:api-keys list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:api-keys list", obj, format, explicitFormat, transform) } func handleInboxesAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/inboxdraft.go b/pkg/cmd/inboxdraft.go index a51e315..514dfa1 100644 --- a/pkg/cmd/inboxdraft.go +++ b/pkg/cmd/inboxdraft.go @@ -361,8 +361,9 @@ func handleInboxesDraftsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts create", obj, format, explicitFormat, transform) } func handleInboxesDraftsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -405,8 +406,9 @@ func handleInboxesDraftsUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts update", obj, format, explicitFormat, transform) } func handleInboxesDraftsList(ctx context.Context, cmd *cli.Command) error { @@ -447,8 +449,9 @@ func handleInboxesDraftsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts list", obj, format, explicitFormat, transform) } func handleInboxesDraftsDelete(ctx context.Context, cmd *cli.Command) error { @@ -525,8 +528,9 @@ func handleInboxesDraftsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts get", obj, format, explicitFormat, transform) } func handleInboxesDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -570,8 +574,9 @@ func handleInboxesDraftsGetAttachment(ctx context.Context, cmd *cli.Command) err obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts get-attachment", obj, format, explicitFormat, transform) } func handleInboxesDraftsSend(ctx context.Context, cmd *cli.Command) error { @@ -614,6 +619,7 @@ func handleInboxesDraftsSend(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:drafts send", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts send", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/inboxlist.go b/pkg/cmd/inboxlist.go index 9fe9be2..9e3fcef 100644 --- a/pkg/cmd/inboxlist.go +++ b/pkg/cmd/inboxlist.go @@ -185,8 +185,9 @@ func handleInboxesListsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:lists create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists create", obj, format, explicitFormat, transform) } func handleInboxesListsList(ctx context.Context, cmd *cli.Command) error { @@ -230,8 +231,9 @@ func handleInboxesListsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:lists list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists list", obj, format, explicitFormat, transform) } func handleInboxesListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -312,6 +314,7 @@ func handleInboxesListsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:lists get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/inboxmessage.go b/pkg/cmd/inboxmessage.go index 7278ad5..0360b6a 100644 --- a/pkg/cmd/inboxmessage.go +++ b/pkg/cmd/inboxmessage.go @@ -584,8 +584,9 @@ func handleInboxesMessagesUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages update", obj, format, explicitFormat, transform) } func handleInboxesMessagesList(ctx context.Context, cmd *cli.Command) error { @@ -626,8 +627,9 @@ func handleInboxesMessagesList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages list", obj, format, explicitFormat, transform) } func handleInboxesMessagesForward(ctx context.Context, cmd *cli.Command) error { @@ -670,8 +672,9 @@ func handleInboxesMessagesForward(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages forward", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages forward", obj, format, explicitFormat, transform) } func handleInboxesMessagesGet(ctx context.Context, cmd *cli.Command) error { @@ -714,8 +717,9 @@ func handleInboxesMessagesGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get", obj, format, explicitFormat, transform) } func handleInboxesMessagesGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -759,8 +763,9 @@ func handleInboxesMessagesGetAttachment(ctx context.Context, cmd *cli.Command) e obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get-attachment", obj, format, explicitFormat, transform) } func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { @@ -803,8 +808,9 @@ func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages get-raw", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get-raw", obj, format, explicitFormat, transform) } func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { @@ -847,8 +853,9 @@ func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages reply", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages reply", obj, format, explicitFormat, transform) } func handleInboxesMessagesReplyAll(ctx context.Context, cmd *cli.Command) error { @@ -891,8 +898,9 @@ func handleInboxesMessagesReplyAll(ctx context.Context, cmd *cli.Command) error obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages reply-all", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages reply-all", obj, format, explicitFormat, transform) } func handleInboxesMessagesSend(ctx context.Context, cmd *cli.Command) error { @@ -933,6 +941,7 @@ func handleInboxesMessagesSend(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:messages send", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages send", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/inboxthread.go b/pkg/cmd/inboxthread.go index d679a57..f46448c 100644 --- a/pkg/cmd/inboxthread.go +++ b/pkg/cmd/inboxthread.go @@ -183,8 +183,9 @@ func handleInboxesThreadsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:threads list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads list", obj, format, explicitFormat, transform) } func handleInboxesThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -261,8 +262,9 @@ func handleInboxesThreadsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:threads get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads get", obj, format, explicitFormat, transform) } func handleInboxesThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -306,6 +308,7 @@ func handleInboxesThreadsGetAttachment(ctx context.Context, cmd *cli.Command) er obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "inboxes:threads get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads get-attachment", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/list.go b/pkg/cmd/list.go index 8442109..3a481ff 100644 --- a/pkg/cmd/list.go +++ b/pkg/cmd/list.go @@ -164,8 +164,9 @@ func handleListsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "lists create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "lists create", obj, format, explicitFormat, transform) } func handleListsList(ctx context.Context, cmd *cli.Command) error { @@ -208,8 +209,9 @@ func handleListsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "lists list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "lists list", obj, format, explicitFormat, transform) } func handleListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -288,6 +290,7 @@ func handleListsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "lists get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "lists get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/metric.go b/pkg/cmd/metric.go index 7b1768b..f85c0b5 100644 --- a/pkg/cmd/metric.go +++ b/pkg/cmd/metric.go @@ -85,6 +85,7 @@ func handleMetricsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "metrics list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "metrics list", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/organization.go b/pkg/cmd/organization.go index d2aea0f..88a392c 100644 --- a/pkg/cmd/organization.go +++ b/pkg/cmd/organization.go @@ -51,6 +51,7 @@ func handleOrganizationsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "organizations get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "organizations get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/pod.go b/pkg/cmd/pod.go index 64243e3..fb7fba4 100644 --- a/pkg/cmd/pod.go +++ b/pkg/cmd/pod.go @@ -120,8 +120,9 @@ func handlePodsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods create", obj, format, explicitFormat, transform) } func handlePodsList(ctx context.Context, cmd *cli.Command) error { @@ -154,8 +155,9 @@ func handlePodsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods list", obj, format, explicitFormat, transform) } func handlePodsDelete(ctx context.Context, cmd *cli.Command) error { @@ -214,6 +216,7 @@ func handlePodsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/podapikey.go b/pkg/cmd/podapikey.go index 3b47191..6853129 100644 --- a/pkg/cmd/podapikey.go +++ b/pkg/cmd/podapikey.go @@ -301,8 +301,9 @@ func handlePodsAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:api-keys create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:api-keys create", obj, format, explicitFormat, transform) } func handlePodsAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -343,8 +344,9 @@ func handlePodsAPIKeysList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:api-keys list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:api-keys list", obj, format, explicitFormat, transform) } func handlePodsAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/poddomain.go b/pkg/cmd/poddomain.go index 92b31bd..28aa494 100644 --- a/pkg/cmd/poddomain.go +++ b/pkg/cmd/poddomain.go @@ -215,8 +215,9 @@ func handlePodsDomainsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:domains create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:domains create", obj, format, explicitFormat, transform) } func handlePodsDomainsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -259,8 +260,9 @@ func handlePodsDomainsUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:domains update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:domains update", obj, format, explicitFormat, transform) } func handlePodsDomainsList(ctx context.Context, cmd *cli.Command) error { @@ -301,8 +303,9 @@ func handlePodsDomainsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:domains list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:domains list", obj, format, explicitFormat, transform) } func handlePodsDomainsDelete(ctx context.Context, cmd *cli.Command) error { @@ -379,8 +382,9 @@ func handlePodsDomainsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:domains get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:domains get", obj, format, explicitFormat, transform) } func handlePodsDomainsGetZoneFile(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/poddraft.go b/pkg/cmd/poddraft.go index 1ecf2bc..5f204f2 100644 --- a/pkg/cmd/poddraft.go +++ b/pkg/cmd/poddraft.go @@ -143,8 +143,9 @@ func handlePodsDraftsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:drafts list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:drafts list", obj, format, explicitFormat, transform) } func handlePodsDraftsGet(ctx context.Context, cmd *cli.Command) error { @@ -187,8 +188,9 @@ func handlePodsDraftsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:drafts get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:drafts get", obj, format, explicitFormat, transform) } func handlePodsDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -232,6 +234,7 @@ func handlePodsDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:drafts get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:drafts get-attachment", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/podinbox.go b/pkg/cmd/podinbox.go index aa0729b..39436f8 100644 --- a/pkg/cmd/podinbox.go +++ b/pkg/cmd/podinbox.go @@ -184,8 +184,9 @@ func handlePodsInboxesCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:inboxes create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes create", obj, format, explicitFormat, transform) } func handlePodsInboxesUpdate(ctx context.Context, cmd *cli.Command) error { @@ -228,8 +229,9 @@ func handlePodsInboxesUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:inboxes update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes update", obj, format, explicitFormat, transform) } func handlePodsInboxesList(ctx context.Context, cmd *cli.Command) error { @@ -270,8 +272,9 @@ func handlePodsInboxesList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:inboxes list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes list", obj, format, explicitFormat, transform) } func handlePodsInboxesDelete(ctx context.Context, cmd *cli.Command) error { @@ -348,6 +351,7 @@ func handlePodsInboxesGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:inboxes get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/podlist.go b/pkg/cmd/podlist.go index 10c0a14..7eca84a 100644 --- a/pkg/cmd/podlist.go +++ b/pkg/cmd/podlist.go @@ -185,8 +185,9 @@ func handlePodsListsCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:lists create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:lists create", obj, format, explicitFormat, transform) } func handlePodsListsList(ctx context.Context, cmd *cli.Command) error { @@ -230,8 +231,9 @@ func handlePodsListsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:lists list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:lists list", obj, format, explicitFormat, transform) } func handlePodsListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -312,6 +314,7 @@ func handlePodsListsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:lists get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:lists get", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/podmetric.go b/pkg/cmd/podmetric.go index 88579b1..33109b5 100644 --- a/pkg/cmd/podmetric.go +++ b/pkg/cmd/podmetric.go @@ -98,6 +98,7 @@ func handlePodsMetricsQuery(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:metrics query", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:metrics query", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/podthread.go b/pkg/cmd/podthread.go index 92ce97d..811bfef 100644 --- a/pkg/cmd/podthread.go +++ b/pkg/cmd/podthread.go @@ -183,8 +183,9 @@ func handlePodsThreadsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:threads list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:threads list", obj, format, explicitFormat, transform) } func handlePodsThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -261,8 +262,9 @@ func handlePodsThreadsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:threads get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:threads get", obj, format, explicitFormat, transform) } func handlePodsThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -306,6 +308,7 @@ func handlePodsThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "pods:threads get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "pods:threads get-attachment", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/thread.go b/pkg/cmd/thread.go index c41f595..1007226 100644 --- a/pkg/cmd/thread.go +++ b/pkg/cmd/thread.go @@ -155,8 +155,9 @@ func handleThreadsList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "threads list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "threads list", obj, format, explicitFormat, transform) } func handleThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -222,8 +223,9 @@ func handleThreadsGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "threads get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "threads get", obj, format, explicitFormat, transform) } func handleThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -266,6 +268,7 @@ func handleThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "threads get-attachment", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "threads get-attachment", obj, format, explicitFormat, transform) } diff --git a/pkg/cmd/webhook.go b/pkg/cmd/webhook.go index afff2aa..4c1b45b 100644 --- a/pkg/cmd/webhook.go +++ b/pkg/cmd/webhook.go @@ -172,8 +172,9 @@ func handleWebhooksCreate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "webhooks create", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "webhooks create", obj, format, explicitFormat, transform) } func handleWebhooksUpdate(ctx context.Context, cmd *cli.Command) error { @@ -214,8 +215,9 @@ func handleWebhooksUpdate(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "webhooks update", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "webhooks update", obj, format, explicitFormat, transform) } func handleWebhooksList(ctx context.Context, cmd *cli.Command) error { @@ -248,8 +250,9 @@ func handleWebhooksList(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "webhooks list", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "webhooks list", obj, format, explicitFormat, transform) } func handleWebhooksDelete(ctx context.Context, cmd *cli.Command) error { @@ -308,6 +311,7 @@ func handleWebhooksGet(ctx context.Context, cmd *cli.Command) error { obj := gjson.ParseBytes(res) format := cmd.Root().String("format") + explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, "webhooks get", obj, format, transform) + return ShowJSON(os.Stdout, os.Stderr, "webhooks get", obj, format, explicitFormat, transform) } From ea26a8c2a975386b3a00bf181d877e3eeb40c3f1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 03:53:10 +0000 Subject: [PATCH 03/31] feat(cli): alias parameters in data with `x-stainless-cli-data-alias` --- internal/requestflag/innerflag.go | 19 ++++++++++-- internal/requestflag/requestflag.go | 9 ++++++ pkg/cmd/flagoptions.go | 47 +++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/internal/requestflag/innerflag.go b/internal/requestflag/innerflag.go index 102624f..eeeb8bc 100644 --- a/internal/requestflag/innerflag.go +++ b/internal/requestflag/innerflag.go @@ -22,14 +22,29 @@ type InnerFlag[ Aliases []string // aliases that are allowed for this flag Validator func(T) error // custom function to validate this flag value - OuterFlag cli.Flag // The flag on which this inner flag will set values - InnerField string // The inner field which this flag will set + OuterFlag cli.Flag // The flag on which this inner flag will set values + InnerField string // The inner field which this flag will set + DataAliases []string // alternate names recognized in YAML values passed as the outer flag +} + +// GetDataAliases returns the aliases recognized when parsing inner field keys from piped or flag YAML. +func (f *InnerFlag[T]) GetDataAliases() []string { + return f.DataAliases +} + +// GetInnerField returns the API field name that this inner flag sets on its outer flag's value. +// For example, the flag --parent.foo targeting a parameter whose OpenAPI property name is "foo" +// would return "foo". This is distinct from the flag's CLI name and from any DataAliases entries. +func (f *InnerFlag[T]) GetInnerField() string { + return f.InnerField } type HasOuterFlag interface { cli.Flag SetOuterFlag(cli.Flag) GetOuterFlag() cli.Flag + GetInnerField() string + GetDataAliases() []string } func (f *InnerFlag[T]) SetOuterFlag(flag cli.Flag) { diff --git a/internal/requestflag/requestflag.go b/internal/requestflag/requestflag.go index bdef64f..bfaf064 100644 --- a/internal/requestflag/requestflag.go +++ b/internal/requestflag/requestflag.go @@ -48,6 +48,10 @@ type Flag[ // binary` in the OpenAPI spec. FileInput bool + // DataAliases is a list of alternate names for this parameter recognized when parsing piped YAML/JSON + // input. Values keyed by any alias are translated to the canonical API name before being sent. + DataAliases []string + // unexported fields for internal use count int // number of times the flag has been set hasBeenSet bool // whether the flag has been set from env or file @@ -65,6 +69,7 @@ type InRequest interface { GetBodyPath() string IsBodyRoot() bool IsFileInput() bool + GetDataAliases() []string } func (f Flag[T]) GetQueryPath() string { @@ -87,6 +92,10 @@ func (f Flag[T]) IsFileInput() bool { return f.FileInput } +func (f Flag[T]) GetDataAliases() []string { + return f.DataAliases +} + // The values that will be sent in different parts of a request. type RequestContents struct { Queries map[string]any diff --git a/pkg/cmd/flagoptions.go b/pkg/cmd/flagoptions.go index 0d94ce4..9eb5221 100644 --- a/pkg/cmd/flagoptions.go +++ b/pkg/cmd/flagoptions.go @@ -309,6 +309,12 @@ func flagOptions( requestContents := requestflag.ExtractRequestContents(cmd) + // Translate inner-field aliases in YAML values that came from flags (e.g. + // `--parent '{"alias": val}'` resolving to the canonical inner field). + if bodyMap, ok := requestContents.Body.(map[string]any); ok { + applyDataAliases(cmd, bodyMap) + } + stdinConsumedByPipe := false if (bodyType == MultipartFormEncoded || bodyType == ApplicationJSON) && !ignoreStdin && isInputPiped() { pipeData, err := io.ReadAll(os.Stdin) @@ -323,6 +329,7 @@ func flagOptions( return nil, fmt.Errorf("Failed to parse piped data as YAML/JSON:\n%w", err) } if bodyMap, ok := bodyData.(map[string]any); ok { + applyDataAliases(cmd, bodyMap) if flagMap, ok := requestContents.Body.(map[string]any); ok { maps.Copy(bodyMap, flagMap) requestContents.Body = bodyMap @@ -485,6 +492,46 @@ func flagOptions( // as a file path without needing the "@" prefix. type FilePathValue string +// applyDataAliases rewrites keys in a body map based on flag `DataAliases` metadata. For top-level flags, +// `{alias: value}` becomes `{canonical: value}`. For inner flags (those registered under an outer flag +// via WithInnerFlags), the alias translation is also applied to the nested map under the outer flag's +// body path, so values like `--parent '{"alias": val}'` resolve to the canonical inner field name. +func applyDataAliases(cmd *cli.Command, bodyMap map[string]any) { + for _, flag := range cmd.Flags { + // Inner flags: rewrite aliases inside the nested map under the outer flag's body path. + if inner, ok := flag.(requestflag.HasOuterFlag); ok { + outer, outerOk := inner.GetOuterFlag().(requestflag.InRequest) + if !outerOk { + continue + } + if nested, ok := bodyMap[outer.GetBodyPath()].(map[string]any); ok && inner.GetInnerField() != "" { + rewriteAliases(nested, inner.GetInnerField(), inner.GetDataAliases()) + } + continue + } + // Top-level flags: rewrite aliases in the body map. + if inReq, ok := flag.(requestflag.InRequest); ok && inReq.GetBodyPath() != "" { + rewriteAliases(bodyMap, inReq.GetBodyPath(), inReq.GetDataAliases()) + } + } +} + +// rewriteAliases replaces each alias key in m with the canonical key, preserving the value. The +// "canonical" key is the name the API itself expects (the OpenAPI property/field name) — e.g. for +// a top-level flag, the parameter's BodyPath; for an inner flag, the inner field name. Aliases are +// the user-facing alternate names declared via x-stainless-cli-data-alias. +func rewriteAliases(m map[string]any, canonical string, aliases []string) { + for _, alias := range aliases { + if alias == "" || alias == canonical { + continue + } + if val, exists := m[alias]; exists { + m[canonical] = val + delete(m, alias) + } + } +} + // wrapFileInputValues replaces string values for FileInput flags (type: string, format: binary) with // FilePathValue sentinel values. embedFilesValue recognizes FilePathValue and reads the file contents // directly, so the user doesn't need to type the "@" prefix. This handles both values set via explicit From d227554129ec4bddcf6ba84af9f08fe49247ea82 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 03:23:12 +0000 Subject: [PATCH 04/31] chore(cli): switch long lists of positional args over to param structs --- cmd/agentmail/main.go | 7 +++- pkg/cmd/agent.go | 15 ++++++-- pkg/cmd/apikey.go | 15 ++++++-- pkg/cmd/cmdutil.go | 84 +++++++++++++++++++++++++++-------------- pkg/cmd/cmdutil_test.go | 31 ++++++++++++--- pkg/cmd/domain.go | 29 +++++++++++--- pkg/cmd/draft.go | 22 +++++++++-- pkg/cmd/inbox.go | 36 +++++++++++++++--- pkg/cmd/inboxapikey.go | 15 ++++++-- pkg/cmd/inboxdraft.go | 43 +++++++++++++++++---- pkg/cmd/inboxlist.go | 22 +++++++++-- pkg/cmd/inboxmessage.go | 64 ++++++++++++++++++++++++++----- pkg/cmd/inboxthread.go | 22 +++++++++-- pkg/cmd/list.go | 22 +++++++++-- pkg/cmd/metric.go | 8 +++- pkg/cmd/organization.go | 8 +++- pkg/cmd/pod.go | 22 +++++++++-- pkg/cmd/podapikey.go | 15 ++++++-- pkg/cmd/poddomain.go | 29 +++++++++++--- pkg/cmd/poddraft.go | 22 +++++++++-- pkg/cmd/podinbox.go | 29 +++++++++++--- pkg/cmd/podlist.go | 22 +++++++++-- pkg/cmd/podmetric.go | 8 +++- pkg/cmd/podthread.go | 22 +++++++++-- pkg/cmd/thread.go | 22 +++++++++-- pkg/cmd/webhook.go | 29 +++++++++++--- 26 files changed, 531 insertions(+), 132 deletions(-) diff --git a/cmd/agentmail/main.go b/cmd/agentmail/main.go index 6853420..6cb588d 100644 --- a/cmd/agentmail/main.go +++ b/cmd/agentmail/main.go @@ -43,7 +43,12 @@ func main() { fmt.Fprintf(os.Stderr, "%s %q: %d %s\n", apierr.Request.Method, apierr.Request.URL, apierr.Response.StatusCode, http.StatusText(apierr.Response.StatusCode)) format := app.String("format-error") json := gjson.Parse(apierr.RawJSON()) - show_err := cmd.ShowJSON(os.Stdout, os.Stderr, "Error", json, format, app.IsSet("format-error"), app.String("transform-error")) + show_err := cmd.ShowJSON(json, cmd.ShowJSONOpts{ + ExplicitFormat: app.IsSet("format-error"), + Format: format, + Title: "Error", + Transform: app.String("transform-error"), + }) if show_err != nil { // Just print the original error: fmt.Fprintf(os.Stderr, "%s\n", err.Error()) diff --git a/pkg/cmd/agent.go b/pkg/cmd/agent.go index b446260..9b2cbea 100644 --- a/pkg/cmd/agent.go +++ b/pkg/cmd/agent.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -85,7 +84,12 @@ func handleAgentSignUp(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "agent sign-up", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "agent sign-up", + Transform: transform, + }) } func handleAgentVerify(ctx context.Context, cmd *cli.Command) error { @@ -120,5 +124,10 @@ func handleAgentVerify(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "agent verify", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "agent verify", + Transform: transform, + }) } diff --git a/pkg/cmd/apikey.go b/pkg/cmd/apikey.go index 28a95d6..4800ce7 100644 --- a/pkg/cmd/apikey.go +++ b/pkg/cmd/apikey.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -285,7 +284,12 @@ func handleAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "api-keys create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "api-keys create", + Transform: transform, + }) } func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -320,7 +324,12 @@ func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "api-keys list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "api-keys list", + Transform: transform, + }) } func handleAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/cmdutil.go b/pkg/cmd/cmdutil.go index d0d9826..d15bae7 100644 --- a/pkg/cmd/cmdutil.go +++ b/pkg/cmd/cmdutil.go @@ -368,36 +368,58 @@ func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format const warningExploreNotSupported = "Warning: Output format 'explore' not supported for non-terminal output; falling back to 'json'\n" -// Display JSON to the user in various different formats. The explicitFormat parameter indicates -// whether the format was explicitly set by the user (via --format), which controls whether we -// silently fall back to json when explore is requested on non-terminal output. Warnings are -// written to stderr. -func ShowJSON(out *os.File, stderr io.Writer, title string, res gjson.Result, format string, explicitFormat bool, transform string) error { - if transform != "" { - transformed := res.Get(transform) +// ShowJSONOpts configures how JSON output is displayed. +type ShowJSONOpts struct { + ExplicitFormat bool // true if the user explicitly passed --format + Format string // output format (auto, explore, json, jsonl, pretty, raw, yaml) + Stderr io.Writer // stderr for warnings; injectable for testing; defaults to os.Stderr + Stdout *os.File // stdout (or pager); injectable for testing; defaults to os.Stdout + Title string // display title + Transform string // GJSON path to extract before displaying +} + +func (o *ShowJSONOpts) setDefaults() { + if o.Stderr == nil { + o.Stderr = os.Stderr + } + if o.Stdout == nil { + o.Stdout = os.Stdout + } +} + +// ShowJSON displays a single JSON result to the user. +func ShowJSON(res gjson.Result, opts ShowJSONOpts) error { + opts.setDefaults() + + if opts.Transform != "" { + transformed := res.Get(opts.Transform) if transformed.Exists() { res = transformed } } - switch strings.ToLower(format) { + switch strings.ToLower(opts.Format) { case "auto": - return ShowJSON(out, stderr, title, res, "json", explicitFormat, "") + jsonOpts := opts + jsonOpts.Format = "json" + return ShowJSON(res, jsonOpts) case "explore": - if !isTerminal(out) { - if explicitFormat { - fmt.Fprint(stderr, warningExploreNotSupported) + if !isTerminal(opts.Stdout) { + if opts.ExplicitFormat { + fmt.Fprint(opts.Stderr, warningExploreNotSupported) } - return ShowJSON(out, stderr, title, res, "json", explicitFormat, transform) + jsonOpts := opts + jsonOpts.Format = "json" + return ShowJSON(res, jsonOpts) } - return jsonview.ExploreJSON(title, res) + return jsonview.ExploreJSON(opts.Title, res) default: - bytes, err := formatJSON(out, title, res, format, transform) + bytes, err := formatJSON(opts.Stdout, opts.Title, res, opts.Format, opts.Transform) if err != nil { return err } - _, err = out.Write(bytes) + _, err = opts.Stdout.Write(bytes) return err } } @@ -411,16 +433,17 @@ type hasRawJSON interface { RawJSON() string } -// For an iterator over different value types, display its values to the user in -// different formats. -// -1 is used to signal no limit of items to display -func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, iter jsonview.Iterator[T], format string, explicitFormat bool, transform string, itemsToDisplay int64) error { +// ShowJSONIterator displays an iterator of values to the user. Use itemsToDisplay = -1 for no limit. +func ShowJSONIterator[T any](iter jsonview.Iterator[T], itemsToDisplay int64, opts ShowJSONOpts) error { + opts.setDefaults() + + format := opts.Format if format == "explore" { - if isTerminal(stdout) { - return jsonview.ExploreJSONStream(title, iter) + if isTerminal(opts.Stdout) { + return jsonview.ExploreJSONStream(opts.Title, iter) } - if explicitFormat { - fmt.Fprint(stderr, warningExploreNotSupported) + if opts.ExplicitFormat { + fmt.Fprint(opts.Stderr, warningExploreNotSupported) } format = "json" } @@ -448,7 +471,7 @@ func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, it } obj = gjson.ParseBytes(jsonData) } - json, err := formatJSON(stdout, title, obj, format, transform) + json, err := formatJSON(opts.Stdout, opts.Title, obj, format, opts.Transform) if err != nil { return err } @@ -465,7 +488,7 @@ func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, it } if !usePager { - _, err := stdout.Write(output) + _, err := opts.Stdout.Write(output) if err != nil { return err } @@ -473,13 +496,16 @@ func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, it return iter.Err() } - return streamOutput(title, func(pager *os.File) error { - // Write the output we used during the initial terminal size computation + return streamOutput(opts.Title, func(pager *os.File) error { _, err := pager.Write(output) if err != nil { return err } + pagerOpts := opts + pagerOpts.Format = format + pagerOpts.Stdout = pager + for iter.Next() { if itemsToDisplay == 0 { break @@ -495,7 +521,7 @@ func ShowJSONIterator[T any](stdout *os.File, stderr io.Writer, title string, it } obj = gjson.ParseBytes(jsonData) } - if err := ShowJSON(pager, stderr, title, obj, format, explicitFormat, transform); err != nil { + if err := ShowJSON(obj, pagerOpts); err != nil { return err } itemsToDisplay -= 1 diff --git a/pkg/cmd/cmdutil_test.go b/pkg/cmd/cmdutil_test.go index ba5e3f0..a5799aa 100644 --- a/pkg/cmd/cmdutil_test.go +++ b/pkg/cmd/cmdutil_test.go @@ -244,7 +244,12 @@ func TestExploreFallback(t *testing.T) { var stderr bytes.Buffer res := gjson.Parse(`{"id":"abc"}`) - err = ShowJSON(w, &stderr, "test", res, "explore", false, "") + err = ShowJSON(res, ShowJSONOpts{ + Format: "explore", + Stderr: &stderr, + Stdout: w, + Title: "test", + }) w.Close() require.NoError(t, err) @@ -274,7 +279,13 @@ func TestExploreFallback(t *testing.T) { var stderr bytes.Buffer res := gjson.Parse(`{"id":"abc"}`) - err = ShowJSON(w, &stderr, "test", res, "explore", true, "") + err = ShowJSON(res, ShowJSONOpts{ + ExplicitFormat: true, + Format: "explore", + Stderr: &stderr, + Stdout: w, + Title: "test", + }) w.Close() require.NoError(t, err) @@ -290,7 +301,12 @@ func TestExploreFallback(t *testing.T) { var stderr bytes.Buffer res := gjson.Parse(`{"id":"abc"}`) - err = ShowJSON(w, &stderr, "test", res, "explore", false, "") + err = ShowJSON(res, ShowJSONOpts{ + Format: "explore", + Stderr: &stderr, + Stdout: w, + Title: "test", + }) w.Close() require.NoError(t, err) @@ -327,8 +343,13 @@ func captureShowJSONIterator[T any](t *testing.T, iter jsonview.Iterator[T], for require.NoError(t, err) defer r.Close() - var stderr bytes.Buffer - err = ShowJSONIterator(w, &stderr, "test", iter, format, false, transform, itemsToDisplay) + err = ShowJSONIterator(iter, itemsToDisplay, ShowJSONOpts{ + Format: format, + Stderr: io.Discard, + Stdout: w, + Title: "test", + Transform: transform, + }) w.Close() require.NoError(t, err) diff --git a/pkg/cmd/domain.go b/pkg/cmd/domain.go index 62a5dcd..84ff5ca 100644 --- a/pkg/cmd/domain.go +++ b/pkg/cmd/domain.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -174,7 +173,12 @@ func handleDomainsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "domains create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "domains create", + Transform: transform, + }) } func handleDomainsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -217,7 +221,12 @@ func handleDomainsUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "domains update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "domains update", + Transform: transform, + }) } func handleDomainsList(ctx context.Context, cmd *cli.Command) error { @@ -252,7 +261,12 @@ func handleDomainsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "domains list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "domains list", + Transform: transform, + }) } func handleDomainsDelete(ctx context.Context, cmd *cli.Command) error { @@ -313,7 +327,12 @@ func handleDomainsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "domains get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "domains get", + Transform: transform, + }) } func handleDomainsGetZoneFile(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/draft.go b/pkg/cmd/draft.go index b7b9ca3..1020791 100644 --- a/pkg/cmd/draft.go +++ b/pkg/cmd/draft.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -122,7 +121,12 @@ func handleDraftsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "drafts list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "drafts list", + Transform: transform, + }) } func handleDraftsGet(ctx context.Context, cmd *cli.Command) error { @@ -158,7 +162,12 @@ func handleDraftsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "drafts get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "drafts get", + Transform: transform, + }) } func handleDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -203,5 +212,10 @@ func handleDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "drafts get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "drafts get-attachment", + Transform: transform, + }) } diff --git a/pkg/cmd/inbox.go b/pkg/cmd/inbox.go index 68bb4ae..a6a58ba 100644 --- a/pkg/cmd/inbox.go +++ b/pkg/cmd/inbox.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -198,7 +197,12 @@ func handleInboxesCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes create", + Transform: transform, + }) } func handleInboxesUpdate(ctx context.Context, cmd *cli.Command) error { @@ -241,7 +245,12 @@ func handleInboxesUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes update", + Transform: transform, + }) } func handleInboxesList(ctx context.Context, cmd *cli.Command) error { @@ -276,7 +285,12 @@ func handleInboxesList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes list", + Transform: transform, + }) } func handleInboxesDelete(ctx context.Context, cmd *cli.Command) error { @@ -337,7 +351,12 @@ func handleInboxesGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes get", + Transform: transform, + }) } func handleInboxesListMetrics(ctx context.Context, cmd *cli.Command) error { @@ -380,5 +399,10 @@ func handleInboxesListMetrics(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes list-metrics", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes list-metrics", + Transform: transform, + }) } diff --git a/pkg/cmd/inboxapikey.go b/pkg/cmd/inboxapikey.go index 7a1b8f9..0df3a94 100644 --- a/pkg/cmd/inboxapikey.go +++ b/pkg/cmd/inboxapikey.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -303,7 +302,12 @@ func handleInboxesAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:api-keys create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:api-keys create", + Transform: transform, + }) } func handleInboxesAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -346,7 +350,12 @@ func handleInboxesAPIKeysList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:api-keys list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:api-keys list", + Transform: transform, + }) } func handleInboxesAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/inboxdraft.go b/pkg/cmd/inboxdraft.go index 514dfa1..bbf96f2 100644 --- a/pkg/cmd/inboxdraft.go +++ b/pkg/cmd/inboxdraft.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -363,7 +362,12 @@ func handleInboxesDraftsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts create", + Transform: transform, + }) } func handleInboxesDraftsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -408,7 +412,12 @@ func handleInboxesDraftsUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts update", + Transform: transform, + }) } func handleInboxesDraftsList(ctx context.Context, cmd *cli.Command) error { @@ -451,7 +460,12 @@ func handleInboxesDraftsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts list", + Transform: transform, + }) } func handleInboxesDraftsDelete(ctx context.Context, cmd *cli.Command) error { @@ -530,7 +544,12 @@ func handleInboxesDraftsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts get", + Transform: transform, + }) } func handleInboxesDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -576,7 +595,12 @@ func handleInboxesDraftsGetAttachment(ctx context.Context, cmd *cli.Command) err format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts get-attachment", + Transform: transform, + }) } func handleInboxesDraftsSend(ctx context.Context, cmd *cli.Command) error { @@ -621,5 +645,10 @@ func handleInboxesDraftsSend(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:drafts send", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:drafts send", + Transform: transform, + }) } diff --git a/pkg/cmd/inboxlist.go b/pkg/cmd/inboxlist.go index 9e3fcef..004bb98 100644 --- a/pkg/cmd/inboxlist.go +++ b/pkg/cmd/inboxlist.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -187,7 +186,12 @@ func handleInboxesListsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:lists create", + Transform: transform, + }) } func handleInboxesListsList(ctx context.Context, cmd *cli.Command) error { @@ -233,7 +237,12 @@ func handleInboxesListsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:lists list", + Transform: transform, + }) } func handleInboxesListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -316,5 +325,10 @@ func handleInboxesListsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:lists get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:lists get", + Transform: transform, + }) } diff --git a/pkg/cmd/inboxmessage.go b/pkg/cmd/inboxmessage.go index 0360b6a..64ae35c 100644 --- a/pkg/cmd/inboxmessage.go +++ b/pkg/cmd/inboxmessage.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -586,7 +585,12 @@ func handleInboxesMessagesUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages update", + Transform: transform, + }) } func handleInboxesMessagesList(ctx context.Context, cmd *cli.Command) error { @@ -629,7 +633,12 @@ func handleInboxesMessagesList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages list", + Transform: transform, + }) } func handleInboxesMessagesForward(ctx context.Context, cmd *cli.Command) error { @@ -674,7 +683,12 @@ func handleInboxesMessagesForward(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages forward", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages forward", + Transform: transform, + }) } func handleInboxesMessagesGet(ctx context.Context, cmd *cli.Command) error { @@ -719,7 +733,12 @@ func handleInboxesMessagesGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages get", + Transform: transform, + }) } func handleInboxesMessagesGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -765,7 +784,12 @@ func handleInboxesMessagesGetAttachment(ctx context.Context, cmd *cli.Command) e format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages get-attachment", + Transform: transform, + }) } func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { @@ -810,7 +834,12 @@ func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages get-raw", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages get-raw", + Transform: transform, + }) } func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { @@ -855,7 +884,12 @@ func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages reply", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages reply", + Transform: transform, + }) } func handleInboxesMessagesReplyAll(ctx context.Context, cmd *cli.Command) error { @@ -900,7 +934,12 @@ func handleInboxesMessagesReplyAll(ctx context.Context, cmd *cli.Command) error format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages reply-all", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages reply-all", + Transform: transform, + }) } func handleInboxesMessagesSend(ctx context.Context, cmd *cli.Command) error { @@ -943,5 +982,10 @@ func handleInboxesMessagesSend(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:messages send", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:messages send", + Transform: transform, + }) } diff --git a/pkg/cmd/inboxthread.go b/pkg/cmd/inboxthread.go index f46448c..72a8825 100644 --- a/pkg/cmd/inboxthread.go +++ b/pkg/cmd/inboxthread.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -185,7 +184,12 @@ func handleInboxesThreadsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:threads list", + Transform: transform, + }) } func handleInboxesThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -264,7 +268,12 @@ func handleInboxesThreadsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:threads get", + Transform: transform, + }) } func handleInboxesThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -310,5 +319,10 @@ func handleInboxesThreadsGetAttachment(ctx context.Context, cmd *cli.Command) er format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "inboxes:threads get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "inboxes:threads get-attachment", + Transform: transform, + }) } diff --git a/pkg/cmd/list.go b/pkg/cmd/list.go index 3a481ff..5084041 100644 --- a/pkg/cmd/list.go +++ b/pkg/cmd/list.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -166,7 +165,12 @@ func handleListsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "lists create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "lists create", + Transform: transform, + }) } func handleListsList(ctx context.Context, cmd *cli.Command) error { @@ -211,7 +215,12 @@ func handleListsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "lists list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "lists list", + Transform: transform, + }) } func handleListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -292,5 +301,10 @@ func handleListsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "lists get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "lists get", + Transform: transform, + }) } diff --git a/pkg/cmd/metric.go b/pkg/cmd/metric.go index f85c0b5..7594261 100644 --- a/pkg/cmd/metric.go +++ b/pkg/cmd/metric.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -87,5 +86,10 @@ func handleMetricsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "metrics list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "metrics list", + Transform: transform, + }) } diff --git a/pkg/cmd/organization.go b/pkg/cmd/organization.go index 88a392c..26c9f41 100644 --- a/pkg/cmd/organization.go +++ b/pkg/cmd/organization.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-go" @@ -53,5 +52,10 @@ func handleOrganizationsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "organizations get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "organizations get", + Transform: transform, + }) } diff --git a/pkg/cmd/pod.go b/pkg/cmd/pod.go index fb7fba4..ba89712 100644 --- a/pkg/cmd/pod.go +++ b/pkg/cmd/pod.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -122,7 +121,12 @@ func handlePodsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods create", + Transform: transform, + }) } func handlePodsList(ctx context.Context, cmd *cli.Command) error { @@ -157,7 +161,12 @@ func handlePodsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods list", + Transform: transform, + }) } func handlePodsDelete(ctx context.Context, cmd *cli.Command) error { @@ -218,5 +227,10 @@ func handlePodsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods get", + Transform: transform, + }) } diff --git a/pkg/cmd/podapikey.go b/pkg/cmd/podapikey.go index 6853129..4b69467 100644 --- a/pkg/cmd/podapikey.go +++ b/pkg/cmd/podapikey.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -303,7 +302,12 @@ func handlePodsAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:api-keys create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:api-keys create", + Transform: transform, + }) } func handlePodsAPIKeysList(ctx context.Context, cmd *cli.Command) error { @@ -346,7 +350,12 @@ func handlePodsAPIKeysList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:api-keys list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:api-keys list", + Transform: transform, + }) } func handlePodsAPIKeysDelete(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/poddomain.go b/pkg/cmd/poddomain.go index 28aa494..ff74137 100644 --- a/pkg/cmd/poddomain.go +++ b/pkg/cmd/poddomain.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -217,7 +216,12 @@ func handlePodsDomainsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:domains create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:domains create", + Transform: transform, + }) } func handlePodsDomainsUpdate(ctx context.Context, cmd *cli.Command) error { @@ -262,7 +266,12 @@ func handlePodsDomainsUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:domains update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:domains update", + Transform: transform, + }) } func handlePodsDomainsList(ctx context.Context, cmd *cli.Command) error { @@ -305,7 +314,12 @@ func handlePodsDomainsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:domains list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:domains list", + Transform: transform, + }) } func handlePodsDomainsDelete(ctx context.Context, cmd *cli.Command) error { @@ -384,7 +398,12 @@ func handlePodsDomainsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:domains get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:domains get", + Transform: transform, + }) } func handlePodsDomainsGetZoneFile(ctx context.Context, cmd *cli.Command) error { diff --git a/pkg/cmd/poddraft.go b/pkg/cmd/poddraft.go index 5f204f2..477fd63 100644 --- a/pkg/cmd/poddraft.go +++ b/pkg/cmd/poddraft.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -145,7 +144,12 @@ func handlePodsDraftsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:drafts list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:drafts list", + Transform: transform, + }) } func handlePodsDraftsGet(ctx context.Context, cmd *cli.Command) error { @@ -190,7 +194,12 @@ func handlePodsDraftsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:drafts get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:drafts get", + Transform: transform, + }) } func handlePodsDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -236,5 +245,10 @@ func handlePodsDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:drafts get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:drafts get-attachment", + Transform: transform, + }) } diff --git a/pkg/cmd/podinbox.go b/pkg/cmd/podinbox.go index 39436f8..19358ac 100644 --- a/pkg/cmd/podinbox.go +++ b/pkg/cmd/podinbox.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -186,7 +185,12 @@ func handlePodsInboxesCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:inboxes create", + Transform: transform, + }) } func handlePodsInboxesUpdate(ctx context.Context, cmd *cli.Command) error { @@ -231,7 +235,12 @@ func handlePodsInboxesUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:inboxes update", + Transform: transform, + }) } func handlePodsInboxesList(ctx context.Context, cmd *cli.Command) error { @@ -274,7 +283,12 @@ func handlePodsInboxesList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:inboxes list", + Transform: transform, + }) } func handlePodsInboxesDelete(ctx context.Context, cmd *cli.Command) error { @@ -353,5 +367,10 @@ func handlePodsInboxesGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:inboxes get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:inboxes get", + Transform: transform, + }) } diff --git a/pkg/cmd/podlist.go b/pkg/cmd/podlist.go index 7eca84a..74c3782 100644 --- a/pkg/cmd/podlist.go +++ b/pkg/cmd/podlist.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -187,7 +186,12 @@ func handlePodsListsCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:lists create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:lists create", + Transform: transform, + }) } func handlePodsListsList(ctx context.Context, cmd *cli.Command) error { @@ -233,7 +237,12 @@ func handlePodsListsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:lists list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:lists list", + Transform: transform, + }) } func handlePodsListsDelete(ctx context.Context, cmd *cli.Command) error { @@ -316,5 +325,10 @@ func handlePodsListsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:lists get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:lists get", + Transform: transform, + }) } diff --git a/pkg/cmd/podmetric.go b/pkg/cmd/podmetric.go index 33109b5..3930e57 100644 --- a/pkg/cmd/podmetric.go +++ b/pkg/cmd/podmetric.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -100,5 +99,10 @@ func handlePodsMetricsQuery(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:metrics query", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:metrics query", + Transform: transform, + }) } diff --git a/pkg/cmd/podthread.go b/pkg/cmd/podthread.go index 811bfef..1638e2d 100644 --- a/pkg/cmd/podthread.go +++ b/pkg/cmd/podthread.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -185,7 +184,12 @@ func handlePodsThreadsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:threads list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:threads list", + Transform: transform, + }) } func handlePodsThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -264,7 +268,12 @@ func handlePodsThreadsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:threads get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:threads get", + Transform: transform, + }) } func handlePodsThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -310,5 +319,10 @@ func handlePodsThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "pods:threads get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "pods:threads get-attachment", + Transform: transform, + }) } diff --git a/pkg/cmd/thread.go b/pkg/cmd/thread.go index 1007226..b4a49e7 100644 --- a/pkg/cmd/thread.go +++ b/pkg/cmd/thread.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -157,7 +156,12 @@ func handleThreadsList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "threads list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "threads list", + Transform: transform, + }) } func handleThreadsDelete(ctx context.Context, cmd *cli.Command) error { @@ -225,7 +229,12 @@ func handleThreadsGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "threads get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "threads get", + Transform: transform, + }) } func handleThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { @@ -270,5 +279,10 @@ func handleThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "threads get-attachment", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "threads get-attachment", + Transform: transform, + }) } diff --git a/pkg/cmd/webhook.go b/pkg/cmd/webhook.go index 4c1b45b..02a0cb0 100644 --- a/pkg/cmd/webhook.go +++ b/pkg/cmd/webhook.go @@ -5,7 +5,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/agentmail-to/agentmail-cli/internal/apiquery" "github.com/agentmail-to/agentmail-cli/internal/requestflag" @@ -174,7 +173,12 @@ func handleWebhooksCreate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "webhooks create", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "webhooks create", + Transform: transform, + }) } func handleWebhooksUpdate(ctx context.Context, cmd *cli.Command) error { @@ -217,7 +221,12 @@ func handleWebhooksUpdate(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "webhooks update", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "webhooks update", + Transform: transform, + }) } func handleWebhooksList(ctx context.Context, cmd *cli.Command) error { @@ -252,7 +261,12 @@ func handleWebhooksList(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "webhooks list", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "webhooks list", + Transform: transform, + }) } func handleWebhooksDelete(ctx context.Context, cmd *cli.Command) error { @@ -313,5 +327,10 @@ func handleWebhooksGet(ctx context.Context, cmd *cli.Command) error { format := cmd.Root().String("format") explicitFormat := cmd.Root().IsSet("format") transform := cmd.Root().String("transform") - return ShowJSON(os.Stdout, os.Stderr, "webhooks get", obj, format, explicitFormat, transform) + return ShowJSON(obj, ShowJSONOpts{ + ExplicitFormat: explicitFormat, + Format: format, + Title: "webhooks get", + Transform: transform, + }) } From 1da7c3edc342f6ef4d1aff1083d0b98e8aec47ad Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:42:33 +0000 Subject: [PATCH 05/31] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d6b0c8a..957be15 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 94 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-830c24d3ff39df5248fd06a0e32a64a57bdf6ed4f58bb33244cab98fa7c3476e.yml -openapi_spec_hash: c71d36752561924eb2e11bce3f93c32f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-e0a11b43915053701813adfcbf5bc7573d2a74f63b7abb8cfdedc9565ac3f134.yml +openapi_spec_hash: ec0c63b37bac5e4ef29bc2ca02e81203 config_hash: 8ab5eb1bfc282411f0283d386a319f23 From 0e6001439c676f9b793176e39417f69ff94d01ac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 05:49:41 +0000 Subject: [PATCH 06/31] chore(ci): support manually triggering release workflow --- .github/workflows/publish-release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index ebb534a..81520dc 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -10,6 +10,7 @@ on: push: tags: - "v*" + workflow_dispatch: {} jobs: goreleaser: runs-on: ubuntu-latest From 65a86ee9ddb38368eebc5a472380d9d85b4fb6c5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 05:50:59 +0000 Subject: [PATCH 07/31] feat(cli): send filename and content type when reading input from files --- pkg/cmd/flagoptions.go | 65 +++++++++++++++++++++++++++++++++++-- pkg/cmd/flagoptions_test.go | 59 ++++++++++++++++++++++++++++++--- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/flagoptions.go b/pkg/cmd/flagoptions.go index 9eb5221..8ad5f59 100644 --- a/pkg/cmd/flagoptions.go +++ b/pkg/cmd/flagoptions.go @@ -7,9 +7,11 @@ import ( "fmt" "io" "maps" + "mime" "mime/multipart" "net/http" "os" + "path/filepath" "reflect" "strings" "unicode/utf8" @@ -36,7 +38,14 @@ const ( type FileEmbedStyle int const ( + // EmbedText reads referenced files fully into memory and substitutes the file's contents back into the + // value as a string. Binary files are base64-encoded. Used for JSON request bodies and for headers and + // query parameters, where the file contents need to be serialized inline. EmbedText FileEmbedStyle = iota + + // EmbedIOReader replaces file references with an io.Reader that streams the file's contents. Used for + // `multipart/form-data` and `application/octet-stream` request bodies, where files are uploaded as binary + // parts rather than embedded into a text value. EmbedIOReader ) @@ -142,6 +151,20 @@ func embedFilesValue(v reflect.Value, embedStyle FileEmbedStyle, stdin *onceStdi if s == "" { return v, nil } + if embedStyle == EmbedIOReader { + if isStdinPath(s) { + r, err := stdin.read() + if err != nil { + return v, err + } + return reflect.ValueOf(io.NopCloser(r)), nil + } + upload, err := openFileUpload(s) + if err != nil { + return v, err + } + return reflect.ValueOf(upload), nil + } if isStdinPath(s) { content, err := stdin.readAll() if err != nil { @@ -250,7 +273,7 @@ func embedFilesValue(v reflect.Value, embedStyle FileEmbedStyle, stdin *onceStdi return reflect.ValueOf(io.NopCloser(r)), nil } - file, err := os.Open(filename) + upload, err := openFileUpload(filename) if err != nil { if !expectsFile { // For strings that start with "@" and don't look like a filename, return the string @@ -258,7 +281,7 @@ func embedFilesValue(v reflect.Value, embedStyle FileEmbedStyle, stdin *onceStdi } return v, err } - return reflect.ValueOf(file), nil + return reflect.ValueOf(upload), nil } } return v, nil @@ -492,6 +515,44 @@ func flagOptions( // as a file path without needing the "@" prefix. type FilePathValue string +// fileUpload wraps an io.Reader with filename and content-type metadata for +// use as a multipart form part. The apiform encoder detects the Filename and +// ContentType methods and uses them to populate the Content-Disposition +// filename and the Content-Type header on the part. +type fileUpload struct { + io.Reader // apiform checks for reader and reads its contents during encode + filename string + contentType string +} + +func (f fileUpload) Filename() string { return f.filename } +func (f fileUpload) ContentType() string { return f.contentType } +func (f fileUpload) Close() error { + if c, ok := f.Reader.(io.Closer); ok { + return c.Close() + } + return nil +} + +// openFileUpload opens the file at path and returns a fileUpload whose filename +// is the path's basename and whose content type is derived from the file +// extension (falling back to application/octet-stream when unknown). +func openFileUpload(path string) (fileUpload, error) { + file, err := os.Open(path) + if err != nil { + return fileUpload{}, err + } + contentType := mime.TypeByExtension(filepath.Ext(path)) + if contentType == "" { + contentType = "application/octet-stream" + } + return fileUpload{ + Reader: file, + filename: filepath.Base(path), + contentType: contentType, + }, nil +} + // applyDataAliases rewrites keys in a body map based on flag `DataAliases` metadata. For top-level flags, // `{alias: value}` becomes `{canonical: value}`. For inner flags (those registered under an outer flag // via WithInnerFlags), the alias translation is also applied to the nested map under the outer flag's diff --git a/pkg/cmd/flagoptions_test.go b/pkg/cmd/flagoptions_test.go index 039b9ff..00734ca 100644 --- a/pkg/cmd/flagoptions_test.go +++ b/pkg/cmd/flagoptions_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -31,7 +30,7 @@ func TestIsUTF8TextFile(t *testing.T) { } for _, tt := range tests { - assert.Equal(t, tt.expected, isUTF8TextFile(tt.content)) + require.Equal(t, tt.expected, isUTF8TextFile(tt.content)) } } @@ -226,10 +225,10 @@ func TestEmbedFiles(t *testing.T) { got, err := embedFiles(tt.input, EmbedText, nil) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { require.NoError(t, err) - assert.Equal(t, tt.want, got) + require.Equal(t, tt.want, got) } }) @@ -238,7 +237,7 @@ func TestEmbedFiles(t *testing.T) { _, err := embedFiles(tt.input, EmbedIOReader, nil) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { require.NoError(t, err) } @@ -333,6 +332,56 @@ func TestEmbedFilesStdin(t *testing.T) { }) } +// TestEmbedFilesUploadMetadata verifies that EmbedIOReader mode wraps file readers with filename and +// content-type metadata so the multipart encoder populates `Content-Disposition` and `Content-Type` headers. +func TestEmbedFilesUploadMetadata(t *testing.T) { + t.Parallel() + + tmpDir := t.TempDir() + writeTestFile(t, tmpDir, "hello.txt", "hi") + writeTestFile(t, tmpDir, "page.html", "
") + writeTestFile(t, tmpDir, "blob.bin", "\x00\x01") + + cases := []struct { + basename string + wantContentType string + }{ + {"hello.txt", "text/plain; charset=utf-8"}, + {"page.html", "text/html; charset=utf-8"}, + {"blob.bin", "application/octet-stream"}, + } + + for _, tc := range cases { + t.Run("AtPrefix_"+tc.basename, func(t *testing.T) { + t.Parallel() + + path := filepath.Join(tmpDir, tc.basename) + withEmbedded, err := embedFiles(map[string]any{"file": "@" + path}, EmbedIOReader, nil) + require.NoError(t, err) + + upload, ok := withEmbedded.(map[string]any)["file"].(fileUpload) + require.True(t, ok, "expected fileUpload, got %T", withEmbedded.(map[string]any)["file"]) + require.Equal(t, tc.basename, upload.Filename()) + require.Equal(t, upload.ContentType(), tc.wantContentType) + require.NoError(t, upload.Close()) + }) + + t.Run("FilePathValue_"+tc.basename, func(t *testing.T) { + t.Parallel() + + path := filepath.Join(tmpDir, tc.basename) + withEmbedded, err := embedFiles(map[string]any{"file": FilePathValue(path)}, EmbedIOReader, nil) + require.NoError(t, err) + + upload, ok := withEmbedded.(map[string]any)["file"].(fileUpload) + require.True(t, ok, "expected fileUpload, got %T", withEmbedded.(map[string]any)["file"]) + require.Equal(t, tc.basename, upload.Filename()) + require.Equal(t, upload.ContentType(), tc.wantContentType) + require.NoError(t, upload.Close()) + }) + } +} + func writeTestFile(t *testing.T, dir, filename, content string) { t.Helper() From f9df419dc3ba3b15a8a267db59207e81eea217f5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 05:52:51 +0000 Subject: [PATCH 08/31] feat(cli): add `--raw-output`/`-r` option to print raw (non-JSON) strings --- pkg/cmd/agent.go | 2 ++ pkg/cmd/apikey.go | 2 ++ pkg/cmd/cmd.go | 5 +++++ pkg/cmd/cmdutil.go | 14 ++++++++++---- pkg/cmd/cmdutil_test.go | 37 +++++++++++++++++++++++++++++++++---- pkg/cmd/domain.go | 4 ++++ pkg/cmd/draft.go | 3 +++ pkg/cmd/inbox.go | 5 +++++ pkg/cmd/inboxapikey.go | 2 ++ pkg/cmd/inboxdraft.go | 6 ++++++ pkg/cmd/inboxlist.go | 3 +++ pkg/cmd/inboxmessage.go | 9 +++++++++ pkg/cmd/inboxthread.go | 3 +++ pkg/cmd/list.go | 3 +++ pkg/cmd/metric.go | 1 + pkg/cmd/organization.go | 1 + pkg/cmd/pod.go | 3 +++ pkg/cmd/podapikey.go | 2 ++ pkg/cmd/poddomain.go | 4 ++++ pkg/cmd/poddraft.go | 3 +++ pkg/cmd/podinbox.go | 4 ++++ pkg/cmd/podlist.go | 3 +++ pkg/cmd/podmetric.go | 1 + pkg/cmd/podthread.go | 3 +++ pkg/cmd/thread.go | 3 +++ pkg/cmd/webhook.go | 4 ++++ 26 files changed, 122 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/agent.go b/pkg/cmd/agent.go index 9b2cbea..75f271a 100644 --- a/pkg/cmd/agent.go +++ b/pkg/cmd/agent.go @@ -87,6 +87,7 @@ func handleAgentSignUp(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "agent sign-up", Transform: transform, }) @@ -127,6 +128,7 @@ func handleAgentVerify(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "agent verify", Transform: transform, }) diff --git a/pkg/cmd/apikey.go b/pkg/cmd/apikey.go index 4800ce7..0757427 100644 --- a/pkg/cmd/apikey.go +++ b/pkg/cmd/apikey.go @@ -287,6 +287,7 @@ func handleAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "api-keys create", Transform: transform, }) @@ -327,6 +328,7 @@ func handleAPIKeysList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "api-keys list", Transform: transform, }) diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index bede572..d89cb34 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -73,6 +73,11 @@ func init() { Name: "transform-error", Usage: "The GJSON transformation for errors.", }, + &cli.BoolFlag{ + Name: "raw-output", + Aliases: []string{"r"}, + Usage: "If the result is a string, print it without JSON quotes. This can be useful for making output transforms talk to non-JSON-based systems.", + }, &requestflag.Flag[string]{ Name: "api-key", Sources: cli.EnvVars("AGENTMAIL_API_KEY"), diff --git a/pkg/cmd/cmdutil.go b/pkg/cmd/cmdutil.go index d15bae7..4e9de4e 100644 --- a/pkg/cmd/cmdutil.go +++ b/pkg/cmd/cmdutil.go @@ -323,16 +323,21 @@ func shouldUseColors(w io.Writer) bool { return isTerminal(w) } -func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format string, transform string) ([]byte, error) { +func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format string, transform string, rawOutput bool) ([]byte, error) { if transform != "" { transformed := res.Get(transform) if transformed.Exists() { res = transformed } } + // Modeled after `jq -r` (`--raw-output`): if the result is a string, print it without JSON quotes so that + // it's easier to pipe into other programs. + if rawOutput && res.Type == gjson.String { + return []byte(res.Str + "\n"), nil + } switch strings.ToLower(format) { case "auto": - return formatJSON(expectedOutput, title, res, "json", "") + return formatJSON(expectedOutput, title, res, "json", "", rawOutput) case "pretty": return []byte(jsonview.RenderJSON(title, res) + "\n"), nil case "json": @@ -372,6 +377,7 @@ const warningExploreNotSupported = "Warning: Output format 'explore' not support type ShowJSONOpts struct { ExplicitFormat bool // true if the user explicitly passed --format Format string // output format (auto, explore, json, jsonl, pretty, raw, yaml) + RawOutput bool // like jq -r: print strings without JSON quotes Stderr io.Writer // stderr for warnings; injectable for testing; defaults to os.Stderr Stdout *os.File // stdout (or pager); injectable for testing; defaults to os.Stdout Title string // display title @@ -414,7 +420,7 @@ func ShowJSON(res gjson.Result, opts ShowJSONOpts) error { } return jsonview.ExploreJSON(opts.Title, res) default: - bytes, err := formatJSON(opts.Stdout, opts.Title, res, opts.Format, opts.Transform) + bytes, err := formatJSON(opts.Stdout, opts.Title, res, opts.Format, opts.Transform, opts.RawOutput) if err != nil { return err } @@ -471,7 +477,7 @@ func ShowJSONIterator[T any](iter jsonview.Iterator[T], itemsToDisplay int64, op } obj = gjson.ParseBytes(jsonData) } - json, err := formatJSON(opts.Stdout, opts.Title, obj, format, opts.Transform) + json, err := formatJSON(opts.Stdout, opts.Title, obj, format, opts.Transform, opts.RawOutput) if err != nil { return err } diff --git a/pkg/cmd/cmdutil_test.go b/pkg/cmd/cmdutil_test.go index a5799aa..cbfc652 100644 --- a/pkg/cmd/cmdutil_test.go +++ b/pkg/cmd/cmdutil_test.go @@ -159,7 +159,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123","name":"test"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "id") + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "id", false) require.NoError(t, err) require.Equal(t, `"abc123"`+"\n", string(formatted)) }) @@ -168,7 +168,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123","name":"test"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "") + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "", false) require.NoError(t, err) require.Equal(t, `{"id":"abc123","name":"test"}`+"\n", string(formatted)) }) @@ -177,7 +177,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"data":{"items":[1,2,3]}}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "data.items") + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "data.items", false) require.NoError(t, err) require.Equal(t, "[1,2,3]\n", string(formatted)) }) @@ -186,11 +186,40 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "missing") + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "missing", false) require.NoError(t, err) // Transform path doesn't exist, so original result is returned require.Equal(t, `{"id":"abc123"}`+"\n", string(formatted)) }) + + t.Run("RawOutputString", func(t *testing.T) { + t.Parallel() + + res := gjson.Parse(`{"id":"abc123","name":"test"}`) + formatted, err := formatJSON(os.Stdout, "test", res, "json", "id", true) + require.NoError(t, err) + require.Equal(t, "abc123\n", string(formatted)) + }) + + t.Run("RawOutputNonString", func(t *testing.T) { + t.Parallel() + + // --raw-output has no effect on non-string values + res := gjson.Parse(`{"count":42}`) + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "count", true) + require.NoError(t, err) + require.Equal(t, "42\n", string(formatted)) + }) + + t.Run("RawOutputObject", func(t *testing.T) { + t.Parallel() + + // --raw-output has no effect on objects + res := gjson.Parse(`{"nested":{"a":1}}`) + formatted, err := formatJSON(os.Stdout, "test", res, "raw", "nested", true) + require.NoError(t, err) + require.Equal(t, `{"a":1}`+"\n", string(formatted)) + }) } func TestShowJSONIterator(t *testing.T) { diff --git a/pkg/cmd/domain.go b/pkg/cmd/domain.go index 84ff5ca..facdb1a 100644 --- a/pkg/cmd/domain.go +++ b/pkg/cmd/domain.go @@ -176,6 +176,7 @@ func handleDomainsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "domains create", Transform: transform, }) @@ -224,6 +225,7 @@ func handleDomainsUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "domains update", Transform: transform, }) @@ -264,6 +266,7 @@ func handleDomainsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "domains list", Transform: transform, }) @@ -330,6 +333,7 @@ func handleDomainsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "domains get", Transform: transform, }) diff --git a/pkg/cmd/draft.go b/pkg/cmd/draft.go index 1020791..0b5a8b9 100644 --- a/pkg/cmd/draft.go +++ b/pkg/cmd/draft.go @@ -124,6 +124,7 @@ func handleDraftsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "drafts list", Transform: transform, }) @@ -165,6 +166,7 @@ func handleDraftsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "drafts get", Transform: transform, }) @@ -215,6 +217,7 @@ func handleDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "drafts get-attachment", Transform: transform, }) diff --git a/pkg/cmd/inbox.go b/pkg/cmd/inbox.go index a6a58ba..f6b2dd1 100644 --- a/pkg/cmd/inbox.go +++ b/pkg/cmd/inbox.go @@ -200,6 +200,7 @@ func handleInboxesCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes create", Transform: transform, }) @@ -248,6 +249,7 @@ func handleInboxesUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes update", Transform: transform, }) @@ -288,6 +290,7 @@ func handleInboxesList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes list", Transform: transform, }) @@ -354,6 +357,7 @@ func handleInboxesGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes get", Transform: transform, }) @@ -402,6 +406,7 @@ func handleInboxesListMetrics(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes list-metrics", Transform: transform, }) diff --git a/pkg/cmd/inboxapikey.go b/pkg/cmd/inboxapikey.go index 0df3a94..a59e810 100644 --- a/pkg/cmd/inboxapikey.go +++ b/pkg/cmd/inboxapikey.go @@ -305,6 +305,7 @@ func handleInboxesAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:api-keys create", Transform: transform, }) @@ -353,6 +354,7 @@ func handleInboxesAPIKeysList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:api-keys list", Transform: transform, }) diff --git a/pkg/cmd/inboxdraft.go b/pkg/cmd/inboxdraft.go index bbf96f2..0f11108 100644 --- a/pkg/cmd/inboxdraft.go +++ b/pkg/cmd/inboxdraft.go @@ -365,6 +365,7 @@ func handleInboxesDraftsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts create", Transform: transform, }) @@ -415,6 +416,7 @@ func handleInboxesDraftsUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts update", Transform: transform, }) @@ -463,6 +465,7 @@ func handleInboxesDraftsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts list", Transform: transform, }) @@ -547,6 +550,7 @@ func handleInboxesDraftsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts get", Transform: transform, }) @@ -598,6 +602,7 @@ func handleInboxesDraftsGetAttachment(ctx context.Context, cmd *cli.Command) err return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts get-attachment", Transform: transform, }) @@ -648,6 +653,7 @@ func handleInboxesDraftsSend(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:drafts send", Transform: transform, }) diff --git a/pkg/cmd/inboxlist.go b/pkg/cmd/inboxlist.go index 004bb98..c0517a1 100644 --- a/pkg/cmd/inboxlist.go +++ b/pkg/cmd/inboxlist.go @@ -189,6 +189,7 @@ func handleInboxesListsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:lists create", Transform: transform, }) @@ -240,6 +241,7 @@ func handleInboxesListsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:lists list", Transform: transform, }) @@ -328,6 +330,7 @@ func handleInboxesListsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:lists get", Transform: transform, }) diff --git a/pkg/cmd/inboxmessage.go b/pkg/cmd/inboxmessage.go index 64ae35c..e1b480c 100644 --- a/pkg/cmd/inboxmessage.go +++ b/pkg/cmd/inboxmessage.go @@ -588,6 +588,7 @@ func handleInboxesMessagesUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages update", Transform: transform, }) @@ -636,6 +637,7 @@ func handleInboxesMessagesList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages list", Transform: transform, }) @@ -686,6 +688,7 @@ func handleInboxesMessagesForward(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages forward", Transform: transform, }) @@ -736,6 +739,7 @@ func handleInboxesMessagesGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages get", Transform: transform, }) @@ -787,6 +791,7 @@ func handleInboxesMessagesGetAttachment(ctx context.Context, cmd *cli.Command) e return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages get-attachment", Transform: transform, }) @@ -837,6 +842,7 @@ func handleInboxesMessagesGetRaw(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages get-raw", Transform: transform, }) @@ -887,6 +893,7 @@ func handleInboxesMessagesReply(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages reply", Transform: transform, }) @@ -937,6 +944,7 @@ func handleInboxesMessagesReplyAll(ctx context.Context, cmd *cli.Command) error return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages reply-all", Transform: transform, }) @@ -985,6 +993,7 @@ func handleInboxesMessagesSend(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:messages send", Transform: transform, }) diff --git a/pkg/cmd/inboxthread.go b/pkg/cmd/inboxthread.go index 72a8825..59738c6 100644 --- a/pkg/cmd/inboxthread.go +++ b/pkg/cmd/inboxthread.go @@ -187,6 +187,7 @@ func handleInboxesThreadsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:threads list", Transform: transform, }) @@ -271,6 +272,7 @@ func handleInboxesThreadsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:threads get", Transform: transform, }) @@ -322,6 +324,7 @@ func handleInboxesThreadsGetAttachment(ctx context.Context, cmd *cli.Command) er return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "inboxes:threads get-attachment", Transform: transform, }) diff --git a/pkg/cmd/list.go b/pkg/cmd/list.go index 5084041..d269bea 100644 --- a/pkg/cmd/list.go +++ b/pkg/cmd/list.go @@ -168,6 +168,7 @@ func handleListsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "lists create", Transform: transform, }) @@ -218,6 +219,7 @@ func handleListsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "lists list", Transform: transform, }) @@ -304,6 +306,7 @@ func handleListsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "lists get", Transform: transform, }) diff --git a/pkg/cmd/metric.go b/pkg/cmd/metric.go index 7594261..380516a 100644 --- a/pkg/cmd/metric.go +++ b/pkg/cmd/metric.go @@ -89,6 +89,7 @@ func handleMetricsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "metrics list", Transform: transform, }) diff --git a/pkg/cmd/organization.go b/pkg/cmd/organization.go index 26c9f41..1af9601 100644 --- a/pkg/cmd/organization.go +++ b/pkg/cmd/organization.go @@ -55,6 +55,7 @@ func handleOrganizationsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "organizations get", Transform: transform, }) diff --git a/pkg/cmd/pod.go b/pkg/cmd/pod.go index ba89712..c6ac651 100644 --- a/pkg/cmd/pod.go +++ b/pkg/cmd/pod.go @@ -124,6 +124,7 @@ func handlePodsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods create", Transform: transform, }) @@ -164,6 +165,7 @@ func handlePodsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods list", Transform: transform, }) @@ -230,6 +232,7 @@ func handlePodsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods get", Transform: transform, }) diff --git a/pkg/cmd/podapikey.go b/pkg/cmd/podapikey.go index 4b69467..46d0731 100644 --- a/pkg/cmd/podapikey.go +++ b/pkg/cmd/podapikey.go @@ -305,6 +305,7 @@ func handlePodsAPIKeysCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:api-keys create", Transform: transform, }) @@ -353,6 +354,7 @@ func handlePodsAPIKeysList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:api-keys list", Transform: transform, }) diff --git a/pkg/cmd/poddomain.go b/pkg/cmd/poddomain.go index ff74137..fd25dad 100644 --- a/pkg/cmd/poddomain.go +++ b/pkg/cmd/poddomain.go @@ -219,6 +219,7 @@ func handlePodsDomainsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:domains create", Transform: transform, }) @@ -269,6 +270,7 @@ func handlePodsDomainsUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:domains update", Transform: transform, }) @@ -317,6 +319,7 @@ func handlePodsDomainsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:domains list", Transform: transform, }) @@ -401,6 +404,7 @@ func handlePodsDomainsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:domains get", Transform: transform, }) diff --git a/pkg/cmd/poddraft.go b/pkg/cmd/poddraft.go index 477fd63..c989561 100644 --- a/pkg/cmd/poddraft.go +++ b/pkg/cmd/poddraft.go @@ -147,6 +147,7 @@ func handlePodsDraftsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:drafts list", Transform: transform, }) @@ -197,6 +198,7 @@ func handlePodsDraftsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:drafts get", Transform: transform, }) @@ -248,6 +250,7 @@ func handlePodsDraftsGetAttachment(ctx context.Context, cmd *cli.Command) error return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:drafts get-attachment", Transform: transform, }) diff --git a/pkg/cmd/podinbox.go b/pkg/cmd/podinbox.go index 19358ac..c004633 100644 --- a/pkg/cmd/podinbox.go +++ b/pkg/cmd/podinbox.go @@ -188,6 +188,7 @@ func handlePodsInboxesCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:inboxes create", Transform: transform, }) @@ -238,6 +239,7 @@ func handlePodsInboxesUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:inboxes update", Transform: transform, }) @@ -286,6 +288,7 @@ func handlePodsInboxesList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:inboxes list", Transform: transform, }) @@ -370,6 +373,7 @@ func handlePodsInboxesGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:inboxes get", Transform: transform, }) diff --git a/pkg/cmd/podlist.go b/pkg/cmd/podlist.go index 74c3782..7a97f1e 100644 --- a/pkg/cmd/podlist.go +++ b/pkg/cmd/podlist.go @@ -189,6 +189,7 @@ func handlePodsListsCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:lists create", Transform: transform, }) @@ -240,6 +241,7 @@ func handlePodsListsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:lists list", Transform: transform, }) @@ -328,6 +330,7 @@ func handlePodsListsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:lists get", Transform: transform, }) diff --git a/pkg/cmd/podmetric.go b/pkg/cmd/podmetric.go index 3930e57..56882e9 100644 --- a/pkg/cmd/podmetric.go +++ b/pkg/cmd/podmetric.go @@ -102,6 +102,7 @@ func handlePodsMetricsQuery(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:metrics query", Transform: transform, }) diff --git a/pkg/cmd/podthread.go b/pkg/cmd/podthread.go index 1638e2d..9858421 100644 --- a/pkg/cmd/podthread.go +++ b/pkg/cmd/podthread.go @@ -187,6 +187,7 @@ func handlePodsThreadsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:threads list", Transform: transform, }) @@ -271,6 +272,7 @@ func handlePodsThreadsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:threads get", Transform: transform, }) @@ -322,6 +324,7 @@ func handlePodsThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "pods:threads get-attachment", Transform: transform, }) diff --git a/pkg/cmd/thread.go b/pkg/cmd/thread.go index b4a49e7..96dd42b 100644 --- a/pkg/cmd/thread.go +++ b/pkg/cmd/thread.go @@ -159,6 +159,7 @@ func handleThreadsList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "threads list", Transform: transform, }) @@ -232,6 +233,7 @@ func handleThreadsGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "threads get", Transform: transform, }) @@ -282,6 +284,7 @@ func handleThreadsGetAttachment(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "threads get-attachment", Transform: transform, }) diff --git a/pkg/cmd/webhook.go b/pkg/cmd/webhook.go index 02a0cb0..99254d4 100644 --- a/pkg/cmd/webhook.go +++ b/pkg/cmd/webhook.go @@ -176,6 +176,7 @@ func handleWebhooksCreate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "webhooks create", Transform: transform, }) @@ -224,6 +225,7 @@ func handleWebhooksUpdate(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "webhooks update", Transform: transform, }) @@ -264,6 +266,7 @@ func handleWebhooksList(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "webhooks list", Transform: transform, }) @@ -330,6 +333,7 @@ func handleWebhooksGet(ctx context.Context, cmd *cli.Command) error { return ShowJSON(obj, ShowJSONOpts{ ExplicitFormat: explicitFormat, Format: format, + RawOutput: cmd.Root().Bool("raw-output"), Title: "webhooks get", Transform: transform, }) From 0e944460e3f00ab8cb1040bb18e0380bb3574dbe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 05:57:45 +0000 Subject: [PATCH 09/31] chore(cli): use `ShowJSONOpts` as argument to `formatJSON` instead of many positionals --- pkg/cmd/cmdutil.go | 54 ++++++++++++++++++++--------------------- pkg/cmd/cmdutil_test.go | 14 +++++------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/pkg/cmd/cmdutil.go b/pkg/cmd/cmdutil.go index 4e9de4e..644b807 100644 --- a/pkg/cmd/cmdutil.go +++ b/pkg/cmd/cmdutil.go @@ -323,26 +323,29 @@ func shouldUseColors(w io.Writer) bool { return isTerminal(w) } -func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format string, transform string, rawOutput bool) ([]byte, error) { - if transform != "" { - transformed := res.Get(transform) +func formatJSON(res gjson.Result, opts ShowJSONOpts) ([]byte, error) { + if opts.Transform != "" { + transformed := res.Get(opts.Transform) if transformed.Exists() { res = transformed } } // Modeled after `jq -r` (`--raw-output`): if the result is a string, print it without JSON quotes so that // it's easier to pipe into other programs. - if rawOutput && res.Type == gjson.String { + if opts.RawOutput && res.Type == gjson.String { return []byte(res.Str + "\n"), nil } - switch strings.ToLower(format) { + switch strings.ToLower(opts.Format) { case "auto": - return formatJSON(expectedOutput, title, res, "json", "", rawOutput) + autoOpts := opts + autoOpts.Format = "json" + autoOpts.Transform = "" + return formatJSON(res, autoOpts) case "pretty": - return []byte(jsonview.RenderJSON(title, res) + "\n"), nil + return []byte(jsonview.RenderJSON(opts.Title, res) + "\n"), nil case "json": prettyJSON := pretty.Pretty([]byte(res.Raw)) - if shouldUseColors(expectedOutput) { + if shouldUseColors(opts.Stdout) { return pretty.Color(prettyJSON, pretty.TerminalStyle), nil } else { return prettyJSON, nil @@ -350,7 +353,7 @@ func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format case "jsonl": // @ugly is gjson syntax for "no whitespace", so it fits on one line oneLineJSON := res.Get("@ugly").Raw - if shouldUseColors(expectedOutput) { + if shouldUseColors(opts.Stdout) { bytes := append(pretty.Color([]byte(oneLineJSON), pretty.TerminalStyle), '\n') return bytes, nil } else { @@ -364,10 +367,10 @@ func formatJSON(expectedOutput *os.File, title string, res gjson.Result, format if err := json2yaml.Convert(&yaml, input); err != nil { return nil, err } - _, err := expectedOutput.Write([]byte(yaml.String())) + _, err := opts.Stdout.Write([]byte(yaml.String())) return nil, err default: - return nil, fmt.Errorf("Invalid format: %s, valid formats are: %s", format, strings.Join(OutputFormats, ", ")) + return nil, fmt.Errorf("Invalid format: %s, valid formats are: %s", opts.Format, strings.Join(OutputFormats, ", ")) } } @@ -397,18 +400,11 @@ func (o *ShowJSONOpts) setDefaults() { func ShowJSON(res gjson.Result, opts ShowJSONOpts) error { opts.setDefaults() - if opts.Transform != "" { - transformed := res.Get(opts.Transform) - if transformed.Exists() { - res = transformed - } - } - switch strings.ToLower(opts.Format) { case "auto": - jsonOpts := opts - jsonOpts.Format = "json" - return ShowJSON(res, jsonOpts) + autoOpts := opts + autoOpts.Format = "json" + return ShowJSON(res, autoOpts) case "explore": if !isTerminal(opts.Stdout) { if opts.ExplicitFormat { @@ -418,9 +414,15 @@ func ShowJSON(res gjson.Result, opts ShowJSONOpts) error { jsonOpts.Format = "json" return ShowJSON(res, jsonOpts) } + if opts.Transform != "" { + transformed := res.Get(opts.Transform) + if transformed.Exists() { + res = transformed + } + } return jsonview.ExploreJSON(opts.Title, res) default: - bytes, err := formatJSON(opts.Stdout, opts.Title, res, opts.Format, opts.Transform, opts.RawOutput) + bytes, err := formatJSON(res, opts) if err != nil { return err } @@ -443,15 +445,14 @@ type hasRawJSON interface { func ShowJSONIterator[T any](iter jsonview.Iterator[T], itemsToDisplay int64, opts ShowJSONOpts) error { opts.setDefaults() - format := opts.Format - if format == "explore" { + if opts.Format == "explore" { if isTerminal(opts.Stdout) { return jsonview.ExploreJSONStream(opts.Title, iter) } if opts.ExplicitFormat { fmt.Fprint(opts.Stderr, warningExploreNotSupported) } - format = "json" + opts.Format = "json" } terminalWidth, terminalHeight, err := term.GetSize(os.Stdout.Fd()) @@ -477,7 +478,7 @@ func ShowJSONIterator[T any](iter jsonview.Iterator[T], itemsToDisplay int64, op } obj = gjson.ParseBytes(jsonData) } - json, err := formatJSON(opts.Stdout, opts.Title, obj, format, opts.Transform, opts.RawOutput) + json, err := formatJSON(obj, opts) if err != nil { return err } @@ -509,7 +510,6 @@ func ShowJSONIterator[T any](iter jsonview.Iterator[T], itemsToDisplay int64, op } pagerOpts := opts - pagerOpts.Format = format pagerOpts.Stdout = pager for iter.Next() { diff --git a/pkg/cmd/cmdutil_test.go b/pkg/cmd/cmdutil_test.go index cbfc652..2388ce6 100644 --- a/pkg/cmd/cmdutil_test.go +++ b/pkg/cmd/cmdutil_test.go @@ -159,7 +159,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123","name":"test"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "id", false) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout, Transform: "id"}) require.NoError(t, err) require.Equal(t, `"abc123"`+"\n", string(formatted)) }) @@ -168,7 +168,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123","name":"test"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "", false) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout}) require.NoError(t, err) require.Equal(t, `{"id":"abc123","name":"test"}`+"\n", string(formatted)) }) @@ -177,7 +177,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"data":{"items":[1,2,3]}}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "data.items", false) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout, Transform: "data.items"}) require.NoError(t, err) require.Equal(t, "[1,2,3]\n", string(formatted)) }) @@ -186,7 +186,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "missing", false) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout, Transform: "missing"}) require.NoError(t, err) // Transform path doesn't exist, so original result is returned require.Equal(t, `{"id":"abc123"}`+"\n", string(formatted)) @@ -196,7 +196,7 @@ func TestFormatJSON(t *testing.T) { t.Parallel() res := gjson.Parse(`{"id":"abc123","name":"test"}`) - formatted, err := formatJSON(os.Stdout, "test", res, "json", "id", true) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "json", Stdout: os.Stdout, Transform: "id", RawOutput: true}) require.NoError(t, err) require.Equal(t, "abc123\n", string(formatted)) }) @@ -206,7 +206,7 @@ func TestFormatJSON(t *testing.T) { // --raw-output has no effect on non-string values res := gjson.Parse(`{"count":42}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "count", true) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout, Transform: "count", RawOutput: true}) require.NoError(t, err) require.Equal(t, "42\n", string(formatted)) }) @@ -216,7 +216,7 @@ func TestFormatJSON(t *testing.T) { // --raw-output has no effect on objects res := gjson.Parse(`{"nested":{"a":1}}`) - formatted, err := formatJSON(os.Stdout, "test", res, "raw", "nested", true) + formatted, err := formatJSON(res, ShowJSONOpts{Format: "raw", Stdout: os.Stdout, Transform: "nested", RawOutput: true}) require.NoError(t, err) require.Equal(t, `{"a":1}`+"\n", string(formatted)) }) From 8b39e720cbe7e3c2c150bd7f2a563dd0feb298bf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 03:20:34 +0000 Subject: [PATCH 10/31] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index 9ebb7d3..bbc786d 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From c7f1282aabb0958db3b8dd601bdca796e5dc0f57 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 02:50:11 +0000 Subject: [PATCH 11/31] chore(internal): codegen related update --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 81083cd..aea6acd 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/agentmail-to/agentmail-cli go 1.25 require ( - github.com/agentmail-to/agentmail-go v0.8.0 + github.com/agentmail-to/agentmail-go v0.8.1 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.6 github.com/charmbracelet/lipgloss v1.1.0 diff --git a/go.sum b/go.sum index 1089e67..66abdfe 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/agentmail-to/agentmail-go v0.8.0 h1:7Ek7UHIO0U2rrN6ib2gL1/W3LEkHdQfvQsHu0j3T+CQ= -github.com/agentmail-to/agentmail-go v0.8.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= +github.com/agentmail-to/agentmail-go v0.8.1 h1:Te5F4q4E1JM1hgqPXm5wuWneEi2Adfpoei73iTj59EE= +github.com/agentmail-to/agentmail-go v0.8.1/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= From 271e6ab44f3633a8c6c54323d7e1ef809ff9a788 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 19:36:02 +0000 Subject: [PATCH 12/31] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 957be15..ba2223a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 94 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-e0a11b43915053701813adfcbf5bc7573d2a74f63b7abb8cfdedc9565ac3f134.yml -openapi_spec_hash: ec0c63b37bac5e4ef29bc2ca02e81203 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-18101510657cc51b6f072219c469a002a6c92e2ef6d13008be105510845a832f.yml +openapi_spec_hash: bee4395e55747c75bfe3799ac6abf061 config_hash: 8ab5eb1bfc282411f0283d386a319f23 From 5b36c5391637ffda46b95c9095acda6f6be532e9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 04:30:10 +0000 Subject: [PATCH 13/31] chore(internal): codegen related update --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aea6acd..ee3b42b 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/agentmail-to/agentmail-cli go 1.25 require ( - github.com/agentmail-to/agentmail-go v0.8.1 + github.com/agentmail-to/agentmail-go v0.9.0 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.6 github.com/charmbracelet/lipgloss v1.1.0 diff --git a/go.sum b/go.sum index 66abdfe..1db991a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/agentmail-to/agentmail-go v0.8.1 h1:Te5F4q4E1JM1hgqPXm5wuWneEi2Adfpoei73iTj59EE= -github.com/agentmail-to/agentmail-go v0.8.1/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= +github.com/agentmail-to/agentmail-go v0.9.0 h1:HSj60k0F9EvAmFLAdxVcddnUPx9F6wnM5EHVuRqtdkI= +github.com/agentmail-to/agentmail-go v0.9.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= From 3a2b15dcf2210d33a59c9483c2e8bd336e78499c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 21:29:08 +0000 Subject: [PATCH 14/31] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ba2223a..cbd6104 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 94 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-18101510657cc51b6f072219c469a002a6c92e2ef6d13008be105510845a832f.yml -openapi_spec_hash: bee4395e55747c75bfe3799ac6abf061 +openapi_spec_hash: 485c40cab6b7ae69327ddc44a2ff82c9 config_hash: 8ab5eb1bfc282411f0283d386a319f23 From 062570454c9d38f42ce8690e6b20777b61fc0c70 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 05:05:37 +0000 Subject: [PATCH 15/31] ci: pin trigger-release-please github action --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ee3b42b..fec3e09 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/agentmail-to/agentmail-cli go 1.25 require ( - github.com/agentmail-to/agentmail-go v0.9.0 + github.com/agentmail-to/agentmail-go v0.10.0 github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.6 github.com/charmbracelet/lipgloss v1.1.0 diff --git a/go.sum b/go.sum index 1db991a..d7930d9 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/agentmail-to/agentmail-go v0.9.0 h1:HSj60k0F9EvAmFLAdxVcddnUPx9F6wnM5EHVuRqtdkI= -github.com/agentmail-to/agentmail-go v0.9.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= +github.com/agentmail-to/agentmail-go v0.10.0 h1:seHlvGOojKTO+mkdQLULm1G9NTQNh+sdPjXTySheQQE= +github.com/agentmail-to/agentmail-go v0.10.0/go.mod h1:3NrKbeXLQKRgb9gj2bmCoN9WXDTy9y9yacV070xpvDU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= From 1b982f78a9d150901b940791d7bc05fe1a396e49 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 05:10:43 +0000 Subject: [PATCH 16/31] fix(cli): correctly load zsh autocompletion --- .../autocomplete/shellscripts/zsh_autocomplete.zsh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/autocomplete/shellscripts/zsh_autocomplete.zsh b/internal/autocomplete/shellscripts/zsh_autocomplete.zsh index 4d4bdcd..d937171 100644 --- a/internal/autocomplete/shellscripts/zsh_autocomplete.zsh +++ b/internal/autocomplete/shellscripts/zsh_autocomplete.zsh @@ -1,5 +1,4 @@ -#!/bin/zsh -compdef ____APPNAME___zsh_autocomplete __APPNAME__ +#compdef __APPNAME__ ____APPNAME___zsh_autocomplete() { @@ -44,3 +43,14 @@ ____APPNAME___zsh_autocomplete() { ;; esac } + +# When installed in fpath (e.g., via Homebrew's zsh_completion stanza), this file +# is autoloaded as the function ___APPNAME__ and its body becomes that function's +# body. Detect that case via funcstack and dispatch to the completion function. +# When sourced (e.g., `source <(__APPNAME__ @completion zsh)`), register the +# function with compdef instead. +if [[ "${funcstack[1]}" = "___APPNAME__" ]]; then + ____APPNAME___zsh_autocomplete "$@" +else + compdef ____APPNAME___zsh_autocomplete __APPNAME__ +fi From c6d3d0faba7569980c2f7824f335ee4bdea88e72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 05:16:04 +0000 Subject: [PATCH 17/31] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index cbd6104..2cd935c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 94 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail%2Fagentmail-18101510657cc51b6f072219c469a002a6c92e2ef6d13008be105510845a832f.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/agentmail/agentmail-c97dd45dc91d256d4a19c2d7ca44cc45acdc7f4c6e30a9e3ffb7f70d052e404e.yml openapi_spec_hash: 485c40cab6b7ae69327ddc44a2ff82c9 config_hash: 8ab5eb1bfc282411f0283d386a319f23 From f105a97104a8e6be911e6419733d9c7628577d84 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 05:18:27 +0000 Subject: [PATCH 18/31] fix: flags for nullable body scalar fields are strictly typed --- internal/requestflag/innerflag.go | 16 +- internal/requestflag/requestflag.go | 128 +++++++++- internal/requestflag/requestflag_test.go | 234 ++++++++++++++++++ pkg/cmd/apikey.go | 78 +++--- pkg/cmd/domain.go | 8 +- pkg/cmd/draft.go | 6 +- pkg/cmd/inbox.go | 20 +- pkg/cmd/inboxapikey.go | 76 +++--- pkg/cmd/inboxdraft.go | 86 +++---- pkg/cmd/inboxlist.go | 6 +- pkg/cmd/inboxmessage.go | 290 ++++++++++++----------- pkg/cmd/inboxthread.go | 14 +- pkg/cmd/list.go | 6 +- pkg/cmd/metric.go | 6 +- pkg/cmd/pod.go | 10 +- pkg/cmd/podapikey.go | 76 +++--- pkg/cmd/poddomain.go | 8 +- pkg/cmd/poddraft.go | 6 +- pkg/cmd/podinbox.go | 14 +- pkg/cmd/podlist.go | 6 +- pkg/cmd/podmetric.go | 6 +- pkg/cmd/podthread.go | 14 +- pkg/cmd/thread.go | 14 +- pkg/cmd/webhook.go | 8 +- 24 files changed, 768 insertions(+), 368 deletions(-) diff --git a/internal/requestflag/innerflag.go b/internal/requestflag/innerflag.go index eeeb8bc..528915f 100644 --- a/internal/requestflag/innerflag.go +++ b/internal/requestflag/innerflag.go @@ -14,7 +14,8 @@ import ( type InnerFlag[ T []any | []map[string]any | []DateTimeValue | []DateValue | []TimeValue | []string | []float64 | []int64 | []bool | any | map[string]any | DateTimeValue | DateValue | TimeValue | - string | float64 | int64 | bool, + string | float64 | int64 | bool | + *string | *float64 | *int64 | *bool | *DateTimeValue | *DateValue | *TimeValue, ] struct { Name string // name of the flag DefaultText string // default text of the flag for usage purposes @@ -25,6 +26,12 @@ type InnerFlag[ OuterFlag cli.Flag // The flag on which this inner flag will set values InnerField string // The inner field which this flag will set DataAliases []string // alternate names recognized in YAML values passed as the outer flag + + // OuterIsArrayOfObjects tells an untyped outer flag (Flag[any], used for nullable + // complex schemas) to seed its underlying value as []map[string]any rather than + // map[string]any before SetInnerField runs. The hint is ignored for typed outer + // flags whose zero value already carries a dispatchable reflect.Kind. + OuterIsArrayOfObjects bool } // GetDataAliases returns the aliases recognized when parsing inner field keys from piped or flag YAML. @@ -76,6 +83,10 @@ func (f *InnerFlag[T]) Set(name string, rawVal string) error { } } + if seeder, ok := f.OuterFlag.(InnerFieldSeeder); ok { + seeder.SeedInnerCollection(f.OuterIsArrayOfObjects) + } + if settableInnerField, ok := f.OuterFlag.(SettableInnerField); ok { settableInnerField.SetInnerField(f.InnerField, parsedValue) } else { @@ -136,6 +147,9 @@ func (f *InnerFlag[T]) TypeName() string { if ty == nil { return "" } + if ty.Kind() == reflect.Pointer { + ty = ty.Elem() + } // Get base type name with special handling for built-in types getTypeName := func(t reflect.Type) string { diff --git a/internal/requestflag/requestflag.go b/internal/requestflag/requestflag.go index bfaf064..54c2509 100644 --- a/internal/requestflag/requestflag.go +++ b/internal/requestflag/requestflag.go @@ -15,10 +15,15 @@ import ( // Flag [T] is a generic flag base which can be used to implement the most // common interfaces used by urfave/cli. Additionally, it allows specifying // where in an HTTP request the flag values should be placed (e.g. query, body, etc.). +// +// Pointer-to-primitive type parameters (e.g. *string) are used for flags whose underlying +// schema is nullable. They give flags a tri-state: unset (excluded from the request), +// set to the literal "null" (nil pointer → JSON null), or set to a value (*v → JSON value). type Flag[ T []any | []map[string]any | []DateTimeValue | []DateValue | []TimeValue | []string | []float64 | []int64 | []bool | any | map[string]any | DateTimeValue | DateValue | TimeValue | - string | float64 | int64 | bool, + string | float64 | int64 | bool | + *string | *float64 | *int64 | *bool | *DateTimeValue | *DateValue | *TimeValue, ] struct { Name string // name of the flag Category string // category of the flag, if any @@ -341,6 +346,11 @@ func (f *Flag[T]) TypeName() string { if ty == nil { return "" } + // Deref pointer-typed flags so --help surfaces the pointee kind (e.g. "string"), not + // Go's pointer syntax. + if ty.Kind() == reflect.Pointer { + ty = ty.Elem() + } // Get base type name with special handling for built-in types getTypeName := func(t reflect.Type) string { @@ -396,6 +406,8 @@ func (f *Flag[T]) IsMultiValueFlag() bool { } func (f *Flag[T]) IsBoolFlag() bool { + // Flag[*bool] is deliberately not treated as a bool flag — the pointer form needs an + // explicit value (`--foo true`, `--foo null`) to disambiguate the tri-state. _, isBool := any(f.Default).(bool) return isBool } @@ -419,7 +431,8 @@ func (f Flag[T]) IsLocal() bool { type cliValue[ T []any | []map[string]any | []DateTimeValue | []DateValue | []TimeValue | []string | []float64 | []int64 | []bool | any | map[string]any | DateTimeValue | DateValue | TimeValue | string | - float64 | int64 | bool, + float64 | int64 | bool | + *string | *float64 | *int64 | *bool | *DateTimeValue | *DateValue | *TimeValue, ] struct { value T } @@ -429,12 +442,27 @@ type cliValue[ func parseCLIArg[ T []any | []map[string]any | []DateTimeValue | []DateValue | []TimeValue | []string | []float64 | []int64 | []bool | any | map[string]any | DateTimeValue | DateValue | TimeValue | string | - float64 | int64 | bool, + float64 | int64 | bool | + *string | *float64 | *int64 | *bool | *DateTimeValue | *DateValue | *TimeValue, ](value string) (T, error) { var parsedValue any var err error var empty T + + if value == "null" { + switch any(empty).(type) { + // Pointer-to-primitive: explicit nil gives the tri-state its "null" state + // (unset / null / value). Without this, numeric flags would fail to parse + // "null" and string flags would accept the literal word as a raw value. + case *string, *int64, *float64, *bool, *DateValue, *DateTimeValue, *TimeValue: + return empty, nil + // Maps marshal nil as JSON null natively; short-circuit avoids a YAML round-trip. + case map[string]any: + return empty, nil + } + } + switch any(empty).(type) { case string: parsedValue = value @@ -465,6 +493,48 @@ func parseCLIArg[ parsedValue = t } + // Pointer-to-primitive flags reach here only when `value != "null"`; we parse the + // pointee type and return its address so JSON marshaling emits the underlying value. + case *string: + v := value + parsedValue = &v + case *int64: + var v int64 + v, err = strconv.ParseInt(value, 0, 64) + if err == nil { + parsedValue = &v + } + case *float64: + var v float64 + v, err = strconv.ParseFloat(value, 64) + if err == nil { + parsedValue = &v + } + case *bool: + var v bool + v, err = strconv.ParseBool(value) + if err == nil { + parsedValue = &v + } + case *DateTimeValue: + var dt DateTimeValue + err = (&dt).Parse(value) + if err == nil { + parsedValue = &dt + } + case *DateValue: + var d DateValue + err = (&d).Parse(value) + if err == nil { + parsedValue = &d + } + case *TimeValue: + var t TimeValue + err = (&t).Parse(value) + if err == nil { + parsedValue = &t + } + default: if strings.HasPrefix(value, "@") { // File literals like @file.txt should work here @@ -501,6 +571,13 @@ func parseCLIArg[ } +// Ptr returns a pointer to its argument. It is used to initialize `Default` on pointer-typed +// Flag values, since Go does not allow taking the address of a composite literal's element +// or of an untyped constant. +func Ptr[T any](v T) *T { + return &v +} + // Assuming this string failed to parse as valid YAML, this function will // return true for strings that can reasonably be interpreted as a string literal, // like identifiers (`foo_bar`), UUIDs (`945b2f0c-8e89-487a-b02c-f851c69ea459`), @@ -594,6 +671,15 @@ func (c *cliValue[T]) String() string { // For basic types, use standard string representation return fmt.Sprintf("%v", v) + case *string, *int64, *float64, *bool, *DateTimeValue, *DateValue, *TimeValue: + // Pointer-to-primitive: nil renders as "null" (the CLI literal that produces it); + // non-nil derefs to the pointee's standard representation. + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "null" + } + return fmt.Sprintf("%v", rv.Elem().Interface()) + default: // For complex types, convert to YAML yamlBytes, err := yaml.MarshalWithOptions(c.value, yaml.Flow(true)) @@ -705,6 +791,15 @@ type SettableInnerField interface { SetInnerField(string, any) } +// InnerFieldSeeder lets an InnerFlag prepare its outer flag's underlying value +// before dispatching SetInnerField. This is only meaningful for Flag[any] — +// the codegen output for nullable complex schemas — whose untyped-nil zero +// value would otherwise have no reflect.Kind for the inner-field switch to +// dispatch on. +type InnerFieldSeeder interface { + SeedInnerCollection(isArrayOfObjects bool) +} + func (f *Flag[T]) SetInnerField(field string, val any) { if f.value == nil { f.value = &cliValue[T]{} @@ -718,6 +813,33 @@ func (f *Flag[T]) SetInnerField(field string, val any) { } } +// SeedInnerCollection initializes a Flag[any]'s underlying value as an empty +// map[string]any or []map[string]any so subsequent SetInnerField calls have a +// dispatchable reflect.Kind. For typed Flag[T] this is a no-op: the type +// assertion fails and the existing reflect.Kind on the typed-nil zero value +// already routes correctly. +func (f *Flag[T]) SeedInnerCollection(isArrayOfObjects bool) { + if f.value == nil { + f.value = &cliValue[T]{} + } + cv, ok := f.value.(*cliValue[T]) + if !ok { + return + } + if reflect.ValueOf(cv.value).Kind() != reflect.Invalid { + return + } + if isArrayOfObjects { + if seed, ok := any([]map[string]any{}).(T); ok { + cv.value = seed + } + return + } + if seed, ok := any(map[string]any{}).(T); ok { + cv.value = seed + } +} + func (c *cliValue[T]) SetInnerField(field string, val any) { flagVal := c.value flagValReflect := reflect.ValueOf(flagVal) diff --git a/internal/requestflag/requestflag_test.go b/internal/requestflag/requestflag_test.go index 0e86e07..06ffb72 100644 --- a/internal/requestflag/requestflag_test.go +++ b/internal/requestflag/requestflag_test.go @@ -1,6 +1,7 @@ package requestflag import ( + "encoding/json" "fmt" "testing" "time" @@ -616,6 +617,178 @@ func TestYamlHandling(t *testing.T) { }) } +// TestNullLiteralHandling pins how each Flag[T] type handles the literal value "null" +// when passed via the CLI. Pointer-typed flags serialize nil as JSON null, which is how +// nullable body fields (`anyOf: [T, null]` / `{nullable: true}`) let users clear a field +// via `--foo null`. Non-pointer primitive flags treat "null" as a raw value — these are +// non-nullable schemas where explicit null has no API semantics anyway. +func TestNullLiteralHandling(t *testing.T) { + t.Parallel() + + assertJSONBody := func(t *testing.T, value any, expected string) { + t.Helper() + body, err := json.Marshal(map[string]any{"foo": value}) + assert.NoError(t, err) + assert.JSONEq(t, expected, string(body)) + } + + t.Run("Flag[any] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[any]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[string] null is the raw string \"null\"", func(t *testing.T) { + t.Parallel() + cv := &cliValue[string]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":"null"}`) + }) + + t.Run("Flag[int64] null errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[int64]{} + assert.Error(t, cv.Set("null")) + }) + + t.Run("Flag[*string] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*string]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*string] value sends the string", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*string]{} + assert.NoError(t, cv.Set("1.1")) + assertJSONBody(t, cv.Get(), `{"foo":"1.1"}`) + }) + + t.Run("Flag[*int64] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*int64]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*int64] value sends the integer", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*int64]{} + assert.NoError(t, cv.Set("42")) + assertJSONBody(t, cv.Get(), `{"foo":42}`) + }) + + t.Run("Flag[*int64] invalid value errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*int64]{} + assert.Error(t, cv.Set("not-an-int")) + }) + + t.Run("Flag[*bool] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*bool]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*bool] value sends the boolean", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*bool]{} + assert.NoError(t, cv.Set("true")) + assertJSONBody(t, cv.Get(), `{"foo":true}`) + }) + + t.Run("Flag[*float64] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*float64]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*float64] value sends the float", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*float64]{} + assert.NoError(t, cv.Set("1.5")) + assertJSONBody(t, cv.Get(), `{"foo":1.5}`) + }) + + t.Run("Flag[*float64] invalid value errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*float64]{} + assert.Error(t, cv.Set("not-a-float")) + }) + + t.Run("Flag[*DateValue] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateValue]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*DateValue] value sends the date", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateValue]{} + assert.NoError(t, cv.Set("2023-05-15")) + assertJSONBody(t, cv.Get(), `{"foo":"2023-05-15"}`) + }) + + t.Run("Flag[*DateValue] invalid value errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateValue]{} + assert.Error(t, cv.Set("not-a-date")) + }) + + t.Run("Flag[*DateTimeValue] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateTimeValue]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*DateTimeValue] value sends the datetime", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateTimeValue]{} + assert.NoError(t, cv.Set("2023-05-15T14:30:45Z")) + assertJSONBody(t, cv.Get(), `{"foo":"2023-05-15T14:30:45Z"}`) + }) + + t.Run("Flag[*DateTimeValue] invalid value errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*DateTimeValue]{} + assert.Error(t, cv.Set("not-a-datetime")) + }) + + t.Run("Flag[*TimeValue] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*TimeValue]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) + + t.Run("Flag[*TimeValue] value sends the time", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*TimeValue]{} + assert.NoError(t, cv.Set("14:30:45")) + assertJSONBody(t, cv.Get(), `{"foo":"14:30:45"}`) + }) + + t.Run("Flag[*TimeValue] invalid value errors", func(t *testing.T) { + t.Parallel() + cv := &cliValue[*TimeValue]{} + assert.Error(t, cv.Set("not-a-time")) + }) + + // Nullable maps don't need pointer wrapping — a nil map already marshals as JSON null. + t.Run("Flag[map[string]any] null sends JSON null", func(t *testing.T) { + t.Parallel() + cv := &cliValue[map[string]any]{} + assert.NoError(t, cv.Set("null")) + assertJSONBody(t, cv.Get(), `{"foo":null}`) + }) +} + func TestFlagTypeNames(t *testing.T) { t.Parallel() @@ -646,3 +819,64 @@ func TestFlagTypeNames(t *testing.T) { }) } } + +// TestInnerFlagDispatchOnUntypedFlag pins inner-flag behavior for `Flag[any]`, +// which is the codegen output for nullable complex schemas (`anyOf: [T, null]` +// or `{nullable: true}`). The untyped-nil zero value carries no reflect.Kind, +// so SetInnerField has nowhere to dispatch the assignment — without explicit +// help the inner-field value silently drops. +func TestInnerFlagDispatchOnUntypedFlag(t *testing.T) { + t.Parallel() + + t.Run("nullable array of objects appends element from inner flag", func(t *testing.T) { + t.Parallel() + outer := &Flag[any]{Name: "mcp-server"} + assert.NoError(t, outer.PreParse()) + + nameFlag := &InnerFlag[string]{ + Name: "mcp-server.name", InnerField: "name", + OuterFlag: outer, OuterIsArrayOfObjects: true, + } + assert.NoError(t, nameFlag.Set("mcp-server.name", "first")) + + body, err := json.Marshal(map[string]any{"foo": outer.Get()}) + assert.NoError(t, err) + assert.JSONEq(t, `{"foo":[{"name":"first"}]}`, string(body)) + }) + + t.Run("nullable object sets field from inner flag", func(t *testing.T) { + t.Parallel() + outer := &Flag[any]{Name: "metadata"} + assert.NoError(t, outer.PreParse()) + + keyFlag := &InnerFlag[string]{ + Name: "metadata.key", InnerField: "key", OuterFlag: outer, + } + assert.NoError(t, keyFlag.Set("metadata.key", "value")) + + body, err := json.Marshal(map[string]any{"foo": outer.Get()}) + assert.NoError(t, err) + assert.JSONEq(t, `{"foo":{"key":"value"}}`, string(body)) + }) + + t.Run("multiple inner flags merge into the trailing element", func(t *testing.T) { + t.Parallel() + outer := &Flag[any]{Name: "mcp-server"} + assert.NoError(t, outer.PreParse()) + + nameFlag := &InnerFlag[string]{ + Name: "mcp-server.name", InnerField: "name", + OuterFlag: outer, OuterIsArrayOfObjects: true, + } + urlFlag := &InnerFlag[string]{ + Name: "mcp-server.url", InnerField: "url", + OuterFlag: outer, OuterIsArrayOfObjects: true, + } + assert.NoError(t, nameFlag.Set("mcp-server.name", "first")) + assert.NoError(t, urlFlag.Set("mcp-server.url", "https://example.com")) + + body, err := json.Marshal(map[string]any{"foo": outer.Get()}) + assert.NoError(t, err) + assert.JSONEq(t, `{"foo":[{"name":"first","url":"https://example.com"}]}`, string(body)) + }) +} diff --git a/pkg/cmd/apikey.go b/pkg/cmd/apikey.go index 0757427..a1e4225 100644 --- a/pkg/cmd/apikey.go +++ b/pkg/cmd/apikey.go @@ -19,7 +19,7 @@ var apiKeysCreate = requestflag.WithInnerFlags(cli.Command{ Usage: "**CLI:**", Suggest: true, Flags: []cli.Flag{ - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "name", Usage: "Name of api key.", BodyPath: "name", @@ -34,177 +34,177 @@ var apiKeysCreate = requestflag.WithInnerFlags(cli.Command{ HideHelpCommand: true, }, map[string][]requestflag.HasOuterFlag{ "permissions": { - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.api-key-create", Usage: "Create API keys.", InnerField: "api_key_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.api-key-delete", Usage: "Delete API keys.", InnerField: "api_key_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.api-key-read", Usage: "Read API keys.", InnerField: "api_key_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.domain-create", Usage: "Create domains.", InnerField: "domain_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.domain-delete", Usage: "Delete domains.", InnerField: "domain_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.domain-read", Usage: "Read domain details.", InnerField: "domain_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.domain-update", Usage: "Update domains.", InnerField: "domain_update", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.draft-create", Usage: "Create drafts.", InnerField: "draft_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.draft-delete", Usage: "Delete drafts.", InnerField: "draft_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.draft-read", Usage: "Read drafts.", InnerField: "draft_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.draft-send", Usage: "Send drafts.", InnerField: "draft_send", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.draft-update", Usage: "Update drafts.", InnerField: "draft_update", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.inbox-create", Usage: "Create new inboxes.", InnerField: "inbox_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.inbox-delete", Usage: "Delete inboxes.", InnerField: "inbox_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.inbox-read", Usage: "Read inbox details.", InnerField: "inbox_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.inbox-update", Usage: "Update inbox settings.", InnerField: "inbox_update", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.label-blocked-read", Usage: "Access messages labeled blocked.", InnerField: "label_blocked_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.label-spam-read", Usage: "Access messages labeled spam.", InnerField: "label_spam_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.label-trash-read", Usage: "Access messages labeled trash.", InnerField: "label_trash_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.list-entry-create", Usage: "Create list entries.", InnerField: "list_entry_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.list-entry-delete", Usage: "Delete list entries.", InnerField: "list_entry_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.list-entry-read", Usage: "Read list entries.", InnerField: "list_entry_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.message-read", Usage: "Read messages.", InnerField: "message_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.message-send", Usage: "Send messages.", InnerField: "message_send", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.message-update", Usage: "Update message labels.", InnerField: "message_update", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.metrics-read", Usage: "Read metrics.", InnerField: "metrics_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.pod-create", Usage: "Create pods.", InnerField: "pod_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.pod-delete", Usage: "Delete pods.", InnerField: "pod_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.pod-read", Usage: "Read pods.", InnerField: "pod_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.thread-delete", Usage: "Delete threads.", InnerField: "thread_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.thread-read", Usage: "Read threads.", InnerField: "thread_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.webhook-create", Usage: "Create webhooks.", InnerField: "webhook_create", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.webhook-delete", Usage: "Delete webhooks.", InnerField: "webhook_delete", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.webhook-read", Usage: "Read webhook configurations.", InnerField: "webhook_read", }, - &requestflag.InnerFlag[any]{ + &requestflag.InnerFlag[*bool]{ Name: "permissions.webhook-update", Usage: "Update webhooks.", InnerField: "webhook_update", @@ -217,17 +217,17 @@ var apiKeysList = cli.Command{ Usage: "**CLI:**", Suggest: true, Flags: []cli.Flag{ - &requestflag.Flag[any]{ + &requestflag.Flag[*bool]{ Name: "ascending", Usage: "Sort in ascending temporal order.", QueryPath: "ascending", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*int64]{ Name: "limit", Usage: "Limit of number of items returned.", QueryPath: "limit", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "page-token", Usage: "Page token for pagination.", QueryPath: "page_token", diff --git a/pkg/cmd/domain.go b/pkg/cmd/domain.go index facdb1a..85af514 100644 --- a/pkg/cmd/domain.go +++ b/pkg/cmd/domain.go @@ -46,7 +46,7 @@ var domainsUpdate = cli.Command{ Usage: "The ID of the domain.", Required: true, }, - &requestflag.Flag[any]{ + &requestflag.Flag[*bool]{ Name: "feedback-enabled", Usage: "Bounce and complaint notifications are sent to your inboxes.", BodyPath: "feedback_enabled", @@ -61,17 +61,17 @@ var domainsList = cli.Command{ Usage: "**CLI:**", Suggest: true, Flags: []cli.Flag{ - &requestflag.Flag[any]{ + &requestflag.Flag[*bool]{ Name: "ascending", Usage: "Sort in ascending temporal order.", QueryPath: "ascending", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*int64]{ Name: "limit", Usage: "Limit of number of items returned.", QueryPath: "limit", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "page-token", Usage: "Page token for pagination.", QueryPath: "page_token", diff --git a/pkg/cmd/draft.go b/pkg/cmd/draft.go index 0b5a8b9..3d79ad0 100644 --- a/pkg/cmd/draft.go +++ b/pkg/cmd/draft.go @@ -24,7 +24,7 @@ var draftsList = cli.Command{ Usage: "Timestamp after which to filter by.", QueryPath: "after", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*bool]{ Name: "ascending", Usage: "Sort in ascending temporal order.", QueryPath: "ascending", @@ -39,12 +39,12 @@ var draftsList = cli.Command{ Usage: "Labels to filter by.", QueryPath: "labels", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*int64]{ Name: "limit", Usage: "Limit of number of items returned.", QueryPath: "limit", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "page-token", Usage: "Page token for pagination.", QueryPath: "page_token", diff --git a/pkg/cmd/inbox.go b/pkg/cmd/inbox.go index f6b2dd1..8c94641 100644 --- a/pkg/cmd/inbox.go +++ b/pkg/cmd/inbox.go @@ -19,22 +19,22 @@ var inboxesCreate = cli.Command{ Usage: "**CLI:**", Suggest: true, Flags: []cli.Flag{ - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "client-id", Usage: "Client ID of inbox.", BodyPath: "client_id", }, - &requestflag.Flag[any]{ + &requestflag.Flag[*string]{ Name: "display-name", Usage: "Display name: `Display Name