github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/cmd/internal/svc/codegen/init.go (about) 1 package codegen 2 3 import ( 4 "bufio" 5 "fmt" 6 "github.com/go-git/go-billy/v5/osfs" 7 "github.com/go-git/go-git/v5" 8 "github.com/go-git/go-git/v5/plumbing/cache" 9 "github.com/go-git/go-git/v5/storage/filesystem" 10 "github.com/iancoleman/strcase" 11 "github.com/sirupsen/logrus" 12 "github.com/unionj-cloud/go-doudou/cmd/internal/executils" 13 "github.com/unionj-cloud/go-doudou/toolkit/sliceutils" 14 "github.com/unionj-cloud/go-doudou/toolkit/stringutils" 15 "github.com/unionj-cloud/go-doudou/version" 16 "os" 17 "path/filepath" 18 "runtime" 19 "strings" 20 "text/template" 21 ) 22 23 const svcTmpl = `/** 24 * Generated by go-doudou {{.Version}}. 25 * You can edit it as your need. 26 */ 27 package service 28 29 import ( 30 "context" 31 "{{.VoPackage}}" 32 ) 33 34 //go:generate go-doudou svc http --handler -c --doc 35 //go:generate go-doudou svc grpc 36 37 type {{.SvcName}} interface { 38 // You can define your service methods as your need. Below is an example. 39 // You can also add annotations here like @role(admin) to add meta data to routes for 40 // implementing your own middlewares 41 PageUsers(ctx context.Context, query vo.PageQuery) (data vo.PageRet, err error) 42 } 43 ` 44 45 const voTmpl = `/** 46 * Generated by go-doudou {{.Version}}. 47 * You can edit it as your need. 48 */ 49 package vo 50 51 //go:generate go-doudou name --file $GOFILE 52 53 type PageFilter struct { 54 // 真实姓名,前缀匹配 55 Name string 56 // 所属部门ID 57 Dept int 58 } 59 60 type Order struct { 61 Col string 62 Sort string 63 } 64 65 type Page struct { 66 // 排序规则 67 Orders []Order 68 // 页码 69 PageNo int 70 // 每页行数 71 Size int 72 } 73 74 // 分页筛选条件 75 type PageQuery struct { 76 Filter PageFilter 77 Page Page 78 } 79 80 type PageRet struct { 81 Items interface{} 82 PageNo int 83 PageSize int 84 Total int 85 HasNext bool 86 } 87 88 type UserVo struct { 89 Id int 90 Name string 91 Phone string 92 Dept string 93 } 94 ` 95 96 const modTmpl = `module {{.ModName}} 97 98 go {{.GoVersion}} 99 100 require ( 101 github.com/ascarter/requestid v0.0.0-20170313220838-5b76ab3d4aee 102 github.com/brianvoe/gofakeit/v6 v6.10.0 103 github.com/go-resty/resty/v2 v2.6.0 104 github.com/go-sql-driver/mysql v1.6.0 105 github.com/gorilla/handlers v1.5.1 106 github.com/iancoleman/strcase v0.1.3 107 github.com/jmoiron/sqlx v1.3.1 108 github.com/kelseyhightower/envconfig v1.4.0 109 github.com/opentracing-contrib/go-stdlib v1.0.0 110 github.com/opentracing/opentracing-go v1.2.0 111 github.com/pkg/errors v0.9.1 112 github.com/rs/zerolog v1.28.0 113 github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 114 github.com/grpc-ecosystem/go-grpc-middleware/providers/zerolog/v2 v2.0.0-rc.2 115 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2 116 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 117 github.com/prometheus/client_golang v1.11.0 118 google.golang.org/grpc v1.38.0 119 google.golang.org/protobuf v1.26.0 120 github.com/unionj-cloud/go-doudou ` + version.Release + ` 121 )` 122 123 const gitignoreTmpl = `# Binaries for programs and plugins 124 *.exe 125 *.exe~ 126 *.dll 127 *.so 128 *.dylib 129 130 # Output of the go coverage tool, specifically when used with LiteIDE 131 *.out 132 133 # Dependency directories (remove the comment below to include it) 134 # vendor/ 135 **/*.local 136 .DS_Store 137 .idea` 138 139 const envTmpl = `` 140 141 const dockerignorefileTmpl = `**/*.local 142 ` 143 144 const dockerfileTmpl = `FROM devopsworks/golang-upx:1.18 AS builder 145 146 ENV GO111MODULE=on 147 ENV GOPROXY=https://goproxy.cn,direct 148 ARG user 149 ENV HOST_USER=$user 150 151 WORKDIR /repo 152 153 # all the steps are cached 154 ADD go.mod . 155 ADD go.sum . 156 # if go.mod/go.sum not changed, this step is also cached 157 RUN go mod download 158 159 ADD . ./ 160 RUN go mod vendor 161 162 RUN export GDD_VER=$(go list -mod=vendor -m -f '{{` + "`" + `{{` + "`" + `}} .Version {{` + "`" + `}}` + "`" + `}}' github.com/unionj-cloud/go-doudou) && \ 163 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags="-s -w -X 'github.com/unionj-cloud/go-doudou/framework/buildinfo.BuildUser=$HOST_USER' -X 'github.com/unionj-cloud/go-doudou/framework/buildinfo.BuildTime=$(date)' -X 'github.com/unionj-cloud/go-doudou/framework/buildinfo.GddVer=$GDD_VER'" -mod vendor -o api cmd/main.go && \ 164 strip api && /usr/local/bin/upx api 165 166 FROM alpine:3.14 167 168 COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai 169 ENV TZ="Asia/Shanghai" 170 171 WORKDIR /repo 172 173 COPY --from=builder /repo/api ./ 174 175 COPY .env* ./ 176 177 ENTRYPOINT ["/repo/api"] 178 ` 179 180 func getGoVersionNum(goVersion string) string { 181 vnums := sliceutils.StringSlice2InterfaceSlice(strings.Split(strings.TrimPrefix(strings.TrimSpace(goVersion), "go"), ".")) 182 nums := make([]interface{}, 2) 183 copy(nums, vnums) 184 return fmt.Sprintf("%s.%s", nums...) 185 } 186 187 // InitProj inits a service project 188 // dir is root path 189 // modName is module name 190 func InitProj(dir string, modName string, runner executils.Runner) { 191 var ( 192 err error 193 svcName string 194 svcfile string 195 modfile string 196 vodir string 197 vofile string 198 goVersion string 199 firstLine string 200 f *os.File 201 tpl *template.Template 202 envfile string 203 out []byte 204 ) 205 if stringutils.IsEmpty(dir) { 206 dir, _ = os.Getwd() 207 } 208 _ = os.MkdirAll(dir, os.ModePerm) 209 210 gitInit(dir) 211 gitIgnore(dir) 212 213 if out, err = runner.Output("go", "version"); err != nil { 214 panic(err) 215 } 216 // go version go1.13 darwin/amd64 217 goVersion = getGoVersionNum(strings.Split(strings.TrimSpace(string(out)), " ")[2]) 218 if stringutils.IsEmpty(modName) { 219 modName = filepath.Base(dir) 220 } 221 modfile = filepath.Join(dir, "go.mod") 222 if _, err = os.Stat(modfile); os.IsNotExist(err) { 223 if f, err = os.Create(modfile); err != nil { 224 panic(err) 225 } 226 defer f.Close() 227 228 tpl, _ = template.New("go.mod.tmpl").Parse(modTmpl) 229 _ = tpl.Execute(f, struct { 230 ModName string 231 GoVersion string 232 }{ 233 ModName: modName, 234 GoVersion: goVersion, 235 }) 236 } else { 237 logrus.Warnf("file %s already exists", modfile) 238 } 239 240 envfile = filepath.Join(dir, ".env") 241 if _, err = os.Stat(envfile); os.IsNotExist(err) { 242 if f, err = os.Create(envfile); err != nil { 243 panic(err) 244 } 245 defer f.Close() 246 247 tpl, _ = template.New(".env.tmpl").Parse(envTmpl) 248 _ = tpl.Execute(f, struct { 249 SvcName string 250 }{ 251 SvcName: modName, 252 }) 253 } else { 254 logrus.Warnf("file %s already exists", envfile) 255 } 256 257 vodir = filepath.Join(dir, "vo") 258 if err = os.MkdirAll(vodir, os.ModePerm); err != nil { 259 panic(err) 260 } 261 vofile = filepath.Join(vodir, "vo.go") 262 if _, err = os.Stat(vofile); os.IsNotExist(err) { 263 if f, err = os.Create(vofile); err != nil { 264 panic(err) 265 } 266 defer f.Close() 267 268 tpl, _ = template.New("vo.go.tmpl").Parse(voTmpl) 269 _ = tpl.Execute(f, struct { 270 Version string 271 }{ 272 Version: version.Release, 273 }) 274 } else { 275 logrus.Warnf("file %s already exists", vofile) 276 } 277 278 svcName = strcase.ToCamel(filepath.Base(dir)) 279 svcfile = filepath.Join(dir, "svc.go") 280 if _, err = os.Stat(svcfile); os.IsNotExist(err) { 281 if f, err = os.Open(modfile); err != nil { 282 panic(err) 283 } 284 defer f.Close() 285 reader := bufio.NewReader(f) 286 firstLine, _ = reader.ReadString('\n') 287 modName = strings.TrimSpace(strings.TrimPrefix(firstLine, "module")) 288 289 if f, err = os.Create(svcfile); err != nil { 290 panic(err) 291 } 292 defer f.Close() 293 294 tpl, _ = template.New("svc.go.tmpl").Parse(svcTmpl) 295 _ = tpl.Execute(f, struct { 296 VoPackage string 297 SvcName string 298 Version string 299 }{ 300 VoPackage: modName + "/vo", 301 SvcName: svcName, 302 Version: version.Release, 303 }) 304 } else { 305 logrus.Warnf("file %s already exists", svcfile) 306 } 307 308 dockerfile := filepath.Join(dir, "Dockerfile") 309 if _, err = os.Stat(dockerfile); os.IsNotExist(err) { 310 if f, err = os.Create(dockerfile); err != nil { 311 panic(err) 312 } 313 defer f.Close() 314 315 tpl, _ = template.New("dockerfile.tmpl").Parse(dockerfileTmpl) 316 _ = tpl.Execute(f, nil) 317 } else { 318 logrus.Warnf("file %s already exists", dockerfile) 319 } 320 321 dockerignorefile := filepath.Join(dir, ".dockerignore") 322 if _, err = os.Stat(dockerignorefile); os.IsNotExist(err) { 323 if f, err = os.Create(dockerignorefile); err != nil { 324 panic(err) 325 } 326 defer f.Close() 327 328 tpl, _ = template.New("dockerignorefile.tmpl").Parse(dockerignorefileTmpl) 329 _ = tpl.Execute(f, nil) 330 } else { 331 logrus.Warnf("file %s already exists", dockerignorefile) 332 } 333 } 334 335 // InitSvc inits a service project, test purpose only 336 func InitSvc(dir string) { 337 var ( 338 err error 339 modName string 340 svcName string 341 svcfile string 342 modfile string 343 vodir string 344 vofile string 345 goVersion string 346 firstLine string 347 f *os.File 348 tpl *template.Template 349 envfile string 350 ) 351 if stringutils.IsEmpty(dir) { 352 dir, _ = os.Getwd() 353 } 354 _ = os.MkdirAll(dir, os.ModePerm) 355 356 gitInit(dir) 357 gitIgnore(dir) 358 359 goVersion = getGoVersionNum(runtime.Version()) 360 modName = filepath.Base(dir) 361 modfile = filepath.Join(dir, "go.mod") 362 if _, err = os.Stat(modfile); os.IsNotExist(err) { 363 if f, err = os.Create(modfile); err != nil { 364 panic(err) 365 } 366 defer f.Close() 367 368 tpl, _ = template.New("go.mod.tmpl").Parse(modTmpl) 369 _ = tpl.Execute(f, struct { 370 ModName string 371 GoVersion string 372 }{ 373 ModName: modName, 374 GoVersion: goVersion, 375 }) 376 } else { 377 logrus.Warnf("file %s already exists", "go.mod") 378 } 379 380 envfile = filepath.Join(dir, ".env") 381 if _, err = os.Stat(envfile); os.IsNotExist(err) { 382 if f, err = os.Create(envfile); err != nil { 383 panic(err) 384 } 385 defer f.Close() 386 387 tpl, _ = template.New(".env.tmpl").Parse(envTmpl) 388 _ = tpl.Execute(f, struct { 389 SvcName string 390 }{ 391 SvcName: modName, 392 }) 393 } else { 394 logrus.Warnf("file %s already exists", vofile) 395 } 396 397 vodir = filepath.Join(dir, "vo") 398 if err = os.MkdirAll(vodir, os.ModePerm); err != nil { 399 panic(err) 400 } 401 vofile = filepath.Join(vodir, "vo.go") 402 if _, err = os.Stat(vofile); os.IsNotExist(err) { 403 if f, err = os.Create(vofile); err != nil { 404 panic(err) 405 } 406 defer f.Close() 407 408 tpl, _ = template.New("vo.go.tmpl").Parse(voTmpl) 409 _ = tpl.Execute(f, struct { 410 Version string 411 }{ 412 Version: version.Release, 413 }) 414 } else { 415 logrus.Warnf("file %s already exists", vofile) 416 } 417 418 svcName = strcase.ToCamel(filepath.Base(dir)) 419 svcfile = filepath.Join(dir, "svc.go") 420 if _, err = os.Stat(svcfile); os.IsNotExist(err) { 421 if f, err = os.Open(modfile); err != nil { 422 panic(err) 423 } 424 reader := bufio.NewReader(f) 425 firstLine, _ = reader.ReadString('\n') 426 modName = strings.TrimSpace(strings.TrimPrefix(firstLine, "module")) 427 fmt.Println(modName) 428 429 if f, err = os.Create(svcfile); err != nil { 430 panic(err) 431 } 432 defer f.Close() 433 434 tpl, _ = template.New("svc.go.tmpl").Parse(svcTmpl) 435 _ = tpl.Execute(f, struct { 436 VoPackage string 437 SvcName string 438 Version string 439 }{ 440 VoPackage: modName + "/vo", 441 SvcName: svcName, 442 Version: version.Release, 443 }) 444 } else { 445 logrus.Warnf("file %s already exists", svcfile) 446 } 447 448 dockerfile := filepath.Join(dir, "Dockerfile") 449 if _, err = os.Stat(dockerfile); os.IsNotExist(err) { 450 if f, err = os.Create(dockerfile); err != nil { 451 panic(err) 452 } 453 defer f.Close() 454 455 tpl, _ = template.New("dockerfile.tmpl").Parse(dockerfileTmpl) 456 _ = tpl.Execute(f, nil) 457 } else { 458 logrus.Warnf("file %s already exists", dockerfile) 459 } 460 } 461 462 // gitIgnore adds .gitignore file 463 func gitIgnore(dir string) { 464 var ( 465 gitignorefile string 466 err error 467 f *os.File 468 tpl *template.Template 469 ) 470 gitignorefile = filepath.Join(dir, ".gitignore") 471 if _, err = os.Stat(gitignorefile); os.IsNotExist(err) { 472 if f, err = os.Create(gitignorefile); err != nil { 473 panic(err) 474 } 475 defer f.Close() 476 477 tpl, _ = template.New(".gitignore.tmpl").Parse(gitignoreTmpl) 478 _ = tpl.Execute(f, nil) 479 } else { 480 logrus.Warnf("file %s already exists", ".gitignore") 481 } 482 } 483 484 // gitInit inits git repository 485 func gitInit(dir string) { 486 fs := osfs.New(dir) 487 dot, _ := fs.Chroot(".git") 488 storage := filesystem.NewStorage(dot, cache.NewObjectLRUDefault()) 489 490 _, _ = git.Init(storage, fs) 491 }