readysite / website / internal / content / schema / field.go
3.1 KB
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
}
← Back