go-duck-cli 1.0.8 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -15
- package/generators/ai_docs.js +130 -0
- package/generators/broker.js +63 -0
- package/generators/config.js +149 -7
- package/generators/devops.js +210 -43
- package/generators/docs.js +23 -4
- package/generators/elasticsearch.js +263 -0
- package/generators/kratos.js +229 -41
- package/generators/metering.js +280 -48
- package/generators/migrations.js +92 -198
- package/generators/mqtt.js +2 -39
- package/generators/multitenancy.js +274 -71
- package/generators/nats.js +39 -0
- package/generators/outbox.js +171 -0
- package/generators/postgrest.js +7 -3
- package/generators/postman.js +405 -0
- package/generators/repository.js +27 -0
- package/generators/router.js +27 -0
- package/generators/security.js +95 -14
- package/generators/serverless.js +147 -0
- package/generators/storage.js +589 -0
- package/generators/swagger.js +84 -60
- package/generators/telemetry.js +23 -32
- package/generators/websocket.js +55 -21
- package/index.js +481 -116
- package/package.json +6 -4
- package/parser/gdl.js +163 -24
- package/templates/docs/index.html.hbs +5 -5
- package/templates/docs/layout.hbs +221 -62
- package/templates/docs/pages/audit.hbs +83 -35
- package/templates/docs/pages/cli.hbs +18 -0
- package/templates/docs/pages/configuration.hbs +241 -0
- package/templates/docs/pages/datadog.hbs +46 -0
- package/templates/docs/pages/elasticsearch.hbs +121 -0
- package/templates/docs/pages/federation.hbs +241 -0
- package/templates/docs/pages/gdl-advanced.hbs +91 -0
- package/templates/docs/pages/gdl-annotations.hbs +137 -0
- package/templates/docs/pages/gdl-entities.hbs +134 -0
- package/templates/docs/pages/gdl-relationships.hbs +80 -0
- package/templates/docs/pages/gdl.hbs +60 -204
- package/templates/docs/pages/graphql.hbs +58 -44
- package/templates/docs/pages/grpc.hbs +53 -90
- package/templates/docs/pages/hybrid-store.hbs +127 -0
- package/templates/docs/pages/index.hbs +418 -149
- package/templates/docs/pages/keycloak.hbs +43 -0
- package/templates/docs/pages/legend.hbs +116 -0
- package/templates/docs/pages/mosquitto.hbs +39 -0
- package/templates/docs/pages/multitenancy.hbs +139 -71
- package/templates/docs/pages/otel.hbs +40 -0
- package/templates/docs/pages/realtime.hbs +38 -12
- package/templates/docs/pages/redis.hbs +40 -0
- package/templates/docs/pages/rest.hbs +120 -202
- package/templates/docs/pages/saga.hbs +94 -0
- package/templates/docs/pages/security.hbs +150 -44
- package/templates/docs/pages/serverless.hbs +157 -0
- package/templates/docs/pages/storage.hbs +127 -0
- package/templates/docs/pages/wizard.hbs +683 -0
- package/templates/docs/triple_identity_registry.png +0 -0
- package/templates/go/controller.go.hbs +287 -283
- package/templates/go/entity.go.hbs +17 -15
- package/templates/go/main.go.hbs +47 -180
- package/templates/go/migrator.go.hbs +65 -0
- package/templates/go/router.go.hbs +272 -0
- package/templates/graphql/resolver.go.hbs +53 -34
- package/templates/graphql/schema.graphql.hbs +17 -5
- package/templates/kratos/service.go.hbs +169 -34
- package/templates/proto/entity.proto.hbs +10 -14
- package/test_nested.gdl +21 -0
- package/templates/docs/intro.mp4 +0 -0
- package/test_parser.js +0 -9
|
@@ -1,50 +1,69 @@
|
|
|
1
1
|
package graph
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
"encoding/json"
|
|
5
4
|
"net/http"
|
|
5
|
+
{{#if entities}}
|
|
6
6
|
"{{app_name}}/models"
|
|
7
|
+
{{/if}}
|
|
7
8
|
|
|
8
9
|
"github.com/gin-gonic/gin"
|
|
9
10
|
"gorm.io/gorm"
|
|
11
|
+
"fmt"
|
|
10
12
|
)
|
|
11
13
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
func
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
// Resolver for each entity (Federated)
|
|
15
|
+
{{#each entities}}
|
|
16
|
+
func Resolve{{capitalize name}}Federated(silos map[string]*gorm.DB, id uint) ([]interface{}, error) {
|
|
17
|
+
var results []interface{}
|
|
18
|
+
for role, db := range silos {
|
|
19
|
+
var e models.{{capitalize name}}
|
|
20
|
+
if err := db.First(&e, id).Error; err == nil {
|
|
21
|
+
results = append(results, gin.H{
|
|
22
|
+
"role": role,
|
|
23
|
+
"data": e,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return results, nil
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
func ResolveAll{{capitalize name}}sFederated(silos map[string]*gorm.DB) ([]interface{}, error) {
|
|
31
|
+
var results []interface{}
|
|
32
|
+
for role, db := range silos {
|
|
33
|
+
var list []models.{{capitalize name}}
|
|
34
|
+
if err := db.Find(&list).Error; err == nil {
|
|
35
|
+
results = append(results, gin.H{
|
|
36
|
+
"role": role,
|
|
37
|
+
"items": list,
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return results, nil
|
|
23
42
|
}
|
|
43
|
+
{{/each}}
|
|
24
44
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
c.
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
}
|
|
45
|
+
// HandleGraphQLRequest is the main bridge for the Federated Gin context
|
|
46
|
+
func HandleGraphQLRequest(c *gin.Context) {
|
|
47
|
+
siloConns, exists := c.Get("tenantSiloConns")
|
|
48
|
+
if !exists {
|
|
49
|
+
c.JSON(http.StatusForbidden, gin.H{"error": "No tenant context found"})
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
conns := siloConns.(map[string]*gorm.DB)
|
|
32
53
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if err := db.First(&e, id).Error; err != nil {
|
|
38
|
-
return nil, err
|
|
39
|
-
}
|
|
40
|
-
return &e, nil
|
|
41
|
-
}
|
|
54
|
+
var input struct {
|
|
55
|
+
Query string `json:"query"`
|
|
56
|
+
Variables map[string]interface{} `json:"variables"`
|
|
57
|
+
}
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{
|
|
59
|
+
if err := c.BindJSON(&input); err != nil {
|
|
60
|
+
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid GraphQL request"})
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// This is where real schema execution would happen using 'conns'
|
|
65
|
+
// For POC, return successful federation state
|
|
66
|
+
c.JSON(http.StatusOK, gin.H{
|
|
67
|
+
"data": "Federated GraphQL Handler active with " + fmt.Sprintf("%d", len(conns)) + " silos.",
|
|
68
|
+
})
|
|
69
|
+
}
|
|
@@ -48,17 +48,29 @@ enum {{name}} {
|
|
|
48
48
|
}
|
|
49
49
|
{{/each}}
|
|
50
50
|
|
|
51
|
+
{{#each entities}}
|
|
52
|
+
type Federated{{capitalize name}}List {
|
|
53
|
+
role: String!
|
|
54
|
+
items: [{{capitalize name}}]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type Federated{{capitalize name}} {
|
|
58
|
+
role: String!
|
|
59
|
+
data: {{capitalize name}}
|
|
60
|
+
}
|
|
61
|
+
{{/each}}
|
|
62
|
+
|
|
51
63
|
type Query {
|
|
52
64
|
{{#each entities}}
|
|
53
|
-
get{{capitalize name}}(id: ID!): {{name}}
|
|
54
|
-
list{{capitalize name}}s(page: Int, size: Int): [{{name}}]
|
|
65
|
+
get{{capitalize name}}(id: ID!): [Federated{{capitalize name}}]
|
|
66
|
+
list{{capitalize name}}s(page: Int, size: Int): [Federated{{capitalize name}}List]
|
|
55
67
|
{{/each}}
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
type Mutation {
|
|
59
71
|
{{#each entities}}
|
|
60
|
-
create{{capitalize name}}(input: Create{{name}}Input!): {{name}}
|
|
61
|
-
update{{capitalize name}}(id: ID!, input: Update{{name}}Input!): {{name}}
|
|
62
|
-
delete{{capitalize name}}(id: ID!): Boolean
|
|
72
|
+
create{{capitalize name}}(input: Create{{capitalize name}}Input!): Federated{{capitalize name}}
|
|
73
|
+
update{{capitalize name}}(id: ID!, input: Update{{capitalize name}}Input!): Federated{{capitalize name}}
|
|
74
|
+
delete{{capitalize name}}(id: ID!): Boolean
|
|
63
75
|
{{/each}}
|
|
64
76
|
}
|
|
@@ -2,12 +2,28 @@ package service
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
|
+
{{#if isDocument}}
|
|
6
|
+
"fmt"
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if (hasNested fields)}}
|
|
9
|
+
"encoding/json"
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{#if (hasInstant fields)}}
|
|
12
|
+
"time"
|
|
13
|
+
{{/if}}
|
|
5
14
|
pb "{{projectName}}/api/v1"
|
|
6
15
|
"{{projectName}}/internal/repository"
|
|
7
16
|
"{{projectName}}/models"
|
|
8
17
|
{{#if (hasJson fields)}}
|
|
9
18
|
"gorm.io/datatypes"
|
|
10
19
|
{{/if}}
|
|
20
|
+
{{#if isDocument}}
|
|
21
|
+
"go.mongodb.org/mongo-driver/bson"
|
|
22
|
+
"go.mongodb.org/mongo-driver/mongo"
|
|
23
|
+
"go.mongodb.org/mongo-driver/mongo/options"
|
|
24
|
+
{{else}}
|
|
25
|
+
"gorm.io/gorm"
|
|
26
|
+
{{/if}}
|
|
11
27
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
12
28
|
)
|
|
13
29
|
|
|
@@ -21,84 +37,203 @@ func New{{capitalize name}}Service(repo *repository.Repository) *{{capitalize na
|
|
|
21
37
|
}
|
|
22
38
|
|
|
23
39
|
func (s *{{capitalize name}}Service) Create{{capitalize name}}(ctx context.Context, req *pb.Create{{capitalize name}}Request) (*pb.{{capitalize name}}Reply, error) {
|
|
40
|
+
{{#if isDocument}}
|
|
41
|
+
db, ok := ctx.Value("tenantMongoDB").(*mongo.Database)
|
|
42
|
+
if !ok { return nil, fmt.Errorf("mongo database not found in context") }
|
|
43
|
+
{{else}}
|
|
44
|
+
siloConns, _ := ctx.Value("tenantSiloConns").(map[string]*gorm.DB)
|
|
45
|
+
{{/if}}
|
|
46
|
+
federatedData := make(map[string]*pb.{{capitalize name}})
|
|
47
|
+
|
|
24
48
|
entity := &models.{{capitalize name}}{
|
|
25
49
|
{{#each fields}}
|
|
26
|
-
{{
|
|
50
|
+
{{#if (eq (toLowerCase type) "localdate")}}
|
|
51
|
+
{{capitalize name}}: parseDate(req.{{toProtoFieldName name}}),
|
|
52
|
+
{{else if (eq (toLowerCase type) "instant")}}
|
|
53
|
+
{{capitalize name}}: parseInstant(req.{{toProtoFieldName name}}),
|
|
54
|
+
{{else if (eq (toLowerCase type) "datetime")}}
|
|
55
|
+
{{capitalize name}}: parseInstant(req.{{toProtoFieldName name}}),
|
|
56
|
+
{{else if (isJson type)}}
|
|
57
|
+
{{capitalize name}}: datatypes.JSON(req.{{toProtoFieldName name}}),
|
|
58
|
+
{{else if isNested}}
|
|
59
|
+
// Nested fields are mapped via JSON for simplicity in gRPC
|
|
60
|
+
{{else}}
|
|
61
|
+
{{capitalize name}}: {{#if (toGoCast type)}}{{toGoCast type}}(req.{{toProtoFieldName name}}){{else}}req.{{toProtoFieldName name}}{{/if}},
|
|
62
|
+
{{/if}}
|
|
27
63
|
{{/each}}
|
|
28
64
|
}
|
|
29
|
-
|
|
30
|
-
|
|
65
|
+
|
|
66
|
+
{{#if isDocument}}
|
|
67
|
+
{{#each fields}}{{#if isNested}}
|
|
68
|
+
json.Unmarshal([]byte(req.{{toProtoFieldName name}}), &entity.{{capitalize name}})
|
|
69
|
+
{{/if}}{{/each}}
|
|
70
|
+
res, err := db.Collection("{{toLowerCase name}}s").InsertOne(ctx, entity)
|
|
71
|
+
if err == nil {
|
|
72
|
+
entity.ID = fmt.Sprintf("%v", res.InsertedID)
|
|
73
|
+
federatedData["tenant"] = map{{capitalize name}}ToPb(entity)
|
|
74
|
+
}
|
|
75
|
+
{{else}}
|
|
76
|
+
for role, db := range siloConns {
|
|
77
|
+
if err := db.WithContext(ctx).Create(entity).Error; err == nil {
|
|
78
|
+
federatedData[role] = map{{capitalize name}}ToPb(entity)
|
|
79
|
+
}
|
|
31
80
|
}
|
|
81
|
+
{{/if}}
|
|
82
|
+
|
|
32
83
|
return &pb.{{capitalize name}}Reply{
|
|
33
|
-
|
|
84
|
+
FederatedData: federatedData,
|
|
34
85
|
}, nil
|
|
35
86
|
}
|
|
36
87
|
|
|
37
88
|
func (s *{{capitalize name}}Service) Get{{capitalize name}}(ctx context.Context, req *pb.Get{{capitalize name}}Request) (*pb.{{capitalize name}}Reply, error) {
|
|
89
|
+
federatedData := make(map[string]*pb.{{capitalize name}})
|
|
90
|
+
|
|
91
|
+
{{#if isDocument}}
|
|
92
|
+
db, _ := ctx.Value("tenantMongoDB").(*mongo.Database)
|
|
38
93
|
var entity models.{{capitalize name}}
|
|
39
|
-
if err :=
|
|
40
|
-
|
|
94
|
+
if err := db.Collection("{{toLowerCase name}}s").FindOne(ctx, bson.M{"_id": req.Id}).Decode(&entity); err == nil {
|
|
95
|
+
federatedData["tenant"] = map{{capitalize name}}ToPb(&entity)
|
|
96
|
+
}
|
|
97
|
+
{{else}}
|
|
98
|
+
siloConns, _ := ctx.Value("tenantSiloConns").(map[string]*gorm.DB)
|
|
99
|
+
for role, db := range siloConns {
|
|
100
|
+
var entity models.{{capitalize name}}
|
|
101
|
+
if err := db.WithContext(ctx).First(&entity, req.Id).Error; err == nil {
|
|
102
|
+
federatedData[role] = map{{capitalize name}}ToPb(&entity)
|
|
103
|
+
}
|
|
41
104
|
}
|
|
105
|
+
{{/if}}
|
|
106
|
+
|
|
42
107
|
return &pb.{{capitalize name}}Reply{
|
|
43
|
-
|
|
108
|
+
FederatedData: federatedData,
|
|
44
109
|
}, nil
|
|
45
110
|
}
|
|
46
111
|
|
|
47
112
|
func (s *{{capitalize name}}Service) Update{{capitalize name}}(ctx context.Context, req *pb.Update{{capitalize name}}Request) (*pb.{{capitalize name}}Reply, error) {
|
|
113
|
+
federatedData := make(map[string]*pb.{{capitalize name}})
|
|
114
|
+
|
|
48
115
|
var entity models.{{capitalize name}}
|
|
49
|
-
if
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
116
|
+
{{#if isDocument}}
|
|
117
|
+
entity.ID = req.Id
|
|
118
|
+
{{/if}}
|
|
53
119
|
{{#each fields}}
|
|
54
|
-
|
|
120
|
+
{{#if (eq (toLowerCase type) "localdate")}}
|
|
121
|
+
entity.{{capitalize name}} = parseDate(req.{{toProtoFieldName name}})
|
|
122
|
+
{{else if (eq (toLowerCase type) "instant")}}
|
|
123
|
+
entity.{{capitalize name}} = parseInstant(req.{{toProtoFieldName name}})
|
|
124
|
+
{{else if (eq (toLowerCase type) "datetime")}}
|
|
125
|
+
entity.{{capitalize name}} = parseInstant(req.{{toProtoFieldName name}})
|
|
126
|
+
{{else if (isJson type)}}
|
|
127
|
+
entity.{{capitalize name}} = datatypes.JSON(req.{{toProtoFieldName name}})
|
|
128
|
+
{{else if isNested}}
|
|
129
|
+
json.Unmarshal([]byte(req.{{toProtoFieldName name}}), &entity.{{capitalize name}})
|
|
130
|
+
{{else}}
|
|
131
|
+
entity.{{capitalize name}} = {{#if (toGoCast type)}}{{toGoCast type}}(req.{{toProtoFieldName name}}){{else}}req.{{toProtoFieldName name}}{{/if}}
|
|
132
|
+
{{/if}}
|
|
55
133
|
{{/each}}
|
|
56
134
|
|
|
57
|
-
if
|
|
58
|
-
|
|
135
|
+
{{#if isDocument}}
|
|
136
|
+
db, _ := ctx.Value("tenantMongoDB").(*mongo.Database)
|
|
137
|
+
if _, err := db.Collection("{{toLowerCase name}}s").ReplaceOne(ctx, bson.M{"_id": req.Id}, entity); err == nil {
|
|
138
|
+
federatedData["tenant"] = map{{capitalize name}}ToPb(&entity)
|
|
139
|
+
}
|
|
140
|
+
{{else}}
|
|
141
|
+
siloConns, _ := ctx.Value("tenantSiloConns").(map[string]*gorm.DB)
|
|
142
|
+
for role, db := range siloConns {
|
|
143
|
+
if err := db.WithContext(ctx).Model(&models.{{capitalize name}}{}).Where("id = ?", req.Id).Save(&entity).Error; err == nil {
|
|
144
|
+
federatedData[role] = map{{capitalize name}}ToPb(&entity)
|
|
145
|
+
}
|
|
59
146
|
}
|
|
147
|
+
{{/if}}
|
|
148
|
+
|
|
60
149
|
return &pb.{{capitalize name}}Reply{
|
|
61
|
-
|
|
150
|
+
FederatedData: federatedData,
|
|
62
151
|
}, nil
|
|
63
152
|
}
|
|
64
153
|
|
|
65
154
|
func (s *{{capitalize name}}Service) Delete{{capitalize name}}(ctx context.Context, req *pb.Delete{{capitalize name}}Request) (*pb.Delete{{capitalize name}}Reply, error) {
|
|
66
|
-
|
|
67
|
-
|
|
155
|
+
{{#if isDocument}}
|
|
156
|
+
db, _ := ctx.Value("tenantMongoDB").(*mongo.Database)
|
|
157
|
+
db.Collection("{{toLowerCase name}}s").DeleteOne(ctx, bson.M{"_id": req.Id})
|
|
158
|
+
{{else}}
|
|
159
|
+
siloConns, _ := ctx.Value("tenantSiloConns").(map[string]*gorm.DB)
|
|
160
|
+
for _, db := range siloConns {
|
|
161
|
+
db.WithContext(ctx).Where("id = ?", req.Id).Delete(&models.{{capitalize name}}{})
|
|
68
162
|
}
|
|
69
|
-
|
|
163
|
+
{{/if}}
|
|
164
|
+
return &pb.Delete{{capitalize name}}Reply{Message: "Delete completed"}, nil
|
|
70
165
|
}
|
|
71
166
|
|
|
72
167
|
func (s *{{capitalize name}}Service) List{{capitalize name}}(ctx context.Context, req *pb.List{{capitalize name}}Request) (*pb.List{{capitalize name}}Reply, error) {
|
|
73
|
-
|
|
168
|
+
federatedResults := make(map[string]*pb.{{capitalize name}}List)
|
|
74
169
|
var total int64
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
db.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
170
|
+
|
|
171
|
+
{{#if isDocument}}
|
|
172
|
+
db, _ := ctx.Value("tenantMongoDB").(*mongo.Database)
|
|
173
|
+
var results []models.{{capitalize name}}
|
|
174
|
+
opts := options.Find().SetSkip(int64((req.Page - 1) * req.PageSize)).SetLimit(int64(req.PageSize))
|
|
175
|
+
cursor, err := db.Collection("{{toLowerCase name}}s").Find(ctx, bson.M{}, opts)
|
|
176
|
+
if err == nil {
|
|
177
|
+
cursor.All(ctx, &results)
|
|
178
|
+
items := make([]*pb.{{capitalize name}}, len(results))
|
|
179
|
+
for i, r := range results {
|
|
180
|
+
items[i] = map{{capitalize name}}ToPb(&r)
|
|
181
|
+
}
|
|
182
|
+
federatedResults["tenant"] = &pb.{{capitalize name}}List{Items: items}
|
|
183
|
+
count, _ := db.Collection("{{toLowerCase name}}s").CountDocuments(ctx, bson.M{})
|
|
184
|
+
total = count
|
|
82
185
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for
|
|
86
|
-
|
|
186
|
+
{{else}}
|
|
187
|
+
siloConns, _ := ctx.Value("tenantSiloConns").(map[string]*gorm.DB)
|
|
188
|
+
for role, db := range siloConns {
|
|
189
|
+
var results []models.{{capitalize name}}
|
|
190
|
+
query := db.WithContext(ctx).Model(&models.{{capitalize name}}{})
|
|
191
|
+
|
|
192
|
+
var count int64
|
|
193
|
+
query.Count(&count)
|
|
194
|
+
total += count
|
|
195
|
+
|
|
196
|
+
offset := (req.Page - 1) * req.PageSize
|
|
197
|
+
if err := query.Limit(int(req.PageSize)).Offset(int(offset)).Find(&results).Error; err == nil {
|
|
198
|
+
items := make([]*pb.{{capitalize name}}, len(results))
|
|
199
|
+
for i, r := range results {
|
|
200
|
+
items[i] = map{{capitalize name}}ToPb(&r)
|
|
201
|
+
}
|
|
202
|
+
federatedResults[role] = &pb.{{capitalize name}}List{Items: items}
|
|
203
|
+
}
|
|
87
204
|
}
|
|
205
|
+
{{/if}}
|
|
88
206
|
|
|
89
207
|
return &pb.List{{capitalize name}}Reply{
|
|
90
|
-
|
|
91
|
-
Total:
|
|
208
|
+
FederatedResults: federatedResults,
|
|
209
|
+
Total: total,
|
|
92
210
|
}, nil
|
|
93
211
|
}
|
|
94
212
|
|
|
95
213
|
func map{{capitalize name}}ToPb(m *models.{{capitalize name}}) *pb.{{capitalize name}} {
|
|
96
214
|
return &pb.{{capitalize name}}{
|
|
97
|
-
Id: uint64(m.ID),
|
|
215
|
+
Id: {{#if isDocument}}m.ID{{else}}uint64(m.ID){{/if}},
|
|
98
216
|
{{#each fields}}
|
|
99
|
-
{{
|
|
217
|
+
{{#if (eq (toLowerCase type) "localdate")}}
|
|
218
|
+
{{toProtoFieldName name}}: m.{{capitalize name}}.Format("2006-01-02"),
|
|
219
|
+
{{else if (eq (toLowerCase type) "instant")}}
|
|
220
|
+
{{toProtoFieldName name}}: m.{{capitalize name}}.Format(time.RFC3339),
|
|
221
|
+
{{else if (eq (toLowerCase type) "datetime")}}
|
|
222
|
+
{{toProtoFieldName name}}: m.{{capitalize name}}.Format(time.RFC3339),
|
|
223
|
+
{{else if (isJson type)}}
|
|
224
|
+
{{toProtoFieldName name}}: string(m.{{capitalize name}}),
|
|
225
|
+
{{else if isNested}}
|
|
226
|
+
{{toProtoFieldName name}}: (func() string { b, _ := json.Marshal(m.{{capitalize name}}); return string(b) })(),
|
|
227
|
+
{{else}}
|
|
228
|
+
{{toProtoFieldName name}}: {{#if (toProtoCast type)}}{{toProtoCast type}}(m.{{capitalize name}}){{else}}m.{{capitalize name}}{{/if}},
|
|
229
|
+
{{/if}}
|
|
100
230
|
{{/each}}
|
|
231
|
+
{{#if isAudited}}
|
|
232
|
+
CreatedAt: timestamppb.New(m.CreatedDate),
|
|
233
|
+
UpdatedAt: timestamppb.New(m.LastModifiedDate),
|
|
234
|
+
{{else}}
|
|
101
235
|
CreatedAt: timestamppb.New(m.CreatedAt),
|
|
102
236
|
UpdatedAt: timestamppb.New(m.UpdatedAt),
|
|
237
|
+
{{/if}}
|
|
103
238
|
}
|
|
104
239
|
}
|
|
@@ -38,7 +38,7 @@ service {{capitalize name}}Service {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
message {{capitalize name}} {
|
|
41
|
-
uint64 id = 1;
|
|
41
|
+
{{#if isDocument}}string{{else}}uint64{{/if}} id = 1;
|
|
42
42
|
{{#each fields}}
|
|
43
43
|
{{toProtoType type}} {{name}} = {{add @index 2}};
|
|
44
44
|
{{/each}}
|
|
@@ -53,14 +53,14 @@ message Create{{capitalize name}}Request {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
message Update{{capitalize name}}Request {
|
|
56
|
-
uint64 id = 1;
|
|
56
|
+
{{#if isDocument}}string{{else}}uint64{{/if}} id = 1;
|
|
57
57
|
{{#each fields}}
|
|
58
58
|
{{toProtoType type}} {{name}} = {{add @index 2}};
|
|
59
59
|
{{/each}}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
message Delete{{capitalize name}}Request {
|
|
63
|
-
uint64 id = 1;
|
|
63
|
+
{{#if isDocument}}string{{else}}uint64{{/if}} id = 1;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
message Delete{{capitalize name}}Reply {
|
|
@@ -68,11 +68,15 @@ message Delete{{capitalize name}}Reply {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
message Get{{capitalize name}}Request {
|
|
71
|
-
uint64 id = 1;
|
|
71
|
+
{{#if isDocument}}string{{else}}uint64{{/if}} id = 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
message {{capitalize name}}List {
|
|
75
|
+
repeated {{capitalize name}} items = 1;
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
message {{capitalize name}}Reply {
|
|
75
|
-
{{capitalize name}}
|
|
79
|
+
map<string, {{capitalize name}}> federated_data = 1;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
message List{{capitalize name}}Request {
|
|
@@ -82,14 +86,6 @@ message List{{capitalize name}}Request {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
message List{{capitalize name}}Reply {
|
|
85
|
-
|
|
89
|
+
map<string, {{capitalize name}}List> federated_results = 1;
|
|
86
90
|
int64 total = 2;
|
|
87
91
|
}
|
|
88
|
-
{{#each enums}}
|
|
89
|
-
enum {{capitalize name}} {
|
|
90
|
-
{{capitalize name}}_UNSPECIFIED = 0;
|
|
91
|
-
{{#each values}}
|
|
92
|
-
{{capitalize ../name}}_{{this}} = {{add @index 1}};
|
|
93
|
-
{{/each}}
|
|
94
|
-
}
|
|
95
|
-
{{/each}}
|
package/test_nested.gdl
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@Document @Audited @Federated
|
|
2
|
+
entity PatientRecord {
|
|
3
|
+
patientId String required unique
|
|
4
|
+
clinicalData {
|
|
5
|
+
vitals {
|
|
6
|
+
bpm Integer
|
|
7
|
+
temp Float
|
|
8
|
+
}
|
|
9
|
+
notes Text
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
relationship OneToMany {
|
|
14
|
+
PatientRecord to ClinicalNote
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enum PatientStatus {
|
|
18
|
+
ACTIVE, INACTIVE, DECEASED
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
open PatientRecord(read, create)
|
package/templates/docs/intro.mp4
DELETED
|
Binary file
|
package/test_parser.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
|
|
3
|
-
const content = fs.readFileSync('../GDL/app.gdl', 'utf8');
|
|
4
|
-
const relRegex = /relationship\s+(\w+)\s*\{([^}]*)\}/g;
|
|
5
|
-
let match;
|
|
6
|
-
while ((match = relRegex.exec(content)) !== null) {
|
|
7
|
-
console.log('Type:', match[1]);
|
|
8
|
-
console.log('Block:', match[2]);
|
|
9
|
-
}
|