update proto generation from DSL

This commit is contained in:
2025-09-01 15:57:22 -06:00
parent ca0736b92c
commit c6f14e1787
4 changed files with 308 additions and 64 deletions

View File

@ -128,12 +128,40 @@ func (ti *TemplateInterpreter) Interpret(masonryInput string, tmplText string) (
} }
return 8080 return 8080
}, },
"getServerHostPort": func(settings []lang.ServerSetting) string {
host := "localhost"
port := 8080
for _, s := range settings {
if s.Host != nil {
host = *s.Host
}
if s.Port != nil {
port = *s.Port
}
}
return fmt.Sprintf("%s:%d", host, port)
},
"slice": func() []interface{} { "slice": func() []interface{} {
return []interface{}{} return []interface{}{}
}, },
"append": func(slice []interface{}, item interface{}) []interface{} { "append": func(slice []interface{}, item interface{}) []interface{} {
return append(slice, item) return append(slice, item)
}, },
"add": func(a, b int) int {
return a + b
},
"derefString": func(s *string) string {
if s != nil {
return *s
}
return ""
},
"derefInt": func(i *int) int {
if i != nil {
return *i
}
return 0
},
}).Parse(tmplText)) }).Parse(tmplText))
data := struct { data := struct {
@ -219,12 +247,40 @@ func NewTemplateRegistry() *TemplateRegistry {
} }
return 8080 return 8080
}, },
"getServerHostPort": func(settings []lang.ServerSetting) string {
host := "localhost"
port := 8080
for _, s := range settings {
if s.Host != nil {
host = *s.Host
}
if s.Port != nil {
port = *s.Port
}
}
return fmt.Sprintf("%s:%d", host, port)
},
"slice": func() []interface{} { "slice": func() []interface{} {
return []interface{}{} return []interface{}{}
}, },
"append": func(slice []interface{}, item interface{}) []interface{} { "append": func(slice []interface{}, item interface{}) []interface{} {
return append(slice, item) return append(slice, item)
}, },
"add": func(a, b int) int {
return a + b
},
"derefString": func(s *string) string {
if s != nil {
return *s
}
return ""
},
"derefInt": func(i *int) int {
if i != nil {
return *i
}
return 0
},
} }
return tr return tr
} }

View File

@ -1,105 +1,287 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by Masonry DSL CLI tool. DO NOT EDIT.
syntax = "proto3"; syntax = "proto3";
package {{ .AppName }}; {{- $serverName := "MyService" }}
{{- $serverHost := "localhost:8080" }}
{{- range .AST.Definitions }}
{{- if .Server }}
{{- $serverName = .Server.Name }}
{{- $serverHost = getServerHostPort .Server.Settings }}
{{- end }}
{{- end }}
package {{ $serverName | title }};
import "gorm/options/gorm.proto"; import "gorm/options/gorm.proto";
//import "gorm/types/types.proto"; import "gorm/types/types.proto";
import "google/api/annotations.proto"; import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
option go_package = "./;pb"; option go_package = "./;pb";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: { info: {
title: "Your API Title" title: "{{ $serverName | title }} API"
version: "v1.0" version: "v1.0"
description: "Your API description" description: "Generated API for {{ $serverName }}"
} }
host: "localhost:8080" // Set the server host host: "{{ $serverHost }}"
}; };
service {{ .AppNameCaps }} { service {{ $serverName | title }}Service {
option (gorm.server).autogen = true; option (gorm.server).autogen = true;
// Add your service methods here
rpc CreateProduct (CreateProductRequest) returns (CreateProductResponse) { {{- range .AST.Definitions }}
{{- if .Entity }}
{{- $entityName := .Entity.Name }}
// CRUD operations for {{ $entityName }}
rpc Create{{ $entityName }} (Create{{ $entityName }}Request) returns (Create{{ $entityName }}Response) {
option (google.api.http) = { option (google.api.http) = {
post: "/v1/Product" post: "/v1/{{ $entityName | title }}"
body: "*" body: "*"
}; };
} }
rpc ReadProduct (ReadProductRequest) returns (ReadProductResponse) { rpc Read{{ $entityName }} (Read{{ $entityName }}Request) returns (Read{{ $entityName }}Response) {
option (google.api.http) = { option (google.api.http) = {
get: "/v1/Product/{id}" get: "/v1/{{ $entityName | title }}/{id}"
}; };
} }
rpc ListProducts (ListProductsRequest) returns (ListProductsResponse) { rpc List{{ $entityName }}s (List{{ $entityName }}sRequest) returns (List{{ $entityName }}sResponse) {
option (google.api.http) = { option (google.api.http) = {
get: "/v1/Product" get: "/v1/{{ $entityName | title }}"
}; };
} }
rpc UpdateProduct (UpdateProductRequest) returns (UpdateProductResponse) { rpc Update{{ $entityName }} (Update{{ $entityName }}Request) returns (Update{{ $entityName }}Response) {
option (google.api.http) = { option (google.api.http) = {
put: "/v1/Product" put: "/v1/{{ $entityName | title }}"
body: "*" body: "*"
}; };
} }
rpc DeleteProduct (DeleteProductRequest) returns (DeleteProductResponse) { rpc Delete{{ $entityName }} (Delete{{ $entityName }}Request) returns (Delete{{ $entityName }}Response) {
option (gorm.method).object_type = "Product"; option (gorm.method).object_type = "{{ $entityName }}";
option (google.api.http) = { option (google.api.http) = {
delete: "/v1/Product/{id}" delete: "/v1/{{ $entityName | title }}/{id}"
}; };
} }
{{- end }}
{{- end }}
{{- range .AST.Definitions }}
{{- if .Endpoint }}
{{- $method := .Endpoint.Method }}
{{- $path := .Endpoint.Path }}
{{- $entity := .Endpoint.Entity }}
{{- $handlerName := pathToHandlerName $path }}
// Custom endpoint: {{ $method }} {{ $path }}
rpc {{ $handlerName }}{{ $method }} ({{ $handlerName }}{{ $method }}Request) returns ({{ $handlerName }}{{ $method }}Response) {
option (google.api.http) = {
{{- if eq $method "GET" }}
get: "{{ $path }}"
{{- else if eq $method "POST" }}
post: "{{ $path }}"
body: "*"
{{- else if eq $method "PUT" }}
put: "{{ $path }}"
body: "*"
{{- else if eq $method "PATCH" }}
patch: "{{ $path }}"
body: "*"
{{- else if eq $method "DELETE" }}
delete: "{{ $path }}"
{{- end }}
};
}
{{- end }}
{{- end }}
} }
message Create{{ .ObjName }}Request { {{- range .AST.Definitions }}
{{ .ObjName }} payload = 1; {{- if .Entity }}
{{- $entityName := .Entity.Name }}
// CRUD Request/Response messages for {{ $entityName }}
message Create{{ $entityName }}Request {
{{ $entityName }} payload = 1;
} }
message Create{{ .ObjName }}Response { message Create{{ $entityName }}Response {
{{ .ObjName }} result = 1; {{ $entityName }} result = 1;
} }
message Read{{ .ObjName }}Request { message Read{{ $entityName }}Request {
uint64 id = 1; {{- $idField := "" }}
{{- $idType := "uint64" }}
{{- range .Entity.Fields }}
{{- if eq .Name "id" }}
{{- $idField = .Name }}
{{- if eq .Type "uuid" }}
{{- $idType = "string" }}
{{- else if eq .Type "string" }}
{{- $idType = "string" }}
{{- else }}
{{- $idType = "uint64" }}
{{- end }}
{{- end }}
{{- end }}
{{ $idType }} id = 1;
} }
message Read{{ .ObjName }}Response { message Read{{ $entityName }}Response {
{{ .ObjName }} result = 1; {{ $entityName }} result = 1;
} }
message List{{ .ObjName }}sRequest {} message List{{ $entityName }}sRequest {
int32 page_size = 1;
message List{{ .ObjName }}sResponse { string page_token = 2;
repeated {{ .ObjName }} results = 1;
} }
message Update{{ .ObjName }}Request { message List{{ $entityName }}sResponse {
{{ .ObjName }} payload = 1; repeated {{ $entityName }} results = 1;
string next_page_token = 2;
} }
message Update{{ .ObjName }}Response { message Update{{ $entityName }}Request {
{{ .ObjName }} result = 1; {{ $entityName }} payload = 1;
} }
message Delete{{ .ObjName }}Request { message Update{{ $entityName }}Response {
uint64 id = 1; {{ $entityName }} result = 1;
} }
message Delete{{ .ObjName }}Response {} message Delete{{ $entityName }}Request {
{{- $idType := "uint64" }}
{{- range .Entity.Fields }}
{{- if eq .Name "id" }}
{{- if eq .Type "uuid" }}
{{- $idType = "string" }}
{{- else if eq .Type "string" }}
{{- $idType = "string" }}
{{- else }}
{{- $idType = "uint64" }}
{{- end }}
{{- end }}
{{- end }}
{{ $idType }} id = 1;
}
message {{ .ObjName }} { message Delete{{ $entityName }}Response {}
{{- end }}
{{- end }}
{{- range .AST.Definitions }}
{{- if .Endpoint }}
{{- $method := .Endpoint.Method }}
{{- $path := .Endpoint.Path }}
{{- $handlerName := pathToHandlerName $path }}
// Custom endpoint messages for {{ $method }} {{ $path }}
message {{ $handlerName }}{{ $method }}Request {
{{- if .Endpoint.Params }}
{{- $fieldNum := 1 }}
{{- range .Endpoint.Params }}
{{ goType .Type }} {{ .Name }} = {{ $fieldNum }};
{{- $fieldNum = add $fieldNum 1 }}
{{- end }}
{{- end }}
}
message {{ $handlerName }}{{ $method }}Response {
{{- if .Endpoint.Response }}
{{- if eq .Endpoint.Response.Type "list" }}
repeated {{ .Endpoint.Entity }} results = 1;
{{- else }}
{{ .Endpoint.Response.Type }} result = 1;
{{- end }}
{{- else }}
bool success = 1;
{{- end }}
}
{{- end }}
{{- end }}
{{- range .AST.Definitions }}
{{- if .Entity }}
{{- $entityName := .Entity.Name }}
// {{ $entityName }} entity message
message {{ $entityName }} {
option (gorm.opts).ormable = true; option (gorm.opts).ormable = true;
uint64 id = 1; {{- if .Entity.Description }}
// add object fields here // {{ .Entity.Description }}
{{- end }}
{{- $fieldNum := 1 }}
{{- range .Entity.Fields }}
{{- $protoType := "string" }}
{{- $gormTags := slice }}
{{- if eq .Type "string" }}
{{- $protoType = "string" }}
{{- else if eq .Type "int" }}
{{- $protoType = "int64" }}
{{- else if eq .Type "uuid" }}
{{- $protoType = "string" }}
{{- $gormTags = append $gormTags "type:uuid" }}
{{- else if eq .Type "boolean" }}
{{- $protoType = "bool" }}
{{- else if eq .Type "timestamp" }}
{{- $protoType = "google.protobuf.Timestamp" }}
{{- else if eq .Type "text" }}
{{- $protoType = "string" }}
{{- $gormTags = append $gormTags "type:text" }}
{{- else }}
{{- $protoType = "string" }}
{{- end }}
{{- if .Required }}
{{- $gormTags = append $gormTags "not null" }}
{{- end }}
{{- if .Unique }}
{{- $gormTags = append $gormTags "unique" }}
{{- end }}
{{- if .Index }}
{{- $gormTags = append $gormTags "index" }}
{{- end }}
{{- if .Default }}
{{- $gormTags = append $gormTags (printf "default:%s" (derefString .Default)) }}
{{- end }}
{{- if .Relationship }}
{{- if eq .Relationship.Cardinality "one" }}
{{- if .Relationship.ForeignKey }}
{{- $gormTags = append $gormTags (printf "foreignKey:%s" (derefString .Relationship.ForeignKey)) }}
{{- else }}
{{- $gormTags = append $gormTags (printf "foreignKey:%sID" .Name) }}
{{- end }}
{{- else if eq .Relationship.Cardinality "many" }}
{{- $protoType = printf "repeated %s" .Relationship.Type }}
{{- if .Relationship.Through }}
{{- $gormTags = append $gormTags (printf "many2many:%s" (derefString .Relationship.Through)) }}
{{- else }}
{{- $gormTags = append $gormTags (printf "foreignKey:%sID" $entityName) }}
{{- end }}
{{- end }}
{{- end }}
{{ $protoType }} {{ .Name }} = {{ $fieldNum }}
{{- if $gormTags }}
[(gorm.field).tag = {
{{- range $i, $tag := $gormTags }}
{{- if $i }}, {{ end }}{{ $tag }}
{{- end }}
}]
{{- end }};
{{- $fieldNum = add $fieldNum 1 }}
{{- end }}
} }
{{- end }}
{{- end }}

View File

@ -18,6 +18,12 @@ Masonry is a library that provides and implements all the basics necessary to bu
- [ ] - [ ]
- [ ] - [ ]
## DSL Features
- [ ] Indicate values that are based on Environment variables
- [ ] Yaml file to include custom template functions (Otto for JS)
- [ ] On Entities, we should indicate what CRUD functions should be implemented instead of implementing all, or forcing the user to define each in the Endpoints section
## Design Philosophy (changeable...) ## Design Philosophy (changeable...)
The goal of this project is to make building software for web and mobile applications as fast as possible while maintaining The goal of this project is to make building software for web and mobile applications as fast as possible while maintaining

0
test_proto_template.go Normal file
View File