diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b10d67af..c5407a00 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.44" + ".": "0.1.0-alpha.45" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c7a6304d..a1c68516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.1.0-alpha.45 (2025-10-02) + +Full Changelog: [v0.1.0-alpha.44...v0.1.0-alpha.45](https://github.com/stainless-api/stainless-api-cli/compare/v0.1.0-alpha.44...v0.1.0-alpha.45) + +### Features + +* added `--output-filter` flag and `--error-format` flag to support better visualization options ([2768e5b](https://github.com/stainless-api/stainless-api-cli/commit/2768e5b0255ae79e44ed54f583c4809f19801afe)) +* better support for positional arguments ([799d88f](https://github.com/stainless-api/stainless-api-cli/commit/799d88f441c5d1d5dca82a5590fceefdc1823f42)) + + +### Chores + +* **internal:** codegen related update ([2f9d764](https://github.com/stainless-api/stainless-api-cli/commit/2f9d764f660458d0e84e11adea9f1d418e8f1013)) +* **internal:** codegen related update ([c7df1a7](https://github.com/stainless-api/stainless-api-cli/commit/c7df1a7401a51fe9657ca9fa7f1aff2d37f60851)) + ## 0.1.0-alpha.44 (2025-09-22) Full Changelog: [v0.1.0-alpha.43...v0.1.0-alpha.44](https://github.com/stainless-api/stainless-api-cli/compare/v0.1.0-alpha.43...v0.1.0-alpha.44) diff --git a/cmd/stl/main.go b/cmd/stl/main.go index 41583992..d3f5cc5a 100644 --- a/cmd/stl/main.go +++ b/cmd/stl/main.go @@ -11,6 +11,7 @@ import ( "github.com/stainless-api/stainless-api-cli/pkg/cmd" "github.com/stainless-api/stainless-api-go" + "github.com/tidwall/gjson" ) func main() { @@ -19,8 +20,9 @@ func main() { var apierr *stainless.Error if errors.As(err, &apierr) { 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") - show_err := cmd.ShowJSON("Error", apierr.RawJSON(), format) + format := app.String("format-error") + json := gjson.Parse(apierr.RawJSON()) + show_err := cmd.ShowJSON("Error", json, format, app.String("transform-error")) if show_err != nil { // Just print the original error: fmt.Fprintf(os.Stderr, "%s\n", err.Error()) diff --git a/go.mod b/go.mod index 26bb4340..8ac27a6b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/stainless-api/stainless-api-cli -go 1.24.0 +go 1.24.4 toolchain go1.24.7 @@ -20,8 +20,8 @@ require ( github.com/tidwall/gjson v1.18.0 github.com/tidwall/pretty v1.2.1 github.com/tidwall/sjson v1.2.5 - github.com/urfave/cli-docs/v3 v3.0.0-alpha6 - github.com/urfave/cli/v3 v3.3.2 + github.com/urfave/cli-docs/v3 v3.1.0 + github.com/urfave/cli/v3 v3.4.1 golang.org/x/term v0.35.0 ) diff --git a/go.sum b/go.sum index 2c27d9b4..672188ab 100644 --- a/go.sum +++ b/go.sum @@ -113,10 +113,10 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -github.com/urfave/cli-docs/v3 v3.0.0-alpha6 h1:w/l/N0xw1rO/aHRIGXJ0lDwwYFOzilup1qGvIytP3BI= -github.com/urfave/cli-docs/v3 v3.0.0-alpha6/go.mod h1:p7Z4lg8FSTrPB9GTaNyTrK3ygffHZcK3w0cU2VE+mzU= -github.com/urfave/cli/v3 v3.3.2 h1:BYFVnhhZ8RqT38DxEYVFPPmGFTEf7tJwySTXsVRrS/o= -github.com/urfave/cli/v3 v3.3.2/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +github.com/urfave/cli-docs/v3 v3.1.0 h1:Sa5xm19IpE5gpm6tZzXdfjdFxn67PnEsE4dpXF7vsKw= +github.com/urfave/cli-docs/v3 v3.1.0/go.mod h1:59d+5Hz1h6GSGJ10cvcEkbIe3j233t4XDqI72UIx7to= +github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM= +github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= diff --git a/pkg/cmd/build.go b/pkg/cmd/build.go index c76612e8..1ee00be5 100644 --- a/pkg/cmd/build.go +++ b/pkg/cmd/build.go @@ -438,6 +438,10 @@ var buildsCompare = cli.Command{ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } // Handle file flags by reading files and mutating JSON body if err := applyFileFlag(cmd, "openapi-spec", "revision.openapi\\.yml.content"); err != nil { @@ -459,7 +463,7 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error { if err != nil { return err } - + buildGroup.Property("build_id", res.ID) if cmd.Bool("wait") { @@ -483,12 +487,22 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error { } } + data := gjson.Parse(string(res.RawJSON())) format := cmd.Root().String("format") - return ShowJSON("builds create", res.RawJSON(), format) + transform := cmd.Root().String("transform") + return ShowJSON("builds create", data, format, transform) } func handleBuildsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("build-id") && len(unusedArgs) > 0 { + cmd.Set("build-id", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } var res []byte _, err := cc.client.Builds.Get( context.TODO(), @@ -500,8 +514,10 @@ func handleBuildsRetrieve(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("builds retrieve", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("builds retrieve", json, format, transform) } // pullBuildOutputs pulls the outputs for a completed build @@ -775,6 +791,10 @@ func pullOutput(output, url, ref, targetDir string, targetGroup *Group) error { func handleBuildsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.BuildListParams{} var res []byte _, err := cc.client.Builds.List( @@ -787,12 +807,18 @@ func handleBuildsList(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("builds list", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("builds list", json, format, transform) } func handleBuildsCompare(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.BuildCompareParams{} var res []byte _, err := cc.client.Builds.Compare( @@ -805,6 +831,8 @@ func handleBuildsCompare(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("builds compare", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("builds compare", json, format, transform) } diff --git a/pkg/cmd/builddiagnostic.go b/pkg/cmd/builddiagnostic.go index 34e22f62..aa6ca7b7 100644 --- a/pkg/cmd/builddiagnostic.go +++ b/pkg/cmd/builddiagnostic.go @@ -4,10 +4,12 @@ package cmd import ( "context" + "fmt" "github.com/stainless-api/stainless-api-cli/pkg/jsonflag" "github.com/stainless-api/stainless-api-go" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -60,6 +62,14 @@ var buildsDiagnosticsList = cli.Command{ func handleBuildsDiagnosticsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("build-id") && len(unusedArgs) > 0 { + cmd.Set("build-id", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.BuildDiagnosticListParams{} var res []byte _, err := cc.client.Builds.Diagnostics.List( @@ -73,6 +83,8 @@ func handleBuildsDiagnosticsList(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("builds:diagnostics list", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("builds:diagnostics list", json, format, transform) } diff --git a/pkg/cmd/buildtargetoutput.go b/pkg/cmd/buildtargetoutput.go index fed4e519..377a3031 100644 --- a/pkg/cmd/buildtargetoutput.go +++ b/pkg/cmd/buildtargetoutput.go @@ -9,6 +9,7 @@ import ( "github.com/stainless-api/stainless-api-cli/pkg/jsonflag" "github.com/stainless-api/stainless-api-go" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -62,6 +63,10 @@ var buildsTargetOutputsRetrieve = cli.Command{ func handleBuildsTargetOutputsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } buildID := cmd.String("build-id") if buildID == "" { @@ -75,17 +80,21 @@ func handleBuildsTargetOutputsRetrieve(ctx context.Context, cmd *cli.Command) er params := stainless.BuildTargetOutputGetParams{ BuildID: buildID, } + var resBytes []byte res, err := cc.client.Builds.TargetOutputs.Get( context.TODO(), params, option.WithMiddleware(cc.AsMiddleware()), + option.WithResponseBodyInto(&resBytes), ) if err != nil { return err } + json := gjson.Parse(string(resBytes)) format := cmd.Root().String("format") - if err := ShowJSON("builds:target_outputs retrieve", res.RawJSON(), format); err != nil { + transform := cmd.Root().String("transform") + if err := ShowJSON("builds:target_outputs retrieve", json, format, transform); err != nil { return err } diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index f46e90e3..ab24c557 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -43,15 +43,34 @@ stl builds create --branch `, }, &cli.StringFlag{ Name: "format", - Usage: "The format for data output (one of: " + strings.Join(OutputFormats[:], ", ") + ")", + Usage: "The format for displaying response data (one of: " + strings.Join(OutputFormats, ", ") + ")", Value: "auto", Validator: func(format string) error { - if !slices.Contains(OutputFormats[:], strings.ToLower(format)) { - return fmt.Errorf("format must be one of: %s", strings.Join(OutputFormats[:], ", ")) + if !slices.Contains(OutputFormats, strings.ToLower(format)) { + return fmt.Errorf("format must be one of: %s", strings.Join(OutputFormats, ", ")) } return nil }, }, + &cli.StringFlag{ + Name: "format-error", + Usage: "The format for displaying error data (one of: " + strings.Join(OutputFormats, ", ") + ")", + Value: "auto", + Validator: func(format string) error { + if !slices.Contains(OutputFormats, strings.ToLower(format)) { + return fmt.Errorf("format must be one of: %s", strings.Join(OutputFormats, ", ")) + } + return nil + }, + }, + &cli.StringFlag{ + Name: "transform", + Usage: "The GJSON transformation for data output.", + }, + &cli.StringFlag{ + Name: "transform-error", + Usage: "The GJSON transformation for errors.", + }, &cli.StringFlag{ Name: "environment", Usage: "Set the environment for API requests", diff --git a/pkg/cmd/org.go b/pkg/cmd/org.go index 363ff718..720492f0 100644 --- a/pkg/cmd/org.go +++ b/pkg/cmd/org.go @@ -4,8 +4,10 @@ package cmd import ( "context" + "fmt" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -31,6 +33,14 @@ var orgsList = cli.Command{ func handleOrgsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("org") && len(unusedArgs) > 0 { + cmd.Set("org", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } var res []byte _, err := cc.client.Orgs.Get( context.TODO(), @@ -42,12 +52,18 @@ func handleOrgsRetrieve(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("orgs retrieve", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("orgs retrieve", json, format, transform) } func handleOrgsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } var res []byte _, err := cc.client.Orgs.List( context.TODO(), @@ -58,6 +74,8 @@ func handleOrgsList(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("orgs list", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("orgs list", json, format, transform) } diff --git a/pkg/cmd/project.go b/pkg/cmd/project.go index 158b2940..bcf85fec 100644 --- a/pkg/cmd/project.go +++ b/pkg/cmd/project.go @@ -4,10 +4,12 @@ package cmd import ( "context" + "fmt" "github.com/stainless-api/stainless-api-cli/pkg/jsonflag" "github.com/stainless-api/stainless-api-go" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -118,6 +120,10 @@ var projectsList = cli.Command{ func handleProjectsCreate(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectNewParams{} var res []byte _, err := cc.client.Projects.New( @@ -130,12 +136,18 @@ func handleProjectsCreate(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects create", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects create", json, format, transform) } func handleProjectsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectGetParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -151,12 +163,18 @@ func handleProjectsRetrieve(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects retrieve", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects retrieve", json, format, transform) } func handleProjectsUpdate(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectUpdateParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -172,12 +190,18 @@ func handleProjectsUpdate(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects update", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects update", json, format, transform) } func handleProjectsList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectListParams{} var res []byte _, err := cc.client.Projects.List( @@ -190,6 +214,8 @@ func handleProjectsList(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects list", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects list", json, format, transform) } diff --git a/pkg/cmd/projectbranch.go b/pkg/cmd/projectbranch.go index 8c7c478e..a9b97e57 100644 --- a/pkg/cmd/projectbranch.go +++ b/pkg/cmd/projectbranch.go @@ -4,10 +4,12 @@ package cmd import ( "context" + "fmt" "github.com/stainless-api/stainless-api-cli/pkg/jsonflag" "github.com/stainless-api/stainless-api-go" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -125,6 +127,10 @@ var projectsBranchesRebase = cli.Command{ func handleProjectsBranchesCreate(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectBranchNewParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -140,12 +146,22 @@ func handleProjectsBranchesCreate(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:branches create", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:branches create", json, format, transform) } func handleProjectsBranchesRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("branch") && len(unusedArgs) > 0 { + cmd.Set("branch", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectBranchGetParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -162,12 +178,18 @@ func handleProjectsBranchesRetrieve(ctx context.Context, cmd *cli.Command) error return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:branches retrieve", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:branches retrieve", json, format, transform) } func handleProjectsBranchesList(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectBranchListParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -183,12 +205,22 @@ func handleProjectsBranchesList(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:branches list", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:branches list", json, format, transform) } func handleProjectsBranchesDelete(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("branch") && len(unusedArgs) > 0 { + cmd.Set("branch", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectBranchDeleteParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -205,12 +237,22 @@ func handleProjectsBranchesDelete(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:branches delete", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:branches delete", json, format, transform) } func handleProjectsBranchesRebase(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if !cmd.IsSet("branch") && len(unusedArgs) > 0 { + cmd.Set("branch", unusedArgs[0]) + unusedArgs = unusedArgs[1:] + } + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectBranchRebaseParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -227,6 +269,8 @@ func handleProjectsBranchesRebase(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:branches rebase", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:branches rebase", json, format, transform) } diff --git a/pkg/cmd/projectconfig.go b/pkg/cmd/projectconfig.go index 92bc50cb..14c3eb8c 100644 --- a/pkg/cmd/projectconfig.go +++ b/pkg/cmd/projectconfig.go @@ -4,10 +4,12 @@ package cmd import ( "context" + "fmt" "github.com/stainless-api/stainless-api-cli/pkg/jsonflag" "github.com/stainless-api/stainless-api-go" "github.com/stainless-api/stainless-api-go/option" + "github.com/tidwall/gjson" "github.com/urfave/cli/v3" ) @@ -65,6 +67,10 @@ var projectsConfigsGuess = cli.Command{ func handleProjectsConfigsRetrieve(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectConfigGetParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -80,12 +86,18 @@ func handleProjectsConfigsRetrieve(ctx context.Context, cmd *cli.Command) error return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:configs retrieve", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:configs retrieve", json, format, transform) } func handleProjectsConfigsGuess(ctx context.Context, cmd *cli.Command) error { cc := getAPICommandContext(cmd) + unusedArgs := cmd.Args().Slice() + if len(unusedArgs) > 0 { + return fmt.Errorf("Unexpected extra arguments: %v", unusedArgs) + } params := stainless.ProjectConfigGuessParams{} if cmd.IsSet("project") { params.Project = stainless.String(cmd.Value("project").(string)) @@ -101,6 +113,8 @@ func handleProjectsConfigsGuess(ctx context.Context, cmd *cli.Command) error { return err } + json := gjson.Parse(string(res)) format := cmd.Root().String("format") - return ShowJSON("projects:configs guess", string(res), format) + transform := cmd.Root().String("transform") + return ShowJSON("projects:configs guess", json, format, transform) } diff --git a/pkg/cmd/util.go b/pkg/cmd/util.go index 166a5143..a7abec7a 100644 --- a/pkg/cmd/util.go +++ b/pkg/cmd/util.go @@ -355,17 +355,23 @@ func shouldUseColors(w io.Writer) bool { return isTerminal(w) } -func ShowJSON(title, jsonText, format string) error { +func ShowJSON(title string, res gjson.Result, format string, transform string) error { + if format != "raw" && transform != "" { + transformed := res.Get(transform) + if transformed.Exists() { + res = transformed + } + } switch strings.ToLower(format) { case "auto": - return ShowJSON(title, jsonText, "json") + return ShowJSON(title, res, "json", "") case "explore": - return jsonview.ExploreJSON(title, jsonText) + return jsonview.ExploreJSON(title, res) case "pretty": - jsonview.DisplayJSON(title, jsonText) + jsonview.DisplayJSON(title, res) return nil case "json": - prettyJSON := pretty.Pretty([]byte(jsonText)) + prettyJSON := pretty.Pretty([]byte(res.Raw)) if shouldUseColors(os.Stdout) { fmt.Print(string(pretty.Color(prettyJSON, pretty.TerminalStyle))) } else { @@ -373,10 +379,10 @@ func ShowJSON(title, jsonText, format string) error { } return nil case "raw": - fmt.Println(jsonText) + fmt.Println(res.Raw) return nil case "yaml": - input := strings.NewReader(jsonText) + input := strings.NewReader(res.Raw) var yaml strings.Builder if err := json2yaml.Convert(&yaml, input); err != nil { return err @@ -384,6 +390,6 @@ func ShowJSON(title, jsonText, format string) error { fmt.Print(yaml.String()) return nil default: - return fmt.Errorf("Invalid format: %s, valid formats are: %s", format, strings.Join(OutputFormats[:], ", ")) + return fmt.Errorf("Invalid format: %s, valid formats are: %s", format, strings.Join(OutputFormats, ", ")) } } diff --git a/pkg/cmd/version.go b/pkg/cmd/version.go index 5f9bfc8d..cab81ffa 100644 --- a/pkg/cmd/version.go +++ b/pkg/cmd/version.go @@ -2,4 +2,4 @@ package cmd -const Version = "0.1.0-alpha.44" // x-release-please-version +const Version = "0.1.0-alpha.45" // x-release-please-version diff --git a/pkg/jsonview/explorer.go b/pkg/jsonview/explorer.go index 4b8f7588..96a7a6f9 100644 --- a/pkg/jsonview/explorer.go +++ b/pkg/jsonview/explorer.go @@ -217,9 +217,8 @@ type JSONViewer struct { help help.Model } -func ExploreJSON(title, jsonStr string) error { - data := gjson.Parse(jsonStr) - view, err := newView("", data, false) +func ExploreJSON(title string, json gjson.Result) error { + view, err := newView("", json, false) if err != nil { return err } diff --git a/pkg/jsonview/staticdisplay.go b/pkg/jsonview/staticdisplay.go index 2b9bc5b5..4eaf65bc 100644 --- a/pkg/jsonview/staticdisplay.go +++ b/pkg/jsonview/staticdisplay.go @@ -13,7 +13,6 @@ import ( const ( tabWidth = 2 - maxDepth = 4 ) var ( @@ -29,11 +28,11 @@ var ( Padding(0, 1) ) -func formatJSON(jsonStr string, width int) string { - if !gjson.Valid(jsonStr) { +func formatJSON(json gjson.Result, width int) string { + if !json.Exists() { return nullValueStyle.Render("Invalid JSON") } - return formatResult(gjson.Parse(jsonStr), 0, width) + return formatResult(json, 0, width) } func formatResult(result gjson.Result, indent, width int) string { @@ -66,17 +65,13 @@ func formatResult(result gjson.Result, indent, width int) string { } func isSingleLine(result gjson.Result, indent int) bool { - return !(result.IsObject() || result.IsArray()) || (indent >= maxDepth) + return !(result.IsObject() || result.IsArray()) } func formatJSONArray(result gjson.Result, indent, width int) string { items := result.Array() if len(items) == 0 { - return nullValueStyle.Render("(none)") - } - - if indent >= maxDepth { - return bulletStyle.Render(formatArray(result)) + return nullValueStyle.Render(" (none)") } numberWidth := lipgloss.Width(fmt.Sprintf("%d. ", len(items))) @@ -106,14 +101,6 @@ func formatJSONObject(result gjson.Result, indent, width int) string { return nullValueStyle.Render("(empty)") } - if indent >= maxDepth { - short := formatObject(result) - if lipgloss.Width(short) > width { - short = truncate.String(short, uint(width-1)) + "…" - } - return bulletStyle.Render(short) - } - var items []string for _, key := range keys { value := result.Get(key.String()) @@ -136,17 +123,17 @@ func getIndent(indent int) string { return strings.Repeat(" ", indent*tabWidth) } -func RenderJSON(title string, jsonStr string) string { +func RenderJSON(title string, json gjson.Result) string { width, _, err := term.GetSize(os.Stdout.Fd()) if err != nil { width = 80 } width -= containerStyle.GetBorderLeftSize() + containerStyle.GetBorderRightSize() + containerStyle.GetPaddingLeft() + containerStyle.GetPaddingRight() - content := strings.TrimLeft(formatJSON(jsonStr, width), "\n") + content := strings.TrimLeft(formatJSON(json, width), "\n") return titleStyle.Render(title) + "\n" + containerStyle.Render(content) } -func DisplayJSON(title string, jsonStr string) { - fmt.Println(RenderJSON(title, jsonStr)) +func DisplayJSON(title string, json gjson.Result) { + fmt.Println(RenderJSON(title, json)) }