Skip to content

Commit

Permalink
Merge pull request #1 from prgres/fix/entoas-example-annotation
Browse files Browse the repository at this point in the history
fix(entoas): example annotation ent#586
  • Loading branch information
prgres authored Jun 30, 2024
2 parents bbd64e9 + dfe3666 commit cd4926c
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 57 deletions.
101 changes: 70 additions & 31 deletions entoas/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,27 +534,49 @@ var (
max16 int64 = math.MaxInt16
maxu16 int64 = math.MaxUint16
maxu32 int64 = math.MaxUint32
types = map[string]*ogen.Schema{
"bool": ogen.Bool(),
"time.Time": ogen.DateTime(),
"string": ogen.String(),
"[]byte": ogen.Bytes(),
"uuid.UUID": ogen.UUID(),
"int": ogen.Int(),
"int8": ogen.Int32().SetMinimum(&min8).SetMaximum(&max8),
"int16": ogen.Int32().SetMinimum(&min16).SetMaximum(&max16),
"int32": ogen.Int32(),
"uint": ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32),
"uint8": ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu8),
"uint16": ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu16),
"uint32": ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32),
"int64": ogen.Int64(),
"uint64": ogen.Int64().SetMinimum(&zero),
"float32": ogen.Float(),
"float64": ogen.Double(),
}
)

func types(t string) *ogen.Schema {
switch t {
case "bool":
return ogen.Bool()
case "time.Time":
return ogen.DateTime()
case "string":
return ogen.String()
case "[]byte":
return ogen.Bytes()
case "uuid.UUID":
return ogen.UUID()
case "int":
return ogen.Int()
case "int8":
return ogen.Int32().SetMinimum(&min8).SetMaximum(&max8)
case "int16":
return ogen.Int32().SetMinimum(&min16).SetMaximum(&max16)
case "int32":
return ogen.Int32()
case "uint":
return ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32)
case "uint8":
return ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu8)
case "uint16":
return ogen.Int32().SetMinimum(&zero).SetMaximum(&maxu16)
case "uint32":
return ogen.Int64().SetMinimum(&zero).SetMaximum(&maxu32)
case "int64":
return ogen.Int64()
case "uint64":
return ogen.Int64().SetMinimum(&zero)
case "float32":
return ogen.Float()
case "float64":
return ogen.Double()
default:
return nil
}
}

// OgenSchema returns the ogen.Schema to use for the given gen.Field.
func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
// If there is a custom property given on the field use it.
Expand All @@ -565,8 +587,12 @@ func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
if ant.Schema != nil {
return ant.Schema, nil
}
// Enum values need special case.
if f.IsEnum() {

var schema *ogen.Schema
s := f.Type.String()

switch {
case f.IsEnum(): // Enum values need special case.
var d json.RawMessage
if f.Default {
d, err = json.Marshal(f.DefaultValue().(string))
Expand All @@ -581,20 +607,33 @@ func OgenSchema(f *gen.Field) (*ogen.Schema, error) {
return nil, err
}
}
return ogen.String().AsEnum(d, vs...), nil
}
s := f.Type.String()
// Handle slice types.
if strings.HasPrefix(s, "[]") {
if t, ok := types[s[2:]]; ok {
return t.AsArray(), nil
schema = ogen.String().AsEnum(d, vs...)

case strings.HasPrefix(s, "[]"): // Handle slice types.
t := types(s[2:])
if t != nil {
schema = t.AsArray()
break
}
fallthrough

default:
schema = types(s)
}
t, ok := types[s]
if !ok {

if schema == nil {
return nil, fmt.Errorf("no OAS-type exists for type %q of field %s", s, f.StructField())
}
return t, nil

if ant.Example != nil {
jv, err := json.Marshal(ant.Example)
if err != nil {
return nil, fmt.Errorf("cannot marshal example annotation for field %s", f.Name)
}
schema.Example = jv
}

return schema, nil
}

// NodeOperations returns the list of operations to expose for this node.
Expand Down
41 changes: 41 additions & 0 deletions entoas/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,47 @@ func TestOgenSchema(t *testing.T) {
}
}

func TestOgenSchema_Example(t *testing.T) {
t.Parallel()
entFields := map[*entfield.Descriptor]*ogen.Schema{
entfield.String("name").
Annotations(Example("name")).Descriptor(): func() *ogen.Schema {
schema := ogen.String()
v, err := json.Marshal("name")
require.NoError(t, err)
schema.Example = v
return schema
}(),
entfield.Float32("total").
Annotations(Example("total")).Descriptor(): func() *ogen.Schema {
schema := ogen.Float()
v, err := json.Marshal("total")
require.NoError(t, err)
schema.Example = v
return schema
}(),
}

for d, ex := range entFields {
t.Run(d.Name, func(t *testing.T) {
f, err := load.NewField(d)
require.NoError(t, err)
gf := &gen.Field{
Name: f.Name,
Type: f.Info,
Annotations: f.Annotations,
}
ant, err := FieldAnnotation(gf)
require.NoError(t, err)
require.Equal(t, ant.Example, gf.Name)

ac, err := OgenSchema(gf)
require.NoError(t, err)
require.Equal(t, ex, ac)
})
}
}

func TestOperation_Title(t *testing.T) {
t.Parallel()
require.Equal(t, "Create", OpCreate.Title())
Expand Down
60 changes: 40 additions & 20 deletions entoas/internal/pets/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@
"type": "object",
"properties": {
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -409,7 +410,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
},
"categories": {
"type": "array",
Expand Down Expand Up @@ -564,7 +566,8 @@
"type": "object",
"properties": {
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -573,7 +576,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
},
"categories": {
"type": "array",
Expand Down Expand Up @@ -1215,7 +1219,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1224,7 +1229,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand All @@ -1239,7 +1245,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1248,7 +1255,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
},
"categories": {
"type": "array",
Expand Down Expand Up @@ -1278,7 +1286,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1287,7 +1296,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand All @@ -1302,7 +1312,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1311,7 +1322,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand All @@ -1323,7 +1335,8 @@
"type": "object",
"properties": {
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1332,7 +1345,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
},
"owner": {
"$ref": "#/components/schemas/PetRead_Owner"
Expand Down Expand Up @@ -1368,7 +1382,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1377,7 +1392,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand Down Expand Up @@ -1407,7 +1423,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1416,7 +1433,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand Down Expand Up @@ -1551,7 +1569,8 @@
"type": "integer"
},
"name": {
"type": "string"
"type": "string",
"example": "Kuro"
},
"nicknames": {
"type": "array",
Expand All @@ -1560,7 +1579,8 @@
}
},
"age": {
"type": "integer"
"type": "integer",
"example": 1
}
},
"required": [
Expand Down
Loading

0 comments on commit cd4926c

Please sign in to comment.