Refactor architecture: eliminate auto-discovery and consolidate packages
- Remove auto-discovery entirely (~450 lines) * Delete internal/content/discoverer.go * Simplify enhancer to single-phase processing * Remove duplicate container expansion logic - Consolidate repository implementations * Move internal/content/client.go → internal/db/http_client.go * Group all repository implementations in db/ package - Add file utilities to engine following Go stdlib patterns * Add engine.ProcessFile() and ProcessDirectory() methods * Engine now handles both content processing AND file operations - Move site management to dedicated package * Move internal/content/site_manager.go → internal/sites/manager.go * Clear separation of site lifecycle from content processing - Preserve container expansion (syntactic sugar) * .insertr on containers still auto-applies to viable children * Container detection logic consolidated in engine/utils.go Result: Clean architecture with single source of truth for .insertr processing
This commit is contained in:
227
internal/sites/manager.go
Normal file
227
internal/sites/manager.go
Normal file
@@ -0,0 +1,227 @@
|
||||
package sites
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/insertr/insertr/internal/config"
|
||||
"github.com/insertr/insertr/internal/content"
|
||||
"github.com/insertr/insertr/internal/db"
|
||||
"github.com/insertr/insertr/internal/engine"
|
||||
"maps"
|
||||
)
|
||||
|
||||
// SiteManager handles registration and enhancement of static sites
|
||||
type SiteManager struct {
|
||||
sites map[string]*config.SiteConfig
|
||||
enhancer *content.Enhancer
|
||||
mutex sync.RWMutex
|
||||
devMode bool
|
||||
contentClient db.ContentRepository
|
||||
authProvider *engine.AuthProvider
|
||||
}
|
||||
|
||||
// NewSiteManager creates a new site manager
|
||||
func NewSiteManager(contentClient db.ContentRepository, devMode bool) *SiteManager {
|
||||
return &SiteManager{
|
||||
sites: make(map[string]*config.SiteConfig),
|
||||
enhancer: content.NewDefaultEnhancer(contentClient, ""), // siteID will be set per operation
|
||||
devMode: devMode,
|
||||
contentClient: contentClient,
|
||||
authProvider: &engine.AuthProvider{Type: "mock"}, // default
|
||||
}
|
||||
}
|
||||
|
||||
// NewSiteManagerWithAuth creates a new site manager with auth provider
|
||||
func NewSiteManagerWithAuth(contentClient db.ContentRepository, devMode bool, authProvider *engine.AuthProvider) *SiteManager {
|
||||
if authProvider == nil {
|
||||
authProvider = &engine.AuthProvider{Type: "mock"}
|
||||
}
|
||||
return &SiteManager{
|
||||
sites: make(map[string]*config.SiteConfig),
|
||||
contentClient: contentClient,
|
||||
authProvider: authProvider,
|
||||
devMode: devMode,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterSite adds a site to the manager
|
||||
func (sm *SiteManager) RegisterSite(config *config.SiteConfig) error {
|
||||
sm.mutex.Lock()
|
||||
defer sm.mutex.Unlock()
|
||||
|
||||
// Validate site configuration
|
||||
if config.SiteID == "" {
|
||||
return fmt.Errorf("site_id is required")
|
||||
}
|
||||
if config.Path == "" {
|
||||
return fmt.Errorf("path is required for site %s", config.SiteID)
|
||||
}
|
||||
|
||||
// Check if path exists, auto-create enhancement directories
|
||||
if _, err := os.Stat(config.Path); os.IsNotExist(err) {
|
||||
// Auto-create directory if it appears to be an enhancement target
|
||||
if strings.HasSuffix(config.Path, "_enhanced") {
|
||||
log.Printf("📁 Creating enhancement directory: %s", config.Path)
|
||||
if err := os.MkdirAll(config.Path, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create enhancement directory %s: %w", config.Path, err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("site path does not exist: %s", config.Path)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to absolute path
|
||||
absPath, err := filepath.Abs(config.Path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to resolve absolute path for %s: %w", config.Path, err)
|
||||
}
|
||||
config.Path = absPath
|
||||
|
||||
sm.sites[config.SiteID] = config
|
||||
log.Printf("📁 Registered site %s at %s", config.SiteID, config.Path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterSites bulk registers multiple sites from configuration
|
||||
func (sm *SiteManager) RegisterSites(configs []*config.SiteConfig) error {
|
||||
for _, config := range configs {
|
||||
if err := sm.RegisterSite(config); err != nil {
|
||||
return fmt.Errorf("failed to register site %s: %w", config.SiteID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSite returns a registered site configuration
|
||||
func (sm *SiteManager) GetSite(siteID string) (*config.SiteConfig, bool) {
|
||||
sm.mutex.RLock()
|
||||
defer sm.mutex.RUnlock()
|
||||
|
||||
site, exists := sm.sites[siteID]
|
||||
return site, exists
|
||||
}
|
||||
|
||||
// GetAllSites returns all registered sites
|
||||
func (sm *SiteManager) GetAllSites() map[string]*config.SiteConfig {
|
||||
sm.mutex.RLock()
|
||||
defer sm.mutex.RUnlock()
|
||||
|
||||
// Return a copy to prevent external modification
|
||||
result := make(map[string]*config.SiteConfig)
|
||||
maps.Copy(result, sm.sites)
|
||||
return result
|
||||
}
|
||||
|
||||
// IsAutoEnhanceEnabled checks if a site has auto-enhancement enabled
|
||||
func (sm *SiteManager) IsAutoEnhanceEnabled(siteID string) bool {
|
||||
sm.mutex.RLock()
|
||||
defer sm.mutex.RUnlock()
|
||||
|
||||
site, exists := sm.sites[siteID]
|
||||
return exists && site.AutoEnhance
|
||||
}
|
||||
|
||||
// EnhanceSite performs enhancement from source to output directory
|
||||
func (sm *SiteManager) EnhanceSite(siteID string) error {
|
||||
sm.mutex.RLock()
|
||||
site, exists := sm.sites[siteID]
|
||||
sm.mutex.RUnlock()
|
||||
|
||||
if !exists {
|
||||
return fmt.Errorf("site %s is not registered", siteID)
|
||||
}
|
||||
|
||||
// Use source path if available, otherwise use main path (for backwards compatibility)
|
||||
sourcePath := site.SourcePath
|
||||
if sourcePath == "" {
|
||||
sourcePath = site.Path
|
||||
}
|
||||
outputPath := site.Path
|
||||
|
||||
log.Printf("🔄 Enhancing site %s from %s to %s", siteID, sourcePath, outputPath)
|
||||
|
||||
// Create output directory if it doesn't exist
|
||||
if err := os.MkdirAll(outputPath, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create output directory %s: %w", outputPath, err)
|
||||
}
|
||||
|
||||
// Create enhancer with auth provider for this operation
|
||||
// Discovery disabled by default - developers should explicitly mark elements with class="insertr"
|
||||
discoveryConfig := config.DiscoveryConfig{
|
||||
Enabled: false, // Changed from true - respect developer intent
|
||||
Aggressive: false,
|
||||
Containers: true,
|
||||
Individual: true,
|
||||
}
|
||||
|
||||
// Override with site-specific discovery config if provided
|
||||
if site.Discovery != nil {
|
||||
discoveryConfig = *site.Discovery
|
||||
log.Printf("🔧 Using site-specific discovery config for %s: enabled=%v, aggressive=%v",
|
||||
siteID, discoveryConfig.Enabled, discoveryConfig.Aggressive)
|
||||
}
|
||||
|
||||
config := content.EnhancementConfig{
|
||||
Discovery: discoveryConfig,
|
||||
ContentInjection: true,
|
||||
GenerateIDs: true,
|
||||
}
|
||||
enhancer := content.NewEnhancerWithAuth(sm.contentClient, siteID, config, sm.authProvider)
|
||||
|
||||
// Perform enhancement from source to output
|
||||
if err := enhancer.EnhanceDirectory(sourcePath, outputPath); err != nil {
|
||||
return fmt.Errorf("failed to enhance site %s: %w", siteID, err)
|
||||
}
|
||||
|
||||
log.Printf("✅ Successfully enhanced site %s", siteID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnhanceAllSites enhances all registered sites that have auto-enhancement enabled
|
||||
func (sm *SiteManager) EnhanceAllSites() error {
|
||||
sm.mutex.RLock()
|
||||
sites := make([]*config.SiteConfig, 0, len(sm.sites))
|
||||
for _, site := range sm.sites {
|
||||
if site.AutoEnhance {
|
||||
sites = append(sites, site)
|
||||
}
|
||||
}
|
||||
sm.mutex.RUnlock()
|
||||
|
||||
var errors []error
|
||||
for _, site := range sites {
|
||||
if err := sm.EnhanceSite(site.SiteID); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return fmt.Errorf("enhancement failed for some sites: %v", errors)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStats returns statistics about registered sites
|
||||
func (sm *SiteManager) GetStats() map[string]any {
|
||||
sm.mutex.RLock()
|
||||
defer sm.mutex.RUnlock()
|
||||
|
||||
autoEnhanceCount := 0
|
||||
for _, site := range sm.sites {
|
||||
if site.AutoEnhance {
|
||||
autoEnhanceCount++
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"total_sites": len(sm.sites),
|
||||
"auto_enhance_sites": autoEnhanceCount,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user