# 🔄 Migration Guide: From go-zero Plugin to Standalone Tool This document explains how `go-doc` was extracted from go-zero and made independent. ## 📊 What Changed? ### 1. **Module Independence** **Before (go-zero plugin):** ```go // Part of go-zero's internal tools package swagger // in tools/goctl/api/plugin/swagger/ ``` **After (standalone):** ```go module go-doc package swagger // in internal/swagger/ ``` ### 2. **Dependency Reduction** #### Removed Internal Dependencies | Dependency | Replaced With | Reason | |:-----------|:--------------|:-------| | `go-zero/tools/goctl/internal/version` | Custom version in `main.go` | Internal package not accessible | | `go-zero/tools/goctl/util` | `go-doc/internal/util` | Self-contained utilities | | `go-zero/tools/goctl/util/stringx` | `go-doc/internal/util` | Custom string manipulation | | `go-zero/tools/goctl/util/pathx` | `go-doc/internal/util` | Custom path utilities | | `google.golang.org/grpc/metadata` | Direct map access | Simplified KV retrieval | #### Kept Essential Dependencies ```go require ( github.com/go-openapi/spec v0.21.0 // Swagger spec github.com/spf13/cobra v1.8.1 // CLI framework github.com/zeromicro/go-zero/tools/goctl v1.9.0 // API parser only gopkg.in/yaml.v2 v2.4.0 // YAML output ) ``` ### 3. **Project Structure** **Before:** ``` go-zero/ └── tools/ └── goctl/ └── api/ └── plugin/ └── swagger/ ├── swagger.go ├── parameter.go └── ... ``` **After:** ``` go-doc/ ├── cmd/ │ └── go-doc/ │ └── main.go # Standalone entry point ├── internal/ │ ├── swagger/ # Core logic (from go-zero) │ │ ├── swagger.go │ │ ├── parameter.go │ │ └── ... │ └── util/ # Self-contained utilities │ ├── util.go │ ├── stringx.go │ └── pathx.go └── example/ ``` ### 4. **Import Path Changes** **Before:** ```go import ( "github.com/zeromicro/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util/stringx" "github.com/zeromicro/go-zero/tools/goctl/internal/version" "google.golang.org/grpc/metadata" ) ``` **After:** ```go import ( "go-doc/internal/util" ) ``` ### 5. **Metadata Handling** **Before (using gRPC metadata):** ```go func getStringFromKV(properties map[string]string, key string) string { md := metadata.New(properties) val := md.Get(key) if len(val) == 0 { return "" } return val[0] } ``` **After (direct map access):** ```go func getStringFromKVOrDefault(properties map[string]string, key string, def string) string { if len(properties) == 0 { return def } val, ok := properties[key] if !ok { return def } str, err := strconv.Unquote(val) if err != nil || len(str) == 0 { return def } return str } ``` ### 6. **Version Information** **Before:** ```go ext.Add("x-goctl-version", version.BuildVersion) ext.Add("x-github", "https://github.com/zeromicro/go-zero") ``` **After:** ```go ext.Add("x-generator", "go-doc") ext.Add("x-github", "https://github.com/danielchan-25/go-doc") ``` ## 🔧 Implementation Details ### Custom Utilities Created #### 1. **util.TrimWhiteSpace** ```go // Replaces: go-zero/tools/goctl/util.TrimWhiteSpace func TrimWhiteSpace(s string) string { return strings.Map(func(r rune) rune { if unicode.IsSpace(r) { return -1 } return r }, s) } ``` #### 2. **util.FieldsAndTrimSpace** ```go // Replaces: go-zero/tools/goctl/util.FieldsAndTrimSpace func FieldsAndTrimSpace(s string, fn func(rune) bool) []string { fields := strings.FieldsFunc(s, fn) result := make([]string, 0, len(fields)) for _, field := range fields { trimmed := strings.TrimSpace(field) if len(trimmed) > 0 { result = append(result, trimmed) } } return result } ``` #### 3. **util.String (for ToCamel/Untitle)** ```go // Replaces: go-zero/tools/goctl/util/stringx type String struct { source string } func From(s string) String { return String{source: s} } func (s String) ToCamel() string { /* implementation */ } func (s String) Untitle() string { /* implementation */ } ``` #### 4. **util.MkdirIfNotExist** ```go // Replaces: go-zero/tools/goctl/util/pathx.MkdirIfNotExist func MkdirIfNotExist(dir string) error { if _, err := os.Stat(dir); os.IsNotExist(err) { return os.MkdirAll(dir, 0755) } return nil } ``` ## ✅ Compatibility ### What's Still Compatible? ✅ **API File Format** - 100% compatible with go-zero `.api` files ✅ **Swagger Output** - Generates identical OpenAPI 2.0 specifications ✅ **All Features** - All swagger generation features preserved ✅ **Tag Syntax** - Same tag options (range, enum, default, example, etc.) ### What's Different? ⚠️ **Generated Metadata** - `x-generator: "go-doc"` instead of `x-goctl-version` - `x-github` points to go-doc repository - Build date format remains the same ⚠️ **Module Name** - Import as `go-doc` not part of go-zero ⚠️ **Binary Name** - `go-doc` instead of `goctl api plugin -plugin swagger` ## 🚀 Migration Steps for Users If you were using go-zero's swagger plugin: ### Old Way (go-zero plugin): ```bash goctl api plugin -plugin swagger -api example.api -dir output ``` ### New Way (standalone go-doc): ```bash go-doc -a example.api -d output ``` ## 📝 Benefits of Independence 1. ✅ **Smaller Binary** - Only swagger generation, no full goctl 2. ✅ **Faster Installation** - Fewer dependencies 3. ✅ **Clearer Purpose** - Single responsibility 4. ✅ **Easier Maintenance** - Self-contained codebase 5. ✅ **Flexible Updates** - Independent release cycle ## 🙏 Attribution This tool was extracted from the excellent [go-zero](https://github.com/zeromicro/go-zero) project. We are grateful to the go-zero team for their foundational work. --- **Original Source:** https://github.com/zeromicro/go-zero/tree/master/tools/goctl/api/plugin/swagger **License:** MIT (both original and this project)