Skip to content

Commit cd4926c

Browse files
authored
Merge pull request #1 from prgres/fix/entoas-example-annotation
fix(entoas): example annotation ent#586
2 parents bbd64e9 + dfe3666 commit cd4926c

File tree

4 files changed

+163
-57
lines changed

4 files changed

+163
-57
lines changed

entoas/generator.go

+70-31
Original file line numberDiff line numberDiff line change
@@ -534,27 +534,49 @@ var (
534534
max16 int64 = math.MaxInt16
535535
maxu16 int64 = math.MaxUint16
536536
maxu32 int64 = math.MaxUint32
537-
types = map[string]*ogen.Schema{
538-
"bool": ogen.Bool(),
539-
"time.Time": ogen.DateTime(),
540-
"string": ogen.String(),
541-
"[]byte": ogen.Bytes(),
542-
"uuid.UUID": ogen.UUID(),
543-
"int": ogen.Int(),
544-
"int8": ogen.Int32().SetMinimum(&min8).SetMaximum(&max8),
545-
"int16": ogen.Int32().SetMinimum(&min16).SetMaximum(&max16),
546-
"int32": ogen.Int32(),
547-
"uint": ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32),
548-
"uint8": ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu8),
549-
"uint16": ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu16),
550-
"uint32": ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32),
551-
"int64": ogen.Int64(),
552-
"uint64": ogen.Int64().SetMinimum(&zero),
553-
"float32": ogen.Float(),
554-
"float64": ogen.Double(),
555-
}
556537
)
557538

539+
func types(t string) *ogen.Schema {
540+
switch t {
541+
case "bool":
542+
return ogen.Bool()
543+
case "time.Time":
544+
return ogen.DateTime()
545+
case "string":
546+
return ogen.String()
547+
case "[]byte":
548+
return ogen.Bytes()
549+
case "uuid.UUID":
550+
return ogen.UUID()
551+
case "int":
552+
return ogen.Int()
553+
case "int8":
554+
return ogen.Int32().SetMinimum(&min8).SetMaximum(&max8)
555+
case "int16":
556+
return ogen.Int32().SetMinimum(&min16).SetMaximum(&max16)
557+
case "int32":
558+
return ogen.Int32()
559+
case "uint":
560+
return ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32)
561+
case "uint8":
562+
return ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu8)
563+
case "uint16":
564+
return ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu16)
565+
case "uint32":
566+
return ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32)
567+
case "int64":
568+
return ogen.Int64()
569+
case "uint64":
570+
return ogen.Int64().SetMinimum(&zero)
571+
case "float32":
572+
return ogen.Float()
573+
case "float64":
574+
return ogen.Double()
575+
default:
576+
return nil
577+
}
578+
}
579+
558580
// OgenSchema returns the ogen.Schema to use for the given gen.Field.
559581
func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
560582
// If there is a custom property given on the field use it.
@@ -565,8 +587,12 @@ func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
565587
if ant.Schema != nil {
566588
return ant.Schema, nil
567589
}
568-
// Enum values need special case.
569-
if f.IsEnum() {
590+
591+
var schema *ogen.Schema
592+
s := f.Type.String()
593+
594+
switch {
595+
case f.IsEnum(): // Enum values need special case.
570596
var d json.RawMessage
571597
if f.Default {
572598
d, err = json.Marshal(f.DefaultValue().(string))
@@ -581,20 +607,33 @@ func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
581607
return nil, err
582608
}
583609
}
584-
return ogen.String().AsEnum(d, vs...), nil
585-
}
586-
s := f.Type.String()
587-
// Handle slice types.
588-
if strings.HasPrefix(s, "[]") {
589-
if t, ok := types[s[2:]]; ok {
590-
return t.AsArray(), nil
610+
schema = ogen.String().AsEnum(d, vs...)
611+
612+
case strings.HasPrefix(s, "[]"): // Handle slice types.
613+
t := types(s[2:])
614+
if t != nil {
615+
schema = t.AsArray()
616+
break
591617
}
618+
fallthrough
619+
620+
default:
621+
schema = types(s)
592622
}
593-
t, ok := types[s]
594-
if !ok {
623+
624+
if schema == nil {
595625
return nil, fmt.Errorf("no OAS-type exists for type %q of field %s", s, f.StructField())
596626
}
597-
return t, nil
627+
628+
if ant.Example != nil {
629+
jv, err := json.Marshal(ant.Example)
630+
if err != nil {
631+
return nil, fmt.Errorf("cannot marshal example annotation for field %s", f.Name)
632+
}
633+
schema.Example = jv
634+
}
635+
636+
return schema, nil
598637
}
599638

600639
// NodeOperations returns the list of operations to expose for this node.

entoas/generator_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,47 @@ func TestOgenSchema(t *testing.T) {
102102
}
103103
}
104104

105+
func TestOgenSchema_Example(t *testing.T) {
106+
t.Parallel()
107+
entFields := map[*entfield.Descriptor]*ogen.Schema{
108+
entfield.String("name").
109+
Annotations(Example("name")).Descriptor(): func() *ogen.Schema {
110+
schema := ogen.String()
111+
v, err := json.Marshal("name")
112+
require.NoError(t, err)
113+
schema.Example = v
114+
return schema
115+
}(),
116+
entfield.Float32("total").
117+
Annotations(Example("total")).Descriptor(): func() *ogen.Schema {
118+
schema := ogen.Float()
119+
v, err := json.Marshal("total")
120+
require.NoError(t, err)
121+
schema.Example = v
122+
return schema
123+
}(),
124+
}
125+
126+
for d, ex := range entFields {
127+
t.Run(d.Name, func(t *testing.T) {
128+
f, err := load.NewField(d)
129+
require.NoError(t, err)
130+
gf := &gen.Field{
131+
Name: f.Name,
132+
Type: f.Info,
133+
Annotations: f.Annotations,
134+
}
135+
ant, err := FieldAnnotation(gf)
136+
require.NoError(t, err)
137+
require.Equal(t, ant.Example, gf.Name)
138+
139+
ac, err := OgenSchema(gf)
140+
require.NoError(t, err)
141+
require.Equal(t, ex, ac)
142+
})
143+
}
144+
}
145+
105146
func TestOperation_Title(t *testing.T) {
106147
t.Parallel()
107148
require.Equal(t, "Create", OpCreate.Title())

entoas/internal/pets/openapi.json

+40-20
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,8 @@
400400
"type": "object",
401401
"properties": {
402402
"name": {
403-
"type": "string"
403+
"type": "string",
404+
"example": "Kuro"
404405
},
405406
"nicknames": {
406407
"type": "array",
@@ -409,7 +410,8 @@
409410
}
410411
},
411412
"age": {
412-
"type": "integer"
413+
"type": "integer",
414+
"example": 1
413415
},
414416
"categories": {
415417
"type": "array",
@@ -564,7 +566,8 @@
564566
"type": "object",
565567
"properties": {
566568
"name": {
567-
"type": "string"
569+
"type": "string",
570+
"example": "Kuro"
568571
},
569572
"nicknames": {
570573
"type": "array",
@@ -573,7 +576,8 @@
573576
}
574577
},
575578
"age": {
576-
"type": "integer"
579+
"type": "integer",
580+
"example": 1
577581
},
578582
"categories": {
579583
"type": "array",
@@ -1215,7 +1219,8 @@
12151219
"type": "integer"
12161220
},
12171221
"name": {
1218-
"type": "string"
1222+
"type": "string",
1223+
"example": "Kuro"
12191224
},
12201225
"nicknames": {
12211226
"type": "array",
@@ -1224,7 +1229,8 @@
12241229
}
12251230
},
12261231
"age": {
1227-
"type": "integer"
1232+
"type": "integer",
1233+
"example": 1
12281234
}
12291235
},
12301236
"required": [
@@ -1239,7 +1245,8 @@
12391245
"type": "integer"
12401246
},
12411247
"name": {
1242-
"type": "string"
1248+
"type": "string",
1249+
"example": "Kuro"
12431250
},
12441251
"nicknames": {
12451252
"type": "array",
@@ -1248,7 +1255,8 @@
12481255
}
12491256
},
12501257
"age": {
1251-
"type": "integer"
1258+
"type": "integer",
1259+
"example": 1
12521260
},
12531261
"categories": {
12541262
"type": "array",
@@ -1278,7 +1286,8 @@
12781286
"type": "integer"
12791287
},
12801288
"name": {
1281-
"type": "string"
1289+
"type": "string",
1290+
"example": "Kuro"
12821291
},
12831292
"nicknames": {
12841293
"type": "array",
@@ -1287,7 +1296,8 @@
12871296
}
12881297
},
12891298
"age": {
1290-
"type": "integer"
1299+
"type": "integer",
1300+
"example": 1
12911301
}
12921302
},
12931303
"required": [
@@ -1302,7 +1312,8 @@
13021312
"type": "integer"
13031313
},
13041314
"name": {
1305-
"type": "string"
1315+
"type": "string",
1316+
"example": "Kuro"
13061317
},
13071318
"nicknames": {
13081319
"type": "array",
@@ -1311,7 +1322,8 @@
13111322
}
13121323
},
13131324
"age": {
1314-
"type": "integer"
1325+
"type": "integer",
1326+
"example": 1
13151327
}
13161328
},
13171329
"required": [
@@ -1323,7 +1335,8 @@
13231335
"type": "object",
13241336
"properties": {
13251337
"name": {
1326-
"type": "string"
1338+
"type": "string",
1339+
"example": "Kuro"
13271340
},
13281341
"nicknames": {
13291342
"type": "array",
@@ -1332,7 +1345,8 @@
13321345
}
13331346
},
13341347
"age": {
1335-
"type": "integer"
1348+
"type": "integer",
1349+
"example": 1
13361350
},
13371351
"owner": {
13381352
"$ref": "#/components/schemas/PetRead_Owner"
@@ -1368,7 +1382,8 @@
13681382
"type": "integer"
13691383
},
13701384
"name": {
1371-
"type": "string"
1385+
"type": "string",
1386+
"example": "Kuro"
13721387
},
13731388
"nicknames": {
13741389
"type": "array",
@@ -1377,7 +1392,8 @@
13771392
}
13781393
},
13791394
"age": {
1380-
"type": "integer"
1395+
"type": "integer",
1396+
"example": 1
13811397
}
13821398
},
13831399
"required": [
@@ -1407,7 +1423,8 @@
14071423
"type": "integer"
14081424
},
14091425
"name": {
1410-
"type": "string"
1426+
"type": "string",
1427+
"example": "Kuro"
14111428
},
14121429
"nicknames": {
14131430
"type": "array",
@@ -1416,7 +1433,8 @@
14161433
}
14171434
},
14181435
"age": {
1419-
"type": "integer"
1436+
"type": "integer",
1437+
"example": 1
14201438
}
14211439
},
14221440
"required": [
@@ -1551,7 +1569,8 @@
15511569
"type": "integer"
15521570
},
15531571
"name": {
1554-
"type": "string"
1572+
"type": "string",
1573+
"example": "Kuro"
15551574
},
15561575
"nicknames": {
15571576
"type": "array",
@@ -1560,7 +1579,8 @@
15601579
}
15611580
},
15621581
"age": {
1563-
"type": "integer"
1582+
"type": "integer",
1583+
"example": 1
15641584
}
15651585
},
15661586
"required": [

0 commit comments

Comments
 (0)