feat(09-03): compile ordered Winter form schemas
- Strict config_form and fields documents keep source order and JSON scalar types - Unknown keys, partials, path escape, and a mismatched modelClass fail activation with plugin context - List-only controllers still activate when config_form.yaml is absent
This commit is contained in:
71
cabana/schema_types.go
Normal file
71
cabana/schema_types.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package cabana
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// FormSchema is the locale-neutral form contract compiled once at boot.
|
||||
// Display strings stay as source keys until a request localizes a copy.
|
||||
type FormSchema struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
ModelClass string `json:"modelClass,omitempty"`
|
||||
Fields []FormField `json:"fields"`
|
||||
}
|
||||
|
||||
// FormField is one Winter field in source order. JSON keys keep Winter spelling.
|
||||
type FormField struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Span string `json:"span,omitempty"`
|
||||
Tab string `json:"tab,omitempty"`
|
||||
Size string `json:"size,omitempty"`
|
||||
Context *fieldContext `json:"context,omitempty"`
|
||||
NameFrom string `json:"nameFrom,omitempty"`
|
||||
EmptyOption string `json:"emptyOption,omitempty"`
|
||||
Relation string `json:"relation,omitempty"`
|
||||
Required bool `json:"required,omitempty"`
|
||||
Default *jsonScalar `json:"default,omitempty"`
|
||||
Attributes map[string]jsonScalar `json:"attributes,omitempty"`
|
||||
Options []FormOption `json:"options,omitempty"`
|
||||
|
||||
optionsMethod string
|
||||
}
|
||||
|
||||
// FormOption is one dropdown choice. Value keeps the YAML scalar's JSON type.
|
||||
type FormOption struct {
|
||||
Value jsonScalar `json:"value"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
// jsonScalar is a JSON scalar that still emits false, 0, and empty string.
|
||||
type jsonScalar struct {
|
||||
raw json.RawMessage
|
||||
}
|
||||
|
||||
func (s jsonScalar) MarshalJSON() ([]byte, error) {
|
||||
if len(s.raw) == 0 {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
return s.raw, nil
|
||||
}
|
||||
|
||||
// fieldContext preserves a single Winter context string or a source-ordered list.
|
||||
type fieldContext struct {
|
||||
single bool
|
||||
values []string
|
||||
}
|
||||
|
||||
func (c fieldContext) MarshalJSON() ([]byte, error) {
|
||||
if c.single {
|
||||
text := ""
|
||||
if len(c.values) > 0 {
|
||||
text = c.values[0]
|
||||
}
|
||||
return json.Marshal(text)
|
||||
}
|
||||
values := c.values
|
||||
if values == nil {
|
||||
values = []string{}
|
||||
}
|
||||
return json.Marshal(values)
|
||||
}
|
||||
Reference in New Issue
Block a user