Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at dev 2.8 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Console; 4 5use Illuminate\Console\Command; 6use SocialDept\AtpSchema\Parser\SchemaLoader; 7use SocialDept\AtpSchema\Validation\LexiconValidator; 8 9class ValidateCommand extends Command 10{ 11 /** 12 * The name and signature of the console command. 13 */ 14 protected $signature = 'schema:validate 15 {nsid : The NSID of the schema to validate} 16 {--data= : JSON data to validate against the schema} 17 {--file= : Path to file containing JSON data to validate}'; 18 19 /** 20 * The console command description. 21 */ 22 protected $description = 'Validate data against ATProto Lexicon schemas'; 23 24 /** 25 * Execute the console command. 26 */ 27 public function handle(): int 28 { 29 $nsid = $this->argument('nsid'); 30 $dataJson = $this->option('data'); 31 $dataFile = $this->option('file'); 32 33 if (! $dataJson && ! $dataFile) { 34 $this->error('Either --data or --file option must be provided'); 35 36 return self::FAILURE; 37 } 38 39 try { 40 // Load data 41 if ($dataFile) { 42 if (! file_exists($dataFile)) { 43 $this->error("File not found: {$dataFile}"); 44 45 return self::FAILURE; 46 } 47 48 $dataJson = file_get_contents($dataFile); 49 } 50 51 $data = json_decode($dataJson, true); 52 53 if (json_last_error() !== JSON_ERROR_NONE) { 54 $this->error('Invalid JSON: '.json_last_error_msg()); 55 56 return self::FAILURE; 57 } 58 59 // Load schema and validate 60 $sources = config('schema.sources', []); 61 $loader = new SchemaLoader($sources); 62 $validator = new LexiconValidator($loader); 63 64 $this->info("Validating data against schema: {$nsid}"); 65 66 $document = $loader->load($nsid); 67 68 $errors = $validator->validateWithErrors($data, $document); 69 70 if (empty($errors)) { 71 $this->info('✓ Validation passed'); 72 73 return self::SUCCESS; 74 } 75 76 $this->error('✗ Validation failed:'); 77 $this->newLine(); 78 79 foreach ($errors as $field => $fieldErrors) { 80 $this->line(" {$field}:"); 81 foreach ($fieldErrors as $error) { 82 $this->line(" - {$error}"); 83 } 84 } 85 86 return self::FAILURE; 87 } catch (\Exception $e) { 88 $this->error('Validation error: '.$e->getMessage()); 89 90 if ($this->output->isVerbose()) { 91 $this->error($e->getTraceAsString()); 92 } 93 94 return self::FAILURE; 95 } 96 } 97}