Build Reactive Signals for Bluesky's AT Protocol Firehose in Laravel
1<?php
2
3namespace SocialDept\AtpSignals\Commands;
4
5use Illuminate\Console\Command;
6use Illuminate\Support\Collection;
7use SocialDept\AtpSignals\Services\SignalRegistry;
8
9class ListSignalsCommand extends Command
10{
11 protected $signature = 'signal:list';
12
13 protected $description = 'List all registered Signals';
14
15 public function handle(SignalRegistry $registry): int
16 {
17 $signals = $this->discoverSignals($registry);
18
19 if ($signals->isEmpty()) {
20 $this->displayNoSignalsWarning();
21
22 return self::SUCCESS;
23 }
24
25 $this->displaySignalCount($signals->count());
26
27 foreach ($signals as $signal) {
28 $this->displaySignalDetails($signal);
29 }
30
31 return self::SUCCESS;
32 }
33
34 private function discoverSignals(SignalRegistry $registry): Collection
35 {
36 $registry->discover();
37
38 return $registry->all();
39 }
40
41 private function displayNoSignalsWarning(): void
42 {
43 $this->warn('No signals registered.');
44 $this->info('Create signals in app/Signals or register them in config/signal.php');
45 }
46
47 private function displaySignalCount(int $count): void
48 {
49 $this->components->info("Found {$count} ".str('signal')->plural($count));
50 $this->newLine();
51 }
52
53 private function displaySignalDetails(object $signal): void
54 {
55 $className = class_basename($signal);
56 $fullClassName = get_class($signal);
57
58 $this->line(" <fg=green>•</> <options=bold>{$className}</>");
59 $this->line(" <fg=gray>Class:</> {$fullClassName}");
60
61 $this->displayEventTypes($signal);
62 $this->displayCollections($signal);
63 $this->displayDids($signal);
64 $this->displayQueueInfo($signal);
65
66 $this->newLine();
67 }
68
69 private function displayEventTypes(object $signal): void
70 {
71 $eventTypes = collect($signal->eventTypes())
72 ->map(fn ($type) => "<fg=cyan>{$type}</>")
73 ->join(', ');
74
75 $this->line(" <fg=gray>Events:</> {$eventTypes}");
76 }
77
78 private function displayCollections(object $signal): void
79 {
80 $collections = $signal->collections()
81 ? collect($signal->collections())->map(fn ($col) => "<fg=yellow>{$col}</>")->join(', ')
82 : '<fg=gray>All collections</>';
83
84 $this->line(" <fg=gray>Collections:</> {$collections}");
85 }
86
87 private function displayDids(object $signal): void
88 {
89 if (! $signal->dids()) {
90 return;
91 }
92
93 $dids = collect($signal->dids())
94 ->map(fn ($did) => "<fg=magenta>{$did}</>")
95 ->join(', ');
96
97 $this->line(" <fg=gray>DIDs:</> {$dids}");
98 }
99
100 private function displayQueueInfo(object $signal): void
101 {
102 if (! $signal->shouldQueue()) {
103 return;
104 }
105
106 $queue = $signal->queue() ?? 'default';
107
108 $this->line(" <fg=gray>Queue:</> <fg=blue>{$queue}</>");
109 }
110}