Skip to content

Commit

Permalink
project & rbac wip commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cho4036 committed Jan 23, 2024
1 parent 36529ff commit 70be88c
Show file tree
Hide file tree
Showing 21 changed files with 1,685 additions and 34 deletions.
2 changes: 1 addition & 1 deletion api/swagger/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const docTemplate = `{
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"basePath": "{{.Path}}",
"paths": {
"/app-groups": {
"get": {
Expand Down
2 changes: 1 addition & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func init() {
// @name Authorization

// @host tks-api-ft.taco-cat.xyz
// @BasePath /api/1.0/
// @Path /api/1.0/
func main() {
log.Info("*** Arguments *** ")
for i, s := range viper.AllSettings() {
Expand Down
356 changes: 356 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions hack/ast-generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

import (
"go/ast"
"go/parser"
"go/token"
"log"
"os"
)

func main() {
fset := token.NewFileSet()

node, err := parser.ParseFile(fset, "./internal/delivery/api/endpoint.go", nil, parser.ParseComments)
if err != nil {
log.Fatalf("파싱 오류: %v", err)
}

ast.Print(fset, node)

// write ast to file
f, err := os.Create("ast.txt")
if err != nil {
log.Fatalf("파일 생성 오류: %v", err)
}
defer f.Close()
ast.Fprint(f, fset, node, nil)

}
199 changes: 199 additions & 0 deletions hack/endpoint-codegen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package main

import (
"bytes"
"go/ast"
"go/parser"
"go/token"
"html/template"
"io/ioutil"
"log"
"strings"
)

const endpointFilePath = "./internal/delivery/api/endpoint.go"

// endpointDecl은 엔드포인트 선언을 나타냅니다.
type endpointDecl struct {
Name string // 엔드포인트의 이름
Group string // 엔드포인트의 그룹
}

const indexTemplateStr = ` //
package api
type Endpoint int
type EndpointInfo struct {
Name string
Group string
}
`
const endpointTemplateStr = `// Comment below is special purpose for code generation.
// Do not edit this comment.
// Endpoint for Code Generation
const (
{{- range .}}
{{.Name}} Endpoint = iota
{{- end}}
)
`

const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{
{{- range .}}
{{.Name}}: {
Name: "{{.Name}}",
Group: "{{.Group}}",
},
{{- end}}
}
`

const stringFunctionTemplateStr = `func (e Endpoint) String() string {
switch e {
{{- range .}}
case {{.Name}}:
return "{{.Name}}"
{{- end}}
default:
return ""
}
}
`

const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint {
switch name {
{{- range .}}
case "{{.Name}}":
return {{.Name}}
{{- end}}
default:
return -1
}
}
`

func main() {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, endpointFilePath, nil, parser.ParseComments)
if err != nil {
log.Fatalf("failed to parse file: %v", err)
}

var endpoints []endpointDecl
var currentGroup string

// AST를 탐색합니다.
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.GenDecl:
if x.Tok == token.CONST {
if x.Doc != nil {
for _, comment := range x.Doc.List {
// "Endpoint" 주석 이후에 나오는 주석을 그룹 이름으로 사용합니다.
if strings.Contains(comment.Text, "Endpoint for Code Generation") {
continue
}
if strings.HasPrefix(comment.Text, "//") {
currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//"))
}
}
}
for _, spec := range x.Specs {
vs, ok := spec.(*ast.ValueSpec)
if !ok {
continue
}
if vs.Doc != nil {
for _, comment := range vs.Doc.List {
if strings.HasPrefix(comment.Text, "//") {
currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//"))
}
}
}

for _, name := range vs.Names {
endpoints = append(endpoints, endpointDecl{
Name: name.Name,
Group: currentGroup,
})
}
}
}
}
return true
})

// 추출된 엔드포인트 정보를 출력합니다.
for _, ep := range endpoints {
log.Printf("Endpoint: %s, Group: %s\n", ep.Name, ep.Group)
}

// TODO: 추출된 정보를 바탕으로 ApiMap, String() 메서드, GetEndpoint() 함수 코드를 생성합니다.

// contents for index
indexTemplate := template.New("index")
indexTemplate, err = indexTemplate.Parse(indexTemplateStr)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
var indexCode bytes.Buffer
if err := indexTemplate.Execute(&indexCode, endpoints); err != nil {
log.Fatalf("failed to execute template: %v", err)
}

// contents for endpoint
endpointTemplate := template.New("endpoint")
endpointTemplate, err = endpointTemplate.Parse(endpointTemplateStr)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
var endpointCode bytes.Buffer
if err := endpointTemplate.Execute(&endpointCode, endpoints); err != nil {
log.Fatalf("failed to execute template: %v", err)
}

// contents for apiMap
apiMapTemplate := template.New("apiMap")
apiMapTemplate, err = apiMapTemplate.Parse(apiMapTemplateStr)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
var apiMapCode bytes.Buffer
if err := apiMapTemplate.Execute(&apiMapCode, endpoints); err != nil {
log.Fatalf("failed to execute template: %v", err)
}

// contents for stringFunction
stringFunctionTemplate := template.New("stringFunction")
stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
var stringFunctionCode bytes.Buffer
if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil {
log.Fatalf("failed to execute template: %v", err)
}

// contents for getEndpointFunction
getEndpointFunctionTemplate := template.New("getEndpointFunction")
getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
var getEndpointFunctionCode bytes.Buffer
if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil {
log.Fatalf("failed to execute template: %v", err)
}

// replace original file(endpointFilePath) with new contents
contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String()
newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1)

if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil {
log.Fatalf("failed to write file: %v", err)
}

log.Println("Code generation is done.")
}
51 changes: 51 additions & 0 deletions internal/delivery/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package api

//
//import (
// "github.com/gorilla/mux"
// "net/http"
//)
//
//type IApi interface {
// //SetPath()
// API() Api
// //SetMethod()
// //GetMethod() string
// //SetHandler()
// //GetHandler() http.Handler
// //
// //RegisterApi(router *mux.Router)
//}
//type Api struct {
// Path string
// Method string
// Handler http.Handler
//}
//
//func (a Api) GetPath() string {
// return a.Path
//}
//
//func (a Api) GetMethod() string {
// return a.Method
//}
//
//func (a Api) GetHandler() http.Handler {
// return a.Handler
//}
//
//func (a Api) SetBasePath(path string) {
// a.Path = path
//}
//
//func (a Api) SetMethod(method string) {
// a.Method = method
//}
//
//func (a Api) SetHandler(handler http.Handler) {
// a.Handler = handler
//}
//
//func (a Api) RegisterApi(router *mux.Router) {
// router.Handle(a.GetPath(), a.GetHandler())
//}
Loading

0 comments on commit 70be88c

Please sign in to comment.