release: new project template
This commit is contained in:
89
template/creator.go
Normal file
89
template/creator.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
scaffold = map[string]string{
|
||||
"/.gitignore": templateGitignore,
|
||||
"/Makefile": templateMakefile,
|
||||
"/Dockerfile": templateDockerfile,
|
||||
"/docker-compose.yaml": templateDockerCompose,
|
||||
"/buf.yaml": templateBuf,
|
||||
"/buf.gen.yaml": templateBufGen,
|
||||
"/buf.work.yaml": templateBufWork,
|
||||
"/go.mod": templateModule,
|
||||
"/config_dev.yaml": templateDevYaml,
|
||||
"/config_prod.yaml": templateProdYaml,
|
||||
"/proto/v1/file_module.proto": templateApiservicesProto,
|
||||
"/proto/v1/file_model.proto": templateProto,
|
||||
"/proto/v1/buf.yaml": templateBuf,
|
||||
"/cmd/serve.go": templateCmdNewServe,
|
||||
"/cmd/exec.go": templateCmdExec,
|
||||
"/common/time.go": templateCommon,
|
||||
"/config/config.go": templateConfig,
|
||||
"/register/register.go": templateRouter,
|
||||
"/internal/repositories/.gitkeep": "",
|
||||
"/services/.gitkeep": "",
|
||||
"/gen/.gitkeep": "",
|
||||
}
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
Name string
|
||||
Path string
|
||||
SSH string
|
||||
}
|
||||
|
||||
func (b *Builder) Build() error {
|
||||
if err := os.MkdirAll(b.Path, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.write(b.Path+"/"+b.Name+".go", templateMain); err != nil {
|
||||
return err
|
||||
}
|
||||
for sr, v := range scaffold {
|
||||
i := strings.LastIndex(sr, "/")
|
||||
if i > 0 {
|
||||
dir := sr[:i]
|
||||
if err := os.MkdirAll(b.Path+dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := b.write(b.Path+sr, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builder) write(name, tpl string) (err error) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Println("Failed")
|
||||
}
|
||||
}()
|
||||
fmt.Printf("create %s \n", name)
|
||||
data, err := b.parse(tpl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return os.WriteFile(name, data, 0644)
|
||||
}
|
||||
|
||||
func (b *Builder) parse(s string) ([]byte, error) {
|
||||
t, err := template.New("").Parse(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if err := t.Execute(&buf, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
70
template/template_apiservices.go
Normal file
70
template/template_apiservices.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package template
|
||||
|
||||
const templateApiservicesProto = `syntax = "proto3";
|
||||
|
||||
package proto.v1;
|
||||
|
||||
option go_package = "project/gen;genv1";
|
||||
|
||||
|
||||
// @route_group: true
|
||||
// @base_url: /v1/file
|
||||
// @gen_to: ./services/controller/v1/file_controller.go
|
||||
// @rpc_to: ./services/rpc/v1/file_impl.go
|
||||
service FileService {
|
||||
// @desc: 列表
|
||||
// @author: Young Xu
|
||||
// @method: GET
|
||||
// @api: /list
|
||||
rpc List (FileServiceListRequest) returns (FileServiceListResponse);
|
||||
// @desc: 上传
|
||||
// @author: Young Xu
|
||||
// @method: POST
|
||||
// @api: /upload
|
||||
rpc Upload (FileServiceUploadRequest) returns (FileServiceUploadResponse);
|
||||
// @desc: 删除
|
||||
// @author: Young Xu
|
||||
// @method: DELETE
|
||||
// @api: /delete
|
||||
rpc Delete (FileServiceDeleteRequest) returns (FileServiceDeleteResponse);
|
||||
// @desc: 下载
|
||||
// @author: Young Xu
|
||||
// @method: GET
|
||||
// @api: /download
|
||||
rpc Download (FileServiceDownloadRequest) returns (FileServiceDownloadResponse);
|
||||
}
|
||||
|
||||
|
||||
message FileServiceListRequest {
|
||||
string dirname = 1; // 目录
|
||||
}
|
||||
|
||||
message FileServiceListResponse {
|
||||
message Item {
|
||||
int64 file_id = 1; // 文件ID
|
||||
string filename = 2; // 文件名
|
||||
string file_size = 3; // 文件大小
|
||||
string created_at = 4; // 上传时间
|
||||
string dirname = 5; // 文件路径
|
||||
bool is_directory = 6; // 是否是目录
|
||||
}
|
||||
repeated Item items = 1; // 列表
|
||||
}
|
||||
|
||||
message FileServiceUploadRequest {}
|
||||
|
||||
message FileServiceUploadResponse {}
|
||||
|
||||
message FileServiceDeleteRequest {
|
||||
int64 file_id = 1; // 文件名
|
||||
}
|
||||
|
||||
message FileServiceDeleteResponse {}
|
||||
|
||||
message FileServiceDownloadRequest {
|
||||
// @v: required
|
||||
string file_id = 1; // 文件ID
|
||||
}
|
||||
|
||||
message FileServiceDownloadResponse {}
|
||||
`
|
||||
83
template/template_command.go
Normal file
83
template/template_command.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package template
|
||||
|
||||
const templateCmdExec = `package cmd
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gitter.top/common/lormatter"
|
||||
|
||||
"{{.Name}}/config"
|
||||
)
|
||||
|
||||
var (
|
||||
rootCmd = &cobra.Command{}
|
||||
cfgFile string
|
||||
)
|
||||
|
||||
func Execute() {
|
||||
// 预加载配置文件
|
||||
loadConfig()
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
logrus.Fatalf("exec command failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
var formatter = lormatter.Formatter{
|
||||
ShowTime: true,
|
||||
ShowFile: true,
|
||||
}
|
||||
formatter.Register()
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "config_dev.yaml", "config file")
|
||||
rootCmd.AddCommand(apiServerCommand) // API服务
|
||||
rootCmd.AddCommand(grpcServerCommand) // GRPC服务
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
// 初始化配置文件
|
||||
config.New(cfgFile)
|
||||
conf := config.Get()
|
||||
if err := conf.Load(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const templateCmdNewServe = `package cmd
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"{{.Name}}/register"
|
||||
)
|
||||
|
||||
var (
|
||||
apiServerCommand = &cobra.Command{
|
||||
Use: "api",
|
||||
Short: "start api server",
|
||||
Long: "start api server",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
router := register.NewRegister()
|
||||
if err := router.NewRouter(); err != nil {
|
||||
logrus.Errorf("register router failed: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
grpcServerCommand = &cobra.Command{
|
||||
Use: "grpc",
|
||||
Short: "start grpc server",
|
||||
Long: "start grpc server",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
router := register.NewRegister()
|
||||
if err := router.NewGrpc(); err != nil {
|
||||
logrus.Errorf("register grpc failed: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
`
|
||||
10
template/template_common.go
Normal file
10
template/template_common.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package template
|
||||
|
||||
const templateCommon = `package common
|
||||
|
||||
import "time"
|
||||
|
||||
func Unix2Datetime(t int64) string {
|
||||
return time.Unix(t, 0).Format(time.DateTime)
|
||||
}
|
||||
`
|
||||
62
template/template_config.go
Normal file
62
template/template_config.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package template
|
||||
|
||||
const templateConfig = `package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
ServerName string ` + "`" + `yaml:"server-name"` + "`" + `
|
||||
ServerListen string ` + "`" + `yaml:"server-listen"` + "`" + `
|
||||
GrpcListen string ` + "`" + `yaml:"grpc-listen"` + "`" + `
|
||||
Environment string ` + "`" + `yaml:"environment"` + "`" + `
|
||||
}
|
||||
|
||||
type ServerConf struct {
|
||||
ConfigFile string
|
||||
ServerConfig ` + "`" + `yaml:",inline"` + "`" + `
|
||||
}
|
||||
|
||||
var conf *ServerConf
|
||||
|
||||
func New(fileName string) {
|
||||
conf = new(ServerConf)
|
||||
conf.ConfigFile = fileName
|
||||
if err := conf.Load(); err != nil {
|
||||
logrus.Fatalf("read config file failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Get() *ServerConf {
|
||||
if conf == nil {
|
||||
panic("config file not initialized")
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
func (receiver *ServerConf) Load() error {
|
||||
data, err := os.ReadFile(receiver.ConfigFile)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := yaml.Unmarshal(data, receiver); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (receiver *ServerConf) Rewrite() error {
|
||||
data, err := yaml.Marshal(receiver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(receiver.ConfigFile, data, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
`
|
||||
10
template/template_main.go
Normal file
10
template/template_main.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package template
|
||||
|
||||
const templateMain = `package main
|
||||
|
||||
import "{{.Name}}/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
||||
`
|
||||
19
template/template_model.go
Normal file
19
template/template_model.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package template
|
||||
|
||||
const templateProto = `syntax = "proto3";
|
||||
|
||||
package proto.v1;
|
||||
|
||||
option go_package = "project/gen;genv1";
|
||||
|
||||
|
||||
// @table_name: t_file
|
||||
message ModelFileRecord {
|
||||
int64 id = 1;
|
||||
string filename = 2;
|
||||
string file_size = 3;
|
||||
string dirname = 4;
|
||||
int64 created_at = 5;
|
||||
bool is_directory = 6;
|
||||
}
|
||||
`
|
||||
18
template/template_module.go
Normal file
18
template/template_module.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package template
|
||||
|
||||
const templateModule = `module {{.Name}}
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/google/wire v0.5.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.0
|
||||
gitter.top/coco/coco v0.0.1
|
||||
gitter.top/common/lormatter v0.0.0-20230910075849-28d49dccd03a
|
||||
google.golang.org/grpc v1.60.1
|
||||
google.golang.org/protobuf v1.32.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
`
|
||||
99
template/template_plugins_config.go
Normal file
99
template/template_plugins_config.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package template
|
||||
|
||||
const templateGitignore = `.idea
|
||||
{{.Name}}
|
||||
{{.Name}}.exe
|
||||
{{.Name}}.exe~
|
||||
`
|
||||
|
||||
const templateMakefile = `.PHONY : clean all ui api gen wire
|
||||
gen:
|
||||
ifeq ($(wildcard "webui/node_modules"),)
|
||||
buf generate
|
||||
else
|
||||
buf generate --exclude-path webui/node_modules
|
||||
endif
|
||||
|
||||
wire:
|
||||
cd gen/wire && wire
|
||||
|
||||
ui:
|
||||
cd webui && npm install && npm run build
|
||||
|
||||
api:
|
||||
go mod tidy && go build .
|
||||
./{{.Name}} api
|
||||
|
||||
all: gen wire ui api
|
||||
`
|
||||
|
||||
const templateDockerfile = `FROM images.local/golang:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN go install gitter.top/coco/protoc-gen-coco@latest &&\
|
||||
go install github.com/golang/protobuf/protoc-gen-go@latest &&\
|
||||
go install github.com/bufbuild/buf/cmd/...@latest
|
||||
|
||||
COPY . /app
|
||||
RUN npm install ts-proto
|
||||
RUN buf generate --exclude-path node_modules
|
||||
RUN cd webui && npm install && npm run build &&\
|
||||
cd .. && go mod tidy && go build .
|
||||
|
||||
EXPOSE 38080
|
||||
ENTRYPOINT [ "./filesaver", "api" ]
|
||||
`
|
||||
|
||||
const templateDockerCompose = `version: "3"
|
||||
|
||||
services:
|
||||
server:
|
||||
image: xuthus5/{{.Name}}:latest
|
||||
container_name: {{.Name}}
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/containers/{{.Name}}:/app/data
|
||||
ports:
|
||||
- "30001:38080"
|
||||
`
|
||||
|
||||
const templateBuf = `version: v1
|
||||
breaking:
|
||||
use:
|
||||
- FILE
|
||||
lint:
|
||||
use:
|
||||
- DEFAULT
|
||||
except:
|
||||
- MINIMAL
|
||||
`
|
||||
|
||||
const templateBufGen = `version: v1
|
||||
plugins:
|
||||
- plugin: buf.build/protocolbuffers/go
|
||||
out: gen
|
||||
opt: paths=source_relative
|
||||
- plugin: coco
|
||||
out: gen
|
||||
opt:
|
||||
- paths=source_relative
|
||||
- prefix=proto
|
||||
- project_name={{.Name}}
|
||||
- plugin: buf.build/community/stephenh-ts-proto
|
||||
out: ./webui/src/gen
|
||||
opt:
|
||||
- paths=source_relative
|
||||
- snakeToCamel=json
|
||||
- esModuleInterop=true
|
||||
- plugin: buf.build/grpc/go:v1.3.0
|
||||
out: gen
|
||||
opt:
|
||||
- paths=source_relative
|
||||
- require_unimplemented_servers=false
|
||||
`
|
||||
|
||||
const templateBufWork = `version: v1
|
||||
directories:
|
||||
- proto
|
||||
`
|
||||
62
template/template_router.go
Normal file
62
template/template_router.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package template
|
||||
|
||||
const templateRouter = `package register
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitter.top/coco/coco"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
|
||||
"{{.Name}}/config"
|
||||
"{{.Name}}/gen/wire"
|
||||
)
|
||||
|
||||
type Register struct{
|
||||
*config.ServerConf
|
||||
}
|
||||
|
||||
func NewRegister() *Register {
|
||||
return &Register{config.Get()}
|
||||
}
|
||||
|
||||
// NewRouter 注册路由
|
||||
func (receiver *Register) NewRouter() error {
|
||||
// 从这里开始实例化路由注册器
|
||||
var register = coco.NewRegister()
|
||||
register.DefaultRouter(coco.WithListenAddress(receiver.ServerListen),
|
||||
coco.WithGinMode(gin.ReleaseMode), coco.WithCors(), coco.WithRecovery())
|
||||
// register.RegisterStruct(wire.InitFileService())
|
||||
_ = register.PreRun(func() error {
|
||||
engine := register.RawEngine()
|
||||
engine.Static("/assets", "./webui/dist/assets")
|
||||
engine.NoRoute(func(ctx *gin.Context) {
|
||||
ctx.File("./webui/dist/index.html")
|
||||
})
|
||||
return nil
|
||||
})
|
||||
logrus.Infof("start api server: http://%s", receiver.ServerListen)
|
||||
register.Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewGrpc 注册grpc服务端
|
||||
func (receiver *Register) NewGrpc() error {
|
||||
lis, err := net.Listen("tcp", receiver.GrpcListen)
|
||||
if err != nil {
|
||||
logrus.Fatalf("failed to listen grpc: %v", err)
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
//genv1.RegisterFileServiceServer(s, &rpcv1.FileService{})
|
||||
// Register reflection service on gRPC server.
|
||||
reflection.Register(s)
|
||||
logrus.Infof("grpc server: %s", receiver.GrpcListen)
|
||||
if err := s.Serve(lis); err != nil {
|
||||
logrus.Fatalf("failed to serve grpc: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
`
|
||||
13
template/template_yaml.go
Normal file
13
template/template_yaml.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package template
|
||||
|
||||
const templateDevYaml = `server-name: {{.Name}}
|
||||
server-listen: 0.0.0.0:38080
|
||||
grpc-listen: 0.0.0.0:38090
|
||||
environment: dev
|
||||
`
|
||||
|
||||
const templateProdYaml = `server-name: {{.Name}}
|
||||
server-listen: 0.0.0.0:38080
|
||||
grpc-listen: 0.0.0.0:38090
|
||||
environment: prod
|
||||
`
|
||||
Reference in New Issue
Block a user