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.markup",
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}