package command import ( "encoding/json" "errors" "fmt" "io" "os" "strings" runtimeConfig "code.zhecent.com/open/shop-crm-agent/internal/config" "github.com/spf13/cobra" "golang.org/x/term" ) type initializeConfigFunc func(token string) (string, error) type readTokenFunc func(input io.Reader, output io.Writer) (string, error) type initResult struct { Initialized bool `json:"initialized"` EnvFile string `json:"envFile"` } func newInitCmd() *cobra.Command { return newInitCommand(runtimeConfig.Initialize, readTokenFromTerminal) } func newInitCommand(initialize initializeConfigFunc, readToken readTokenFunc) *cobra.Command { return &cobra.Command{ Use: "init", Short: "初始化本地 CRM Agent 凭证", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { token, err := readToken(cmd.InOrStdin(), cmd.ErrOrStderr()) if err != nil { return err } envFile, err := initialize(token) if err != nil { return err } return json.NewEncoder(cmd.OutOrStdout()).Encode(initResult{Initialized: true, EnvFile: envFile}) }, } } func readTokenFromTerminal(input io.Reader, output io.Writer) (string, error) { inputFile, ok := input.(*os.File) if !ok || !term.IsTerminal(int(inputFile.Fd())) { return "", errors.New("shop-crm-agent init 必须在交互式终端运行") } if _, err := fmt.Fprint(output, "请输入 Shop 管理后台创建后仅显示一次的 CRM Agent Token: "); err != nil { return "", err } value, err := term.ReadPassword(int(inputFile.Fd())) _, _ = fmt.Fprintln(output) if err != nil { return "", fmt.Errorf("读取 CRM Agent Token 失败: %w", err) } return strings.TrimSpace(string(value)), nil }