diff --git a/cmd/browser_pools.go b/cmd/browser_pools.go index 76b5f3e..f826f07 100644 --- a/cmd/browser_pools.go +++ b/cmd/browser_pools.go @@ -67,13 +67,9 @@ func (c BrowserPoolsCmd) List(ctx context.Context, in BrowserPoolsListInput) err } for _, p := range *pools { - name := p.Name - if name == "" { - name = "-" - } tableData = append(tableData, []string{ p.ID, - name, + util.OrDash(p.Name), fmt.Sprintf("%d", p.AvailableCount), fmt.Sprintf("%d", p.AcquiredCount), util.FormatLocal(p.CreatedAt), @@ -125,7 +121,6 @@ func (c BrowserPoolsCmd) Create(ctx context.Context, in BrowserPoolsCreateInput) req.KioskMode = kernel.Bool(in.Kiosk.Value) } - // Profile profile, err := buildProfileParam(in.ProfileID, in.ProfileName, in.ProfileSaveChanges) if err != nil { pterm.Error.Println(err.Error()) @@ -139,10 +134,8 @@ func (c BrowserPoolsCmd) Create(ctx context.Context, in BrowserPoolsCreateInput) req.ProxyID = kernel.String(in.ProxyID) } - // Extensions req.Extensions = buildExtensionsParam(in.Extensions) - // Viewport viewport, err := buildViewportParam(in.Viewport) if err != nil { pterm.Error.Println(err.Error()) @@ -194,21 +187,28 @@ func (c BrowserPoolsCmd) Get(ctx context.Context, in BrowserPoolsGetInput) error return nil } - name := pool.Name - if name == "" { - name = "-" - } - tableData := pterm.TableData{ + cfg := pool.BrowserPoolConfig + + rows := pterm.TableData{ {"Property", "Value"}, {"ID", pool.ID}, - {"Name", name}, - {"Size", fmt.Sprintf("%d", pool.BrowserPoolConfig.Size)}, + {"Name", util.OrDash(pool.Name)}, + {"Created At", util.FormatLocal(pool.CreatedAt)}, + {"Size", fmt.Sprintf("%d", cfg.Size)}, {"Available", fmt.Sprintf("%d", pool.AvailableCount)}, {"Acquired", fmt.Sprintf("%d", pool.AcquiredCount)}, - {"Timeout", fmt.Sprintf("%d", pool.BrowserPoolConfig.TimeoutSeconds)}, - {"Created At", util.FormatLocal(pool.CreatedAt)}, - } - PrintTableNoPad(tableData, true) + {"Fill Rate", formatFillRate(cfg.FillRatePerMinute)}, + {"Timeout", fmt.Sprintf("%d seconds", cfg.TimeoutSeconds)}, + {"Headless", fmt.Sprintf("%t", cfg.Headless)}, + {"Stealth", fmt.Sprintf("%t", cfg.Stealth)}, + {"Kiosk Mode", fmt.Sprintf("%t", cfg.KioskMode)}, + {"Profile", formatProfile(cfg.Profile)}, + {"Proxy ID", util.OrDash(cfg.ProxyID)}, + {"Extensions", formatExtensions(cfg.Extensions)}, + {"Viewport", formatViewport(cfg.Viewport)}, + } + + PrintTableNoPad(rows, true) return nil } @@ -258,7 +258,6 @@ func (c BrowserPoolsCmd) Update(ctx context.Context, in BrowserPoolsUpdateInput) req.DiscardAllIdle = kernel.Bool(in.DiscardAllIdle.Value) } - // Profile profile, err := buildProfileParam(in.ProfileID, in.ProfileName, in.ProfileSaveChanges) if err != nil { pterm.Error.Println(err.Error()) @@ -272,10 +271,8 @@ func (c BrowserPoolsCmd) Update(ctx context.Context, in BrowserPoolsUpdateInput) req.ProxyID = kernel.String(in.ProxyID) } - // Extensions req.Extensions = buildExtensionsParam(in.Extensions) - // Viewport viewport, err := buildViewportParam(in.Viewport) if err != nil { pterm.Error.Println(err.Error()) @@ -450,10 +447,8 @@ var browserPoolsFlushCmd = &cobra.Command{ } func init() { - // list flags browserPoolsListCmd.Flags().StringP("output", "o", "", "Output format: json for raw API response") - // create flags browserPoolsCreateCmd.Flags().String("name", "", "Optional unique name for the pool") browserPoolsCreateCmd.Flags().Int64("size", 0, "Number of browsers in the pool") _ = browserPoolsCreateCmd.MarkFlagRequired("size") @@ -469,10 +464,8 @@ func init() { browserPoolsCreateCmd.Flags().StringSlice("extension", []string{}, "Extension IDs or names") browserPoolsCreateCmd.Flags().String("viewport", "", "Viewport size (e.g. 1280x800)") - // get flags browserPoolsGetCmd.Flags().StringP("output", "o", "", "Output format: json for raw API response") - // update flags browserPoolsUpdateCmd.Flags().String("name", "", "Update the pool name") browserPoolsUpdateCmd.Flags().Int64("size", 0, "Number of browsers in the pool") browserPoolsUpdateCmd.Flags().Int64("fill-rate", 0, "Fill rate per minute") @@ -488,13 +481,10 @@ func init() { browserPoolsUpdateCmd.Flags().String("viewport", "", "Viewport size (e.g. 1280x800)") browserPoolsUpdateCmd.Flags().Bool("discard-all-idle", false, "Discard all idle browsers") - // delete flags browserPoolsDeleteCmd.Flags().Bool("force", false, "Force delete even if browsers are leased") - // acquire flags browserPoolsAcquireCmd.Flags().Int64("timeout", 0, "Acquire timeout in seconds") - // release flags browserPoolsReleaseCmd.Flags().String("session-id", "", "Browser session ID to release") _ = browserPoolsReleaseCmd.MarkFlagRequired("session-id") browserPoolsReleaseCmd.Flags().Bool("reuse", true, "Reuse the browser instance") @@ -692,3 +682,42 @@ func buildViewportParam(viewport string) (*kernel.BrowserViewportParam, error) { } return &vp, nil } + +func formatFillRate(rate int64) string { + if rate > 0 { + return fmt.Sprintf("%d%%", rate) + } + return "-" +} + +func formatProfile(profile kernel.BrowserProfile) string { + name := util.FirstOrDash(profile.Name, profile.ID) + if name == "-" { + return "-" + } + if profile.SaveChanges { + return fmt.Sprintf("%s (save changes: true)", name) + } + return fmt.Sprintf("%s (save changes: false)", name) +} + +func formatExtensions(extensions []kernel.BrowserExtension) string { + var names []string + for _, ext := range extensions { + if name := util.FirstOrDash(ext.Name, ext.ID); name != "-" { + names = append(names, name) + } + } + return util.JoinOrDash(names...) +} + +func formatViewport(viewport kernel.BrowserViewport) string { + if viewport.Width == 0 || viewport.Height == 0 { + return "-" + } + s := fmt.Sprintf("%dx%d", viewport.Width, viewport.Height) + if viewport.RefreshRate > 0 { + s += fmt.Sprintf("@%d", viewport.RefreshRate) + } + return s +} diff --git a/pkg/util/format.go b/pkg/util/format.go new file mode 100644 index 0000000..7f64590 --- /dev/null +++ b/pkg/util/format.go @@ -0,0 +1,31 @@ +package util + +import "strings" + +// OrDash returns the string if non-empty, otherwise returns "-". +func OrDash(s string) string { + if s == "" { + return "-" + } + return s +} + +// FirstOrDash returns the first non-empty string from the provided items. +// If all items are empty, it returns "-". +func FirstOrDash(items ...string) string { + for _, item := range items { + if item != "" { + return item + } + } + return "-" +} + +// JoinOrDash joins the provided strings with ", " as separator. +// If no items are provided, it returns "-". +func JoinOrDash(items ...string) string { + if len(items) == 0 { + return "-" + } + return strings.Join(items, ", ") +} diff --git a/pkg/util/format_test.go b/pkg/util/format_test.go new file mode 100644 index 0000000..0b3de2a --- /dev/null +++ b/pkg/util/format_test.go @@ -0,0 +1,26 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestOrDash(t *testing.T) { + assert.Equal(t, "hello", OrDash("hello")) + assert.Equal(t, "-", OrDash("")) +} + +func TestFirstOrDash(t *testing.T) { + assert.Equal(t, "first", FirstOrDash("first", "second", "third")) + assert.Equal(t, "second", FirstOrDash("", "second", "third")) + assert.Equal(t, "third", FirstOrDash("", "", "third")) + assert.Equal(t, "-", FirstOrDash("", "", "")) + assert.Equal(t, "-", FirstOrDash()) +} + +func TestJoinOrDash(t *testing.T) { + assert.Equal(t, "a, b, c", JoinOrDash("a", "b", "c")) + assert.Equal(t, "a", JoinOrDash("a")) + assert.Equal(t, "-", JoinOrDash()) +}