verstak/internal/core/templates/registry.go

135 lines
2.9 KiB
Go

package templates
import (
"encoding/json"
"fmt"
"sort"
"sync"
)
// Registry holds all available templates (system + user overrides).
type Registry struct {
mu sync.RWMutex
templates map[string]*Template
}
func NewRegistry() *Registry {
return &Registry{templates: make(map[string]*Template)}
}
// LoadSystem reads system templates from embedded JSON.
func (r *Registry) LoadSystem() error {
data, err := systemTemplatesFS.ReadFile("system_templates.json")
if err != nil {
return err
}
var sysTemplates []Template
if err := json.Unmarshal(data, &sysTemplates); err != nil {
return err
}
r.mu.Lock()
defer r.mu.Unlock()
for _, t := range sysTemplates {
cp := t
r.templates[t.ID] = &cp
}
return nil
}
// Get returns a template by ID.
func (r *Registry) Get(id string) (*Template, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
t, ok := r.templates[id]
return t, ok
}
// Enabled returns all enabled templates sorted by type+id.
func (r *Registry) Enabled() []*Template {
r.mu.RLock()
defer r.mu.RUnlock()
var result []*Template
for _, t := range r.templates {
if t.Enabled {
result = append(result, t)
}
}
sort.Slice(result, func(i, j int) bool {
if result[i].Type != result[j].Type {
return result[i].Type < result[j].Type
}
return result[i].ID < result[j].ID
})
return result
}
// All returns all registered templates sorted by type+id.
func (r *Registry) All() []*Template {
r.mu.RLock()
defer r.mu.RUnlock()
return sortedCopy(r.templates)
}
func sortedCopy(templates map[string]*Template) []*Template {
result := make([]*Template, 0, len(templates))
for _, t := range templates {
result = append(result, t)
}
sort.Slice(result, func(i, j int) bool {
if result[i].Type != result[j].Type {
return result[i].Type < result[j].Type
}
return result[i].ID < result[j].ID
})
return result
}
// EnabledForParent returns templates that are allowed for a given parent type.
func (r *Registry) EnabledForParent(parentType string) []*Template {
r.mu.RLock()
defer r.mu.RUnlock()
var result []*Template
for _, t := range r.templates {
if !t.Enabled {
continue
}
for _, allowed := range t.AllowedParentTypes {
if allowed == "*" || allowed == parentType {
result = append(result, t)
break
}
}
}
sort.Slice(result, func(i, j int) bool {
if result[i].Type != result[j].Type {
return result[i].Type < result[j].Type
}
return result[i].ID < result[j].ID
})
return result
}
// Enable enables a template by ID.
func (r *Registry) Enable(id string) error {
r.mu.Lock()
defer r.mu.Unlock()
t, ok := r.templates[id]
if !ok {
return fmt.Errorf("template %q not found", id)
}
t.Enabled = true
return nil
}
// Disable disables a template by ID.
func (r *Registry) Disable(id string) error {
r.mu.Lock()
defer r.mu.Unlock()
t, ok := r.templates[id]
if !ok {
return fmt.Errorf("template %q not found", id)
}
t.Enabled = false
return nil
}