diff --git a/Makefile b/Makefile index a97c09b..7005a53 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,16 @@ build: ## build binary file gen: ## generate CURD code ${GO} run ./cmd/gen/main.go +.PHONY: gen_error_code +gen_error_code: ## generate error code + ${GO} generate github.com/TensoRaws/NuxBT-Backend/module/error/gen + .PHONY: test test: tidy ## go test ${GO} test ./... .PHONY: lint -lint: ## go lint +lint: gen_error_code golangci-lint run pre-commit install # pip install pre-commit pre-commit run --all-files diff --git a/module/error/code.go b/module/error/code.go new file mode 100644 index 0000000..5d1b801 --- /dev/null +++ b/module/error/code.go @@ -0,0 +1,22 @@ +package error + +type Code uint32 + +const ( + // DO NOT EDIT + // gen code start + InternalError Code = 10000 + iota + UnknownError + InvalidParams + InvalidToken + InvalidUserName + // gen code end + // DO NOT EDIT +) + +func (c Code) String() string { + if str, ok := codeToString[c]; ok { + return str + } + return "Unknown ErrorCode" +} diff --git a/module/error/code.ts b/module/error/code.ts new file mode 100644 index 0000000..b586bfc --- /dev/null +++ b/module/error/code.ts @@ -0,0 +1,11 @@ +// Code generated by go generate; DO NOT EDIT. +// Code generated by go generate; DO NOT EDIT. +// Code generated by go generate; DO NOT EDIT. + +export const enum ErrorCode { + InternalError = 10000, + UnknownError, + InvalidParams, + InvalidToken, + InvalidUserName +} diff --git a/module/error/code_map.go b/module/error/code_map.go new file mode 100644 index 0000000..9bf694d --- /dev/null +++ b/module/error/code_map.go @@ -0,0 +1,13 @@ +// Code generated by go generate; DO NOT EDIT. +// Code generated by go generate; DO NOT EDIT. +// Code generated by go generate; DO NOT EDIT. +package error + +// codeToString use a map to store the string representation of Code +var codeToString = map[Code]string{ + InternalError: "Internal error", + UnknownError: "Unknown error", + InvalidParams: "Invalid params", + InvalidToken: "Invalid token", + InvalidUserName: "Invalid user name", +} diff --git a/module/error/gen/map.go b/module/error/gen/map.go new file mode 100644 index 0000000..f17de72 --- /dev/null +++ b/module/error/gen/map.go @@ -0,0 +1,177 @@ +//go:generate go run map.go +package main + +import ( + "fmt" + "go/format" + "os" + "path/filepath" + "strconv" + "strings" +) + +// buildConstBlock 从文件 content 中构建 const 块 +func buildConstBlock(filename string) ([]string, uint32) { + var iotaBegin uint32 = 0 + + file, err := os.ReadFile(filename) + if err != nil { + _ = fmt.Errorf("read file error: %v", err) + os.Exit(1) + return nil, 0 + } + + content := string(file) + + // 按 \n\t 分割内容 + lines := strings.Split(content, "\n\t") + + // 构建 const 块 + constBlock := make([]string, 0) + buildBlockFlag := false + for _, line := range lines { + if strings.Contains(line, "gen code start") { + buildBlockFlag = true + continue + } + if strings.Contains(line, "gen code end") { + break + } + if buildBlockFlag { + if strings.Contains(line, "iota") { // OK Code = 10000 + iota + l := strings.Split(line, " ") + constBlock = append(constBlock, l[0]) + // string to uint32 + b, _ := strconv.Atoi(l[3]) + iotaBegin = uint32(b) + } else { + constBlock = append(constBlock, line) + } + } + } + + if iotaBegin == 0 { + fmt.Println("Error: iota not found") + os.Exit(1) + } + + return constBlock, iotaBegin +} + +// handleCapString 按字符串的的大写字母分割字符串,用空格连接,首字母大写 +func handleCapString(str string) string { + var buffer strings.Builder + for i, c := range str { + if i > 0 && 'A' <= c && c <= 'Z' { + buffer.WriteByte(' ') + } + if i == 0 { + buffer.WriteRune(c) + } else { + if 'A' <= c && c <= 'Z' { + // 将大写字母转换为小写字母 + buffer.WriteRune(c + 32) + } else { + buffer.WriteRune(c) + } + } + } + return buffer.String() +} + +// generateMap 生成映射代码 +func generateMap(constBlock []string) string { + var mapLines []string + mapLines = append(mapLines, "// Code generated by go generate; DO NOT EDIT.") + mapLines = append(mapLines, "// Code generated by go generate; DO NOT EDIT.") + mapLines = append(mapLines, "// Code generated by go generate; DO NOT EDIT.") + mapLines = append(mapLines, "package error") + mapLines = append(mapLines, "") + mapLines = append(mapLines, "// codeToString use a map to store the string representation of Code") + mapLines = append(mapLines, "var codeToString = map[Code]string{") + for _, l := range constBlock { + mapLines = append(mapLines, fmt.Sprintf("\t%s: \"%s\",", l, handleCapString(l))) + } + mapLines = append(mapLines, "}") + + // 格式化生成的代码 + var buffer strings.Builder + for _, line := range mapLines { + buffer.WriteString(line + "\n") + } + + source, _ := format.Source([]byte(buffer.String())) + + return string(source) +} + +// generateTypeScriptEnum 生成 TypeScript 的枚举 +func generateTypeScriptEnum(constBlock []string, itoaBegin uint32) string { + var tsLines []string + tsLines = append(tsLines, "// Code generated by go generate; DO NOT EDIT.") + tsLines = append(tsLines, "// Code generated by go generate; DO NOT EDIT.") + tsLines = append(tsLines, "// Code generated by go generate; DO NOT EDIT.") + tsLines = append(tsLines, "") + tsLines = append(tsLines, "export const enum ErrorCode {") + for i, l := range constBlock { + switch { + case i == 0: + tsLines = append(tsLines, fmt.Sprintf(" %s = %s,", l, strconv.Itoa(int(itoaBegin)))) + case i == len(constBlock)-1: + tsLines = append(tsLines, fmt.Sprintf(" %s", l)) + default: + tsLines = append(tsLines, fmt.Sprintf(" %s,", l)) + } + } + tsLines = append(tsLines, "}") + + // 格式化生成的代码 + var buffer strings.Builder + for _, line := range tsLines { + buffer.WriteString(line + "\n") + } + return buffer.String() +} + +func main() { + // 获取当前工作目录 + currentDir, err := os.Getwd() + fmt.Println("currentDir: ", currentDir) + if err != nil { + fmt.Println("Error getting current directory: " + err.Error()) + os.Exit(1) + } + + // 根据相对路径找到文件 + filePath := filepath.Join(currentDir, "module/error/code.go") + mapFilePath := filepath.Join(currentDir, "module/error/code_map.go") + tsFilePath := filepath.Join(currentDir, "module/error/code.ts") + if _, err := os.Stat(filePath); err != nil { + currentDir = filepath.Dir(currentDir) + filePath = filepath.Join(currentDir, "code.go") + mapFilePath = filepath.Join(currentDir, "code_map.go") + tsFilePath = filepath.Join(currentDir, "code.ts") + } + + constBlock, iotaBegin := buildConstBlock(filePath) + + // 生成映射代码 + mapCode := generateMap(constBlock) + + // 生成 TypeScript 的枚举 + tsCode := generateTypeScriptEnum(constBlock, iotaBegin) + + // 写入到 code_map.go 文件 + err = os.WriteFile(mapFilePath, []byte(mapCode), 0644) + if err != nil { + fmt.Println("Error writing code_map.go: " + err.Error()) + os.Exit(1) + } + + // 写入到 code.ts 文件 + err = os.WriteFile(tsFilePath, []byte(tsCode), 0644) + if err != nil { + fmt.Println("Error writing code.ts: " + err.Error()) + os.Exit(1) + } +}