field.go
// Package schema provides collection field types and parsing.
package schema
import (
"encoding/json"
"github.com/readysite/readysite/website/models"
)
// Field types
const (
Text = "text"
Number = "number"
Bool = "bool"
Date = "date"
Email = "email"
URL = "url"
Select = "select"
Relation = "relation"
File = "file"
JSON = "json"
GeoPoint = "geopoint" // Geographic coordinates (lon, lat)
Editor = "editor" // Rich HTML content with sanitization
Autodate = "autodate" // Auto-set timestamp on create/update
)
// Field represents a field definition in a collection schema.
type Field struct {
Name string `json:"name"`
Type string `json:"type"`
Required bool `json:"required,omitempty"`
Unique bool `json:"unique,omitempty"`
Options map[string]any `json:"options,omitempty"`
// Common optional fields that AI might include at top level
Label string `json:"label,omitempty"`
Default any `json:"default,omitempty"`
}
// TextOptions for text fields.
type TextOptions struct {
MaxLength int `json:"maxLength,omitempty"`
Pattern string `json:"pattern,omitempty"`
}
// NumberOptions for number fields.
type NumberOptions struct {
Min *float64 `json:"min,omitempty"`
Max *float64 `json:"max,omitempty"`
OnlyInt bool `json:"onlyInt,omitempty"`
}
// SelectOptions for select fields.
type SelectOptions struct {
Values []string `json:"values"`
Multiple bool `json:"multiple,omitempty"`
}
// RelationOptions for relation fields.
type RelationOptions struct {
Collection string `json:"collection"`
Multiple bool `json:"multiple,omitempty"`
}
// FileOptions for file fields.
type FileOptions struct {
MaxSize int64 `json:"maxSize,omitempty"`
MimeTypes []string `json:"mimeTypes,omitempty"`
Multiple bool `json:"multiple,omitempty"`
}
// GeoPointOptions for geopoint fields.
type GeoPointOptions struct {
// No additional options needed - format is always {lon, lat}
}
// EditorOptions for editor (rich HTML) fields.
type EditorOptions struct {
MaxLength int `json:"maxLength,omitempty"` // Max character count after stripping tags
}
// AutodateOptions for autodate fields.
type AutodateOptions struct {
OnCreate bool `json:"onCreate,omitempty"` // Set on record creation
OnUpdate bool `json:"onUpdate,omitempty"` // Set on record update
}
// GetFields parses the schema from a collection.
func GetFields(c *models.Collection) ([]Field, error) {
var fields []Field
if c.Schema == "" {
return fields, nil
}
err := json.Unmarshal([]byte(c.Schema), &fields)
return fields, err
}
// SetFields sets the schema on a collection.
func SetFields(c *models.Collection, fields []Field) error {
data, err := json.Marshal(fields)
if err != nil {
return err
}
c.Schema = string(data)
return nil
}
// GetField returns a field by name from a collection.
func GetField(c *models.Collection, name string) (*Field, error) {
fields, err := GetFields(c)
if err != nil {
return nil, err
}
for _, f := range fields {
if f.Name == name {
return &f, nil
}
}
return nil, nil
}