Skip to content

Commit

Permalink
Respect required fields in {target,} schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Nymphium committed Apr 30, 2024
1 parent 559e545 commit 46dbf3e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 10 deletions.
15 changes: 15 additions & 0 deletions _example/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ type Error struct {
} `json:"errorFields,omitempty"`
}

// Misc struct for misc resource
type Misc struct {
ID string `json:"id"`
}

// Task struct for task resource
type Task struct {
CompletedAt time.Time `json:"completedAt"`
Expand All @@ -31,6 +36,16 @@ type User struct {
Name string `json:"name"`
}

// MiscCreateRequest struct for misc
// POST: /bool/register
type MiscCreateRequest struct {
Bool bool `json:"bool,omitempty"`
}

// MiscCreateResponse struct for misc
// POST: /bool/register
type MiscCreateResponse Misc

// TaskInstancesRequest struct for task
// GET: /tasks
type TaskInstancesRequest struct {
Expand Down
16 changes: 16 additions & 0 deletions _example/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package taskyapi

import "github.com/lestrrat-go/jsval"

var MiscCreateValidator *jsval.JSVal
var TaskCreateValidator *jsval.JSVal
var TaskInstancesValidator *jsval.JSVal
var TaskSelfValidator *jsval.JSVal
Expand All @@ -22,6 +23,21 @@ func init() {
R1 = jsval.String()
M.SetReference("#/definitions/task/definitions/tags", R0)
M.SetReference("#/definitions/task/definitions/title", R1)
MiscCreateValidator = jsval.New().
SetName("MiscCreateValidator").
SetConstraintMap(M).
SetRoot(
jsval.Object().
Required("bool").
AdditionalProperties(
jsval.EmptyConstraint,
).
AddProp(
"bool",
jsval.Boolean(),
),
)

TaskCreateValidator = jsval.New().
SetName("TaskCreateValidator").
SetConstraintMap(M).
Expand Down
43 changes: 33 additions & 10 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func sortValidator(vals []*jsval.JSVal) []*jsval.JSVal {
}

// NewProperty new property
func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema.Schema, method string) (*Property, error) {
func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema.Schema, method string, schemaRequired bool) (*Property, error) {
// save reference before resolving ref
ref := tp.Reference
fieldSchema, err := resolveSchema(tp, root)
Expand All @@ -116,7 +116,7 @@ func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema
Name: name,
Format: string(fieldSchema.Format),
Types: fieldSchema.Type,
Required: df.IsPropRequired(name),
Required: df.IsPropRequired(name) || schemaRequired,
Pattern: fieldSchema.Pattern,
Reference: ref,
Schema: fieldSchema,
Expand Down Expand Up @@ -145,7 +145,7 @@ func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema
// log.Printf("inline obj: %s: %v", name, fieldSchema.Properties)
var inlineFields []*Property
for k, prop := range fieldSchema.Properties {
f, err := NewProperty(k, prop, df, root, method)
f, err := NewProperty(k, prop, df, root, method, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to perse inline object: %s", k)
}
Expand All @@ -167,7 +167,7 @@ func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema
// log.Printf("resolved inline obj: %s: %v", name, item.Properties)
var inlineFields []*Property
for k, prop := range item.Properties {
f, err := NewProperty(k, prop, df, root, method)
f, err := NewProperty(k, prop, df, root, method, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to perse inline object: %s", k)
}
Expand All @@ -179,7 +179,7 @@ func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema
// log.Printf("resolved inline obj: %s: %v", name, resolvedItem.Properties)
var inlineFields []*Property
for k, prop := range resolvedItem.Properties {
f, err := NewProperty(k, prop, df, root, method)
f, err := NewProperty(k, prop, df, root, method, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to perse inline object: %s", k)
}
Expand All @@ -196,7 +196,7 @@ func NewProperty(name string, tp *schema.Schema, df *schema.Schema, root *schema
// inline object without definitions
var inlineFields []*Property
for k, prop := range fieldSchema.Properties {
f, err := NewProperty(k, prop, df, root, method)
f, err := NewProperty(k, prop, df, root, method, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to perse inline object: %s", k)
}
Expand Down Expand Up @@ -248,7 +248,15 @@ func (p *Parser) ParseResources() (map[string]Resource, error) {
// parse resource field
var flds []*Property
for name, tp := range df.Properties {
fld, err := NewProperty(name, tp, df, p.schema, "")
schemaRequired := false
for _, required := range df.Required {
if required == name {
schemaRequired = true
break
}
}

fld, err := NewProperty(name, tp, df, p.schema, "", schemaRequired)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse %s", id)
}
Expand Down Expand Up @@ -294,7 +302,15 @@ func (p *Parser) ParseActions(res map[string]Resource) (map[string][]Action, err
if e.Schema != nil {
var flds []*Property
for name, tp := range e.Schema.Properties {
fld, err := NewProperty(name, tp, df, p.schema, e.Method)
schemaRequired := false
for _, required := range e.Schema.Required {
if required == name {
schemaRequired = true
break
}
}

fld, err := NewProperty(name, tp, df, p.schema, e.Method, schemaRequired)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse %s", id)
}
Expand All @@ -314,7 +330,14 @@ func (p *Parser) ParseActions(res map[string]Resource) (map[string][]Action, err
case e.TargetSchema.Reference == "":
var flds []*Property
for name, tp := range e.TargetSchema.Properties {
fld, err := NewProperty(name, tp, df, p.schema, e.Method)
schemaRequired := false
for _, required := range e.TargetSchema.Required {
if required == name {
schemaRequired = true
break
}
}
fld, err := NewProperty(name, tp, df, p.schema, e.Method, schemaRequired)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse %s", id)
}
Expand All @@ -335,7 +358,7 @@ func (p *Parser) ParseActions(res map[string]Resource) (map[string][]Action, err
IsPrimary: false,
}
case e.TargetSchema.Reference != "" && !IsRefToMainResource(e.TargetSchema.Reference):
fld, err := NewProperty(e.TargetSchema.ID, e.TargetSchema, df, p.schema, e.Method)
fld, err := NewProperty(e.TargetSchema.ID, e.TargetSchema, df, p.schema, e.Method, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse %s", id)
}
Expand Down
34 changes: 34 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,37 @@ func TestParseActions(t *testing.T) {
}
}
}

func TestParseActions_SchemaRequired(t *testing.T) {
parser := testNewParser(t)
r, err := parser.ParseResources()
if err != nil {
t.Fatal(err)
}

res, err := parser.ParseActions(r)
if err != nil {
t.Fatal(err)
}

a := res["misc"][0]
if a.Href != "/bool/register" {
t.Fatalf("href is not /bool/register, %s", a.Href)
}

name := a.Request.Properties[0]
if name.Name != "bool" {
t.Fatalf("not a target: %s", name.Name)
}
if !name.Required {
t.Fatal("bool is required")
}

isTrue := a.Response.Properties[1]
if isTrue.Name != "isTrue" {
t.Fatalf("not a target: %s", isTrue.Name)
}
if !isTrue.Required {
t.Fatal("isTrue is required")
}
}

0 comments on commit 46dbf3e

Please sign in to comment.