Something went wrong. Try again.
Parse and validate AT Protocol Lexicons with DTO generation for Laravel
Something went wrong. Try again.
5.5 kB · 188 lines
PHP
at dev
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189<?php
namespace SocialDept\AtpSchema\Console;
use Illuminate\Console\Command;use SocialDept\AtpSchema\Parser\SchemaLoader;
class ListCommand extends Command{ /** * The name and signature of the console command. */ protected $signature = 'schema:list {--filter= : Filter schemas by pattern (supports wildcards)} {--type= : Filter by schema type (record, query, procedure, subscription)}';
/** * The console command description. */ protected $description = 'List all available ATProto Lexicon schemas';
/** * Execute the console command. */ public function handle(): int { $filter = $this->option('filter'); $type = $this->option('type');
try { $sources = config('schema.sources', []); $loader = new SchemaLoader($sources);
$schemas = $this->discoverSchemas($sources);
if ($filter) { $schemas = $this->filterSchemas($schemas, $filter); }
if ($type) { $schemas = $this->filterByType($schemas, $type, $loader); }
if (empty($schemas)) { $this->info('No schemas found');
return self::SUCCESS; }
$this->info('Found '.count($schemas).' schema(s):'); $this->newLine();
$tableData = [];
foreach ($schemas as $nsid) { try { $document = $loader->load($nsid);
$schemaType = 'unknown'; if ($document->isRecord()) { $schemaType = 'record'; } elseif ($document->isQuery()) { $schemaType = 'query'; } elseif ($document->isProcedure()) { $schemaType = 'procedure'; } elseif ($document->isSubscription()) { $schemaType = 'subscription'; }
$tableData[] = [ $nsid, $schemaType, $document->description ?? '-', ]; } catch (\Exception $e) { $tableData[] = [ $nsid, 'error', $e->getMessage(), ]; } }
$this->table(['NSID', 'Type', 'Description'], $tableData);
return self::SUCCESS; } catch (\Exception $e) { $this->error('Failed to list schemas: '.$e->getMessage());
if ($this->output->isVerbose()) { $this->error($e->getTraceAsString()); }
return self::FAILURE; } }
/** * Discover all schema files in sources. * * @param array<string> $sources * @return array<string> */ protected function discoverSchemas(array $sources): array { $schemas = [];
foreach ($sources as $source) { if (! is_dir($source)) { continue; }
$schemas = array_merge($schemas, $this->scanDirectory($source)); }
return array_unique($schemas); }
/** * Scan directory for schema files. * * @return array<string> */ protected function scanDirectory(string $directory, string $prefix = ''): array { $schemas = []; $items = scandir($directory);
foreach ($items as $item) { if ($item === '.' || $item === '..') { continue; }
$path = $directory.'/'.$item;
if (is_dir($path)) { $newPrefix = $prefix ? $prefix.'.'.$item : $item; $schemas = array_merge($schemas, $this->scanDirectory($path, $newPrefix)); } elseif (pathinfo($item, PATHINFO_EXTENSION) === 'json' || pathinfo($item, PATHINFO_EXTENSION) === 'php') { $name = pathinfo($item, PATHINFO_FILENAME); $nsid = $prefix ? $prefix.'.'.$name : $name; $schemas[] = $nsid; } }
return $schemas; }
/** * Filter schemas by pattern. * * @param array<string> $schemas * @return array<string> */ protected function filterSchemas(array $schemas, string $pattern): array { $pattern = str_replace('*', '.*', preg_quote($pattern, '/'));
return array_filter($schemas, function ($nsid) use ($pattern) { return preg_match("/^{$pattern}$/", $nsid); }); }
/** * Filter schemas by type. * * @param array<string> $schemas * @return array<string> */ protected function filterByType(array $schemas, string $type, SchemaLoader $loader): array { return array_filter($schemas, function ($nsid) use ($type, $loader) { try { $document = $loader->load($nsid);
return match ($type) { 'record' => $document->isRecord(), 'query' => $document->isQuery(), 'procedure' => $document->isProcedure(), 'subscription' => $document->isSubscription(), default => false, }; } catch (\Exception) { return false; } }); }}