Skip to content

Commit e7e11bc

Browse files
committed
feat(jzero): support different api file use same go_package and fix model.go.tpl
1 parent 78f0ff9 commit e7e11bc

3 files changed

Lines changed: 140 additions & 62 deletions

File tree

cmd/jzero/.template/model/model.go.tpl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ type Model struct {
4444
}
4545

4646
func NewModel(conn sqlx.SqlConn, op ...opts.Opt[modelx.ModelOpts]) Model {
47-
{{range $v := .TableInfos}}
48-
{{if and $.ModelCache (or $v.HasCacheExpiry $v.HasNotFoundExpiry)}}
47+
{{range $v := .TableInfos}}{{if and $.ModelCache (or $v.HasCacheExpiry $v.HasNotFoundExpiry)}}
4948
{{$v.Name | ToCamel}}CacheOpts := opts.DefaultApply(op...).CacheOpts
5049
{{if $v.HasCacheExpiry}}
5150
if expiry, ok := ModelExpiryTable["{{$v.Name}}"]; ok {
@@ -55,12 +54,7 @@ func NewModel(conn sqlx.SqlConn, op ...opts.Opt[modelx.ModelOpts]) Model {
5554
{{if $v.HasNotFoundExpiry}}
5655
if notFoundExpiry, ok := ModelNotFoundExpiryTable["{{$v.Name}}"]; ok {
5756
{{$v.Name | ToCamel}}CacheOpts = append({{$v.Name | ToCamel}}CacheOpts, cache.WithNotFoundExpiry(time.Duration(notFoundExpiry)*time.Millisecond))
58-
}
59-
{{end}}
60-
{{end}}
61-
{{end}}
62-
63-
return Model{
57+
}{{end}}{{end}}{{end}}return Model{
6458
{{range $v := .TableInfos}}{{if and $.ModelCache (or $v.HasCacheExpiry $v.HasNotFoundExpiry)}}{{$v.Name | FirstUpper | ToCamel}}: {{$v.Name}}.New{{ $v.Name | FirstUpper | ToCamel }}Model(conn, append(op, modelx.WithCacheOpts({{$v.Name | ToCamel}}CacheOpts...))...),{{else}}{{$v.Name | FirstUpper | ToCamel}}: {{$v.Name}}.New{{ $v.Name | FirstUpper | ToCamel }}Model(conn, op...),{{end}}
6559
{{end}}
6660
}

cmd/jzero/internal/command/gen/genapi/types.go

Lines changed: 60 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"go/token"
77
"os"
88
"path/filepath"
9+
"sort"
910
"strings"
1011
"sync"
1112

@@ -36,19 +37,19 @@ func (ja *JzeroApi) separateTypesGo(apiFiles []string, apiSpecMap map[string]*sp
3637

3738
// apiFileTypes 表示 API 文件的类型信息
3839
type apiFileTypes struct {
39-
file string
40-
types []spec.Type
41-
goPackage string
42-
typesGoBytes []byte
40+
file string
41+
types []spec.Type
42+
goPackage string
4343
}
4444

4545
// collectAndGenerateTypesByPackage 收集并按包生成 types.go 文件
4646
func (ja *JzeroApi) collectAndGenerateTypesByPackage(apiFiles []string, apiSpecMap map[string]*spec.ApiSpec) (typesWithPackage []apiFileTypes, typesWithoutPackage []spec.Type, err error) {
4747
var eg errgroup.Group
4848
var mu sync.Mutex
49-
results := make([]apiFileTypes, 0, len(apiFiles))
49+
resultsByFile := make([]apiFileTypes, len(apiFiles))
5050

51-
for _, apiFile := range apiFiles {
51+
for i, apiFile := range apiFiles {
52+
index := i
5253
currentFile := apiFile
5354
currentSpec := apiSpecMap[apiFile]
5455

@@ -59,11 +60,7 @@ func (ja *JzeroApi) collectAndGenerateTypesByPackage(apiFiles []string, apiSpecM
5960
}
6061

6162
mu.Lock()
62-
if fileTypes.goPackage != "" {
63-
results = append(results, fileTypes)
64-
} else {
65-
typesWithoutPackage = append(typesWithoutPackage, fileTypes.types...)
66-
}
63+
resultsByFile[index] = fileTypes
6764
mu.Unlock()
6865

6966
return nil
@@ -74,12 +71,32 @@ func (ja *JzeroApi) collectAndGenerateTypesByPackage(apiFiles []string, apiSpecM
7471
return nil, nil, err
7572
}
7673

74+
results := make([]apiFileTypes, 0, len(apiFiles))
75+
typesByPackage := make(map[string][]spec.Type)
76+
77+
for _, fileTypes := range resultsByFile {
78+
if fileTypes.goPackage != "" {
79+
results = append(results, fileTypes)
80+
typesByPackage[fileTypes.goPackage] = append(typesByPackage[fileTypes.goPackage], fileTypes.types...)
81+
continue
82+
}
83+
84+
typesWithoutPackage = append(typesWithoutPackage, fileTypes.types...)
85+
}
86+
7787
// 并发生成有 go_package 的 types.go 文件
7888
eg = errgroup.Group{}
79-
for _, fileTypes := range results {
80-
currentTypes := fileTypes
89+
goPackages := make([]string, 0, len(typesByPackage))
90+
for goPackage := range typesByPackage {
91+
goPackages = append(goPackages, goPackage)
92+
}
93+
sort.Strings(goPackages)
94+
95+
for _, goPackage := range goPackages {
96+
currentPackage := goPackage
97+
currentTypes := typesByPackage[goPackage]
8198
eg.Go(func() error {
82-
return ja.writeTypesFile(currentTypes.goPackage, currentTypes.typesGoBytes)
99+
return ja.writeTypesFile(currentPackage, currentTypes)
83100
})
84101
}
85102

@@ -92,11 +109,6 @@ func (ja *JzeroApi) collectAndGenerateTypesByPackage(apiFiles []string, apiSpecM
92109

93110
// processApiFileTypes 处理单个 API 文件的类型
94111
func (ja *JzeroApi) processApiFileTypes(apiFile string, apiSpec *spec.ApiSpec) (apiFileTypes, error) {
95-
typesGoString, err := gogen.BuildTypes(apiSpec.Types)
96-
if err != nil {
97-
return apiFileTypes{}, err
98-
}
99-
100112
goPackage, hasGoPackage := apiSpec.Info.Properties["go_package"]
101113
if !hasGoPackage || goPackage == "" {
102114
return apiFileTypes{
@@ -105,41 +117,25 @@ func (ja *JzeroApi) processApiFileTypes(apiFile string, apiSpec *spec.ApiSpec) (
105117
}, nil
106118
}
107119

108-
packageName := strings.ToLower(strings.ReplaceAll(goPackage, "/", ""))
109-
typesGoBytes, err := templatex.ParseTemplate("inner_types.go", map[string]any{
110-
"Types": typesGoString,
111-
"Package": packageName,
112-
}, []byte(`// Code generated by jzero. DO NOT EDIT.
113-
package {{.Package}}
114-
115-
import (
116-
"time"
117-
)
118-
119-
var (
120-
_ = time.Now()
121-
)
122-
123-
{{.Types}}`))
124-
if err != nil {
125-
return apiFileTypes{}, err
126-
}
127-
128120
return apiFileTypes{
129-
file: apiFile,
130-
types: apiSpec.Types,
131-
goPackage: goPackage,
132-
typesGoBytes: typesGoBytes,
121+
file: apiFile,
122+
types: apiSpec.Types,
123+
goPackage: goPackage,
133124
}, nil
134125
}
135126

136127
// writeTypesFile 写入 types.go 文件
137-
func (ja *JzeroApi) writeTypesFile(goPackage string, typesGoBytes []byte) error {
128+
func (ja *JzeroApi) writeTypesFile(goPackage string, types []spec.Type) error {
138129
typesDir := filepath.Join("internal", "types", goPackage)
139130
if err := os.MkdirAll(typesDir, 0o755); err != nil {
140131
return err
141132
}
142133

134+
typesGoBytes, err := ja.renderTypesFile(types, strings.ToLower(strings.ReplaceAll(goPackage, "/", "")))
135+
if err != nil {
136+
return err
137+
}
138+
143139
process, err := gosimports.Process("", typesGoBytes, nil)
144140
if err != nil {
145141
return err
@@ -153,15 +149,30 @@ func (ja *JzeroApi) generateDefaultTypesFile(allTypes []spec.Type) error {
153149
// 去重
154150
uniqueTypes := ja.deduplicateTypes(allTypes)
155151

156-
typesGoString, err := gogen.BuildTypes(uniqueTypes)
152+
typesGoBytes, err := ja.renderTypesFile(uniqueTypes, "types")
157153
if err != nil {
158154
return err
159155
}
160156

157+
process, err := gosimports.Process("", typesGoBytes, nil)
158+
if err != nil {
159+
return err
160+
}
161+
162+
return os.WriteFile(filepath.Join("internal", "types", "types.go"), process, 0o644)
163+
}
164+
165+
func (ja *JzeroApi) renderTypesFile(types []spec.Type, packageName string) ([]byte, error) {
166+
typesGoString, err := gogen.BuildTypes(types)
167+
if err != nil {
168+
return nil, err
169+
}
170+
161171
typesGoBytes, err := templatex.ParseTemplate("inner_types.go", map[string]any{
162-
"Types": typesGoString,
172+
"Types": typesGoString,
173+
"Package": packageName,
163174
}, []byte(`// Code generated by jzero. DO NOT EDIT.
164-
package types
175+
package {{.Package}}
165176
166177
import (
167178
"time"
@@ -173,15 +184,10 @@ var (
173184
174185
{{.Types}}`))
175186
if err != nil {
176-
return err
187+
return nil, err
177188
}
178189

179-
process, err := gosimports.Process("", typesGoBytes, nil)
180-
if err != nil {
181-
return err
182-
}
183-
184-
return os.WriteFile(filepath.Join("internal", "types", "types.go"), process, 0o644)
190+
return typesGoBytes, nil
185191
}
186192

187193
// deduplicateTypes 去重类型列表

cmd/jzero/internal/command/gen/genapi/types_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,81 @@ type OldType struct{}
7777
t.Fatalf("separateTypesGo() should keep default types package, got:\n%s", got)
7878
}
7979
}
80+
81+
func TestSeparateTypesGoMergesTypesForSameGoPackage(t *testing.T) {
82+
tmpDir := t.TempDir()
83+
84+
oldWd, err := os.Getwd()
85+
if err != nil {
86+
t.Fatalf("Getwd() error = %v", err)
87+
}
88+
t.Cleanup(func() {
89+
_ = os.Chdir(oldWd)
90+
})
91+
92+
if err := os.Chdir(tmpDir); err != nil {
93+
t.Fatalf("Chdir() error = %v", err)
94+
}
95+
96+
apiSpecMap := map[string]*spec.ApiSpec{
97+
"desc/api/user.api": {
98+
Info: spec.Info{
99+
Properties: map[string]string{
100+
"go_package": "shared",
101+
},
102+
},
103+
Types: []spec.Type{
104+
spec.DefineStruct{
105+
RawName: "UserReq",
106+
Members: []spec.Member{
107+
{
108+
Name: "Name",
109+
Type: spec.PrimitiveType{RawName: "string"},
110+
Tag: "`json:\"name\"`",
111+
},
112+
},
113+
},
114+
},
115+
},
116+
"desc/api/order.api": {
117+
Info: spec.Info{
118+
Properties: map[string]string{
119+
"go_package": "shared",
120+
},
121+
},
122+
Types: []spec.Type{
123+
spec.DefineStruct{
124+
RawName: "OrderReq",
125+
Members: []spec.Member{
126+
{
127+
Name: "Id",
128+
Type: spec.PrimitiveType{RawName: "int64"},
129+
Tag: "`json:\"id\"`",
130+
},
131+
},
132+
},
133+
},
134+
},
135+
}
136+
137+
ja := &JzeroApi{}
138+
if err := ja.separateTypesGo([]string{"desc/api/user.api", "desc/api/order.api"}, apiSpecMap); err != nil {
139+
t.Fatalf("separateTypesGo() error = %v", err)
140+
}
141+
142+
data, err := os.ReadFile(filepath.Join("internal", "types", "shared", "types.go"))
143+
if err != nil {
144+
t.Fatalf("ReadFile() error = %v", err)
145+
}
146+
147+
got := string(data)
148+
for _, want := range []string{
149+
"package shared",
150+
"type UserReq struct",
151+
"type OrderReq struct",
152+
} {
153+
if !strings.Contains(got, want) {
154+
t.Fatalf("separateTypesGo() missing %q in merged file:\n%s", want, got)
155+
}
156+
}
157+
}

0 commit comments

Comments
 (0)