package backend import ( "fmt" "sort" "sync" ) // Constructor builds a Backend from a name and its sub-block of raw config. // The framework hands the adapter only its own slice of imagen.yaml, so the // adapter owns its schema completely. type Constructor func(name string, cfg map[string]any) (Backend, error) // Registry holds the name → Constructor table. Adapters call Register from // their package init() to make themselves available to the CLI. type Registry struct { mu sync.RWMutex ctors map[string]Constructor } // NewRegistry returns an empty registry. func NewRegistry() *Registry { return &Registry{ctors: make(map[string]Constructor)} } // Register adds a constructor under typeName (e.g. "comfyui", "mock"). // Re-registering an existing type panics — names are global per binary. func (r *Registry) Register(typeName string, ctor Constructor) { r.mu.Lock() defer r.mu.Unlock() if _, exists := r.ctors[typeName]; exists { panic(fmt.Sprintf("backend type %q already registered", typeName)) } r.ctors[typeName] = ctor } // Build instantiates a backend of typeName using cfg. instanceName is the // user-facing name from imagen.yaml (e.g. "flux-schnell-local"). func (r *Registry) Build(typeName, instanceName string, cfg map[string]any) (Backend, error) { r.mu.RLock() ctor, ok := r.ctors[typeName] r.mu.RUnlock() if !ok { return nil, fmt.Errorf("backend type %q not registered, available: %v", typeName, r.Types()) } return ctor(instanceName, cfg) } // Types returns the registered backend type names, sorted. func (r *Registry) Types() []string { r.mu.RLock() defer r.mu.RUnlock() out := make([]string, 0, len(r.ctors)) for k := range r.ctors { out = append(out, k) } sort.Strings(out) return out } // Has reports whether typeName is registered. func (r *Registry) Has(typeName string) bool { r.mu.RLock() defer r.mu.RUnlock() _, ok := r.ctors[typeName] return ok } // Default is the process-wide registry adapters register against. var Default = NewRegistry() // Register is shorthand for Default.Register. func Register(typeName string, ctor Constructor) { Default.Register(typeName, ctor) }