+88
atproto/lexicon/language.go
+88
atproto/lexicon/language.go
···
69
69
}
70
70
}
71
71
72
+
// Helper to recurse down the definition tree and set full references on any sub-schemas which need to embed that metadata
73
+
func (s *SchemaDef) SetBase(base string) {
74
+
switch v := s.Inner.(type) {
75
+
case SchemaRecord:
76
+
for i, val := range v.Record.Properties {
77
+
val.SetBase(base)
78
+
v.Record.Properties[i] = val
79
+
}
80
+
s.Inner = v
81
+
case SchemaQuery:
82
+
for i, val := range v.Parameters.Properties {
83
+
val.SetBase(base)
84
+
v.Parameters.Properties[i] = val
85
+
}
86
+
if v.Output != nil && v.Output.Schema != nil {
87
+
v.Output.Schema.SetBase(base)
88
+
}
89
+
s.Inner = v
90
+
case SchemaProcedure:
91
+
for i, val := range v.Parameters.Properties {
92
+
val.SetBase(base)
93
+
v.Parameters.Properties[i] = val
94
+
}
95
+
if v.Input != nil && v.Input.Schema != nil {
96
+
v.Input.Schema.SetBase(base)
97
+
}
98
+
if v.Output != nil && v.Output.Schema != nil {
99
+
v.Output.Schema.SetBase(base)
100
+
}
101
+
s.Inner = v
102
+
case SchemaSubscription:
103
+
for i, val := range v.Parameters.Properties {
104
+
val.SetBase(base)
105
+
v.Parameters.Properties[i] = val
106
+
}
107
+
if v.Message != nil {
108
+
v.Message.Schema.SetBase(base)
109
+
}
110
+
s.Inner = v
111
+
case SchemaArray:
112
+
v.Items.SetBase(base)
113
+
s.Inner = v
114
+
case SchemaObject:
115
+
for i, val := range v.Properties {
116
+
val.SetBase(base)
117
+
v.Properties[i] = val
118
+
}
119
+
s.Inner = v
120
+
case SchemaParams:
121
+
for i, val := range v.Properties {
122
+
val.SetBase(base)
123
+
v.Properties[i] = val
124
+
}
125
+
s.Inner = v
126
+
case SchemaRef:
127
+
// add fully-qualified name
128
+
if strings.HasPrefix(v.Ref, "#") {
129
+
v.fullRef = base + v.Ref
130
+
} else {
131
+
v.fullRef = v.Ref
132
+
}
133
+
s.Inner = v
134
+
case SchemaUnion:
135
+
// add fully-qualified name
136
+
for _, ref := range v.Refs {
137
+
if strings.HasPrefix(ref, "#") {
138
+
ref = base + ref
139
+
}
140
+
v.fullRefs = append(v.fullRefs, ref)
141
+
}
142
+
s.Inner = v
143
+
}
144
+
return
145
+
}
146
+
72
147
func (s SchemaDef) MarshalJSON() ([]byte, error) {
73
148
return json.Marshal(s.Inner)
74
149
}
···
750
825
}
751
826
752
827
func (s *SchemaToken) CheckSchema() error {
828
+
if s.fullName == "" {
829
+
return fmt.Errorf("expected fully-qualified token name")
830
+
}
753
831
return nil
754
832
}
755
833
···
771
849
Type string `json:"type,const=ref"`
772
850
Description *string `json:"description,omitempty"`
773
851
Ref string `json:"ref"`
852
+
// full path of reference
853
+
fullRef string
774
854
}
775
855
776
856
func (s *SchemaRef) CheckSchema() error {
···
778
858
if len(s.Ref) == 0 {
779
859
return fmt.Errorf("empty schema ref")
780
860
}
861
+
if len(s.fullRef) == 0 {
862
+
return fmt.Errorf("empty full schema ref")
863
+
}
781
864
return nil
782
865
}
783
866
···
786
869
Description *string `json:"description,omitempty"`
787
870
Refs []string `json:"refs"`
788
871
Closed *bool `json:"closed,omitempty"`
872
+
// fully qualified
873
+
fullRefs []string
789
874
}
790
875
791
876
func (s *SchemaUnion) CheckSchema() error {
···
795
880
if len(ref) == 0 {
796
881
return fmt.Errorf("empty schema ref")
797
882
}
883
+
}
884
+
if len(s.fullRefs) != len(s.Refs) {
885
+
return fmt.Errorf("union refs were not expanded")
798
886
}
799
887
return nil
800
888
}
+6
-5
atproto/lexicon/lexicon.go
+6
-5
atproto/lexicon/lexicon.go
···
55
55
if _, ok := c.Schemas[name]; ok {
56
56
return fmt.Errorf("catalog already contained a schema with name: %s", name)
57
57
}
58
-
if err := def.CheckSchema(); err != nil {
59
-
return err
60
-
}
61
58
// "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."
62
59
switch s := def.Inner.(type) {
63
60
case SchemaRecord, SchemaQuery, SchemaProcedure, SchemaSubscription:
···
68
65
// add fully-qualified name to token
69
66
s.fullName = name
70
67
def.Inner = s
68
+
}
69
+
def.SetBase(base)
70
+
if err := def.CheckSchema(); err != nil {
71
+
return err
71
72
}
72
73
s := Schema{
73
74
ID: name,
···
167
168
return v.Validate(d)
168
169
case SchemaRef:
169
170
// recurse
170
-
next, err := c.Resolve(v.Ref)
171
+
next, err := c.Resolve(v.fullRef)
171
172
if err != nil {
172
173
return err
173
174
}
···
218
219
219
220
func (c *Catalog) validateUnion(s SchemaUnion, d any) error {
220
221
closed := s.Closed != nil && *s.Closed == true
221
-
for _, ref := range s.Refs {
222
+
for _, ref := range s.fullRefs {
222
223
def, err := c.Resolve(ref)
223
224
if err != nil {
224
225
// TODO: how to actually handle unknown defs?