package models import ( "database/sql/driver" "encoding/json" "errors" "time" ) // Entry is the SEO of one record in one locale on golem15_seo_entries // (D-01): the values an editor set in the record's SEO tab, keyed by the // record's morph type (ModelType, the content descriptor's Model), its id as // text and the locale. TypeKey is the record's content type (signpost key) // and URL the record's public path in that locale when the entry was last // written. An empty value means "inherit": the resolver falls back to the // type template, the global settings and the content. EffectiveTitle and // EffectiveDescription cache the resolved values for duplicate checks. Data // holds values of later fields (schema type, custom JSON-LD) without a // migration per field. type Entry struct { ID uint `gorm:"column:id;primaryKey"` ModelType string `gorm:"column:model_type"` RecordID string `gorm:"column:record_id"` Locale string `gorm:"column:locale"` TypeKey string `gorm:"column:type_key"` URL string `gorm:"column:url"` Title string `gorm:"column:title"` Description string `gorm:"column:description"` Keyphrase string `gorm:"column:keyphrase"` Canonical string `gorm:"column:canonical"` Robots string `gorm:"column:robots"` OGTitle string `gorm:"column:og_title"` OGDescription string `gorm:"column:og_description"` OGImage string `gorm:"column:og_image"` EffectiveTitle string `gorm:"column:effective_title"` EffectiveDescription string `gorm:"column:effective_description"` Data JSONMap `gorm:"column:data"` CreatedAt time.Time `gorm:"column:created_at"` UpdatedAt time.Time `gorm:"column:updated_at"` } func (Entry) TableName() string { return "golem15_seo_entries" } // JSONMap is a jsonb object column. A nil map is stored as {}. type JSONMap map[string]any // Value encodes the map as JSON. func (m JSONMap) Value() (driver.Value, error) { if m == nil { return "{}", nil } raw, err := json.Marshal(map[string]any(m)) if err != nil { return nil, err } return string(raw), nil } // Scan decodes a jsonb object; NULL reads as an empty map. func (m *JSONMap) Scan(src any) error { var raw []byte switch v := src.(type) { case nil: *m = JSONMap{} return nil case []byte: raw = v case string: raw = []byte(v) default: return errors.New("models: unsupported jsonb value") } out := map[string]any{} if len(raw) > 0 { if err := json.Unmarshal(raw, &out); err != nil { return err } } *m = out return nil } func init() { Register(Entry{}) }