Lines 100.00% 26 / 26
Functions and Methods 100.00% 1 / 1
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
AppCatalogResolver 100.00% 26 / 26 100.00% 1 / 1 14 100.00% 1 / 1
 resolveCatalog 100.00% 26 / 26 100.00% 1 / 1 14
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\App;
6
7use Stewart\Contracts\App\AppId;
8use Stewart\Contracts\App\Collection\AppIdCollection;
9use Stewart\Runtime\App\Collection\AppDefinitionCollection;
10use Stewart\Runtime\Config\Collection\AppOverrideCollection;
11use Stewart\Runtime\Exception\ConfigurationException;
12
13final readonly class AppCatalogResolver
14{
15    /** @throws ConfigurationException */
16    public function resolveCatalog(DiscoveryResult $discovered, AppOverrideCollection $overrides, int $workers, AppSelection $selection = new AppSelection()): AppCatalog
17    {
18        $knownIds = $discovered->apps->listAppIds();
19        $unmatchedOverrideIds = [];
20
21        foreach ($selection->onlyIds ?? [] as $selectedId) {
22            if (!$knownIds->containsId($selectedId)) {
23                throw ConfigurationException::appSelectionUnknown($selectedId, $knownIds);
24            }
25        }
26
27        foreach ($overrides as $override) {
28            if ($knownIds->findFirstWhere(static fn(AppId $known): bool => $known->collidesWith($override->id)) !== null) {
29                continue;
30            }
31
32            // The app an unknown override names may live in a file that failed to load, which is reported instead.
33            if (!$discovered->unloadable->isEmpty()) {
34                $unmatchedOverrideIds[] = $override->id;
35
36                continue;
37            }
38
39            throw ConfigurationException::appUnknown($override->id, $knownIds);
40        }
41
42        $enabled = [];
43
44        foreach ($discovered->apps as $app) {
45            $override = $overrides->findMatchingApp($app->id);
46
47            if (!$selection->admitsApp($app->id, $override === null || $override->enabled)) {
48                continue;
49            }
50
51            $worker = $override?->worker;
52
53            if ($worker !== null && $workers > 0 && $worker >= $workers) {
54                throw ConfigurationException::workerIndexOutOfRange($app->id, $worker, $workers);
55            }
56
57            $enabled[] = new AppDefinition(
58                id: $app->id,
59                class: $app->class,
60                options: $override === null ? [] : $override->options,
61                worker: $worker,
62                startsPaused: $override !== null && $override->paused,
63            );
64        }
65
66        return new AppCatalog(AppDefinitionCollection::keyedByAppId($enabled), $knownIds, AppIdCollection::fromList($unmatchedOverrideIds));
67    }
68}