A community based topic aggregation platform built on atproto
1package main 2 3import ( 4 "flag" 5 "fmt" 6 "log" 7 "os" 8 "path/filepath" 9 10 lexicon "github.com/bluesky-social/indigo/atproto/lexicon" 11) 12 13func main() { 14 var ( 15 schemaPath = flag.String("path", "internal/atproto/lexicon", "Path to lexicon schemas directory") 16 verbose = flag.Bool("v", false, "Verbose output") 17 ) 18 flag.Parse() 19 20 if *verbose { 21 log.SetFlags(log.LstdFlags | log.Lshortfile) 22 } 23 24 // Check if path exists 25 if _, err := os.Stat(*schemaPath); os.IsNotExist(err) { 26 log.Fatalf("Schema path does not exist: %s", *schemaPath) 27 } 28 29 // Create a new catalog 30 catalog := lexicon.NewBaseCatalog() 31 32 // Load all schemas from the directory 33 fmt.Printf("Loading schemas from: %s\n", *schemaPath) 34 if err := loadSchemasWithDebug(&catalog, *schemaPath, *verbose); err != nil { 35 log.Fatalf("Failed to load schemas: %v", err) 36 } 37 38 fmt.Printf("✅ Successfully loaded schemas from %s\n", *schemaPath) 39 40 // Validate schema structure by trying to resolve some known schemas 41 if err := validateSchemaStructure(&catalog, *schemaPath, *verbose); err != nil { 42 log.Fatalf("Schema validation failed: %v", err) 43 } 44 45 fmt.Println("✅ All schemas validated successfully!") 46} 47 48// validateSchemaStructure performs additional validation checks 49func validateSchemaStructure(catalog *lexicon.BaseCatalog, schemaPath string, verbose bool) error { 50 var validationErrors []string 51 var schemaFiles []string 52 53 // Collect all JSON schema files 54 err := filepath.Walk(schemaPath, func(path string, info os.FileInfo, err error) error { 55 if err != nil { 56 return err 57 } 58 59 // Only process .json files 60 if !info.IsDir() && filepath.Ext(path) == ".json" { 61 schemaFiles = append(schemaFiles, path) 62 } 63 return nil 64 }) 65 66 if err != nil { 67 return fmt.Errorf("error walking schema directory: %w", err) 68 } 69 70 if verbose { 71 fmt.Printf("\nFound %d schema files to validate:\n", len(schemaFiles)) 72 for _, file := range schemaFiles { 73 fmt.Printf(" - %s\n", file) 74 } 75 } 76 77 // Try to resolve some of our expected schemas 78 expectedSchemas := []string{ 79 "social.coves.actor.profile", 80 "social.coves.community.profile", 81 "social.coves.post.text", 82 "social.coves.richtext.facet", 83 } 84 85 if verbose { 86 fmt.Println("\nValidating key schemas:") 87 } 88 89 for _, schemaID := range expectedSchemas { 90 if _, err := catalog.Resolve(schemaID); err != nil { 91 validationErrors = append(validationErrors, fmt.Sprintf("Failed to resolve schema %s: %v", schemaID, err)) 92 } else if verbose { 93 fmt.Printf(" ✅ %s\n", schemaID) 94 } 95 } 96 97 if len(validationErrors) > 0 { 98 fmt.Println("❌ Schema validation errors found:") 99 for _, errMsg := range validationErrors { 100 fmt.Printf(" %s\n", errMsg) 101 } 102 return fmt.Errorf("found %d validation errors", len(validationErrors)) 103 } 104 105 return nil 106} 107 108// loadSchemasWithDebug loads schemas one by one to identify problematic files 109func loadSchemasWithDebug(catalog *lexicon.BaseCatalog, schemaPath string, verbose bool) error { 110 var schemaFiles []string 111 112 // Collect all JSON schema files 113 err := filepath.Walk(schemaPath, func(path string, info os.FileInfo, err error) error { 114 if err != nil { 115 return err 116 } 117 118 // Only process .json files 119 if !info.IsDir() && filepath.Ext(path) == ".json" { 120 schemaFiles = append(schemaFiles, path) 121 } 122 return nil 123 }) 124 125 if err != nil { 126 return fmt.Errorf("error walking schema directory: %w", err) 127 } 128 129 // Try to load schemas one by one 130 for _, schemaFile := range schemaFiles { 131 if verbose { 132 fmt.Printf(" Loading: %s\n", schemaFile) 133 } 134 135 // Create a temporary catalog for this file 136 tempCatalog := lexicon.NewBaseCatalog() 137 if err := tempCatalog.LoadDirectory(filepath.Dir(schemaFile)); err != nil { 138 return fmt.Errorf("failed to load schema file %s: %w", schemaFile, err) 139 } 140 } 141 142 // If all individual files loaded OK, try loading the whole directory 143 return catalog.LoadDirectory(schemaPath) 144}