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
},
"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{} {
return []interface{}{}
},
"append": func(slice []interface{}, item interface{}) []interface{} {
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))
data := struct {
@ -219,12 +247,40 @@ func NewTemplateRegistry() *TemplateRegistry {
}
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{} {
return []interface{}{}
},
"append": func(slice []interface{}, item interface{}) []interface{} {
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
}

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";
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/types/types.proto";
import "gorm/types/types.proto";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
option go_package = "./;pb";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Your API Title"
title: "{{ $serverName | title }} API"
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;
// Add your service methods here
rpc CreateProduct (CreateProductRequest) returns (CreateProductResponse) {
option (google.api.http) = {
post: "/v1/Product"
body: "*"
};
}
{{- range .AST.Definitions }}
{{- if .Entity }}
{{- $entityName := .Entity.Name }}
rpc ReadProduct (ReadProductRequest) returns (ReadProductResponse) {
option (google.api.http) = {
get: "/v1/Product/{id}"
};
}
// CRUD operations for {{ $entityName }}
rpc Create{{ $entityName }} (Create{{ $entityName }}Request) returns (Create{{ $entityName }}Response) {
option (google.api.http) = {
post: "/v1/{{ $entityName | title }}"
body: "*"
};
}
rpc ListProducts (ListProductsRequest) returns (ListProductsResponse) {
option (google.api.http) = {
get: "/v1/Product"
};
}
rpc Read{{ $entityName }} (Read{{ $entityName }}Request) returns (Read{{ $entityName }}Response) {
option (google.api.http) = {
get: "/v1/{{ $entityName | title }}/{id}"
};
}
rpc UpdateProduct (UpdateProductRequest) returns (UpdateProductResponse) {
option (google.api.http) = {
put: "/v1/Product"
body: "*"
};
}
rpc List{{ $entityName }}s (List{{ $entityName }}sRequest) returns (List{{ $entityName }}sResponse) {
option (google.api.http) = {
get: "/v1/{{ $entityName | title }}"
};
}
rpc DeleteProduct (DeleteProductRequest) returns (DeleteProductResponse) {
option (gorm.method).object_type = "Product";
option (google.api.http) = {
delete: "/v1/Product/{id}"
};
}
rpc Update{{ $entityName }} (Update{{ $entityName }}Request) returns (Update{{ $entityName }}Response) {
option (google.api.http) = {
put: "/v1/{{ $entityName | title }}"
body: "*"
};
}
rpc Delete{{ $entityName }} (Delete{{ $entityName }}Request) returns (Delete{{ $entityName }}Response) {
option (gorm.method).object_type = "{{ $entityName }}";
option (google.api.http) = {
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 {
{{ .ObjName }} payload = 1;
{{- range .AST.Definitions }}
{{- if .Entity }}
{{- $entityName := .Entity.Name }}
// CRUD Request/Response messages for {{ $entityName }}
message Create{{ $entityName }}Request {
{{ $entityName }} payload = 1;
}
message Create{{ .ObjName }}Response {
{{ .ObjName }} result = 1;
message Create{{ $entityName }}Response {
{{ $entityName }} result = 1;
}
message Read{{ .ObjName }}Request {
uint64 id = 1;
message Read{{ $entityName }}Request {
{{- $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 {
{{ .ObjName }} result = 1;
message Read{{ $entityName }}Response {
{{ $entityName }} result = 1;
}
message List{{ .ObjName }}sRequest {}
message List{{ .ObjName }}sResponse {
repeated {{ .ObjName }} results = 1;
message List{{ $entityName }}sRequest {
int32 page_size = 1;
string page_token = 2;
}
message Update{{ .ObjName }}Request {
{{ .ObjName }} payload = 1;
message List{{ $entityName }}sResponse {
repeated {{ $entityName }} results = 1;
string next_page_token = 2;
}
message Update{{ .ObjName }}Response {
{{ .ObjName }} result = 1;
message Update{{ $entityName }}Request {
{{ $entityName }} payload = 1;
}
message Delete{{ .ObjName }}Request {
uint64 id = 1;
message Update{{ $entityName }}Response {
{{ $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;
uint64 id = 1;
// add object fields here
{{- if .Entity.Description }}
// {{ .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...)
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