feat: add cli contract and local browser events
This commit is contained in:
@@ -2,8 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"chub/internal/platform/config"
|
||||
"chub/internal/platform/logging"
|
||||
@@ -18,6 +22,9 @@ import (
|
||||
const version = "0.1.0-dev"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 {
|
||||
os.Exit(runCLI(os.Args[1:], os.Stdout, os.Stderr))
|
||||
}
|
||||
ctx := context.Background()
|
||||
logger := logging.New(os.Stderr)
|
||||
logger.InfoContext(ctx, "chub starting", "version", version)
|
||||
@@ -25,6 +32,67 @@ func main() {
|
||||
app.Main()
|
||||
}
|
||||
|
||||
type cliError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func runCLI(args []string, out, errout io.Writer) int {
|
||||
if len(args) == 0 {
|
||||
return 2
|
||||
}
|
||||
command := args[0]
|
||||
if command == "--help" || command == "-h" {
|
||||
fmt.Fprintln(out, "chub [start|list|stop|restart|events]")
|
||||
return 0
|
||||
}
|
||||
path, err := config.DefaultPath()
|
||||
if err != nil {
|
||||
writeCLIError(errout, "system_error", err.Error())
|
||||
return 6
|
||||
}
|
||||
store, err := config.New(path)
|
||||
if err != nil {
|
||||
writeCLIError(errout, "system_error", err.Error())
|
||||
return 6
|
||||
}
|
||||
switch command {
|
||||
case "list":
|
||||
value, err := store.Load()
|
||||
if err != nil {
|
||||
writeCLIError(errout, "system_error", err.Error())
|
||||
return 6
|
||||
}
|
||||
return writeJSON(out, map[string]any{"instances": value.Instances})
|
||||
case "events":
|
||||
// T-203 exposes a local JSON-lines snapshot; the live in-process bus is
|
||||
// consumed by the UI and will be connected to a loopback transport later.
|
||||
value, err := store.Load()
|
||||
if err != nil {
|
||||
writeCLIError(errout, "system_error", err.Error())
|
||||
return 6
|
||||
}
|
||||
return writeJSON(out, map[string]any{"event": "browser.snapshot", "instances": value.Instances})
|
||||
case "start", "stop", "restart":
|
||||
writeCLIError(errout, "service_unavailable", strings.TrimSpace(command)+" requires the BrowserManager adapter")
|
||||
return 6
|
||||
default:
|
||||
writeCLIError(errout, "invalid_argument", "unknown command: "+command)
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
func writeJSON(out io.Writer, value any) int {
|
||||
if err := json.NewEncoder(out).Encode(value); err != nil {
|
||||
return 6
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func writeCLIError(out io.Writer, code, message string) {
|
||||
_ = json.NewEncoder(out).Encode(cliError{Code: code, Message: message})
|
||||
}
|
||||
|
||||
func runWindow(logger *slog.Logger) {
|
||||
window := new(app.Window)
|
||||
window.Option(app.Title("Chub 浏览器管理"), app.Size(unit.Dp(1100), unit.Dp(720)))
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRunCLIRejectsUnknownCommandWithStableCode(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
if code := runCLI([]string{"wat"}, &out, &out); code != 2 || !strings.Contains(out.String(), `"invalid_argument"`) {
|
||||
t.Fatalf("code=%d output=%s", code, out.String())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user