<?php
declare(strict_types=1);
namespace GNexus\Synapse\Config;
use GNexus\Synapse\Exception\ConfigurationException;
/**
* Конфигурация клиента: base_url, ключ, таймаут, источник по умолчанию.
* Прямые аргументы сильнее env; имена переменных фиксированы для экосистемы:
* SYNAPSE_URL, SYNAPSE_API_KEY, SYNAPSE_TIMEOUT, SYNAPSE_DEFAULT_SOURCE.
*/
final readonly class SynapseConfig
{
public const ENV_URL = 'SYNAPSE_URL';
public const ENV_API_KEY = 'SYNAPSE_API_KEY';
public const ENV_TIMEOUT = 'SYNAPSE_TIMEOUT';
public const ENV_DEFAULT_SOURCE = 'SYNAPSE_DEFAULT_SOURCE';
public function __construct(
public string $baseUrl,
public ?string $apiKey = null,
public float $timeoutSeconds = 10.0,
public string $defaultSource = '',
) {
if (trim($baseUrl) === '') {
throw new ConfigurationException('base_url пуст: передайте url или ' . self::ENV_URL);
}
if (!preg_match('#^https?://#i', $baseUrl)) {
throw new ConfigurationException("base_url без схемы http(s): {$baseUrl}");
}
if ($timeoutSeconds <= 0) {
throw new ConfigurationException("timeoutSeconds={$timeoutSeconds} должен быть > 0");
}
if ($apiKey !== null && $apiKey === '') {
throw new ConfigurationException('api_key пустая строка — укажите ключ или null');
}
}
/** Фолбэк в env: fromGlobals() или из синтетического массива (тесты). */
public static function fromGlobals(array $env = []): self
{
$env = $env === [] ? $_SERVER + $_ENV : $env;
$timeout = $env[self::ENV_TIMEOUT] ?? '';
return new self(
baseUrl: $env[self::ENV_URL] ?? '',
apiKey: isset($env[self::ENV_API_KEY]) && $env[self::ENV_API_KEY] !== ''
? $env[self::ENV_API_KEY]
: null,
timeoutSeconds: $timeout === '' ? 10.0 : (float) $timeout,
defaultSource: $env[self::ENV_DEFAULT_SOURCE] ?? '',
);
}
public function url(string $path): string
{
// путь — с начальным '/'
return rtrim($this->baseUrl, '/') . $path;
}
public function source(): string
{
return $this->defaultSource;
}
}