Lines 100.00% 32 / 32
Functions and Methods 100.00% 3 / 3
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
ConfigReferenceCommand 100.00% 32 / 32 100.00% 3 / 3 4 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 execute 100.00% 23 / 23 100.00% 1 / 1 1
 reference 100.00% 8 / 8 100.00% 1 / 1 2
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Console;
6
7use Stewart\Runtime\Config\EnvironmentOverlay;
8use Stewart\Runtime\Config\StewartConfigSchema;
9use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
10use Symfony\Component\Console\Attribute\AsCommand;
11use Symfony\Component\Console\Command\Command;
12use Symfony\Component\Console\Input\InputInterface;
13use Symfony\Component\Console\Output\OutputInterface;
14
15#[AsCommand(name: self::NAME, description: 'Show every supported option with its type and default')]
16final class ConfigReferenceCommand extends Command
17{
18    public const string NAME = 'config:reference';
19
20    public function __construct(private readonly StewartConfigSchema $schema)
21    {
22        parent::__construct();
23    }
24
25    protected function execute(InputInterface $input, OutputInterface $output): int
26    {
27        $output->writeln([
28            '# Every setting stewart.yaml understands.',
29            '#',
30            '# Any of them can be set from the environment instead: ' . EnvironmentOverlay::PREFIX
31                . ', then the keys,',
32            '# uppercased, joined by a double underscore. A single underscore belongs to a key',
33            '# name. App options and lists take inline YAML, such as [hall, kitchen].',
34            '#',
35            '#   log_level                      ->  ' . EnvironmentOverlay::PREFIX . 'LOG_LEVEL',
36            '#   apps.demo.worker               ->  ' . EnvironmentOverlay::PREFIX . 'APPS__DEMO__WORKER',
37            '#   apps.demo.options.rooms        ->  ' . EnvironmentOverlay::PREFIX . 'APPS__DEMO__OPTIONS__ROOMS',
38            '#   apps.hall.options.motionSensor ->  ' . EnvironmentOverlay::PREFIX . 'APPS__HALL__OPTIONS__MOTION_SENSOR',
39            '#',
40            '# A variable ending in _FILE reads the value from that file, app options included:',
41            '#   ' . EnvironmentOverlay::PREFIX . 'APPS__DEMO__OPTIONS__API_KEY_FILE=/run/secrets/demo fills apiKey.',
42            '# Without this file and without --config, the environment alone is the configuration.',
43            '#',
44            '# A value in this file can also read a variable: ${HA_TOKEN}, or ${HA_TOKEN:-fallback}.',
45            '# The environment wins over this file, and --log-level wins over both.',
46            '',
47        ]);
48
49        $output->writeln($this->reference());
50
51        return Command::SUCCESS;
52    }
53
54    private function reference(): string
55    {
56        $dumped = new YamlReferenceDumper()->dump($this->schema);
57        $lines = explode("\n", $dumped);
58
59        if (str_starts_with($dumped, StewartConfigSchema::ROOT . ":\n")) {
60            array_shift($lines);
61        }
62
63        return implode("\n", array_map(
64            static fn(string $line): string => preg_replace('/^ {4}/', '', $line) ?? $line,
65            $lines,
66        ));
67    }
68}