feat: use go:embed to embed templates (#1756)

master
Kevin Wan 3 years ago committed by GitHub
parent 58a0b17451
commit faad6e27e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,24 @@
syntax = "v1"
info (
title: // TODO: add title
desc: // TODO: add description
author: "{{.gitUser}}"
email: "{{.gitEmail}}"
)
type request {
// TODO: add members here and delete this comment
}
type response {
// TODO: add members here and delete this comment
}
service {{.serviceName}} {
@handler GetUser // TODO: set handler name and delete this comment
get /users/id/:userId(request) returns(response)
@handler CreateUser // TODO: set handler name and delete this comment
post /users/create(request)
}

@ -1,11 +1,12 @@
package apigen
import (
_ "embed"
"errors"
"fmt"
"html/template"
"path/filepath"
"strings"
"text/template"
"github.com/logrusorgru/aurora"
"github.com/urfave/cli"
@ -13,32 +14,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const apiTemplate = `
syntax = "v1"
info (
title: // TODO: add title
desc: // TODO: add description
author: "{{.gitUser}}"
email: "{{.gitEmail}}"
)
type request {
// TODO: add members here and delete this comment
}
type response {
// TODO: add members here and delete this comment
}
service {{.serviceName}} {
@handler GetUser // TODO: set handler name and delete this comment
get /users/id/:userId(request) returns(response)
@handler CreateUser // TODO: set handler name and delete this comment
post /users/create(request)
}
`
//go:embed api.tpl
var apiTemplate string
// ApiCommand create api template file
func ApiCommand(c *cli.Context) error {

@ -2,6 +2,7 @@ package docgen
import (
"bytes"
_ "embed"
"fmt"
"html/template"
"strconv"
@ -13,25 +14,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/util"
)
const (
markdownTemplate = `
### {{.index}}. {{.routeComment}}
1.
- Url: {{.uri}}
- Method: {{.method}}
- Request: {{.requestType}}
- Response: {{.responseType}}
2.
{{.requestContent}}
3.
{{.responseContent}}
`
)
//go:embed markdown.tpl
var markdownTemplate string
func genDoc(api *spec.ApiSpec, dir, filename string) error {
fp, _, err := util.MaybeCreateFile(dir, "", filename)

@ -0,0 +1,16 @@
### {{.index}}. {{.routeComment}}
1. route definition
- Url: {{.uri}}
- Method: {{.method}}
- Request: {{.requestType}}
- Response: {{.responseType}}
2. request definition
{{.requestContent}}
3. response definition
{{.responseContent}}

@ -0,0 +1,3 @@
Name: {{.serviceName}}
Host: {{.host}}
Port: {{.port}}

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"strconv"
@ -12,12 +13,11 @@ import (
const (
defaultPort = 8888
etcDir = "etc"
etcTemplate = `Name: {{.serviceName}}
Host: {{.host}}
Port: {{.port}}
`
)
//go:embed etc.tpl
var etcTemplate string
func genEtc(dir string, cfg *config.Config, api *spec.ApiSpec) error {
filename, err := format.FileNamingFormat(cfg.NamingFormat, api.Service.Name)
if err != nil {

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"path"
"strings"
@ -14,36 +15,10 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/vars"
)
const (
defaultLogicPackage = "logic"
handlerTemplate = `package {{.PkgName}}
const defaultLogicPackage = "logic"
import (
"net/http"
{{if .After1_1_10}}"github.com/zeromicro/go-zero/rest/httpx"{{end}}
{{.ImportPackages}}
)
func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
{{if .HasRequest}}var req types.{{.RequestType}}
if err := httpx.Parse(r, &req); err != nil {
httpx.Error(w, err)
return
}
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
if err != nil {
httpx.Error(w, err)
} else {
{{if .HasResp}}httpx.OkJson(w, resp){{else}}httpx.Ok(w){{end}}
}
}
}
`
)
//go:embed handler.tpl
var handlerTemplate string
type handlerInfo struct {
PkgName string

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"path"
"strconv"
@ -14,32 +15,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/vars"
)
const logicTemplate = `package {{.pkgName}}
import (
{{.imports}}
)
type {{.logic}} struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} {
return &{{.logic}}{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
// todo: add your logic here and delete this line
{{.returnString}}
}
`
//go:embed logic.tpl
var logicTemplate string
func genLogic(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error {
for _, g := range api.Service.Groups {

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"strings"
@ -11,33 +12,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/vars"
)
const mainTemplate = `package main
import (
"flag"
"fmt"
{{.importPackages}}
)
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
`
//go:embed main.tpl
var mainTemplate string
func genMain(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error {
name := strings.ToLower(api.Service.Name)

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"strings"
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
@ -8,27 +9,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/format"
)
var middlewareImplementCode = `
package middleware
import "net/http"
type {{.name}} struct {
}
func New{{.name}}() *{{.name}} {
return &{{.name}}{}
}
func (m *{{.name}})Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// TODO generate middleware implement function, delete after code implementation
// Passthrough to next handler if need
next(w, r)
}
}
`
//go:embed middleware.tpl
var middlewareImplementCode string
func genMiddleware(dir string, cfg *config.Config, api *spec.ApiSpec) error {
middlewares := getMiddleware(api)

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"strings"
@ -11,27 +12,10 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/vars"
)
const (
contextFilename = "service_context"
contextTemplate = `package svc
const contextFilename = "service_context"
import (
{{.configImport}}
)
type ServiceContext struct {
Config {{.config}}
{{.middleware}}
}
func NewServiceContext(c {{.config}}) *ServiceContext {
return &ServiceContext{
Config: c,
{{.middlewareAssignment}}
}
}
`
)
//go:embed svc.tpl
var contextTemplate string
func genServiceContext(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error {
filename, err := format.FileNamingFormat(cfg.NamingFormat, contextFilename)

@ -1,6 +1,7 @@
package gogen
import (
_ "embed"
"fmt"
"io"
"os"
@ -14,16 +15,10 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/format"
)
const (
typesFile = "types"
typesTemplate = `// Code generated by goctl. DO NOT EDIT.
package types{{if .containsTime}}
import (
"time"
){{end}}
{{.types}}
`
)
const typesFile = "types"
//go:embed types.tpl
var typesTemplate string
// BuildTypes gen types to string
func BuildTypes(types []spec.Type) (string, error) {

@ -0,0 +1,26 @@
package {{.PkgName}}
import (
"net/http"
{{if .After1_1_10}}"github.com/zeromicro/go-zero/rest/httpx"{{end}}
{{.ImportPackages}}
)
func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
{{if .HasRequest}}var req types.{{.RequestType}}
if err := httpx.Parse(r, &req); err != nil {
httpx.Error(w, err)
return
}
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
if err != nil {
httpx.Error(w, err)
} else {
{{if .HasResp}}httpx.OkJson(w, resp){{else}}httpx.Ok(w){{end}}
}
}
}

@ -0,0 +1,25 @@
package {{.pkgName}}
import (
{{.imports}}
)
type {{.logic}} struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} {
return &{{.logic}}{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
// todo: add your logic here and delete this line
{{.returnString}}
}

@ -0,0 +1,26 @@
package main
import (
"flag"
"fmt"
{{.importPackages}}
)
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}

@ -0,0 +1,19 @@
package middleware
import "net/http"
type {{.name}} struct {
}
func New{{.name}}() *{{.name}} {
return &{{.name}}{}
}
func (m *{{.name}})Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// TODO generate middleware implement function, delete after code implementation
// Passthrough to next handler if need
next(w, r)
}
}

@ -0,0 +1,17 @@
package svc
import (
{{.configImport}}
)
type ServiceContext struct {
Config {{.config}}
{{.middleware}}
}
func NewServiceContext(c {{.config}}) *ServiceContext {
return &ServiceContext{
Config: c,
{{.middlewareAssignment}}
}
}

@ -0,0 +1,6 @@
// Code generated by goctl. DO NOT EDIT.
package types{{if .containsTime}}
import (
"time"
){{end}}
{{.types}}

@ -0,0 +1,9 @@
{{.indent}}{{.decorator}}
{{.indent}}public {{.returnType}} is{{.property}}() {
{{.indent}} return this.{{.tagValue}};
{{.indent}}}
{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) {
{{.indent}} this.{{.tagValue}} = {{.propertyValue}};
{{.indent}}}

@ -0,0 +1,22 @@
// Code generated by goctl. DO NOT EDIT.
package com.xhb.logic.http.packet.{{.packet}}.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
{{.imports}}
public class {{.className}} extends {{.superClassName}} {
{{.properties}}
{{if .HasProperty}}
public {{.className}}() {
}
public {{.className}}({{.params}}) {
{{.constructorSetter}}
}
{{end}}
{{.getSet}}
}

@ -12,7 +12,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
// JavaCommand the generate java code command entrance
// JavaCommand generates java code command entrance.
func JavaCommand(c *cli.Context) error {
apiFile := c.String("api")
dir := c.String("dir")

@ -3,6 +3,7 @@ package javagen
import (
"bufio"
"bytes"
_ "embed"
"errors"
"fmt"
"io"
@ -18,54 +19,19 @@ import (
)
const (
componentTemplate = `// Code generated by goctl. DO NOT EDIT.
package com.xhb.logic.http.packet.{{.packet}}.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
{{.imports}}
public class {{.className}} extends {{.superClassName}} {
{{.properties}}
{{if .HasProperty}}
public {{.className}}() {
}
public {{.className}}({{.params}}) {
{{.constructorSetter}}
}
{{end}}
{{.getSet}}
}
`
getSetTemplate = `
{{.indent}}{{.decorator}}
{{.indent}}public {{.returnType}} get{{.property}}() {
{{.indent}} return this.{{.tagValue}};
{{.indent}}}
{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) {
{{.indent}} this.{{.tagValue}} = {{.propertyValue}};
{{.indent}}}
`
boolTemplate = `
{{.indent}}{{.decorator}}
{{.indent}}public {{.returnType}} is{{.property}}() {
{{.indent}} return this.{{.tagValue}};
{{.indent}}}
{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) {
{{.indent}} this.{{.tagValue}} = {{.propertyValue}};
{{.indent}}}
`
httpResponseData = "import com.xhb.core.response.HttpResponseData;"
httpData = "import com.xhb.core.packet.HttpData;"
)
var (
//go:embed component.tpl
componentTemplate string
//go:embed getset.tpl
getSetTemplate string
//go:embed bool.tpl
boolTemplate string
)
type componentsContext struct {
api *spec.ApiSpec
requestTypes []spec.Type

@ -2,6 +2,7 @@ package javagen
import (
"bytes"
_ "embed"
"fmt"
"strings"
"text/template"
@ -12,32 +13,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util"
)
const packetTemplate = `package com.xhb.logic.http.packet.{{.packet}};
import com.xhb.core.packet.HttpPacket;
import com.xhb.core.network.HttpRequestClient;
{{.imports}}
{{.doc}}
public class {{.packetName}} extends HttpPacket<{{.responseType}}> {
{{.paramsDeclaration}}
public {{.packetName}}({{.params}}{{if .HasRequestBody}}{{.requestType}} request{{end}}) {
{{if .HasRequestBody}}super(request);{{else}}super(EmptyRequest.instance);{{end}}
{{if .HasRequestBody}}this.request = request;{{end}}{{.paramsSetter}}
}
@Override
public HttpRequestClient.Method requestMethod() {
return HttpRequestClient.Method.{{.method}};
}
@Override
public String requestUri() {
return {{.uri}};
}
}
`
//go:embed packet.tpl
var packetTemplate string
func genPacket(dir, packetName string, api *spec.ApiSpec) error {
for _, route := range api.Service.Routes() {

@ -0,0 +1,9 @@
{{.indent}}{{.decorator}}
{{.indent}}public {{.returnType}} get{{.property}}() {
{{.indent}} return this.{{.tagValue}};
{{.indent}}}
{{.indent}}public void set{{.property}}({{.type}} {{.propertyValue}}) {
{{.indent}} this.{{.tagValue}} = {{.propertyValue}};
{{.indent}}}

@ -0,0 +1,25 @@
package com.xhb.logic.http.packet.{{.packet}};
import com.xhb.core.packet.HttpPacket;
import com.xhb.core.network.HttpRequestClient;
{{.imports}}
{{.doc}}
public class {{.packetName}} extends HttpPacket<{{.responseType}}> {
{{.paramsDeclaration}}
public {{.packetName}}({{.params}}{{if .HasRequestBody}}{{.requestType}} request{{end}}) {
{{if .HasRequestBody}}super(request);{{else}}super(EmptyRequest.instance);{{end}}
{{if .HasRequestBody}}this.request = request;{{end}}{{.paramsSetter}}
}
@Override
public HttpRequestClient.Method requestMethod() {
return HttpRequestClient.Method.{{.method}};
}
@Override
public String requestUri() {
return {{.uri}};
}
}

@ -0,0 +1,22 @@
package {{with .Info}}{{.Desc}}{{end}}
import com.google.gson.Gson
object {{with .Info}}{{.Title}}{{end}}{
{{range .Types}}
data class {{.Name}}({{$length := (len .Members)}}{{range $i,$item := .Members}}
val {{with $item}}{{lowCamelCase .Name}}: {{parseType .Type.Name}}{{end}}{{if ne $i (add $length -1)}},{{end}}{{end}}
){{end}}
{{with .Service}}
{{range .Routes}}suspend fun {{routeToFuncName .Method .Path}}({{with .RequestType}}{{if ne .Name ""}}
req:{{.Name}},{{end}}{{end}}
onOk: (({{with .ResponseType}}{{.Name}}{{end}}) -> Unit)? = null,
onFail: ((String) -> Unit)? = null,
eventually: (() -> Unit)? = null
){
apiRequest("{{upperCase .Method}}","{{.Path}}",{{with .RequestType}}{{if ne .Name ""}}body=req,{{end}}{{end}} onOk = { {{with .ResponseType}}
onOk?.invoke({{if ne .Name ""}}Gson().fromJson(it,{{.Name}}::class.java){{end}}){{end}}
}, onFail = onFail, eventually =eventually)
}
{{end}}{{end}}
}

@ -0,0 +1,61 @@
package {{.}}
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
const val SERVER = "http://localhost:8080"
suspend fun apiRequest(
method: String,
uri: String,
body: Any = "",
onOk: ((String) -> Unit)? = null,
onFail: ((String) -> Unit)? = null,
eventually: (() -> Unit)? = null
) = withContext(Dispatchers.IO) {
val url = URL(SERVER + uri)
with(url.openConnection() as HttpURLConnection) {
connectTimeout = 3000
requestMethod = method
doInput = true
if (method == "POST" || method == "PUT" || method == "PATCH") {
setRequestProperty("Content-Type", "application/json")
doOutput = true
val data = when (body) {
is String -> {
body
}
else -> {
Gson().toJson(body)
}
}
val wr = OutputStreamWriter(outputStream)
wr.write(data)
wr.flush()
}
try {
if (responseCode >= 400) {
BufferedReader(InputStreamReader(errorStream)).use {
val response = it.readText()
onFail?.invoke(response)
}
return@with
}
//response
BufferedReader(InputStreamReader(inputStream)).use {
val response = it.readText()
onOk?.invoke(response)
}
} catch (e: Exception) {
e.message?.let { onFail?.invoke(it) }
}
}
eventually?.invoke()
}

@ -7,7 +7,7 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/parser"
)
// KtCommand the generate kotlin code command entrance
// KtCommand generates kotlin code command entrance
func KtCommand(c *cli.Context) error {
apiFile := c.String("api")
if apiFile == "" {

@ -1,6 +1,7 @@
package ktgen
import (
_ "embed"
"fmt"
"os"
"path/filepath"
@ -10,91 +11,11 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/api/spec"
)
const (
apiBaseTemplate = `package {{.}}
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
const val SERVER = "http://localhost:8080"
suspend fun apiRequest(
method: String,
uri: String,
body: Any = "",
onOk: ((String) -> Unit)? = null,
onFail: ((String) -> Unit)? = null,
eventually: (() -> Unit)? = null
) = withContext(Dispatchers.IO) {
val url = URL(SERVER + uri)
with(url.openConnection() as HttpURLConnection) {
connectTimeout = 3000
requestMethod = method
doInput = true
if (method == "POST" || method == "PUT" || method == "PATCH") {
setRequestProperty("Content-Type", "application/json")
doOutput = true
val data = when (body) {
is String -> {
body
}
else -> {
Gson().toJson(body)
}
}
val wr = OutputStreamWriter(outputStream)
wr.write(data)
wr.flush()
}
try {
if (responseCode >= 400) {
BufferedReader(InputStreamReader(errorStream)).use {
val response = it.readText()
onFail?.invoke(response)
}
return@with
}
//response
BufferedReader(InputStreamReader(inputStream)).use {
val response = it.readText()
onOk?.invoke(response)
}
} catch (e: Exception) {
e.message?.let { onFail?.invoke(it) }
}
}
eventually?.invoke()
}
`
apiTemplate = `package {{with .Info}}{{.Desc}}{{end}}
import com.google.gson.Gson
object {{with .Info}}{{.Title}}{{end}}{
{{range .Types}}
data class {{.Name}}({{$length := (len .Members)}}{{range $i,$item := .Members}}
val {{with $item}}{{lowCamelCase .Name}}: {{parseType .Type.Name}}{{end}}{{if ne $i (add $length -1)}},{{end}}{{end}}
){{end}}
{{with .Service}}
{{range .Routes}}suspend fun {{routeToFuncName .Method .Path}}({{with .RequestType}}{{if ne .Name ""}}
req:{{.Name}},{{end}}{{end}}
onOk: (({{with .ResponseType}}{{.Name}}{{end}}) -> Unit)? = null,
onFail: ((String) -> Unit)? = null,
eventually: (() -> Unit)? = null
){
apiRequest("{{upperCase .Method}}","{{.Path}}",{{with .RequestType}}{{if ne .Name ""}}body=req,{{end}}{{end}} onOk = { {{with .ResponseType}}
onOk?.invoke({{if ne .Name ""}}Gson().fromJson(it,{{.Name}}::class.java){{end}}){{end}}
}, onFail = onFail, eventually =eventually)
}
{{end}}{{end}}
}`
var (
//go:embed apibase.tpl
apiBaseTemplate string
//go:embed api.tpl
apiTemplate string
)
func genBase(dir, pkg string, api *spec.ApiSpec) error {

@ -0,0 +1,12 @@
type Request {
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
}
type Response {
Message string ` + "`" + `json:"message"` + "`" + `
}
service {{.name}}-api {
@handler {{.handler}}Handler
get /from/:name(Request) returns (Response)
}

@ -1,11 +1,12 @@
package new
import (
_ "embed"
"errors"
"html/template"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/urfave/cli"
"github.com/zeromicro/go-zero/tools/goctl/api/gogen"
@ -14,20 +15,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const apiTemplate = `
type Request {
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
}
type Response {
Message string ` + "`" + `json:"message"` + "`" + `
}
service {{.name}}-api {
@handler {{.handler}}Handler
get /from/:name(Request) returns (Response)
}
`
//go:embed api.tpl
var apiTemplate string
// CreateServiceCommand fast create service
func CreateServiceCommand(c *cli.Context) error {

@ -0,0 +1,3 @@
/ Code generated by goctl. DO NOT EDIT.
{{.componentTypes}}

@ -1,6 +1,7 @@
package tsgen
import (
_ "embed"
"path"
"strings"
"text/template"
@ -10,12 +11,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const (
componentsTemplate = `// Code generated by goctl. DO NOT EDIT.
{{.componentTypes}}
`
)
//go:embed components.tpl
var componentsTemplate string
func genComponents(dir string, api *spec.ApiSpec) error {
types := api.Types

@ -1,6 +1,7 @@
package tsgen
import (
_ "embed"
"fmt"
"path"
"strings"
@ -12,12 +13,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const (
handlerTemplate = `{{.imports}}
{{.apis}}
`
)
//go:embed handler.tpl
var handlerTemplate string
func genHandler(dir, webAPI, caller string, api *spec.ApiSpec, unwrapAPI bool) error {
filename := strings.Replace(api.Service.Name, "-api", "", 1) + ".ts"

@ -0,0 +1,3 @@
{{.imports}}
{{.apis}}

@ -0,0 +1,32 @@
FROM golang:{{.Version}}alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
{{if .Chinese}}ENV GOPROXY https://goproxy.cn,direct
{{end}}{{if .HasTimezone}}
RUN apk update --no-cache && apk add --no-cache tzdata
{{end}}
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
{{if .Argument}}COPY {{.GoRelPath}}/etc /app/etc
{{end}}RUN go build -ldflags="-s -w" -o /app/{{.ExeFile}} {{.GoRelPath}}/{{.GoFile}}
FROM {{.BaseImage}}
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
{{if .HasTimezone}}COPY --from=builder /usr/share/zoneinfo/{{.Timezone}} /usr/share/zoneinfo/{{.Timezone}}
ENV TZ {{.Timezone}}
{{end}}
WORKDIR /app
COPY --from=builder /app/{{.ExeFile}} /app/{{.ExeFile}}{{if .Argument}}
COPY --from=builder /app/etc /app/etc{{end}}
{{if .HasPort}}
EXPOSE {{.Port}}
{{end}}
CMD ["./{{.ExeFile}}"{{.Argument}}]

@ -1,6 +1,8 @@
package docker
import (
_ "embed"
"github.com/urfave/cli"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
@ -8,41 +10,11 @@ import (
const (
category = "docker"
dockerTemplateFile = "docker.tpl"
dockerTemplate = `FROM golang:{{.Version}}alpine AS builder
LABEL stage=gobuilder
ENV CGO_ENABLED 0
{{if .Chinese}}ENV GOPROXY https://goproxy.cn,direct
{{end}}{{if .HasTimezone}}
RUN apk update --no-cache && apk add --no-cache tzdata
{{end}}
WORKDIR /build
ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
{{if .Argument}}COPY {{.GoRelPath}}/etc /app/etc
{{end}}RUN go build -ldflags="-s -w" -o /app/{{.ExeFile}} {{.GoRelPath}}/{{.GoFile}}
FROM {{.BaseImage}}
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
{{if .HasTimezone}}COPY --from=builder /usr/share/zoneinfo/{{.Timezone}} /usr/share/zoneinfo/{{.Timezone}}
ENV TZ {{.Timezone}}
{{end}}
WORKDIR /app
COPY --from=builder /app/{{.ExeFile}} /app/{{.ExeFile}}{{if .Argument}}
COPY --from=builder /app/etc /app/etc{{end}}
{{if .HasPort}}
EXPOSE {{.Port}}
{{end}}
CMD ["./{{.ExeFile}}"{{.Argument}}]
`
)
//go:embed docker.tpl
var dockerTemplate string
// Clean deletes all templates files
func Clean() error {
return pathx.Clean(category)

@ -6,7 +6,7 @@ import (
)
// BuildVersion is the version of goctl.
const BuildVersion = "1.3.4"
const BuildVersion = "1.3.5"
var tag = map[string]int{"pre-alpha": 0, "alpha": 1, "pre-bata": 2, "beta": 3, "released": 4, "": 5}

@ -1,6 +1,4 @@
package kube
var deploymentTemplate = `apiVersion: apps/v1
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Name}}
@ -115,4 +113,3 @@ spec:
resource:
name: memory
targetAverageUtilization: 80
`

@ -1,6 +1,4 @@
package kube
var jobTmeplate = `apiVersion: batch/v1
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{.Name}}
@ -37,4 +35,3 @@ spec:
- name: timezone
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
`

@ -1,6 +1,7 @@
package kube
import (
_ "embed"
"errors"
"fmt"
"text/template"
@ -19,6 +20,13 @@ const (
portLimit = 32767
)
var (
//go:embed deployment.tpl
deploymentTemplate string
//go:embed job.tpl
jobTemplate string
)
// Deployment describes the k8s deployment yaml
type Deployment struct {
Name string
@ -113,7 +121,7 @@ func Clean() error {
func GenTemplates(_ *cli.Context) error {
return pathx.InitTemplates(category, map[string]string{
deployTemplateFile: deploymentTemplate,
jobTemplateFile: jobTmeplate,
jobTemplateFile: jobTemplate,
})
}
@ -131,6 +139,6 @@ func Update() error {
return pathx.InitTemplates(category, map[string]string{
deployTemplateFile: deploymentTemplate,
jobTemplateFile: jobTmeplate,
jobTemplateFile: jobTemplate,
})
}

@ -0,0 +1,6 @@
package model
import "errors"
var ErrNotFound = errors.New("not found")
var ErrInvalidObjectId = errors.New("invalid objectId")

@ -0,0 +1,98 @@
package model
import (
"context"
"github.com/globalsign/mgo/bson"
{{if .Cache}}cachec "github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mongoc"{{else}}"github.com/zeromicro/go-zero/core/stores/mongo"{{end}}
)
{{if .Cache}}var prefix{{.Type}}CacheKey = "cache:{{.Type}}:"{{end}}
type {{.Type}}Model interface{
Insert(ctx context.Context,data *{{.Type}}) error
FindOne(ctx context.Context,id string) (*{{.Type}}, error)
Update(ctx context.Context,data *{{.Type}}) error
Delete(ctx context.Context,id string) error
}
type default{{.Type}}Model struct {
{{if .Cache}}*mongoc.Model{{else}}*mongo.Model{{end}}
}
func New{{.Type}}Model(url, collection string{{if .Cache}}, c cachec.CacheConf{{end}}) {{.Type}}Model {
return &default{{.Type}}Model{
Model: {{if .Cache}}mongoc.MustNewModel(url, collection, c){{else}}mongo.MustNewModel(url, collection){{end}},
}
}
func (m *default{{.Type}}Model) Insert(ctx context.Context, data *{{.Type}}) error {
if !data.ID.Valid() {
data.ID = bson.NewObjectId()
}
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
return m.GetCollection(session).Insert(data)
}
func (m *default{{.Type}}Model) FindOne(ctx context.Context, id string) (*{{.Type}}, error) {
if !bson.IsObjectIdHex(id) {
return nil, ErrInvalidObjectId
}
session, err := m.TakeSession()
if err != nil {
return nil, err
}
defer m.PutSession(session)
var data {{.Type}}
{{if .Cache}}key := prefix{{.Type}}CacheKey + id
err = m.GetCollection(session).FindOneId(&data, key, bson.ObjectIdHex(id))
{{- else}}
err = m.GetCollection(session).FindId(bson.ObjectIdHex(id)).One(&data)
{{- end}}
switch err {
case nil:
return &data,nil
case {{if .Cache}}mongoc.ErrNotFound{{else}}mongo.ErrNotFound{{end}}:
return nil,ErrNotFound
default:
return nil,err
}
}
func (m *default{{.Type}}Model) Update(ctx context.Context, data *{{.Type}}) error {
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
{{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex()
return m.GetCollection(session).UpdateId(data.ID, data, key)
{{- else}}
return m.GetCollection(session).UpdateId(data.ID, data)
{{- end}}
}
func (m *default{{.Type}}Model) Delete(ctx context.Context, id string) error {
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
{{if .Cache}}key := prefix{{.Type}}CacheKey + id
return m.GetCollection(session).RemoveId(bson.ObjectIdHex(id), key)
{{- else}}
return m.GetCollection(session).RemoveId(bson.ObjectIdHex(id))
{{- end}}
}

@ -1,112 +1,11 @@
package template
// Text provides the default template for model to generate
var Text = `package model
import _ "embed"
import (
"context"
"github.com/globalsign/mgo/bson"
{{if .Cache}}cachec "github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mongoc"{{else}}"github.com/zeromicro/go-zero/core/stores/mongo"{{end}}
)
{{if .Cache}}var prefix{{.Type}}CacheKey = "cache:{{.Type}}:"{{end}}
type {{.Type}}Model interface{
Insert(ctx context.Context,data *{{.Type}}) error
FindOne(ctx context.Context,id string) (*{{.Type}}, error)
Update(ctx context.Context,data *{{.Type}}) error
Delete(ctx context.Context,id string) error
}
type default{{.Type}}Model struct {
{{if .Cache}}*mongoc.Model{{else}}*mongo.Model{{end}}
}
func New{{.Type}}Model(url, collection string{{if .Cache}}, c cachec.CacheConf{{end}}) {{.Type}}Model {
return &default{{.Type}}Model{
Model: {{if .Cache}}mongoc.MustNewModel(url, collection, c){{else}}mongo.MustNewModel(url, collection){{end}},
}
}
func (m *default{{.Type}}Model) Insert(ctx context.Context, data *{{.Type}}) error {
if !data.ID.Valid() {
data.ID = bson.NewObjectId()
}
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
return m.GetCollection(session).Insert(data)
}
func (m *default{{.Type}}Model) FindOne(ctx context.Context, id string) (*{{.Type}}, error) {
if !bson.IsObjectIdHex(id) {
return nil, ErrInvalidObjectId
}
session, err := m.TakeSession()
if err != nil {
return nil, err
}
defer m.PutSession(session)
var data {{.Type}}
{{if .Cache}}key := prefix{{.Type}}CacheKey + id
err = m.GetCollection(session).FindOneId(&data, key, bson.ObjectIdHex(id))
{{- else}}
err = m.GetCollection(session).FindId(bson.ObjectIdHex(id)).One(&data)
{{- end}}
switch err {
case nil:
return &data,nil
case {{if .Cache}}mongoc.ErrNotFound{{else}}mongo.ErrNotFound{{end}}:
return nil,ErrNotFound
default:
return nil,err
}
}
func (m *default{{.Type}}Model) Update(ctx context.Context, data *{{.Type}}) error {
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
{{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex()
return m.GetCollection(session).UpdateId(data.ID, data, key)
{{- else}}
return m.GetCollection(session).UpdateId(data.ID, data)
{{- end}}
}
func (m *default{{.Type}}Model) Delete(ctx context.Context, id string) error {
session, err := m.TakeSession()
if err != nil {
return err
}
defer m.PutSession(session)
{{if .Cache}}key := prefix{{.Type}}CacheKey + id
return m.GetCollection(session).RemoveId(bson.ObjectIdHex(id), key)
{{- else}}
return m.GetCollection(session).RemoveId(bson.ObjectIdHex(id))
{{- end}}
}
`
// Text provides the default template for model to generate.
//go:embed model.tpl
var Text string
// Error provides the default template for error definition in mongo code generation.
var Error = `
package model
import "errors"
var ErrNotFound = errors.New("not found")
var ErrInvalidObjectId = errors.New("invalid objectId")
`
//go:embed error.tpl
var Error string

@ -0,0 +1,33 @@
{{.head}}
package {{.filePackage}}
import (
"context"
{{.pbPackage}}
{{if ne .pbPackage .protoGoPackage}}{{.protoGoPackage}}{{end}}
"github.com/zeromicro/go-zero/zrpc"
"google.golang.org/grpc"
)
type (
{{.alias}}
{{.serviceName}} interface {
{{.interface}}
}
default{{.serviceName}} struct {
cli zrpc.Client
}
)
func New{{.serviceName}}(cli zrpc.Client) {{.serviceName}} {
return &default{{.serviceName}}{
cli: cli,
}
}
{{.functions}}

@ -0,0 +1,7 @@
package config
import "github.com/zeromicro/go-zero/zrpc"
type Config struct {
zrpc.RpcServerConf
}

@ -0,0 +1,6 @@
Name: {{.serviceName}}.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: {{.serviceName}}.rpc

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
"sort"
@ -17,41 +18,6 @@ import (
)
const (
callTemplateText = `{{.head}}
package {{.filePackage}}
import (
"context"
{{.pbPackage}}
{{if ne .pbPackage .protoGoPackage}}{{.protoGoPackage}}{{end}}
"github.com/zeromicro/go-zero/zrpc"
"google.golang.org/grpc"
)
type (
{{.alias}}
{{.serviceName}} interface {
{{.interface}}
}
default{{.serviceName}} struct {
cli zrpc.Client
}
)
func New{{.serviceName}}(cli zrpc.Client) {{.serviceName}} {
return &default{{.serviceName}}{
cli: cli,
}
}
{{.functions}}
`
callInterfaceFunctionTemplate = `{{if .hasComment}}{{.comment}}
{{end}}{{.method}}(ctx context.Context{{if .hasReq}}, in *{{.pbRequest}}{{end}}, opts ...grpc.CallOption) ({{if .notStream}}*{{.pbResponse}}, {{else}}{{.streamBody}},{{end}} error)`
@ -64,6 +30,9 @@ func (m *default{{.serviceName}}) {{.method}}(ctx context.Context{{if .hasReq}},
`
)
//go:embed call.tpl
var callTemplateText string
// GenCall generates the rpc client code, which is the entry point for the rpc service call.
// It is a layer of encapsulation for the rpc client and shields the details in the pb.
func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"io/ioutil"
"os"
"path/filepath"
@ -11,14 +12,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const configTemplate = `package config
import "github.com/zeromicro/go-zero/zrpc"
type Config struct {
zrpc.RpcServerConf
}
`
//go:embed config.tpl
var configTemplate string
// GenConfig generates the configuration structure definition file of the rpc service,
// which contains the zrpc.RpcServerConf configuration item by default.

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
"strings"
@ -13,13 +14,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
const etcTemplate = `Name: {{.serviceName}}.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: {{.serviceName}}.rpc
`
//go:embed etc.tpl
var etcTemplate string
// GenEtc generates the yaml configuration file of the rpc service,
// including host, port monitoring configuration items and etcd configuration

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
"strings"
@ -14,40 +15,16 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
const (
logicTemplate = `package logic
import (
"context"
{{.imports}}
"github.com/zeromicro/go-zero/core/logx"
)
type {{.logicName}} struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
return &{{.logicName}}{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
{{.functions}}
`
logicFunctionTemplate = `{{if .hasComment}}{{.comment}}{{end}}
const logicFunctionTemplate = `{{if .hasComment}}{{.comment}}{{end}}
func (l *{{.logicName}}) {{.method}} ({{if .hasReq}}in {{.request}}{{if .stream}},stream {{.streamBody}}{{end}}{{else}}stream {{.streamBody}}{{end}}) ({{if .hasReply}}{{.response}},{{end}} error) {
// todo: add your logic here and delete this line
return {{if .hasReply}}&{{.responseType}}{},{{end}} nil
}
`
)
//go:embed logic.tpl
var logicTemplate string
// GenLogic generates the logic file of the rpc service, which corresponds to the RPC definition items in proto.
func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
"strings"
@ -13,44 +14,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
const mainTemplate = `package main
import (
"flag"
"fmt"
{{.imports}}
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/core/service"
"github.com/zeromicro/go-zero/zrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
svr := server.New{{.serviceNew}}Server(ctx)
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
{{.pkg}}.Register{{.service}}Server(grpcServer, svr)
if c.Mode == service.DevMode || c.Mode == service.TestMode {
reflection.Register(grpcServer)
}
})
defer s.Stop()
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
s.Start()
}
`
//go:embed main.tpl
var mainTemplate string
// GenMain generates the main file of the rpc service, which is an rpc service program call entry
func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
"strings"
@ -14,38 +15,16 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
const (
serverTemplate = `{{.head}}
package server
import (
{{if .notStream}}"context"{{end}}
{{.imports}}
)
type {{.server}}Server struct {
svcCtx *svc.ServiceContext
{{.unimplementedServer}}
}
func New{{.server}}Server(svcCtx *svc.ServiceContext) *{{.server}}Server {
return &{{.server}}Server{
svcCtx: svcCtx,
}
}
{{.funcs}}
`
functionTemplate = `
const functionTemplate = `
{{if .hasComment}}{{.comment}}{{end}}
func (s *{{.server}}Server) {{.method}} ({{if .notStream}}ctx context.Context,{{if .hasReq}} in {{.request}}{{end}}{{else}}{{if .hasReq}} in {{.request}},{{end}}stream {{.streamBody}}{{end}}) ({{if .notStream}}{{.response}},{{end}}error) {
l := logic.New{{.logicName}}({{if .notStream}}ctx,{{else}}stream.Context(),{{end}}s.svcCtx)
return l.{{.method}}({{if .hasReq}}in{{if .stream}} ,stream{{end}}{{else}}{{if .stream}}stream{{end}}{{end}})
}
`
)
//go:embed server.tpl
var serverTemplate string
// GenServer generates rpc server file, which is an implementation of rpc server
func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"fmt"
"path/filepath"
@ -11,20 +12,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
const svcTemplate = `package svc
import {{.imports}}
type ServiceContext struct {
Config config.Config
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config:c,
}
}
`
//go:embed svc.tpl
var svcTemplate string
// GenSvc generates the servicecontext.go file, which is the resource dependency of a service,
// such as rpc dependency, model dependency, etc.

@ -0,0 +1,24 @@
package logic
import (
"context"
{{.imports}}
"github.com/zeromicro/go-zero/core/logx"
)
type {{.logicName}} struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
return &{{.logicName}}{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
{{.functions}}

@ -0,0 +1,37 @@
package main
import (
"flag"
"fmt"
{{.imports}}
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/core/service"
"github.com/zeromicro/go-zero/zrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
svr := server.New{{.serviceNew}}Server(ctx)
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
{{.pkg}}.Register{{.service}}Server(grpcServer, svr)
if c.Mode == service.DevMode || c.Mode == service.TestMode {
reflection.Register(grpcServer)
}
})
defer s.Stop()
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
s.Start()
}

@ -1,6 +1,7 @@
package generator
import (
_ "embed"
"path/filepath"
"strings"
@ -9,23 +10,8 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
const rpcTemplateText = `syntax = "proto3";
package {{.package}};
option go_package="./{{.package}}";
message Request {
string ping = 1;
}
message Response {
string pong = 1;
}
service {{.serviceName}} {
rpc Ping(Request) returns(Response);
}
`
//go:embed rpc.tpl
var rpcTemplateText string
// ProtoTmpl returns a sample of a proto file
func ProtoTmpl(out string) error {

@ -0,0 +1,16 @@
syntax = "proto3";
package {{.package}};
option go_package="./{{.package}}";
message Request {
string ping = 1;
}
message Response {
string pong = 1;
}
service {{.serviceName}} {
rpc Ping(Request) returns(Response);
}

@ -0,0 +1,22 @@
{{.head}}
package server
import (
{{if .notStream}}"context"{{end}}
{{.imports}}
)
type {{.server}}Server struct {
svcCtx *svc.ServiceContext
{{.unimplementedServer}}
}
func New{{.server}}Server(svcCtx *svc.ServiceContext) *{{.server}}Server {
return &{{.server}}Server{
svcCtx: svcCtx,
}
}
{{.funcs}}

@ -0,0 +1,13 @@
package svc
import {{.imports}}
type ServiceContext struct {
Config config.Config
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config:c,
}
}
Loading…
Cancel
Save