Files
2026-06-18 18:34:12 +08:00

123 lines
3.3 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package helpers
import (
"encoding/json"
"fmt"
"github.com/spf13/cobra"
)
// devapp_pretty annotates --format pretty output with human-readable status
// labels. Upstream payloads use a numeric enum for app status and the bare
// INIT/AUDIT/... enum for versionStatus. JSON output is NEVER touched
// (transparency contract); only the pretty view gets `*Text` companions.
var devAppStatusLabels = map[int]string{
0: "IN_ACTIVE 已停用",
1: "ACTIVE 已激活",
2: "WAIT_ACTIVE 待激活",
3: "EXPIRED 已过期",
}
var devAppVersionStatusLabels = map[string]string{
"INIT": "未发布(有待发布变更)",
"AUDIT": "发布审核中",
"RELEASE": "已发布生效",
"GRAY": "灰度中",
}
// devAppToolStatusKind classifies which enum family a tool's `status`-like
// fields belong to, so app status 1 (ACTIVE) is never labeled with version
// semantics and vice versa.
var devAppToolStatusKind = map[string]string{
"get_dev_app": "app",
"list_dev_app": "app",
"create_dev_app": "version", // create/update 返回 versionStatus
"update_dev_app": "version",
"create_dev_app_version": "version",
"list_dev_app_versions": "version",
"get_dev_app_version_detail": "version",
"get_dev_app_version_status": "version",
"publish_dev_app_version": "version",
}
func devAppPrettyWanted(cmd *cobra.Command) bool {
format, err := cmd.Flags().GetString("format")
return err == nil && format == "pretty"
}
// devAppPrettyAnnotate walks the response and adds appStatusText /
// versionStatusText next to recognized enum fields, in place.
func devAppPrettyAnnotate(tool string, payload any) {
kind, ok := devAppToolStatusKind[tool]
if !ok {
return
}
devAppAnnotateNode(payload, kind)
}
func devAppAnnotateNode(node any, kind string) {
switch v := node.(type) {
case map[string]any:
devAppAnnotateMap(v, kind)
for _, child := range v {
devAppAnnotateNode(child, kind)
}
case []any:
for _, child := range v {
devAppAnnotateNode(child, kind)
}
}
}
func devAppAnnotateMap(m map[string]any, kind string) {
if kind == "app" {
for _, key := range []string{"status", "appStatus"} {
if n, ok := devAppAsInt(m[key]); ok {
if label, ok := devAppStatusLabels[n]; ok {
m[key+"Text"] = label
}
}
}
return
}
if s, ok := m["versionStatus"].(string); ok {
if label, ok := devAppVersionStatusLabels[s]; ok {
m["versionStatusText"] = label
}
}
}
func devAppAsInt(v any) (int, bool) {
switch n := v.(type) {
case int:
return n, true
case int64:
return int(n), true
case float64:
return int(n), true
case json.Number:
i, err := n.Int64()
return int(i), err == nil
case string:
var i int
if _, err := fmt.Sscanf(n, "%d", &i); err == nil {
return i, true
}
}
return 0, false
}