Files
weichenandCursor bd53e9ba79
ci / vet-and-test (push) Successful in 3s
ci / docker-checkout-hostgateway (push) Successful in 3s
Add a shared error-code catalog so failures can be traced by stable codes.
Services can resolve legacy aliases and expose the catalog over CLI and HTTP instead of ad-hoc error strings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-29 13:43:12 +00:00

177 lines
4.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package cli 实现 errcode 命令:list / show / search / validate / export / serve。
package cli
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"strings"
"error-code-system/errcode"
"error-code-system/server"
)
// Main 执行命令行并返回进程退出码。
func Main(args []string) int {
return Run(args, os.Stdout, os.Stderr)
}
// Run 执行命令。stdout 写结果,stderr 写用法与错误。
func Run(args []string, stdout, stderr io.Writer) int {
if len(args) == 0 {
fmt.Fprintln(stderr, usage)
return 2
}
switch args[0] {
case "list":
return cmdList(args[1:], stdout, stderr)
case "show":
return cmdShow(args[1:], stdout, stderr)
case "search":
return cmdSearch(args[1:], stdout, stderr)
case "validate":
return cmdValidate(args[1:], stdout, stderr)
case "export":
return cmdExport(args[1:], stdout, stderr)
case "serve":
return cmdServe(args[1:], stderr)
case "-h", "--help", "help":
fmt.Fprintln(stdout, usage)
return 0
default:
fmt.Fprintf(stderr, "未知命令 %q\n%s\n", args[0], usage)
return 2
}
}
const usage = `用法:
errcode list [--domain 域] [--json]
errcode show <码或别名>
errcode search <关键词>
errcode validate <码或别名>
errcode export [--domain 域]
errcode serve [--addr :8091]`
func registry() *errcode.Registry { return errcode.Default }
func cmdList(args []string, stdout, stderr io.Writer) int {
fs := flag.NewFlagSet("list", flag.ContinueOnError)
fs.SetOutput(stderr)
domain := fs.String("domain", "", "只列出该域")
asJSON := fs.Bool("json", false, "以 JSON 输出")
if err := fs.Parse(args); err != nil {
return 2
}
defs := registry().List(*domain)
if *asJSON {
enc := json.NewEncoder(stdout)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
if err := enc.Encode(defs); err != nil {
fmt.Fprintln(stderr, err)
return 1
}
return 0
}
for _, def := range defs {
fmt.Fprintf(stdout, "%s\t%d\t%s\t%s\n", def.Code, def.HTTP, def.Retry, def.Summary)
}
return 0
}
func cmdShow(args []string, stdout, stderr io.Writer) int {
if len(args) != 1 {
fmt.Fprintln(stderr, "用法: errcode show <码或别名>")
return 2
}
def, ok := registry().Lookup(args[0])
if !ok {
fmt.Fprintf(stderr, "未登记: %s(回落 %s)\n", args[0], errcode.SysUnknownCode)
return 1
}
enc := json.NewEncoder(stdout)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
if err := enc.Encode(def); err != nil {
fmt.Fprintln(stderr, err)
return 1
}
return 0
}
func cmdSearch(args []string, stdout, stderr io.Writer) int {
if len(args) < 1 {
fmt.Fprintln(stderr, "用法: errcode search <关键词>")
return 2
}
q := strings.Join(args, " ")
for _, def := range registry().Search(q) {
fmt.Fprintf(stdout, "%s\t%s\n", def.Code, def.Summary)
}
return 0
}
func cmdValidate(args []string, stdout, stderr io.Writer) int {
if len(args) != 1 {
fmt.Fprintln(stderr, "用法: errcode validate <码或别名>")
return 2
}
def, ok := registry().Lookup(args[0])
resolved := def
if !ok {
resolved = registry().Resolve(args[0])
}
fmt.Fprintf(stdout, "input=%s known=%t resolved=%s\n", args[0], ok, resolved.Code)
if !ok {
return 1
}
return 0
}
func cmdExport(args []string, stdout, stderr io.Writer) int {
fs := flag.NewFlagSet("export", flag.ContinueOnError)
fs.SetOutput(stderr)
domain := fs.String("domain", "", "只导出该域")
if err := fs.Parse(args); err != nil {
return 2
}
var data []byte
var err error
if *domain == "" {
data, err = registry().ExportJSON()
} else {
encBuf := &strings.Builder{}
enc := json.NewEncoder(encBuf)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
err = enc.Encode(registry().List(*domain))
data = []byte(encBuf.String())
}
if err != nil {
fmt.Fprintln(stderr, err)
return 1
}
if _, err := stdout.Write(data); err != nil {
fmt.Fprintln(stderr, err)
return 1
}
return 0
}
func cmdServe(args []string, stderr io.Writer) int {
fs := flag.NewFlagSet("serve", flag.ContinueOnError)
fs.SetOutput(stderr)
addr := fs.String("addr", server.DefaultAddr, "监听地址")
if err := fs.Parse(args); err != nil {
return 2
}
fmt.Fprintf(stderr, "errcode serve %s\n", *addr)
if err := server.New(registry()).ListenAndServe(*addr); err != nil {
fmt.Fprintln(stderr, err)
return 1
}
return 0
}