homeos/app/Services/AddonRegistry.php

81 lines
2.8 KiB
PHP

<?php
namespace App\Services;
use App\Models\Addon;
/**
* Static catalogue of installable integrations. Each definition is UI-only metadata; runtime
* state (installed?, connected?, secrets) lives on the {@see Addon} row. Adding an integration
* later is a new entry here plus its normalizer under Support/Mqtt (H3).
*/
class AddonRegistry
{
/** @return array<string, array<string, mixed>> */
public static function all(): array
{
return [
'ring' => [
'key' => 'ring',
'name' => 'Ring',
'vendor' => 'Ring',
'icon' => 'doorbell',
// Ring has no local API — the established bridge is ring-mqtt (cloud, token auth).
// The BRIDGE does the Ring login (email/password/2FA) in its own web UI; HomeOS never
// handles Ring credentials. So the addon's job is to guide setup + reflect the
// bridge's real MQTT status — not to collect a password.
'cloud' => true,
'summary_key' => 'addons.ring.summary',
'body_key' => 'addons.ring.body',
'backend' => 'ring-mqtt',
'docs' => 'https://github.com/tsightler/ring-mqtt',
'setup_modal' => 'modals.ring-setup',
],
'smtp' => [
'key' => 'smtp',
'name' => 'E-Mail (SMTP)',
'vendor' => 'SMTP',
'icon' => 'alert',
'cloud' => false,
'summary_key' => 'addons.smtp.summary',
'body_key' => 'addons.smtp.body',
'docs' => 'https://homeos.local',
'setup_modal' => 'modals.smtp-setup',
],
];
}
public static function get(string $key): ?array
{
return static::all()[$key] ?? null;
}
public static function has(string $key): bool
{
return isset(static::all()[$key]);
}
/**
* Merge each catalogue definition with its persisted state, creating rows lazily so the
* page can render before anything is installed.
*
* @return array<int, array<string, mixed>>
*/
public static function withState(): array
{
$rows = Addon::whereIn('key', array_keys(static::all()))->get()->keyBy('key');
return collect(static::all())->map(function (array $def) use ($rows) {
$state = $rows->get($def['key']);
return $def + [
'installed' => (bool) ($state?->installed ?? false),
'status' => $state?->status ?? 'disconnected',
'status_detail' => $state?->status_detail,
'connected_at' => $state?->connected_at,
'uuid' => $state?->uuid,
];
})->values()->all();
}
}