Skip to content

Commit

Permalink
lexicon fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bnewbold committed Feb 29, 2024
1 parent 54260d6 commit 2a5ee98
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 6 deletions.
88 changes: 88 additions & 0 deletions atproto/lexicon/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,81 @@ func (s *SchemaDef) CheckSchema() error {
}
}

// Helper to recurse down the definition tree and set full references on any sub-schemas which need to embed that metadata
func (s *SchemaDef) SetBase(base string) {
switch v := s.Inner.(type) {
case SchemaRecord:
for i, val := range v.Record.Properties {
val.SetBase(base)
v.Record.Properties[i] = val
}
s.Inner = v
case SchemaQuery:
for i, val := range v.Parameters.Properties {
val.SetBase(base)
v.Parameters.Properties[i] = val
}
if v.Output != nil && v.Output.Schema != nil {
v.Output.Schema.SetBase(base)
}
s.Inner = v
case SchemaProcedure:
for i, val := range v.Parameters.Properties {
val.SetBase(base)
v.Parameters.Properties[i] = val
}
if v.Input != nil && v.Input.Schema != nil {
v.Input.Schema.SetBase(base)
}
if v.Output != nil && v.Output.Schema != nil {
v.Output.Schema.SetBase(base)
}
s.Inner = v
case SchemaSubscription:
for i, val := range v.Parameters.Properties {
val.SetBase(base)
v.Parameters.Properties[i] = val
}
if v.Message != nil {
v.Message.Schema.SetBase(base)
}
s.Inner = v
case SchemaArray:
v.Items.SetBase(base)
s.Inner = v
case SchemaObject:
for i, val := range v.Properties {
val.SetBase(base)
v.Properties[i] = val
}
s.Inner = v
case SchemaParams:
for i, val := range v.Properties {
val.SetBase(base)
v.Properties[i] = val
}
s.Inner = v
case SchemaRef:
// add fully-qualified name
if strings.HasPrefix(v.Ref, "#") {
v.fullRef = base + v.Ref
} else {
v.fullRef = v.Ref
}
s.Inner = v
case SchemaUnion:
// add fully-qualified name
for _, ref := range v.Refs {
if strings.HasPrefix(ref, "#") {
ref = base + ref
}
v.fullRefs = append(v.fullRefs, ref)
}
s.Inner = v
}
return
}

func (s SchemaDef) MarshalJSON() ([]byte, error) {
return json.Marshal(s.Inner)
}
Expand Down Expand Up @@ -750,6 +825,9 @@ type SchemaToken struct {
}

func (s *SchemaToken) CheckSchema() error {
if s.fullName == "" {
return fmt.Errorf("expected fully-qualified token name")
}
return nil
}

Expand All @@ -771,13 +849,18 @@ type SchemaRef struct {
Type string `json:"type,const=ref"`
Description *string `json:"description,omitempty"`
Ref string `json:"ref"`
// full path of reference
fullRef string
}

func (s *SchemaRef) CheckSchema() error {
// TODO: more validation of ref string?
if len(s.Ref) == 0 {
return fmt.Errorf("empty schema ref")
}
if len(s.fullRef) == 0 {
return fmt.Errorf("empty full schema ref")
}
return nil
}

Expand All @@ -786,6 +869,8 @@ type SchemaUnion struct {
Description *string `json:"description,omitempty"`
Refs []string `json:"refs"`
Closed *bool `json:"closed,omitempty"`
// fully qualified
fullRefs []string
}

func (s *SchemaUnion) CheckSchema() error {
Expand All @@ -796,6 +881,9 @@ func (s *SchemaUnion) CheckSchema() error {
return fmt.Errorf("empty schema ref")
}
}
if len(s.fullRefs) != len(s.Refs) {
return fmt.Errorf("union refs were not expanded")
}
return nil
}

Expand Down
11 changes: 6 additions & 5 deletions atproto/lexicon/lexicon.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ func (c *Catalog) AddSchemaFile(sf SchemaFile) error {
if _, ok := c.Schemas[name]; ok {
return fmt.Errorf("catalog already contained a schema with name: %s", name)
}
if err := def.CheckSchema(); err != nil {
return err
}
// "A file can have at most one definition with one of the "primary" types. Primary types should always have the name main. It is possible for main to describe a non-primary type."
switch s := def.Inner.(type) {
case SchemaRecord, SchemaQuery, SchemaProcedure, SchemaSubscription:
Expand All @@ -69,6 +66,10 @@ func (c *Catalog) AddSchemaFile(sf SchemaFile) error {
s.fullName = name
def.Inner = s
}
def.SetBase(base)
if err := def.CheckSchema(); err != nil {
return err
}
s := Schema{
ID: name,
Revision: sf.Revision,
Expand Down Expand Up @@ -167,7 +168,7 @@ func (c *Catalog) validateData(def any, d any) error {
return v.Validate(d)
case SchemaRef:
// recurse
next, err := c.Resolve(v.Ref)
next, err := c.Resolve(v.fullRef)
if err != nil {
return err
}
Expand Down Expand Up @@ -218,7 +219,7 @@ func (c *Catalog) validateArray(s SchemaArray, arr []any) error {

func (c *Catalog) validateUnion(s SchemaUnion, d any) error {
closed := s.Closed != nil && *s.Closed == true
for _, ref := range s.Refs {
for _, ref := range s.fullRefs {
def, err := c.Resolve(ref)
if err != nil {
// TODO: how to actually handle unknown defs?
Expand Down
1 change: 0 additions & 1 deletion atproto/lexicon/mimetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ func acceptableMimeType(pattern, val string) bool {
} else {
return pattern == val
}
return false
}

0 comments on commit 2a5ee98

Please sign in to comment.