Lines 80.76% 21 / 26
Methods 75.00% 15 / 20
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 forApp 100.00% 1 / 1 100.00% 1 / 1 1
 getState 100.00% 1 / 1 100.00% 1 / 1 1
 getEntity 100.00% 1 / 1 100.00% 1 / 1 1
 requireState 100.00% 2 / 2 100.00% 1 / 1 1
 getHistory 100.00% 1 / 1 100.00% 1 / 1 1
 listStates 66.66% 2 / 3 0.00% 0 / 1 3.33
 watchStateChanges 100.00% 1 / 1 100.00% 1 / 1 2
 waitForState 100.00% 1 / 1 100.00% 1 / 1 1
 getRegistry 100.00% 1 / 1 100.00% 1 / 1 1
 watchEvents 100.00% 1 / 1 100.00% 1 / 1 1
 watchTrigger 100.00% 1 / 1 100.00% 1 / 1 1
 callService 100.00% 1 / 1 100.00% 1 / 1 1
 callServiceForResponse 0.00% 0 / 1 0.00% 0 / 1 2
 fireEvent 100.00% 1 / 1 100.00% 1 / 1 1
 wasCausedByStewart 100.00% 1 / 1 100.00% 1 / 1 1
 publish 100.00% 4 / 4 100.00% 1 / 1 2
 watchTopic 0.00% 0 / 1 0.00% 0 / 1 2
 watchConnection 0.00% 0 / 1 0.00% 0 / 1 2
 isConnected 0.00% 0 / 1 0.00% 0 / 1 2
48final readonly class WorkerHaContext implements HaContext
49{
50    public function __construct(
51        private StateCache $states,
52        private RegistryCache $registry,
53        private ConnectionStatus $connection,
54        private ServiceCaller $serviceCalls,
55        private HistoryReader $history,
56        private EventFirer $eventFires,
57        private DispatchStreams $streams,
58        private TopicPublisher $topics,
59        private StewartIdentity $identity,
60        private ResourceScope $resourceScope,
61    ) {}
62
63    public function forApp(AppId $appId): self
64    {
65        return new self($this->states, $this->registry, $this->connection, $this->serviceCalls, $this->history, $this->eventFires, $this->streams, $this->topics, $this->identity, ResourceScope::forApp($appId));
66    }
67
68    public function getState(EntityId|string $entityId): ?EntityState
69    {
70        return $this->states->find(EntityId::fromStringOrId($entityId));
71    }
72
73    public function getEntity(EntityId|string $entityId): Entity
74    {
75        return new Entity($this, EntityId::fromStringOrId($entityId));
76    }
77
78    public function requireState(EntityId|string $entityId): EntityState
79    {
80        $id = EntityId::fromStringOrId($entityId);
81
82        return $this->states->find($id) ?? throw StateException::entityNotFound($id);
83    }
84
85    public function getHistory(EntityId|string $entityId, HistoryQuery $query): EntityStateHistory
86    {
87        return $this->history->fetchHistory($this->resourceScope, EntityId::fromStringOrId($entityId), $query);
88    }
89
90    public function listStates(string|EntityId|Selector|SelectorCollection|EntityFilter|null $selector = null): EntityStateCollection
91    {
92        if ($selector instanceof EntityFilter) {
93            return $this->states->getAllStates()->filterByEntityFilter($selector, $this->registry);
94        }
95
96        return $this->states->filterBySelector($selector === null ? null : Selector::fromSpec($selector));
97    }
98
99    public function watchStateChanges(string|EntityId|Selector|SelectorCollection|EntityFilter $selector): StateChangeStream
100    {
101        return $this->streams->watchStateChanges($this->resourceScope, $selector instanceof EntityFilter ? $selector : Selector::fromSpec($selector));
102    }
103
104    public function waitForState(EntityId|string $entityId, string $state, ?Duration $timeout = null): ?EntityState
105    {
106        return $this->getEntity($entityId)->waitForState($state, $timeout);
107    }
108
109    public function getRegistry(): Registry
110    {
111        return $this->registry;
112    }
113
114    public function watchEvents(string|Selector|SelectorCollection $eventType): EventStream
115    {
116        return $this->streams->watchEvents($this->resourceScope, EventTypeSelector::fromSpec($eventType));
117    }
118
119    public function watchTrigger(HaTrigger|HaTriggerCollection|array $trigger, array $variables = []): EventStream
120    {
121        return $this->streams->watchTrigger($this->resourceScope, TriggerSpec::fromSpec($trigger, $variables));
122    }
123
124    public function callService(string $domain, string $service, array $data = [], ?ServiceTargetSource $target = null): EventContext
125    {
126        return $this->serviceCalls->callService($this->resourceScope, $domain, $service, ServiceFields::fromFieldsDroppingNulls($data), $target?->toServiceTarget());
127    }
128
129    public function callServiceForResponse(string $domain, string $service, array $data = [], ?ServiceTargetSource $target = null): ServiceResponse
130    {
131        return $this->serviceCalls->callServiceForResponse($this->resourceScope, $domain, $service, ServiceFields::fromFieldsDroppingNulls($data), $target?->toServiceTarget());
132    }
133
134    public function fireEvent(string $eventType, array $data = []): EventContext
135    {
136        return $this->eventFires->fireEvent($this->resourceScope, new EventPayload($eventType, $data));
137    }
138
139    public function wasCausedByStewart(StateChange|EntityState|HaEvent $subject): bool
140    {
141        return $this->identity->wasCausedByStewart($subject);
142    }
143
144    public function publish(string $topic, bool|int|float|string|array|null $payload = null): void
145    {
146        $topicPayload = new TopicPayload($payload);
147
148        try {
149            $this->topics->publish($this->resourceScope, $topic, $topicPayload);
150        } catch (TransportException $e) {
151            throw TopicException::createForReason(TopicError::PublishFailed, $e, topic: $topic);
152        }
153    }
154
155    public function watchTopic(string|Selector|SelectorCollection $topic): EventStream
156    {
157        return $this->streams->watchTopic($this->resourceScope, Selector::fromSpec($topic));
158    }
159
160    public function watchConnection(): EventStream
161    {
162        return $this->streams->watchConnection($this->resourceScope);
163    }
164
165    public function isConnected(): bool
166    {
167        return $this->connection->connected;
168    }
169}